summaryrefslogtreecommitdiff
path: root/server/handlers.py
diff options
context:
space:
mode:
authorAleš Smodiš <aless@guru.si>2015-10-08 18:56:48 +0200
committerAleš Smodiš <aless@guru.si>2015-10-08 18:56:48 +0200
commit76bfb287b51bd97c9ca0bfc4e7760b7ee8e15b47 (patch)
tree1124ec688054e2adb31f8a12c84115ec55381d7a /server/handlers.py
parentb6eeda1a66da16f90d02dd5d439d5cc5088c1a88 (diff)
Reworked session handling.
* All requests have a session ID, except for the initial create_session system messages. * User session can be in an authenticated or anonymous state. * In anonymous state it is not possible to perform user actions. * Logout has been implemented. * Sessions timeout and are cleared after a period of inactivity (1 hour). * Bugfixed the lang setting handling. * Renamed get_problem -> get_current_solution, return only the user's current solution, not the whole problem data.
Diffstat (limited to 'server/handlers.py')
-rw-r--r--server/handlers.py78
1 files changed, 41 insertions, 37 deletions
diff --git a/server/handlers.py b/server/handlers.py
index a1bfbd7..1ab09f3 100644
--- a/server/handlers.py
+++ b/server/handlers.py
@@ -16,25 +16,20 @@ class CodeqService(object):
pass
-class ProblemList(CodeqService):
- """List all available problems to the client.
+class CreateSession(CodeqService):
+ """Creates a new anonymous session.
+ To promote the session to the authenticated status, a subsequent
+ login or signup must follow.
"""
session_is_optional = True
def process(self, request):
- js = request.data
- language = js.get('language')
- if language is None:
- request.reply({'code': 1, 'message': 'Language was not provided'})
- else:
- request.reply({'code': 0, 'message': 'ok', 'problems': server.problems.list_problems(language)})
+ request.reply({'code': 0, 'message': 'OK', 'sid': server.user_session.UserSession().get_sid()})
class Login(CodeqService):
- """Logs in a client, creating a new session.
+ """Logs in a client, authenticating the session.
"""
- session_is_optional = True
-
def process(self, request):
js = request.data
username = js.get('username')
@@ -44,35 +39,39 @@ class Login(CodeqService):
elif password is None:
request.reply({'code': 2, 'message': 'Password was not provided'})
else:
+ session = request.session
try:
- session = server.user_session.authenticate_and_create_session(username, password)
+ session.login(username, password)
except AuthenticationFailed:
request.reply({'code': 3, 'message': 'Username or password do not match'})
else:
- if request.session:
- request.session.destroy()
settings = session.get_settings()
- request.reply({'code': 0, 'message': 'OK', 'sid':session.get_sid(), 'settings':settings})
+ request.reply({'code': 0, 'message': 'OK', 'settings': settings})
-class Signup(CodeqService):
- session_is_optional = True
+class Logout(CodeqService):
+ def process(self, request):
+ request.session.destroy()
+ request.reply({'code': 0, 'message': 'OK'})
+
+class Signup(CodeqService):
def process(self, request):
js = request.data
username = js.get('username')
password = js.get('password')
+ lang = js.get('lang') or 'en'
if username is None:
request.reply({'code': 1, 'message': 'Username was not provided'})
elif password is None:
request.reply({'code': 2, 'message': 'Password was not provided'})
else:
try:
- server.user_session.signup(username, password)
+ request.session.signup(username, password, lang)
except UserExists:
request.reply({'code': 3, 'message': 'Username already exists'})
except SignupFailed:
- request.reply({'code': 4, 'message': 'Signn up failed'})
+ request.reply({'code': 4, 'message': 'Sign-up failed'})
else:
request.reply({'code': 0, 'message': 'OK'})
@@ -92,7 +91,7 @@ class ChangePassword(CodeqService):
request.reply({'code': 0, 'message': 'OK'})
-class Settings(CodeqService):
+class UpdateSettings(CodeqService):
def process(self, request):
js = request.data
settings = js.get('settings')
@@ -101,7 +100,6 @@ class Settings(CodeqService):
else:
try:
request.session.update_settings(settings)
- request.session.write_settings_to_db()
except NoSuchSession:
request.reply({'code': 2, 'message': 'No such session'})
else:
@@ -246,20 +244,15 @@ class Test(CodeqService):
request.reply({'code': 0, 'message': 'ok', 'hints': hints})
-class GetProblem(CodeqService):
+class GetCurrentSolution(CodeqService):
def process(self, request):
js = request.data
- language = js.get('language')
- problem_group = js.get('problem_group')
- problem = js.get('problem')
- if language is None:
- request.reply({'code': 1, 'message': 'Language identifier not given'})
- elif problem_group is None:
- request.reply({'code': 2, 'message': 'Problem group identifier not given'})
- elif problem is None:
- request.reply({'code': 3, 'message': 'Problem identifier not given'})
+ problem_id = js.get('problem_id')
+ if problem_id is None:
+ request.reply({'code': 1, 'message': 'Problem ID not specified'})
else:
- request.reply({'code': 0, 'message': 'ok', 'data': request.session.get_problem_data(language, problem_group, problem)})
+ request.reply({'code': 0, 'message': 'ok', 'data': request.session.current_solution(problem_id)})
+
class LoadProblem(CodeqService):
def process(self, request):
@@ -273,26 +266,28 @@ class LoadProblem(CodeqService):
else:
request.reply({'code': 0, 'message': 'OK'})
+
class EndProblem(CodeqService):
def process(self, request):
request.session.end_language_session()
request.end()
+
# maps actions to their handlers
incoming_handlers = {
- 'list_problems': ProblemList(),
+ 'create_session': CreateSession(),
'login': Login(),
'signup': Signup(),
'change_password': ChangePassword(),
- 'get_problem': GetProblem(),
- 'logout': None,
+ 'get_current_solution': GetCurrentSolution(),
+ 'logout': Logout(),
'activity': Activity(),
'query': Query(),
'python_exec': PythonExec(),
'python_push': PythonPush(),
'python_stop': PythonStop(),
'hint': Hint(),
- 'settings': Settings(),
+ 'update_settings': UpdateSettings(),
'test': Test(),
'load_problem': LoadProblem(),
'end_problem': EndProblem()
@@ -323,6 +318,7 @@ class Request(object):
"""
if data is None:
self.end()
+ return
if self._original_sid is not None:
sid = data.get('sid')
if sid is None:
@@ -356,10 +352,18 @@ def _invoke_handler(handler, request):
logging.error('ERROR: the request was not concluded!')
request.reply({'code': -1, 'message': 'Request processing did not provide a reply'})
logging.debug('Processing finished')
+ except NotLoggedIn:
+ if request.is_finished:
+ logging.error('Caught the NotLoggedIn exception, but the request has already been replied to!')
+ else:
+ request.reply({'code': -1, 'message': 'Cannot execute the request: not logged in'})
except Exception as e:
logging.critical('ERROR: data processing failed: ' + str(e))
logging.critical(traceback.format_exc())
- request.reply({'code': -1, 'message': 'Internal error: ' + str(e)})
+ if request.is_finished:
+ logging.critical('The request has already been replied to, the client will not be aware of the error!')
+ else:
+ request.reply({'code': -1, 'message': 'Internal error: ' + str(e)})
def serve_request(json_obj):
if not isinstance(json_obj, dict):