Commit e36dfd6c93c5a790a11b44d17737f7864a941aa8
1 parent
9f52cf60
Exists in
master
and in
1 other branch
- Fixed simultaneous logins of same user on different devices.
will invalidate older ones.
Showing
4 changed files
with
27 additions
and
21 deletions
Show diff stats
BUGS.md
1 | 1 | ||
2 | # BUGS | 2 | # BUGS |
3 | 3 | ||
4 | -- esta a permitir 2 logins em simultaneo do mesmo user. fica tudo baralhado... | ||
5 | - shift-enter não está a funcionar | 4 | - shift-enter não está a funcionar |
6 | - falha intermitent no file handler quando o browser envia 2 GET requests ao mesmo tempo (porquê?) | 5 | - falha intermitent no file handler quando o browser envia 2 GET requests ao mesmo tempo (porquê?) |
7 | - nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. | 6 | - nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. |
@@ -34,6 +33,7 @@ | @@ -34,6 +33,7 @@ | ||
34 | 33 | ||
35 | # FIXED | 34 | # FIXED |
36 | 35 | ||
36 | +- esta a permitir 2 logins em simultaneo do mesmo user. fica tudo baralhado se mxerem em simultaneo... | ||
37 | - errar no ultimo topico nao mostra solucao? | 37 | - errar no ultimo topico nao mostra solucao? |
38 | - quando a pergunta devolve comments, este é apresentado, mas fica persistente nas tentativas seguintes. devia ser limpo apos a segunda submissao. | 38 | - quando a pergunta devolve comments, este é apresentado, mas fica persistente nas tentativas seguintes. devia ser limpo apos a segunda submissao. |
39 | - na definicao dos topicos, indicar: | 39 | - na definicao dos topicos, indicar: |
learnapp.py
@@ -73,22 +73,22 @@ class LearnApp(object): | @@ -73,22 +73,22 @@ class LearnApp(object): | ||
73 | # login | 73 | # login |
74 | # ------------------------------------------------------------------------ | 74 | # ------------------------------------------------------------------------ |
75 | async def login(self, uid, try_pw): | 75 | async def login(self, uid, try_pw): |
76 | - if uid.startswith('l'): # remove prefix 'l' | ||
77 | - uid = uid[1:] | ||
78 | - | ||
79 | with self.db_session() as s: | 76 | with self.db_session() as s: |
80 | try: | 77 | try: |
81 | name, password = s.query(Student.name, Student.password).filter_by(id=uid).one() | 78 | name, password = s.query(Student.name, Student.password).filter_by(id=uid).one() |
82 | except: | 79 | except: |
83 | - logger.info(f'User "{uid}" does not exist!') | 80 | + logger.info(f'User "{uid}" does not exist') |
84 | return False | 81 | return False |
85 | 82 | ||
86 | pw_ok = await check_password(try_pw, password) # async bcrypt | 83 | pw_ok = await check_password(try_pw, password) # async bcrypt |
84 | + | ||
87 | if pw_ok: | 85 | if pw_ok: |
88 | if uid in self.online: | 86 | if uid in self.online: |
89 | - logger.warning(f'User "{uid}" already logged in, overwriting state') | 87 | + logger.warning(f'User "{uid}" already logged in, overwriting') |
88 | + counter = self.online[uid]['counter'] | ||
90 | else: | 89 | else: |
91 | - logger.info(f'User "{uid}" logged in successfully') | 90 | + logger.info(f'User "{uid}" logged in') |
91 | + counter = 0 | ||
92 | 92 | ||
93 | with self.db_session() as s: | 93 | with self.db_session() as s: |
94 | tt = s.query(StudentTopic).filter_by(student_id=uid) | 94 | tt = s.query(StudentTopic).filter_by(student_id=uid) |
@@ -102,10 +102,11 @@ class LearnApp(object): | @@ -102,10 +102,11 @@ class LearnApp(object): | ||
102 | 'number': uid, | 102 | 'number': uid, |
103 | 'name': name, | 103 | 'name': name, |
104 | 'state': StudentKnowledge(deps=self.deps, factory=self.factory, state=state), | 104 | 'state': StudentKnowledge(deps=self.deps, factory=self.factory, state=state), |
105 | + 'counter': counter + 1, # counts simultaneous logins | ||
105 | } | 106 | } |
106 | 107 | ||
107 | else: | 108 | else: |
108 | - logger.info(f'User "{uid}" wrong password!') | 109 | + logger.info(f'User "{uid}" wrong password') |
109 | 110 | ||
110 | return pw_ok | 111 | return pw_ok |
111 | 112 | ||
@@ -313,6 +314,10 @@ class LearnApp(object): | @@ -313,6 +314,10 @@ class LearnApp(object): | ||
313 | # ======================================================================== | 314 | # ======================================================================== |
314 | 315 | ||
315 | # ------------------------------------------------------------------------ | 316 | # ------------------------------------------------------------------------ |
317 | + def get_login_counter(self, uid): | ||
318 | + return self.online[uid]['counter'] | ||
319 | + | ||
320 | + # ------------------------------------------------------------------------ | ||
316 | def get_student_name(self, uid): | 321 | def get_student_name(self, uid): |
317 | return self.online[uid].get('name', '') | 322 | return self.online[uid].get('name', '') |
318 | 323 |
serve.py
@@ -75,13 +75,12 @@ class BaseHandler(tornado.web.RequestHandler): | @@ -75,13 +75,12 @@ class BaseHandler(tornado.web.RequestHandler): | ||
75 | return self.application.learn | 75 | return self.application.learn |
76 | 76 | ||
77 | def get_current_user(self): | 77 | def get_current_user(self): |
78 | - cookie = self.get_secure_cookie("user") | 78 | + cookie = self.get_secure_cookie('user') |
79 | if cookie: | 79 | if cookie: |
80 | - user = cookie.decode('utf-8') | ||
81 | - return user | ||
82 | - # 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?? | ||
83 | - # if user in self.learn.online: | ||
84 | - # return user | 80 | + counter = self.get_secure_cookie('counter') |
81 | + uid = cookie.decode('utf-8') | ||
82 | + if counter.decode('utf-8') == str(self.learn.get_login_counter(uid)): | ||
83 | + return uid | ||
85 | 84 | ||
86 | # ---------------------------------------------------------------------------- | 85 | # ---------------------------------------------------------------------------- |
87 | # /auth/login and /auth/logout | 86 | # /auth/login and /auth/logout |
@@ -97,10 +96,11 @@ class LoginHandler(BaseHandler): | @@ -97,10 +96,11 @@ class LoginHandler(BaseHandler): | ||
97 | login_ok = await self.learn.login(uid, pw) | 96 | login_ok = await self.learn.login(uid, pw) |
98 | 97 | ||
99 | if login_ok: | 98 | if login_ok: |
100 | - self.set_secure_cookie("user", str(uid), expires_days=30) | ||
101 | - self.redirect(self.get_argument("next", "/")) | 99 | + self.set_secure_cookie('user', uid) # expires_days=30 |
100 | + self.set_secure_cookie('counter', str(self.learn.get_login_counter(uid))) | ||
101 | + self.redirect('/') | ||
102 | else: | 102 | else: |
103 | - self.render("login.html", error='Número ou senha incorrectos') | 103 | + self.render('login.html', error='Número ou senha incorrectos') |
104 | 104 | ||
105 | 105 | ||
106 | # ---------------------------------------------------------------------------- | 106 | # ---------------------------------------------------------------------------- |
@@ -108,7 +108,8 @@ class LogoutHandler(BaseHandler): | @@ -108,7 +108,8 @@ class LogoutHandler(BaseHandler): | ||
108 | @tornado.web.authenticated | 108 | @tornado.web.authenticated |
109 | def get(self): | 109 | def get(self): |
110 | self.clear_cookie('user') | 110 | self.clear_cookie('user') |
111 | - self.redirect(self.get_argument('next', '/')) | 111 | + self.clear_cookie('counter') |
112 | + self.redirect('/') | ||
112 | 113 | ||
113 | def on_finish(self): | 114 | def on_finish(self): |
114 | self.learn.logout(self.current_user) | 115 | self.learn.logout(self.current_user) |
@@ -309,7 +310,7 @@ class QuestionHandler(BaseHandler): | @@ -309,7 +310,7 @@ class QuestionHandler(BaseHandler): | ||
309 | } | 310 | } |
310 | 311 | ||
311 | else: | 312 | else: |
312 | - logger.error(f'Unknown action: {action}') | 313 | + logging.error(f'Unknown action: {action}') |
313 | 314 | ||
314 | self.write(response) | 315 | self.write(response) |
315 | 316 |
templates/topic.html
@@ -78,7 +78,7 @@ | @@ -78,7 +78,7 @@ | ||
78 | 78 | ||
79 | <!-- <div class="container"> --> | 79 | <!-- <div class="container"> --> |
80 | <div class="row"> | 80 | <div class="row"> |
81 | - <div class="col col-9"> | 81 | + <div class="col col-lg-9"> |
82 | <div class="my-5" id="content"> | 82 | <div class="my-5" id="content"> |
83 | <form action="/question" method="post" id="question_form" autocomplete="off"> | 83 | <form action="/question" method="post" id="question_form" autocomplete="off"> |
84 | {% module xsrf_form_html() %} | 84 | {% module xsrf_form_html() %} |
@@ -91,7 +91,7 @@ | @@ -91,7 +91,7 @@ | ||
91 | </div> | 91 | </div> |
92 | 92 | ||
93 | </div> <!-- col --> | 93 | </div> <!-- col --> |
94 | - <div class="col col-3"> | 94 | + <div class="col col-lg-3"> |
95 | <button class="btn btn-primary btn-lg btn-block my-5" id="submit" data-toggle="tooltip" data-placement="right" title="Shift-Enter">Responder</button> | 95 | <button class="btn btn-primary btn-lg btn-block my-5" id="submit" data-toggle="tooltip" data-placement="right" title="Shift-Enter">Responder</button> |
96 | 96 | ||
97 | <div id="right" style="display: none"> | 97 | <div id="right" style="display: none"> |