Pārlūkot izejas kodu

:construction: Continued work on email valdiation and saving survey state

juan_spike
tomit4 3 gadus atpakaļ
vecāks
revīzija
136266b559

+ 5
- 7
backend/lib/routes/user/generatejwt.js Parādīt failu

@@ -13,8 +13,8 @@ const pluginConfig = {
13 13
 }
14 14
 
15 15
 module.exports = {
16
-    method: 'GET',
17
-    path: '/generatejwt/{hash}',
16
+    method: 'POST',
17
+    path: '/generatejwt',
18 18
     options: {
19 19
         ...pluginConfig.docs.get,
20 20
         tags: ['api'],
@@ -22,11 +22,9 @@ module.exports = {
22 22
         cors: true,
23 23
         handler: async function (request, h) {
24 24
             const { userService } = request.server.services()
25
-            const hash = request.params.hash
26
-            const user = {
27
-                user_email: hash,
28
-            }
29
-            const token = await userService.createToken(user)
25
+            const res = request.payload
26
+
27
+            const token = await userService.createToken(res)
30 28
             try {
31 29
                 return {
32 30
                     ok: true,

+ 4
- 1
backend/lib/routes/user/validatejwt.js Parādīt failu

@@ -28,7 +28,10 @@ module.exports = {
28 28
                 return {
29 29
                     ok: true,
30 30
                     handler: pluginConfig.handlerType,
31
-                    data: { isValid: jwtIsValid.isValid },
31
+                    data: {
32
+                        isValid: jwtIsValid.isValid,
33
+                        payload: jwtIsValid.payload,
34
+                    },
32 35
                 }
33 36
             } catch (err) {
34 37
                 return {

+ 7
- 3
backend/lib/services/user.js Parādīt failu

@@ -63,6 +63,7 @@ module.exports = class UserService extends Schmervice.Service {
63 63
         super(...args)
64 64
         const pwd = new SecurePassword()
65 65
         this.hashedEmail = ''
66
+        // this.hashedEmails = []
66 67
         this.pwd = {
67 68
             hash: Util.promisify(pwd.hash.bind(pwd)),
68 69
             verify: Util.promisify(pwd.verify.bind(pwd)),
@@ -197,7 +198,9 @@ module.exports = class UserService extends Schmervice.Service {
197 198
             {
198 199
                 aud: 'urn:audience:test',
199 200
                 iss: 'urn:issuer:test',
200
-                email: user.user_email,
201
+                email: user.email,
202
+                name: user.name,
203
+                seeking: user.seeking,
201 204
             },
202 205
             {
203 206
                 key: key,
@@ -218,11 +221,11 @@ module.exports = class UserService extends Schmervice.Service {
218 221
     validateToken(token) {
219 222
         const key = this.server.registrations['main-app-plugin'].options.jwtKey
220 223
         const decodedToken = Jwt.token.decode(token)
224
+        console.log('decodedToken :=>', decodedToken)
221 225
         // NOTE: reveals email...perhaps unhashed email belongs here instead...
222
-        // console.log('decodedToken :=>', decodedToken)
223 226
         try {
224 227
             Jwt.token.verify(decodedToken, key)
225
-            return { isValid: true }
228
+            return { isValid: true, payload: decodedToken.decoded.payload }
226 229
         } catch (err) {
227 230
             return { isValid: false, error: err.message }
228 231
         }
@@ -295,5 +298,6 @@ module.exports = class UserService extends Schmervice.Service {
295 298
             },
296 299
         )
297 300
         this.hashedEmail = hashEmail(userEmail)
301
+        // this.hashedEmails.push(hashEmail(userEmail))
298 302
     }
299 303
 }

+ 15
- 10
frontend/src/components/onboarding/Auth.vue Parādīt failu

@@ -34,25 +34,30 @@ export default {
34 34
             default: () => {},
35 35
         },
36 36
     },
37
-    emits: ['update-answers'],
37
+    emits: ['update-answers', 'set-pid'],
38 38
     data: () => ({
39 39
         authenticator: {},
40 40
     }),
41 41
     async created() {
42
+        // establishes new user and emits it up to onboarding for login purposes
42 43
         this.authenticator = new Authenticator()
43 44
         if (this.survey.hasMinResponsesToCreateProfile(this.answered)) {
44 45
             const newUser = await signupUser(this.answered)
45 46
             const newUserId = newUser.user_id
46
-            try {
47
-                await createProfileForUserId(newUserId, this.responses)
48
-            } catch (err) {
49
-                console.error('ERROR :=>', err)
50
-            }
51
-        }
47
+            const newProfile = await createProfileForUserId(
48
+                newUserId,
49
+                this.responses,
50
+            )
52 51
 
53
-        this.authenticator.sendAuthEmail(this.answered)
54
-        // TODO: Consider waiting until email hash is verified...(i.e. not in created)
55
-        signupUser(this.answered)
52
+            // sets jwt authentication cookie to be used in VerifyView.vue
53
+            // TODO: Instead of having this.answered here, simply pass profile_id?
54
+            const jwt = await this.authenticator.generateJwt(this.answered)
55
+            document.cookie = `siimee_jwt=${jwt}; path=/verify`
56
+            // this.$emit('set-pid', newProfile.profile_id)
57
+
58
+            // sends authentication email
59
+            this.authenticator.sendAuthEmail(this.answered)
60
+        }
56 61
     },
57 62
     methods: {
58 63
         // TODO: remove test button above and use a watcher instead to emit this

+ 4
- 3
frontend/src/services/auth.service.js Parādīt failu

@@ -13,13 +13,14 @@ class Authenticator {
13 13
         const isVerified = await db.get(`/user/verify/${hash}`)
14 14
         return isVerified.hashesMatch
15 15
     }
16
-    async generateJwt(hash) {
17
-        const token = await db.get(`/user/generatejwt/${hash}`)
16
+    // TODO: this needs to generate the JWT with the RAW email
17
+    async generateJwt(res) {
18
+        const token = await db.post('/user/generatejwt', res)
18 19
         return token.jwt
19 20
     }
20 21
     async validateJwt(jwt) {
21 22
         const validateJwt = await db.get(`/user/validatejwt/${jwt}`)
22
-        return validateJwt.isValid
23
+        return validateJwt
23 24
     }
24 25
 }
25 26
 

+ 48
- 6
frontend/src/views/OnboardingView.vue Parādīt failu

@@ -15,9 +15,11 @@ main.view--onboarding
15 15
                 :responses='responses'
16 16
                 :survey='survey'
17 17
                 :currentStep='currentStep'
18
+                :jwt='jwt'
18 19
                 :surveyStepsCount='survey.steps.length'
19 20
                 @handle-submit='onSubmit'
20 21
                 @update-answers='updateAnswers'
22
+                @set-pid='setPid'
21 23
                 v-if='step && currentStep == i'
22 24
             ) 
23 25
         .invalidResponseMessage(
@@ -36,6 +38,7 @@ main.view--onboarding
36 38
 <script>
37 39
 import { Authenticator } from '../services/auth.service.js'
38 40
 import { surveyFactory } from '@/utils'
41
+import { currentProfile } from '../services/'
39 42
 import stepViews from '@/components/onboarding'
40 43
 import SurveyCompleteView from './SurveyCompleteView.vue'
41 44
 
@@ -59,16 +62,38 @@ export default {
59 62
         authenticator: {},
60 63
         jwt: '',
61 64
     }),
65
+    computed: {
66
+        // NOTE: perhaps start this off as returning nothing
67
+        // and then add currentProfile in created()?
68
+        profile: () => currentProfile,
69
+    },
62 70
     async created() {
71
+        // console.log('this.profile.id :=>', this.profile.id)
63 72
         if (document.cookie.length) {
64
-            const siimeeToken = this.grabToken(document.cookie)
73
+            // TODO: Remove this this.answered section when:
74
+            // SurveyCompleteView calls all responses from db
75
+            const siimeeAnswers = JSON.parse(
76
+                this.grabCookie(document.cookie, 'siimee_answered'),
77
+            )
78
+            this.answered = {
79
+                name: siimeeAnswers.name,
80
+                email: siimeeAnswers.email,
81
+                seeking: siimeeAnswers.seeking,
82
+            }
83
+            // TODO: Instead, login using siimee_profile_id from cookie
84
+            const siimeeToken = this.grabCookie(document.cookie, 'siimee_jwt')
65 85
             this.jwt = siimeeToken ? siimeeToken : ''
66 86
         }
87
+
67 88
         this.survey = await surveyFactory.createSurvey()
68 89
         this.authenticator = new Authenticator()
69 90
         if (this.jwt.length) {
70
-            const jwtStillValid = await this.authenticator.validateJwt(this.jwt)
71
-            if (jwtStillValid) {
91
+            // TODO: remove once currentProfile is established and user is logged in...
92
+            const jwt = await this.authenticator.validateJwt(this.jwt)
93
+            if (jwt.isValid) {
94
+                // grab profileId from jwt payload and login here
95
+                // use this profile to grab all responses in
96
+                // SurveyCompleteView.vue
72 97
                 this.goToStep(6)
73 98
             } else {
74 99
                 this.goToStep(0)
@@ -83,13 +108,13 @@ export default {
83 108
         goToStep(num) {
84 109
             this.currentStep = num
85 110
         },
86
-        grabToken(cookieString) {
111
+        grabCookie(cookieString, cookieKey) {
87 112
             const cookies = cookieString.split('; ').reduce((prev, current) => {
88 113
                 const [name, ...value] = current.split('=')
89 114
                 prev[name] = value.join('=')
90 115
                 return prev
91 116
             }, {})
92
-            return 'siimee_jwt' in cookies ? cookies['siimee_jwt'] : undefined
117
+            return cookieKey in cookies ? cookies[`${cookieKey}`] : undefined
93 118
         },
94 119
         async updateAnswers(payload) {
95 120
             // null payload is passed on splash page
@@ -102,7 +127,7 @@ export default {
102 127
                     this.invalidResponse = true
103 128
                     return
104 129
                 }
105
-                //
130
+
106 131
                 // once validated, don't log password in answered object
107 132
                 // this.answered[k] = k === 'password' ? undefined : payload.input
108 133
 
@@ -128,6 +153,23 @@ export default {
128 153
                 this.goToStep(this.currentStep + 1)
129 154
             }
130 155
         },
156
+        // NOTE: Brought in from App.vue, might not be necessary...
157
+        // Allows for login after initial email sign up is set
158
+        async setPid(profileId) {
159
+            if (currentProfile.isLoggedIn) {
160
+                currentProfile.logout()
161
+            }
162
+            // ERROR: this._profile is undefinedin login service
163
+            this.profile.id = await currentProfile.login(
164
+                profileId,
165
+                this.$waveui.notify,
166
+            )
167
+            console.log('---')
168
+
169
+            // Change if survey isn't complete...
170
+            // const toRoute = { name: 'HomeView' }
171
+            // this.$router.push(toRoute)
172
+        },
131 173
     },
132 174
 }
133 175
 </script>

+ 24
- 5
frontend/src/views/VerifyView.vue Parādīt failu

@@ -1,6 +1,6 @@
1 1
 <template lang="pug">
2 2
 .wait-message
3
-    p.verify-message Thanks for authenticating your email {{ name }}!
3
+    p.verify-message Thanks for authenticating your email!
4 4
     p.verify-message Please give us a moment to redirect you back to the survey
5 5
 </template>
6 6
 
@@ -15,14 +15,33 @@ export default {
15 15
         this.authenticator = new Authenticator()
16 16
         const hashEmail = this.$route.params.email
17 17
         const hashesMatch = await this.authenticator.verifyAuthEmail(hashEmail)
18
-        if (hashesMatch) {
19
-            const jwt = await this.authenticator.generateJwt(hashEmail)
20
-            document.cookie = `siimee_jwt=${jwt}; path=/onboarding`
18
+        const siimeeToken = this.grabToken(document.cookie)
19
+
20
+        // TODO: remove once currentProfile is established and user is logged in...
21
+        // NOTE: another siimee_jwt cookie for onboarding path instead of verify
22
+        document.cookie = `siimee_jwt=${siimeeToken}; path=/onboarding`
23
+
24
+        const jwt = await this.authenticator.validateJwt(siimeeToken)
25
+
26
+        if (jwt.isValid && hashesMatch) {
27
+            // TODO: set jwt.payload.profile_id as siimee_profile_id
28
+            // remove answers, will query db at SurveyCompleteView.vue
29
+            const siimeeAnswers = JSON.stringify(jwt.payload)
30
+            document.cookie = `siimee_answered=${siimeeAnswers} ; path=/onboarding`
21 31
             this.$router.push('/onboarding')
22 32
         }
23 33
         // else {
24 34
         // render ERROR message above or redirect to 404 (or both?)
25
-        // }
35
+    },
36
+    methods: {
37
+        grabToken(cookieString) {
38
+            const cookies = cookieString.split('; ').reduce((prev, current) => {
39
+                const [name, ...value] = current.split('=')
40
+                prev[name] = value.join('=')
41
+                return prev
42
+            }, {})
43
+            return 'siimee_jwt' in cookies ? cookies['siimee_jwt'] : undefined
44
+        },
26 45
     },
27 46
 }
28 47
 </script>

Notiek ielāde…
Atcelt
Saglabāt