Bläddra i källkod

:pencil2: Cleaned up OnboardingView into methods, works the same as before thus far

juan_spike
tomit4 2 år sedan
förälder
incheckning
a867f27c24

+ 1
- 1
backend/lib/routes/user/getaccess.js Visa fil

@@ -29,7 +29,7 @@ module.exports = {
29 29
             const token = await userService.createToken({
30 30
                 ...res,
31 31
                 // NOTE: Set Expiration Time for Access Token Here
32
-                expires: 60 * 3,
32
+                expires: 60 * 10,
33 33
             })
34 34
             try {
35 35
                 const response = h.response({

+ 1
- 1
backend/lib/routes/user/getsession.js Visa fil

@@ -29,7 +29,7 @@ module.exports = {
29 29
             const token = await userService.createToken({
30 30
                 ...res,
31 31
                 // NOTE: Set Expiration Time for Session Token Here
32
-                expires: 60 * 3,
32
+                expires: 60 * 10,
33 33
             })
34 34
             try {
35 35
                 const response = h.response({

+ 2
- 7
backend/lib/services/user.js Visa fil

@@ -308,11 +308,6 @@ module.exports = class UserService extends Schmervice.Service {
308 308
         if (emailIsRegistered && !emailIsExpired) {
309 309
             return true
310 310
         } else {
311
-            // try {
312
-            // delete this.hashedEmails[hashedEmail]
313
-            // } catch (err) {
314
-            // console.error('ERROR :=>', err)
315
-            // }
316 311
             return false
317 312
         }
318 313
     }
@@ -326,8 +321,8 @@ module.exports = class UserService extends Schmervice.Service {
326 321
         if (Object.keys(this.hashedEmails).includes(hashedEmail)) {
327 322
             return new Error('email address already in cache!!')
328 323
         }
329
-        // Set expiration time for five minutes from now
330
-        const duration = 1000 * 60 * 5
324
+        // Set expiration time for ten minutes from now
325
+        const duration = 1000 * 60 * 10
331 326
 
332 327
         this.hashedEmails[hashedEmail] = Date.now() + duration
333 328
         const sendSmtpEmail = {

+ 3
- 2
frontend/src/services/auth.service.js Visa fil

@@ -7,6 +7,7 @@ class Authenticator {
7 7
     async sendAuthEmail(answered) {
8 8
         return await db.post('/user/sendemail/', answered)
9 9
     }
10
+    // NOTE: doesn't have to be a POST request, could be a GET with token instead of email
10 11
     async checkIfEmailIsRegistered(email) {
11 12
         return await db.post('/user/checkemailregistry/', email)
12 13
     }
@@ -20,8 +21,8 @@ class Authenticator {
20 21
     async getAccessToken(req) {
21 22
         return await db.post('/user/getaccess', req, true)
22 23
     }
23
-    async validateSession(sessionToken) {
24
-        return await db.get('/user/validatesession', sessionToken)
24
+    async validateSession(token) {
25
+        return await db.get('/user/validatesession', token)
25 26
     }
26 27
 }
27 28
 

+ 90
- 74
frontend/src/views/OnboardingView.vue Visa fil

@@ -45,26 +45,7 @@ import stepViews from '@/components/onboarding'
45 45
 import SurveyCompleteView from './SurveyCompleteView.vue'
46 46
 let sessionToken = null
47 47
 let accessToken = null
48
-
49
-/* BRIAN'S NOTE: 
50
-I'll need help here. The logic is getting confusing.
51
-
52
-    1.  Right now both a session and access token are issued 
53
-        (session via Auth.vue, access from VerifyView.vue).
54
-
55
-    2.  There is also a hashedEmail object on the backend's app state:
56
-        {
57
-            hashedEmailString: expiration_in_milliseconds,
58
-            anotherhashedEmailString: expiration_in_milliseconds,
59
-        }
60
-
61
-        TODO: jwt, hashedEmail, cookie expiration should be the same
62
-    3.  The session, access tokens all have jwt expirations as well as cookie expirations
63
-
64
-    4.  Additionally, we have an expiration on each hashedEmail string...
65
-    5.  All the data points to check are here... 
66
-        I just can't quite think straight as of 07/09/2023 at 01:53:22
67
-*/
48
+let currentProfileId = null
68 49
 
69 50
 export default {
70 51
     name: 'OnboardingView',
@@ -77,68 +58,34 @@ export default {
77 58
         aspectQuestions: [],
78 59
         responses: [],
79 60
         currentStep: 0,
80
-        currentProfileId: null,
81 61
         survey: null,
82 62
         invalidResponse: false,
83
-        userEmail: null,
84
-        emailIsRegistered: false,
85 63
         authenticator: {},
86 64
     }),
87 65
     async created() {
88 66
         this.survey = await surveyFactory.createSurvey()
89 67
         this.authenticator = new Authenticator()
90
-        // TODO: Once tokens are coming through headers, refactor all of this into methods, etc.
91
-        // TODO: Consider switch/case() depending on what tokens exist/are valid...
92
-        const sessionToken = this.grabStoredCookie('siimee_session')
93
-        if (!sessionToken) {
94
-            console.warn('WARNING :=> sessionToken not in stored Cookies')
95
-            this.goToStep(0)
96
-        }
97
-        // const accessToken = this.grabStoredCookie('siimee_access')
98
-        // if (!accessToken) {
99
-        // check if sessionToken is valid jwt
100
-        //     // blow up
101
-        // }
102
-        let sessionData
103
-        if (sessionToken) {
104
-            sessionData = await this.authenticator.validateSession(sessionToken)
105
-            console.log('sessionData :=>', sessionData)
106
-        }
107
-        // if (sessionData && !accessToken) {
108
-        if (sessionData) {
109
-            this.userEmail = sessionData.payload.email
110
-            this.emailIsRegistered =
111
-                // QUESTION: Would this logic also be needed in VerifyView??
112
-                await this.authenticator.checkIfEmailIsRegistered(
113
-                    this.userEmail,
114
-                )
115
-        }
116
-        // TODO: EVERY ROUTE WE HIT AFTER THIS HAS TO BE AUTHENTICATED
117
-        // ACCESS TOKEN WORKS
118
-        // START PROTECTING ALL ROUTES
119
-        if (this.emailIsRegistered) {
120
-            const user = await fetchUserByEmail(this.userEmail)
121
-            const userId = user.user_id
122
-            const profilesFromUserId = await fetchProfilesByUserId(userId)
123
-            let profileId
124
-            if (profilesFromUserId.length === 1) {
125
-                profileId = profilesFromUserId[0].profile_id
126
-                this.currentProfileId = profileId
127
-            }
128
-            // if (!profileId) {
129
-            // throw new Error
130
-            // }
131
-            const profile = await fetchProfileByProfileId(profileId)
132
-            profile.responses.forEach(response => {
133
-                this.responses.push({
134
-                    response_key_id: response.response_key_id,
135
-                    val: response.val,
136
-                })
137
-            })
68
+        // TODO: Note that all this try/catch can be in a function instead,
69
+        // since it has to be done on created() and every step after 6...
70
+        sessionToken = this.grabStoredCookie('siimee_session')
71
+        accessToken = this.grabStoredCookie('siimee_access')
72
+        try {
73
+            await this.verifySessionToken(sessionToken)
74
+            const sessionData = await this.verifyAccessToken(accessToken)
75
+            await this.isEmailInRegistry(sessionData.payload.email)
76
+            const userId = await this.grabUserIdByEmail(
77
+                sessionData.payload.email,
78
+            )
79
+            const profileId = await this.grabProfileIdByUserId(userId)
80
+            // TODO: consider different implementation once
81
+            // updateAnswers() no longer relies on this
82
+            currentProfileId = profileId
83
+            this.responses = await this.grabResponsesByProfileId(profileId)
138 84
             this.currentStep = this.responses.length + 3
139 85
             this.goToStep(this.currentStep)
140
-        } else {
141
-            // TODO: CHECK SESSION
86
+        } catch (err) {
87
+            console.error('ERROR :=>', err)
88
+            this.goToStep(0)
142 89
         }
143 90
     },
144 91
     methods: {
@@ -160,6 +107,75 @@ export default {
160 107
                 cookieKey in cookies ? cookies[`${cookieKey}`] : undefined
161 108
             return cookieVal
162 109
         },
110
+        async verifySessionToken(sessionToken) {
111
+            if (!sessionToken) {
112
+                console.warn('WARNING :=> sessionToken is not defined')
113
+            } else return await this.validateToken(sessionToken)
114
+        },
115
+        async verifyAccessToken(accessToken) {
116
+            if (!accessToken) {
117
+                console.warn('WARNING :=> accessToken is not defined')
118
+            } else return await this.validateToken(accessToken)
119
+        },
120
+        async validateToken(token) {
121
+            const validatedToken = await this.authenticator.validateSession(
122
+                token,
123
+            )
124
+            if (validatedToken.error) {
125
+                throw new Error(validatedToken.error)
126
+            } else {
127
+                return validatedToken
128
+            }
129
+        },
130
+        async isEmailInRegistry(email) {
131
+            const emailIsInRegistry =
132
+                await this.authenticator.checkIfEmailIsRegistered(email)
133
+            if (!emailIsInRegistry) {
134
+                throw new Error('Email Is NOT in Registry!')
135
+            } else return emailIsInRegistry // true
136
+        },
137
+        async grabUserIdByEmail(email) {
138
+            const user = await fetchUserByEmail(email)
139
+            if (!user) {
140
+                throw new Error('User NOT found by email')
141
+            } else return user.user_id
142
+        },
143
+        async grabProfileIdByUserId(userId) {
144
+            const profilesFromUserId = await fetchProfilesByUserId(userId)
145
+            if (profilesFromUserId.length === 1) {
146
+                return profilesFromUserId[0].profile_id
147
+            } else {
148
+                // TODO: Refactor once more is known on users with multiple profiles
149
+                console.error(
150
+                    'ERROR :=> Multiple Profiles for this User ID',
151
+                    profilesFromUserId,
152
+                )
153
+                throw new Error('Multiple Profiles for this User ID')
154
+            }
155
+        },
156
+        async grabProfileByProfileId(profileId) {
157
+            const profile = await fetchProfileByProfileId(profileId)
158
+            if (!profile) {
159
+                throw new Error(`No Profile Found for profileId ${profileId}`)
160
+            } else {
161
+                return profile
162
+            }
163
+        },
164
+        async grabResponsesByProfileId(profileId) {
165
+            const responses = []
166
+            const profile = await this.grabProfileByProfileId(profileId)
167
+            if (!profile.responses.length) {
168
+                throw new Error(`No Responses Found for profileId ${profileId}`)
169
+            } else {
170
+                profile.responses.forEach(response => {
171
+                    responses.push({
172
+                        response_key_id: response.response_key_id,
173
+                        val: response.val,
174
+                    })
175
+                })
176
+                return responses
177
+            }
178
+        },
163 179
         async updateAnswers(payload) {
164 180
             if (payload) {
165 181
                 // this.invalidResponse = false
@@ -183,7 +199,7 @@ export default {
183 199
                 console.log('this.responses :=>', this.responses)
184 200
 
185 201
                 // sends latest survey response to db
186
-                if (this.currentProfileId) {
202
+                if (currentProfileId) {
187 203
                     surveyFactory.addNewSurveyAnswer(
188 204
                         this.responses[this.responses.length - 1],
189 205
                         this.currentProfileId,

+ 1
- 1
frontend/src/views/VerifyView.vue Visa fil

@@ -67,7 +67,7 @@ export default {
67 67
                 throw new Error(sessionTokenIsValid.error)
68 68
             } else {
69 69
                 // TODO: Does accessToken need sessionToken data?
70
-                await this.getAccessToken(...sessionToken)
70
+                await this.getAccessToken(sessionTokenIsValid.payload)
71 71
             }
72 72
         },
73 73
     },

Laddar…
Avbryt
Spara