From e36dfd6c93c5a790a11b44d17737f7864a941aa8 Mon Sep 17 00:00:00 2001 From: Miguel Barão Date: Wed, 19 Dec 2018 19:51:16 +0000 Subject: [PATCH] - Fixed simultaneous logins of same user on different devices. will invalidate older ones. --- BUGS.md | 2 +- learnapp.py | 19 ++++++++++++------- serve.py | 23 ++++++++++++----------- templates/topic.html | 4 ++-- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/BUGS.md b/BUGS.md index 52d821e..8f26622 100644 --- a/BUGS.md +++ b/BUGS.md @@ -1,7 +1,6 @@ # BUGS -- esta a permitir 2 logins em simultaneo do mesmo user. fica tudo baralhado... - shift-enter não está a funcionar - falha intermitent no file handler quando o browser envia 2 GET requests ao mesmo tempo (porquê?) - nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. @@ -34,6 +33,7 @@ # FIXED +- esta a permitir 2 logins em simultaneo do mesmo user. fica tudo baralhado se mxerem em simultaneo... - errar no ultimo topico nao mostra solucao? - quando a pergunta devolve comments, este é apresentado, mas fica persistente nas tentativas seguintes. devia ser limpo apos a segunda submissao. - na definicao dos topicos, indicar: diff --git a/learnapp.py b/learnapp.py index e5ec64a..2e6ed64 100644 --- a/learnapp.py +++ b/learnapp.py @@ -73,22 +73,22 @@ class LearnApp(object): # login # ------------------------------------------------------------------------ async def login(self, uid, try_pw): - if uid.startswith('l'): # remove prefix 'l' - uid = uid[1:] - with self.db_session() as s: try: name, password = s.query(Student.name, Student.password).filter_by(id=uid).one() except: - logger.info(f'User "{uid}" does not exist!') + logger.info(f'User "{uid}" does not exist') return False pw_ok = await check_password(try_pw, password) # async bcrypt + if pw_ok: if uid in self.online: - logger.warning(f'User "{uid}" already logged in, overwriting state') + logger.warning(f'User "{uid}" already logged in, overwriting') + counter = self.online[uid]['counter'] else: - logger.info(f'User "{uid}" logged in successfully') + logger.info(f'User "{uid}" logged in') + counter = 0 with self.db_session() as s: tt = s.query(StudentTopic).filter_by(student_id=uid) @@ -102,10 +102,11 @@ class LearnApp(object): 'number': uid, 'name': name, 'state': StudentKnowledge(deps=self.deps, factory=self.factory, state=state), + 'counter': counter + 1, # counts simultaneous logins } else: - logger.info(f'User "{uid}" wrong password!') + logger.info(f'User "{uid}" wrong password') return pw_ok @@ -313,6 +314,10 @@ class LearnApp(object): # ======================================================================== # ------------------------------------------------------------------------ + def get_login_counter(self, uid): + return self.online[uid]['counter'] + + # ------------------------------------------------------------------------ def get_student_name(self, uid): return self.online[uid].get('name', '') diff --git a/serve.py b/serve.py index 6c29311..55eaece 100755 --- a/serve.py +++ b/serve.py @@ -75,13 +75,12 @@ class BaseHandler(tornado.web.RequestHandler): return self.application.learn def get_current_user(self): - cookie = self.get_secure_cookie("user") + cookie = self.get_secure_cookie('user') if cookie: - user = cookie.decode('utf-8') - return user - # FIXME if the cookie exists but user is not in learn.online, this will force new login and store new (duplicate?) cookie. is this correct?? - # if user in self.learn.online: - # return user + counter = self.get_secure_cookie('counter') + uid = cookie.decode('utf-8') + if counter.decode('utf-8') == str(self.learn.get_login_counter(uid)): + return uid # ---------------------------------------------------------------------------- # /auth/login and /auth/logout @@ -97,10 +96,11 @@ class LoginHandler(BaseHandler): login_ok = await self.learn.login(uid, pw) if login_ok: - self.set_secure_cookie("user", str(uid), expires_days=30) - self.redirect(self.get_argument("next", "/")) + self.set_secure_cookie('user', uid) # expires_days=30 + self.set_secure_cookie('counter', str(self.learn.get_login_counter(uid))) + self.redirect('/') else: - self.render("login.html", error='Número ou senha incorrectos') + self.render('login.html', error='Número ou senha incorrectos') # ---------------------------------------------------------------------------- @@ -108,7 +108,8 @@ class LogoutHandler(BaseHandler): @tornado.web.authenticated def get(self): self.clear_cookie('user') - self.redirect(self.get_argument('next', '/')) + self.clear_cookie('counter') + self.redirect('/') def on_finish(self): self.learn.logout(self.current_user) @@ -309,7 +310,7 @@ class QuestionHandler(BaseHandler): } else: - logger.error(f'Unknown action: {action}') + logging.error(f'Unknown action: {action}') self.write(response) diff --git a/templates/topic.html b/templates/topic.html index c24fe74..99e884c 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -78,7 +78,7 @@
-
+
{% module xsrf_form_html() %} @@ -91,7 +91,7 @@
-
+