Commit d4ab394c3f7fcef832451897c50dcaff28f8399d
1 parent
915a24bd
Exists in
master
and in
1 other branch
- removed unused learn.css file.
- added log warning if user already logged in.
Showing
5 changed files
with
33 additions
and
119 deletions
Show diff stats
BUGS.md
... | ... | @@ -32,6 +32,7 @@ |
32 | 32 | |
33 | 33 | # FIXED |
34 | 34 | |
35 | +- check if user already logged in | |
35 | 36 | - mover javascript para ficheiros externos e carregar com script defer src |
36 | 37 | - implementar xsrf. Ver [http://www.tornadoweb.org/en/stable/guide/security.html#cross-site-request-forgery-protection]() |
37 | 38 | - se refs de um topic estao invalidos, nao carrega esse topico. devia haver um error nos logs a indicar qual o ref invalido. | ... | ... |
learnapp.py
... | ... | @@ -47,35 +47,36 @@ class LearnApp(object): |
47 | 47 | # ------------------------------------------------------------------------ |
48 | 48 | # login |
49 | 49 | # ------------------------------------------------------------------------ |
50 | - def login(self, uid, try_pw): | |
50 | + def login(self, uid, pw): | |
51 | + | |
51 | 52 | with self.db_session() as s: |
52 | 53 | student = s.query(Student).filter(Student.id == uid).one_or_none() |
53 | 54 | if student is None: |
54 | 55 | logger.info(f'User "{uid}" does not exist!') |
55 | 56 | return False # student does not exist |
56 | 57 | |
57 | - hashedtry = bcrypt.hashpw(try_pw.encode('utf-8'), student.password) | |
58 | - if hashedtry != student.password: | |
59 | - logger.info(f'User "{uid}" wrong password!') | |
60 | - return False # wrong password | |
61 | - | |
62 | - # success | |
63 | - logger.info(f'User "{uid}" logged in') | |
58 | + if bcrypt.checkpw(pw.encode('utf-8'), student.password): | |
59 | + if uid in self.online: | |
60 | + logger.warning(f'User "{uid}" already logged in, overwriting state') | |
64 | 61 | |
65 | - tt = s.query(StudentTopic).filter(StudentTopic.student_id == uid) | |
66 | - state = {} | |
67 | - for t in tt: | |
68 | - state[t.topic_id] = { | |
62 | + tt = s.query(StudentTopic).filter(StudentTopic.student_id == uid) | |
63 | + state = {t.topic_id: | |
64 | + { | |
69 | 65 | 'level': t.level, |
70 | - 'date': datetime.strptime(t.date, "%Y-%m-%d %H:%M:%S.%f"), | |
66 | + 'date': datetime.strptime(t.date, "%Y-%m-%d %H:%M:%S.%f") | |
67 | + } for t in tt} | |
68 | + | |
69 | + self.online[uid] = { | |
70 | + 'number': student.id, | |
71 | + 'name': student.name, | |
72 | + 'state': StudentKnowledge(self.deps, state=state) | |
71 | 73 | } |
74 | + logger.info(f'User "{uid}" logged in successfully') | |
75 | + return True | |
72 | 76 | |
73 | - self.online[uid] = { | |
74 | - 'number': student.id, | |
75 | - 'name': student.name, | |
76 | - 'state': StudentKnowledge(self.deps, state=state) | |
77 | - } | |
78 | - return True | |
77 | + else: | |
78 | + logger.info(f'User "{uid}" wrong password!') | |
79 | + return False | |
79 | 80 | |
80 | 81 | # ------------------------------------------------------------------------ |
81 | 82 | # logout |
... | ... | @@ -297,7 +298,7 @@ def build_dependency_graph(config={}): |
297 | 298 | # if questions not in configuration then load all, preserving order |
298 | 299 | if not tnode['questions']: |
299 | 300 | tnode['questions'] = [q['ref'] for q in loaded_questions] |
300 | - | |
301 | + | |
301 | 302 | # make questions factory (without repeating same question) |
302 | 303 | tnode['factory'] = {} |
303 | 304 | for q in loaded_questions: | ... | ... |
static/css/learn.css
... | ... | @@ -1,91 +0,0 @@ |
1 | -body { | |
2 | - margin: 0; | |
3 | - padding-top: 100px; | |
4 | -} | |
5 | - | |
6 | -img { | |
7 | - display: block; | |
8 | - margin: auto; | |
9 | - width: 80%; | |
10 | -} | |
11 | - | |
12 | -/* progress bars have height of 4 pixels */ | |
13 | -.progress { | |
14 | - height: 8px; | |
15 | - border-radius: 0px; | |
16 | -} | |
17 | - | |
18 | -/* make markdown tables beautiful */ | |
19 | -table { | |
20 | - border-collapse: collapse; | |
21 | - margin-left: 50px; | |
22 | -} | |
23 | -thead, tbody, td, th { | |
24 | - padding: 5px; | |
25 | - border-bottom: 1px solid #ddd; | |
26 | -} | |
27 | - | |
28 | -textarea { | |
29 | - font-family: monospace !important; | |
30 | -} | |
31 | - | |
32 | -/* Hack to avoid name clash between pygments and mathjax */ | |
33 | -.MathJax .mo, | |
34 | -.MathJax .mi { | |
35 | - color: inherit; | |
36 | -} | |
37 | - | |
38 | -/* ======================================================================== */ | |
39 | -body,html,.row-offcanvas { | |
40 | - height:100%; | |
41 | -} | |
42 | - | |
43 | - | |
44 | -#sidebar { | |
45 | - width: inherit; | |
46 | - min-width: 220px; | |
47 | - max-width: 220px; | |
48 | - background-color:#f5f5f5; | |
49 | - float: left; | |
50 | - height:100%; | |
51 | - position:relative; | |
52 | - overflow-y:auto; | |
53 | - overflow-x:hidden; | |
54 | -} | |
55 | -#main { | |
56 | - padding-top: 10px; | |
57 | - height:100%; | |
58 | - overflow:auto; | |
59 | -} | |
60 | -#body { | |
61 | - padding-bottom: 50px; | |
62 | -} | |
63 | - | |
64 | -/* https://medium.com/wdstack/bootstrap-sidebar-examples-e363021395ff#.ek5vc75p8 | |
65 | - * off Canvas sidebar | |
66 | - * -------------------------------------------------- | |
67 | - */ | |
68 | -@media screen and (max-width: 768px) { | |
69 | - .row-offcanvas { | |
70 | - position: relative; | |
71 | - -webkit-transition: all 0.25s ease-out; | |
72 | - -moz-transition: all 0.25s ease-out; | |
73 | - transition: all 0.25s ease-out; | |
74 | - width:calc(100% + 220px); | |
75 | - } | |
76 | - | |
77 | - .row-offcanvas-left | |
78 | - { | |
79 | - left: -220px; | |
80 | - } | |
81 | - | |
82 | - .row-offcanvas-left.active { | |
83 | - left: 0; | |
84 | - } | |
85 | - | |
86 | - .sidebar-offcanvas { | |
87 | - position: absolute; | |
88 | - top: 0; | |
89 | - } | |
90 | -} | |
91 | - |
static/css/maintopics.css
static/css/topic.css
1 | 1 | .progress { |
2 | - height: 20px; | |
2 | + /*position: fixed;*/ | |
3 | + top: 0; | |
4 | + height: 90px; | |
3 | 5 | border-radius: 0px; |
4 | 6 | } |
5 | 7 | body { |
6 | 8 | margin: 0; |
7 | - padding-top: 70px; | |
8 | - margin-bottom: 80px; /* Margin bottom by footer height */ | |
9 | + padding-top: 0px; | |
10 | + margin-bottom: 60px; /* Margin bottom by footer height */ | |
9 | 11 | } |
12 | + | |
10 | 13 | .footer { |
11 | 14 | position: absolute; |
12 | 15 | bottom: 0; |
13 | 16 | width: 100%; |
14 | - /* Set the fixed height of the footer here */ | |
15 | - height: 60px; | |
16 | - line-height: 60px; /* Vertically center the text there */ | |
17 | + height: 40px; | |
18 | + line-height: 60px; | |
17 | 19 | background-color: #f5f5f5; |
18 | 20 | } |
21 | + | |
19 | 22 | html { |
20 | 23 | position: relative; |
21 | 24 | min-height: 100%; | ... | ... |