From de2ea4c96a007cd1c6545f0b4a063d3392a1a0d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Smodi=C5=A1?= Date: Thu, 15 Oct 2015 16:48:38 +0200 Subject: Implemented python login using authenticated SAML credentials. --- server/handlers.py | 14 +++++++++--- server/user_session.py | 58 ++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 9 deletions(-) (limited to 'server') diff --git a/server/handlers.py b/server/handlers.py index 93818f0..5df7161 100644 --- a/server/handlers.py +++ b/server/handlers.py @@ -284,11 +284,19 @@ class GetUserStat(CodeqService): class SamlLogin(CodeqService): def process(self, request): - data = request.data.get('data') - if data is None: + js = request.data + saml_data = js.get('saml_data') + gui_lang = js.get('gui_lang', 'en') + if saml_data is None: request.reply({'code': 1, 'message': 'SAML user data not specified'}) else: - request.reply({'code': 0, 'message': 'OK'}) # TODO: implement login using SAML credentials + session = request.session + try: + name, email, date_joined, last_login = session.saml_login_or_signup(saml_data, gui_lang) + except Exception as e: + request.reply({'code': 2, 'message': 'SAML login failed: ' + str(e)}) + else: + request.reply({'code': 0, 'message': 'OK', 'name': name, 'email': email, 'joined': date_joined.isoformat(), 'last-login': last_login.isoformat(), 'settings': session.get_settings()}) # maps actions to their handlers diff --git a/server/user_session.py b/server/user_session.py index b5cdd61..739da9a 100644 --- a/server/user_session.py +++ b/server/user_session.py @@ -86,7 +86,10 @@ class UserSession(object): finally: cur.close() finally: - conn.commit() + try: + conn.commit() + except: + pass db.return_connection(conn) def signup(self, username, name, email, password, lang): @@ -110,8 +113,45 @@ class UserSession(object): self.settings = {'gui_lang': lang} finally: cur.close() - finally: conn.commit() + finally: + db.return_connection(conn) + + def saml_login_or_signup(self, saml_data, gui_lang): + uuid = saml_data.get('schacUUID') + if uuid is None: + raise AuthenticationFailed('SAML data does not contain schacUUID') + name = saml_data.get('displayName') + email = saml_data.get('mail') + with self._access_lock: + now = datetime.datetime.utcnow() + conn = db.get_connection() + try: + cur = conn.cursor() + try: + cur.execute('update codeq_user set name = %s, email = %s, saml_data = %s, last_login = %s where username = %s and saml_data is not null returning id, gui_lang, date_joined, robot_address', (name, email, psycopg2.extras.Json(saml_data), str(now), uuid)) + row = cur.fetchone() + if row: + self.uid = row[0] + self.username = uuid + self.settings = {'gui_lang': row[1], 'robot_address': row[3]} + return name, email, row[2], now + else: + cur.execute('insert into codeq_user (username, name, email, is_admin, is_active, date_joined, last_login, gui_lang, saml_data) values (%s, %s, %s, %s, %s, %s, %s, %s, %s) returning id', (uuid, name, email, False, True, str(now), str(now), gui_lang, psycopg2.extras.Json(saml_data))) + row = cur.fetchone() + if row is None: + raise SignupFailed('Sign-up failed') + self.uid = row[0] + self.username = uuid + self.settings = {'gui_lang': gui_lang, 'robot_address': None} + return name, email, now, now + finally: + cur.close() + finally: + try: + conn.commit() + except: + pass db.return_connection(conn) def destroy(self): @@ -150,8 +190,8 @@ class UserSession(object): cur.execute("update codeq_user set gui_lang = %s, robot_address = %s where id = %s", (self.settings['gui_lang'], self.settings['robot_address'], self.uid)) finally: cur.close() - finally: conn.commit() + finally: db.return_connection(conn) def load_language_session(self, problem_id): @@ -178,7 +218,10 @@ class UserSession(object): finally: cur.close() finally: - conn.commit() + try: + conn.commit() + except: + pass db.return_connection(conn) def end_language_session(self): @@ -209,7 +252,10 @@ class UserSession(object): finally: cur.close() finally: - conn.commit() + try: + conn.commit() + except: + pass db.return_connection(conn) def update_solution(self, problem_id, trace, solution): @@ -257,8 +303,8 @@ class UserSession(object): raise PasswordChangeFailed('Password change failed') finally: cur.close() - finally: conn.commit() + finally: db.return_connection(conn) def get_stat(self): -- cgit v1.2.1