[Pharo] Personal fitness tracker web app.
Session isn't logging user in, because attemptLogin: method fails to compare existing user passwordHash attribute with provided password value.
Changed files
src/MyFitnessTracker/MFTLoginRegisterLogoutComponent.class.st
@@ -7,6 +7,31 @@
7
7
#category : #'MyFitnessTracker-Components'
8
8
}
9
9
10
Added:
{ #category : #'as yet unclassified' }
11
Added:
MFTLoginRegisterLogoutComponent >> attemptLogin: aMFTUser [
12
Added:
"Attempt to match aMFTUser passwordHash against an existing user password_hash in the database.
13
Added:
14
Added:
If a matching user is found, hydrate a MFTUser from the existingUser, and keep track of the database connection used to authenticate.
15
Added:
If no matching user is found, kill the connection."
16
Added:
17
Added:
| connection existingUser passwordHash |
18
Added:
connection := (MFTSQLite3Database openOn:
19
Added:
(Smalltalk imageDirectory / 'mft.sqlite3') fullName)
20
Added:
connection.
21
Added:
existingUser := ((connection
22
Added:
execute: 'SELECT * FROM users WHERE username = ?'
23
Added:
value: aMFTUser username) onlyRow: [
24
Added:
Dictionary new ]) asDictionary.
25
Added:
passwordHash := existingUser
26
Added:
at: #password_hash
27
Added:
ifAbsent: [ String empty ].
28
Added:
connection close.
29
Added:
aMFTUser passwordHash = passwordHash
30
Added:
ifTrue: [ self login: (MFTUser newFromDictionary: existingUser) ]
31
Added:
ifFalse: [ "TODO: user should be prompted to retry logging in."
32
Added:
^ nil ]
33
Added:
]
34
Added:
10
35
{ #category : #initialization }
11
36
MFTLoginRegisterLogoutComponent >> initialize [
12
37
@@ -14,6 +39,48 @@
14
39
user := MFTUser new
15
40
]
16
41
42
Added:
{ #category : #login }
43
Added:
MFTLoginRegisterLogoutComponent >> login: aMFTUser [
44
Added:
45
Added:
| connection loginDateAndTime |
46
Added:
self session user: aMFTUser.
47
Added:
self session user isLoggedIn: true.
48
Added:
49
Added:
loginDateAndTime := DateAndTime now asUTC rounded.
50
Added:
user lastConnectionDateTime: loginDateAndTime.
51
Added:
connection := (MFTSQLite3Database openOn:
52
Added:
(Smalltalk imageDirectory / 'mft.sqlite3') fullName)
53
Added:
connection.
54
Added:
connection
55
Added:
execute: 'UPDATE users
56
Added:
SET last_connection_date_time = ?
57
Added:
WHERE username = ?'
58
Added:
value: loginDateAndTime
59
Added:
value: aMFTUser username.
60
Added:
connection close.
61
Added:
self session mainPages at: 1 put: MFTUserHomepageTab new
62
Added:
]
63
Added:
64
Added:
{ #category : #'as yet unclassified' }
65
Added:
MFTLoginRegisterLogoutComponent >> logout [
66
Added:
67
Added:
self session unregistered
68
Added:
]
69
Added:
70
Added:
{ #category : #'as yet unclassified' }
71
Added:
MFTLoginRegisterLogoutComponent >> registerNewUser: aMFTUser [
72
Added:
73
Added:
| connection |
74
Added:
connection := (MFTSQLite3Database openOn:
75
Added:
(Smalltalk imageDirectory / 'mft.sqlite3') fullName)
76
Added:
connection.
77
Added:
connection
78
Added:
execute: 'INSERT INTO users(username,password_hash) VALUES (?, ?);'
79
Added:
value: aMFTUser username
80
Added:
value: aMFTUser passwordHash.
81
Added:
connection close
82
Added:
]
83
Added:
17
84
{ #category : #rendering }
18
85
MFTLoginRegisterLogoutComponent >> renderContentOn: html [
19
86
@@ -76,7 +143,7 @@
76
143
with: 'Cancel'.
77
144
html formButton
78
145
bePrimary;
79
Removed:
callback: [ self session attemptLogin: user ];
146
Added:
callback: [ self attemptLogin: user ];
80
147
with: 'Login' ] ] ] ] ]
81
148
]
82
149
@@ -88,7 +155,7 @@
88
155
html formButton
89
156
beSecondary;
90
157
beSmall;
91
Removed:
callback: [ self session logout ];
158
Added:
callback: [ self logout ];
92
159
with: 'Logout' ]
93
160
]
94
161
@@ -125,6 +192,6 @@
125
192
with: 'Cancel'.
126
193
html formButton
127
194
bePrimary;
128
Removed:
callback: [ self session registerNewUser: user ];
195
Added:
callback: [ self registerNewUser: user ];
129
196
with: 'Register' ] ] ] ] ]
130
197
]
src/MyFitnessTracker/MFTMainNavigationBarComponent.class.st
@@ -2,7 +2,7 @@
2
2
#name : #MFTMainNavigationBarComponent,
3
3
#superclass : #SBSComponent,
4
4
#instVars : [
5
Removed:
'activeTab'
5
Added:
'loginRegisterLogout'
6
6
],
7
7
#category : #'MyFitnessTracker-Components'
8
8
}
@@ -10,14 +10,14 @@
10
10
{ #category : #hooks }
11
11
MFTMainNavigationBarComponent >> children [
12
12
13
Removed:
^ self session mainTabs
13
Added:
^ { loginRegisterLogout }
14
14
]
15
15
16
16
{ #category : #initialization }
17
17
MFTMainNavigationBarComponent >> initialize [
18
18
19
19
super initialize.
20
Removed:
activeTab := self session mainTabs first
20
Added:
loginRegisterLogout := MFTLoginRegisterLogoutComponent new
21
21
]
22
22
23
23
{ #category : #rendering }
@@ -30,8 +30,7 @@
30
30
expandLarge;
31
31
marginBottom: 3;
32
32
paddingLeftAndRight: 3;
33
Removed:
with: [ self renderNavigationBarItemsOn: html ].
34
Removed:
html render: activeTab
33
Added:
with: [ self renderNavigationBarItemsOn: html ]
35
34
]
36
35
37
36
{ #category : #rendering }
@@ -48,13 +47,13 @@
48
47
id: 'navbarCollapsed';
49
48
with: [
50
49
html navigationBarNavigation: [
51
Removed:
self session mainTabs do: [ :tab |
50
Added:
self session mainPages do: [ :page |
52
51
html navigationItem
53
Removed:
beActiveIf: [ activeTab = tab ];
52
Added:
beActiveIf: [ self session activePage = page ];
54
53
with: [
55
54
html navigationLink
56
Removed:
callback: [ activeTab := tab ];
57
Removed:
with: tab title asCapitalizedPhrase ] ].
55
Added:
callback: [ self session activePage: page ];
56
Added:
with: page title asCapitalizedPhrase ] ].
58
57
html navigationItem dropdown with: [
59
58
html navigationLink
60
59
dropdownToggle;
@@ -67,5 +66,5 @@
67
66
html dropdownItem: 'Muscles' ] ] ].
68
67
html div
69
68
class: 'ms-auto';
70
Removed:
with: [ html render: MFTLoginRegisterLogoutComponent new ] ]
69
Added:
with: [ html render: loginRegisterLogout ] ]
71
70
]
src/MyFitnessTracker/MFTScreenComponent.class.st
@@ -3,8 +3,7 @@
3
3
#superclass : #SBSComponent,
4
4
#instVars : [
5
5
'header',
6
Removed:
'footer',
7
Removed:
'mainTabs'
6
Added:
'footer'
8
7
],
9
8
#category : #'MyFitnessTracker-Components'
10
9
}
@@ -14,7 +13,8 @@
14
13
15
14
^ {
16
15
header.
17
Removed:
mainTabs.
16
Added:
self session mainNavigationBar.
17
Added:
self session activePage.
18
18
footer }
19
19
]
20
20
@@ -23,7 +23,6 @@
23
23
24
24
super initialize.
25
25
header := MFTHeaderProspectComponent new.
26
Removed:
mainTabs := MFTMainNavigationBarComponent new.
27
26
footer := MFTFooterComponent new
28
27
]
29
28
@@ -32,6 +31,7 @@
32
31
33
32
html
34
33
render: header;
35
Removed:
render: mainTabs;
34
Added:
render: self session mainNavigationBar;
35
Added:
render: self session activePage;
36
36
render: footer
37
37
]
src/MyFitnessTracker/MFTSession.class.st
@@ -4,44 +4,23 @@
4
4
#instVars : [
5
5
'user',
6
6
'db',
7
Removed:
'mainTabs'
7
Added:
'mainNavigationBar',
8
Added:
'mainPages',
9
Added:
'activePage'
8
10
],
9
11
#category : #MyFitnessTracker
10
12
}
11
13
12
Removed:
{ #category : #'as yet unclassified' }
13
Removed:
MFTSession >> attemptLogin: aMFTUser [
14
Removed:
"Attempt to match aMFTUser passwordHash against an existing user password_hash in the database.
14
Added:
{ #category : #accessing }
15
Added:
MFTSession >> activePage [
15
16
16
Removed:
If a matching user is found, hydrate a MFTUser from the existingUser, and keep track of the database connection used to authenticate.
17
Removed:
If no matching user is found, kill the connection."
18
Removed:
19
Removed:
| connection existingUser passwordHash |
20
Removed:
connection := (MFTSQLite3Database openOn:
21
Removed:
(Smalltalk imageDirectory / 'mft.sqlite3') fullName)
22
Removed:
connection.
23
Removed:
existingUser := ((connection
24
Removed:
execute: 'SELECT * FROM users WHERE username = ?'
25
Removed:
value: aMFTUser username) onlyRow: [
26
Removed:
Dictionary new ]) asDictionary.
27
Removed:
passwordHash := existingUser
28
Removed:
at: #password_hash
29
Removed:
ifAbsent: [ String empty ].
30
Removed:
connection close.
31
Removed:
aMFTUser passwordHash = passwordHash
32
Removed:
ifTrue: [ self login: (MFTUser newFromDictionary: existingUser) ]
33
Removed:
ifFalse: [ ^ nil ]
17
Added:
^ activePage
34
18
]
35
19
36
Removed:
{ #category : #'as yet unclassified' }
37
Removed:
MFTSession >> computeTabsFor: aMFTUser [
20
Added:
{ #category : #accessing }
21
Added:
MFTSession >> activePage: anObject [
38
22
39
Removed:
| newTabs |
40
Removed:
newTabs := mainTabs.
41
Removed:
newTabs at: 1 put: (user isLoggedIn
42
Removed:
ifFalse: [ MFTPublicHomepageTab new ]
43
Removed:
ifTrue: [ MFTUserHomepageTab new ]).
44
Removed:
^ newTabs
23
Added:
activePage := anObject
45
24
]
46
25
47
26
{ #category : #accessing }
@@ -61,74 +40,46 @@
61
40
62
41
super initialize.
63
42
user := MFTUser new.
64
Removed:
mainTabs := OrderedCollection newFromArray: {
65
Removed:
MFTPublicHomepageTab new.
66
Removed:
MFTWorkoutsListTab placeholder.
67
Removed:
MFTWeightsListTab new.
68
Removed:
MFTLearnTab new.
69
Removed:
MFTProfileTab new }
43
Added:
mainNavigationBar := MFTMainNavigationBarComponent new.
44
Added:
mainPages := OrderedCollection newFromArray: {
45
Added:
MFTPublicHomepageTab new.
46
Added:
MFTWorkoutsListTab placeholder.
47
Added:
MFTWeightsListTab new.
48
Added:
MFTLearnTab new.
49
Added:
MFTProfileTab new }.
50
Added:
activePage := mainPages first
70
51
]
71
52
72
Removed:
{ #category : #login }
73
Removed:
MFTSession >> login: aMFTUser [
53
Added:
{ #category : #accessing }
54
Added:
MFTSession >> mainNavigationBar [
74
55
75
Removed:
| connection loginDateAndTime |
76
Removed:
self user: aMFTUser.
77
Removed:
user isLoggedIn: true.
78
Removed:
79
Removed:
loginDateAndTime := DateAndTime now asUTC rounded.
80
Removed:
user lastConnectionDateTime: loginDateAndTime.
81
Removed:
connection := (MFTSQLite3Database openOn:
82
Removed:
(Smalltalk imageDirectory / 'mft.sqlite3') fullName)
83
Removed:
connection.
84
Removed:
connection
85
Removed:
execute: 'UPDATE users
86
Removed:
SET last_connection_date_time = ?
87
Removed:
WHERE username = ?'
88
Removed:
value: loginDateAndTime
89
Removed:
value: aMFTUser username.
90
Removed:
connection close.
91
Removed:
92
Removed:
self updateUserTabs
56
Added:
^ mainNavigationBar
93
57
]
94
58
95
Removed:
{ #category : #login }
96
Removed:
MFTSession >> logout [
59
Added:
{ #category : #accessing }
60
Added:
MFTSession >> mainNavigationBar: anObject [
97
61
98
Removed:
db connection close.
99
Removed:
user := nil
62
Added:
mainNavigationBar := anObject
100
63
]
101
64
102
65
{ #category : #accessing }
103
Removed:
MFTSession >> mainTabs [
66
Added:
MFTSession >> mainPages [
104
67
105
Removed:
^ mainTabs
68
Added:
^ mainPages
106
69
]
107
70
108
71
{ #category : #accessing }
109
Removed:
MFTSession >> mainTabs: anObject [
72
Added:
MFTSession >> mainPages: anObject [
110
73
111
Removed:
mainTabs := anObject
74
Added:
mainPages := anObject
112
75
]
113
76
114
Removed:
{ #category : #'as yet unclassified' }
115
Removed:
MFTSession >> registerNewUser: aMFTUser [
77
Added:
{ #category : #'parent/child' }
78
Added:
MFTSession >> unregistered [
116
79
117
Removed:
| connection |
118
Removed:
connection := (MFTSQLite3Database openOn:
119
Removed:
(Smalltalk imageDirectory / 'mft.sqlite3') fullName)
120
Removed:
connection.
121
Removed:
connection
122
Removed:
execute: 'INSERT INTO users(username,password_hash) VALUES (?, ?);'
123
Removed:
value: aMFTUser username
124
Removed:
value: aMFTUser passwordHash.
125
Removed:
connection close
126
Removed:
]
127
Removed:
128
Removed:
{ #category : #'as yet unclassified' }
129
Removed:
MFTSession >> updateUserTabs [
130
Removed:
131
Removed:
mainTabs := self computeTabsFor: user
80
Added:
db connection close.
81
Added:
user := nil.
82
Added:
super unregistered
132
83
]
133
84
134
85
{ #category : #accessing }