Commit 27e15117341fa400572d0fca9bf9f74dc3094efb
1 parent
785ca6d2
Exists in
master
and in
1 other branch
- login is now async on the bcrypt function that checks the password.
Showing
2 changed files
with
18 additions
and
13 deletions
Show diff stats
app.py
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | from os import path |
4 | 4 | import logging |
5 | 5 | from contextlib import contextmanager # `with` statement in db sessions |
6 | +import asyncio | |
6 | 7 | |
7 | 8 | # user installed packages |
8 | 9 | import bcrypt |
... | ... | @@ -23,8 +24,11 @@ class AppException(Exception): |
23 | 24 | # ============================================================================ |
24 | 25 | # helper functions |
25 | 26 | # ============================================================================ |
26 | -def check_password(try_pw, password): | |
27 | - return password == bcrypt.hashpw(try_pw.encode('utf-8'), password) | |
27 | +async def check_password(try_pw, password): | |
28 | + try_pw = try_pw.encode('utf-8') | |
29 | + loop = asyncio.get_event_loop() | |
30 | + hashed_pw = await loop.run_in_executor(None, bcrypt.hashpw, try_pw, password) | |
31 | + return password == hashed_pw | |
28 | 32 | |
29 | 33 | # ============================================================================ |
30 | 34 | # Application |
... | ... | @@ -69,7 +73,6 @@ class App(object): |
69 | 73 | # connect to database and check registered students |
70 | 74 | dbfile = path.expanduser(self.testfactory['database']) |
71 | 75 | engine = create_engine(f'sqlite:///{dbfile}', echo=False) |
72 | - # self.Session = scoped_session(sessionmaker(bind=engine)) # FIXME not scoped in tornado | |
73 | 76 | self.Session = sessionmaker(bind=engine) |
74 | 77 | |
75 | 78 | try: |
... | ... | @@ -95,7 +98,7 @@ class App(object): |
95 | 98 | logger.critical('----------- !!! Server terminated !!! -----------') |
96 | 99 | |
97 | 100 | # ----------------------------------------------------------------------- |
98 | - def login(self, uid, try_pw): | |
101 | + async def login(self, uid, try_pw): | |
99 | 102 | if uid.startswith('l'): # remove prefix 'l' |
100 | 103 | uid = uid[1:] |
101 | 104 | |
... | ... | @@ -112,7 +115,7 @@ class App(object): |
112 | 115 | self.update_student_password(uid, try_pw) |
113 | 116 | pw_ok = True |
114 | 117 | else: # check password |
115 | - pw_ok = check_password(try_pw, password) | |
118 | + pw_ok = await check_password(try_pw, password) # async bcrypt | |
116 | 119 | |
117 | 120 | if pw_ok: # success |
118 | 121 | self.allowed.discard(uid) # remove from set of allowed students | ... | ... |
serve.py
... | ... | @@ -23,6 +23,9 @@ from app import App, AppException |
23 | 23 | from tools import load_yaml, md_to_html |
24 | 24 | |
25 | 25 | |
26 | +# ------------------------------------------------------------------------- | |
27 | +# Web Application. Routes to handler classes. | |
28 | +# ------------------------------------------------------------------------- | |
26 | 29 | class WebApplication(tornado.web.Application): |
27 | 30 | def __init__(self, testapp, debug=False): |
28 | 31 | handlers = [ |
... | ... | @@ -73,13 +76,10 @@ class LoginHandler(BaseHandler): |
73 | 76 | self.render('login.html', error='') |
74 | 77 | |
75 | 78 | # async |
76 | - def post(self): | |
79 | + async def post(self): | |
77 | 80 | uid = self.get_body_argument('uid') |
78 | 81 | pw = self.get_body_argument('pw') |
79 | - | |
80 | - # loop = asyncio.get_event_loop() | |
81 | - # login_ok = await loop.run_in_executor(None, self.testapp.login, uid, pw) | |
82 | - login_ok = self.testapp.login(uid, pw) | |
82 | + login_ok = await self.testapp.login(uid, pw) | |
83 | 83 | |
84 | 84 | if login_ok: |
85 | 85 | self.set_secure_cookie("user", str(uid), expires_days=30) |
... | ... | @@ -151,10 +151,12 @@ class FileHandler(BaseHandler): |
151 | 151 | |
152 | 152 | |
153 | 153 | # ------------------------------------------------------------------------- |
154 | -# FIXME images missing, needs testing | |
154 | +# Test shown to students | |
155 | 155 | # ------------------------------------------------------------------------- |
156 | 156 | class TestHandler(BaseHandler): |
157 | - templates = { | |
157 | + SUPPORTED_METHODS = ['GET', 'POST'] | |
158 | + | |
159 | + _templates = { | |
158 | 160 | 'radio': 'question-radio.html', |
159 | 161 | 'checkbox': 'question-checkbox.html', |
160 | 162 | 'text': 'question-text.html', |
... | ... | @@ -175,7 +177,7 @@ class TestHandler(BaseHandler): |
175 | 177 | def get(self): |
176 | 178 | uid = self.current_user |
177 | 179 | t = self.testapp.get_student_test(uid) or self.testapp.generate_test(uid) |
178 | - self.render('test.html', t=t, md=md_to_html, templ=self.templates) | |
180 | + self.render('test.html', t=t, md=md_to_html, templ=self._templates) | |
179 | 181 | |
180 | 182 | # POST |
181 | 183 | @tornado.web.authenticated | ... | ... |