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,6 +3,7 @@ | ||
3 | from os import path | 3 | from os import path |
4 | import logging | 4 | import logging |
5 | from contextlib import contextmanager # `with` statement in db sessions | 5 | from contextlib import contextmanager # `with` statement in db sessions |
6 | +import asyncio | ||
6 | 7 | ||
7 | # user installed packages | 8 | # user installed packages |
8 | import bcrypt | 9 | import bcrypt |
@@ -23,8 +24,11 @@ class AppException(Exception): | @@ -23,8 +24,11 @@ class AppException(Exception): | ||
23 | # ============================================================================ | 24 | # ============================================================================ |
24 | # helper functions | 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 | # Application | 34 | # Application |
@@ -69,7 +73,6 @@ class App(object): | @@ -69,7 +73,6 @@ class App(object): | ||
69 | # connect to database and check registered students | 73 | # connect to database and check registered students |
70 | dbfile = path.expanduser(self.testfactory['database']) | 74 | dbfile = path.expanduser(self.testfactory['database']) |
71 | engine = create_engine(f'sqlite:///{dbfile}', echo=False) | 75 | engine = create_engine(f'sqlite:///{dbfile}', echo=False) |
72 | - # self.Session = scoped_session(sessionmaker(bind=engine)) # FIXME not scoped in tornado | ||
73 | self.Session = sessionmaker(bind=engine) | 76 | self.Session = sessionmaker(bind=engine) |
74 | 77 | ||
75 | try: | 78 | try: |
@@ -95,7 +98,7 @@ class App(object): | @@ -95,7 +98,7 @@ class App(object): | ||
95 | logger.critical('----------- !!! Server terminated !!! -----------') | 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 | if uid.startswith('l'): # remove prefix 'l' | 102 | if uid.startswith('l'): # remove prefix 'l' |
100 | uid = uid[1:] | 103 | uid = uid[1:] |
101 | 104 | ||
@@ -112,7 +115,7 @@ class App(object): | @@ -112,7 +115,7 @@ class App(object): | ||
112 | self.update_student_password(uid, try_pw) | 115 | self.update_student_password(uid, try_pw) |
113 | pw_ok = True | 116 | pw_ok = True |
114 | else: # check password | 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 | if pw_ok: # success | 120 | if pw_ok: # success |
118 | self.allowed.discard(uid) # remove from set of allowed students | 121 | self.allowed.discard(uid) # remove from set of allowed students |
serve.py
@@ -23,6 +23,9 @@ from app import App, AppException | @@ -23,6 +23,9 @@ from app import App, AppException | ||
23 | from tools import load_yaml, md_to_html | 23 | from tools import load_yaml, md_to_html |
24 | 24 | ||
25 | 25 | ||
26 | +# ------------------------------------------------------------------------- | ||
27 | +# Web Application. Routes to handler classes. | ||
28 | +# ------------------------------------------------------------------------- | ||
26 | class WebApplication(tornado.web.Application): | 29 | class WebApplication(tornado.web.Application): |
27 | def __init__(self, testapp, debug=False): | 30 | def __init__(self, testapp, debug=False): |
28 | handlers = [ | 31 | handlers = [ |
@@ -73,13 +76,10 @@ class LoginHandler(BaseHandler): | @@ -73,13 +76,10 @@ class LoginHandler(BaseHandler): | ||
73 | self.render('login.html', error='') | 76 | self.render('login.html', error='') |
74 | 77 | ||
75 | # async | 78 | # async |
76 | - def post(self): | 79 | + async def post(self): |
77 | uid = self.get_body_argument('uid') | 80 | uid = self.get_body_argument('uid') |
78 | pw = self.get_body_argument('pw') | 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 | if login_ok: | 84 | if login_ok: |
85 | self.set_secure_cookie("user", str(uid), expires_days=30) | 85 | self.set_secure_cookie("user", str(uid), expires_days=30) |
@@ -151,10 +151,12 @@ class FileHandler(BaseHandler): | @@ -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 | class TestHandler(BaseHandler): | 156 | class TestHandler(BaseHandler): |
157 | - templates = { | 157 | + SUPPORTED_METHODS = ['GET', 'POST'] |
158 | + | ||
159 | + _templates = { | ||
158 | 'radio': 'question-radio.html', | 160 | 'radio': 'question-radio.html', |
159 | 'checkbox': 'question-checkbox.html', | 161 | 'checkbox': 'question-checkbox.html', |
160 | 'text': 'question-text.html', | 162 | 'text': 'question-text.html', |
@@ -175,7 +177,7 @@ class TestHandler(BaseHandler): | @@ -175,7 +177,7 @@ class TestHandler(BaseHandler): | ||
175 | def get(self): | 177 | def get(self): |
176 | uid = self.current_user | 178 | uid = self.current_user |
177 | t = self.testapp.get_student_test(uid) or self.testapp.generate_test(uid) | 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 | # POST | 182 | # POST |
181 | @tornado.web.authenticated | 183 | @tornado.web.authenticated |