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 | 2 | # BUGS |
| 3 | 3 | |
| 4 | -- esta a permitir 2 logins em simultaneo do mesmo user. fica tudo baralhado... | |
| 5 | 4 | - shift-enter não está a funcionar |
| 6 | 5 | - falha intermitent no file handler quando o browser envia 2 GET requests ao mesmo tempo (porquê?) |
| 7 | 6 | - nos topicos learn.yaml, qd falha acrescenta no fim. nao faz sentido. |
| ... | ... | @@ -34,6 +33,7 @@ |
| 34 | 33 | |
| 35 | 34 | # FIXED |
| 36 | 35 | |
| 36 | +- esta a permitir 2 logins em simultaneo do mesmo user. fica tudo baralhado se mxerem em simultaneo... | |
| 37 | 37 | - errar no ultimo topico nao mostra solucao? |
| 38 | 38 | - quando a pergunta devolve comments, este é apresentado, mas fica persistente nas tentativas seguintes. devia ser limpo apos a segunda submissao. |
| 39 | 39 | - na definicao dos topicos, indicar: | ... | ... |
learnapp.py
| ... | ... | @@ -73,22 +73,22 @@ class LearnApp(object): |
| 73 | 73 | # login |
| 74 | 74 | # ------------------------------------------------------------------------ |
| 75 | 75 | async def login(self, uid, try_pw): |
| 76 | - if uid.startswith('l'): # remove prefix 'l' | |
| 77 | - uid = uid[1:] | |
| 78 | - | |
| 79 | 76 | with self.db_session() as s: |
| 80 | 77 | try: |
| 81 | 78 | name, password = s.query(Student.name, Student.password).filter_by(id=uid).one() |
| 82 | 79 | except: |
| 83 | - logger.info(f'User "{uid}" does not exist!') | |
| 80 | + logger.info(f'User "{uid}" does not exist') | |
| 84 | 81 | return False |
| 85 | 82 | |
| 86 | 83 | pw_ok = await check_password(try_pw, password) # async bcrypt |
| 84 | + | |
| 87 | 85 | if pw_ok: |
| 88 | 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 | 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 | 93 | with self.db_session() as s: |
| 94 | 94 | tt = s.query(StudentTopic).filter_by(student_id=uid) |
| ... | ... | @@ -102,10 +102,11 @@ class LearnApp(object): |
| 102 | 102 | 'number': uid, |
| 103 | 103 | 'name': name, |
| 104 | 104 | 'state': StudentKnowledge(deps=self.deps, factory=self.factory, state=state), |
| 105 | + 'counter': counter + 1, # counts simultaneous logins | |
| 105 | 106 | } |
| 106 | 107 | |
| 107 | 108 | else: |
| 108 | - logger.info(f'User "{uid}" wrong password!') | |
| 109 | + logger.info(f'User "{uid}" wrong password') | |
| 109 | 110 | |
| 110 | 111 | return pw_ok |
| 111 | 112 | |
| ... | ... | @@ -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 | 321 | def get_student_name(self, uid): |
| 317 | 322 | return self.online[uid].get('name', '') |
| 318 | 323 | ... | ... |
serve.py
| ... | ... | @@ -75,13 +75,12 @@ class BaseHandler(tornado.web.RequestHandler): |
| 75 | 75 | return self.application.learn |
| 76 | 76 | |
| 77 | 77 | def get_current_user(self): |
| 78 | - cookie = self.get_secure_cookie("user") | |
| 78 | + cookie = self.get_secure_cookie('user') | |
| 79 | 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 | 86 | # /auth/login and /auth/logout |
| ... | ... | @@ -97,10 +96,11 @@ class LoginHandler(BaseHandler): |
| 97 | 96 | login_ok = await self.learn.login(uid, pw) |
| 98 | 97 | |
| 99 | 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 | 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 | 108 | @tornado.web.authenticated |
| 109 | 109 | def get(self): |
| 110 | 110 | self.clear_cookie('user') |
| 111 | - self.redirect(self.get_argument('next', '/')) | |
| 111 | + self.clear_cookie('counter') | |
| 112 | + self.redirect('/') | |
| 112 | 113 | |
| 113 | 114 | def on_finish(self): |
| 114 | 115 | self.learn.logout(self.current_user) |
| ... | ... | @@ -309,7 +310,7 @@ class QuestionHandler(BaseHandler): |
| 309 | 310 | } |
| 310 | 311 | |
| 311 | 312 | else: |
| 312 | - logger.error(f'Unknown action: {action}') | |
| 313 | + logging.error(f'Unknown action: {action}') | |
| 313 | 314 | |
| 314 | 315 | self.write(response) |
| 315 | 316 | ... | ... |
templates/topic.html
| ... | ... | @@ -78,7 +78,7 @@ |
| 78 | 78 | |
| 79 | 79 | <!-- <div class="container"> --> |
| 80 | 80 | <div class="row"> |
| 81 | - <div class="col col-9"> | |
| 81 | + <div class="col col-lg-9"> | |
| 82 | 82 | <div class="my-5" id="content"> |
| 83 | 83 | <form action="/question" method="post" id="question_form" autocomplete="off"> |
| 84 | 84 | {% module xsrf_form_html() %} |
| ... | ... | @@ -91,7 +91,7 @@ |
| 91 | 91 | </div> |
| 92 | 92 | |
| 93 | 93 | </div> <!-- col --> |
| 94 | - <div class="col col-3"> | |
| 94 | + <div class="col col-lg-3"> | |
| 95 | 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 | 97 | <div id="right" style="display: none"> | ... | ... |