Commit e36dfd6c93c5a790a11b44d17737f7864a941aa8

Authored by Miguel Barão
1 parent 9f52cf60
Exists in master and in 1 other branch dev

- Fixed simultaneous logins of same user on different devices.

will invalidate older ones.
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">
... ...