Browse Source

:construction: Closer and closer still to finalizing auth

tags/0.0.3^2
tomit4 3 years ago
parent
commit
389d3fd836

+ 5
- 1
backend/lib/routes/user/create-profile.js View File

67
                 }
67
                 }
68
                 /** Grab payload info */
68
                 /** Grab payload info */
69
                 const res = request.payload
69
                 const res = request.payload
70
+                /** Don't log password in response table */
71
+                const resWithoutPass = res.filter(r => {
72
+                    return r.response_key_id !== 9
73
+                })
70
                 const profile =
74
                 const profile =
71
                     await profileService.saveResponsesCreateProfileFor(
75
                     await profileService.saveResponsesCreateProfileFor(
72
                         userId,
76
                         userId,
73
-                        res,
77
+                        resWithoutPass,
74
                     )
78
                     )
75
                 return h
79
                 return h
76
                     .response({
80
                     .response({

+ 1
- 1
backend/lib/services/user.js View File

206
                 email: user.email,
206
                 email: user.email,
207
                 name: user.name,
207
                 name: user.name,
208
                 seeking: user.seeking,
208
                 seeking: user.seeking,
209
+                profile_id: user.profile_id,
209
             },
210
             },
210
             {
211
             {
211
                 key: key,
212
                 key: key,
227
     validateToken(token) {
228
     validateToken(token) {
228
         const key = this.server.registrations['main-app-plugin'].options.jwtKey
229
         const key = this.server.registrations['main-app-plugin'].options.jwtKey
229
         const decodedToken = Jwt.token.decode(token)
230
         const decodedToken = Jwt.token.decode(token)
230
-        console.log('decodedToken :=>', decodedToken)
231
         // NOTE: reveals email...perhaps unhashed email belongs here instead...
231
         // NOTE: reveals email...perhaps unhashed email belongs here instead...
232
         try {
232
         try {
233
             Jwt.token.verify(decodedToken, key)
233
             Jwt.token.verify(decodedToken, key)

+ 19
- 13
frontend/src/components/onboarding/Auth.vue View File

34
             default: () => {},
34
             default: () => {},
35
         },
35
         },
36
     },
36
     },
37
-    emits: ['update-answers', 'set-pid'],
37
+    emits: ['update-answers'],
38
     data: () => ({
38
     data: () => ({
39
         authenticator: {},
39
         authenticator: {},
40
     }),
40
     }),
41
     async created() {
41
     async created() {
42
-        // establishes new user and emits it up to onboarding for login purposes
42
+        // Establishes New User And Sends Auth Email
43
         this.authenticator = new Authenticator()
43
         this.authenticator = new Authenticator()
44
-        if (this.survey.hasMinResponsesToCreateProfile(this.answered)) {
45
-            const newUser = await signupUser(this.answered)
44
+        if (this.survey.hasMinResponsesToCreateProfile(this.responses)) {
45
+            const userPass = this.responses.find(
46
+                response => response.response_key_id === 9,
47
+            )
48
+            const newUser = await signupUser({
49
+                ...this.answered,
50
+                password: userPass.val,
51
+            })
46
             const newUserId = newUser.user_id
52
             const newUserId = newUser.user_id
47
-            await createProfileForUserId(newUserId, this.responses)
53
+            const newProfile = await createProfileForUserId(
54
+                newUserId,
55
+                this.responses,
56
+            )
48
             const jwt = await this.authenticator.generateJwt({
57
             const jwt = await this.authenticator.generateJwt({
49
                 ...this.answered,
58
                 ...this.answered,
50
                 expiration: 60 * 10,
59
                 expiration: 60 * 10,
60
+                profile_id: newProfile.profile_id,
51
             })
61
             })
52
-            document.cookie = `siimee_jwt=${jwt}; path=/verify`
62
+            document.cookie = `siimee_jwt=${jwt}; path=/verify; secure`
63
+            await this.authenticator.sendAuthEmail(this.answered)
64
+        } else {
65
+            console.error('ERROR :=>')
53
         }
66
         }
54
-
55
-        // sets jwt authentication cookie to be used in VerifyView.vue and
56
-        // OnboardingView.vue
57
-        // TODO: Instead of having this.answered here, simply pass profile_id?
58
-
59
-        // sends authentication email
60
-        await this.authenticator.sendAuthEmail(this.answered)
61
     },
67
     },
62
     methods: {
68
     methods: {
63
         // TODO: remove test button above and use a watcher instead to emit this
69
         // TODO: remove test button above and use a watcher instead to emit this

+ 7
- 8
frontend/src/entities/survey/survey.js View File

44
     }
44
     }
45
 
45
 
46
     hasMinResponsesToCreateProfile(responses) {
46
     hasMinResponsesToCreateProfile(responses) {
47
-        if (
48
-            responses.name &&
49
-            responses.email &&
50
-            responses.seeking &&
51
-            responses.password
52
-        ) {
53
-            return true
54
-        } else return false
47
+        const neededResponseKeys = [8, 7, 11, 9]
48
+        const hasNeededResponseKey = responses => {
49
+            return responses.every(response => {
50
+                neededResponseKeys.includes(response.response_key_id)
51
+            })
52
+        }
53
+        return hasNeededResponseKey
55
     }
54
     }
56
 
55
 
57
     validateAnswer(payload) {
56
     validateAnswer(payload) {

+ 31
- 41
frontend/src/views/OnboardingView.vue View File

18
                 :surveyStepsCount='survey.steps.length'
18
                 :surveyStepsCount='survey.steps.length'
19
                 @handle-submit='onSubmit'
19
                 @handle-submit='onSubmit'
20
                 @update-answers='updateAnswers'
20
                 @update-answers='updateAnswers'
21
-                @set-pid='setPid'
22
                 v-if='step && currentStep == i'
21
                 v-if='step && currentStep == i'
23
             ) 
22
             ) 
24
         .invalidResponseMessage(
23
         .invalidResponseMessage(
31
             p(v-if='currentStep != 0') You have completed: {{ currentStep }} / {{ survey.steps.length }} survey steps
30
             p(v-if='currentStep != 0') You have completed: {{ currentStep }} / {{ survey.steps.length }} survey steps
32
 
31
 
33
     article(v-else)
32
     article(v-else)
34
-        SurveyCompleteView(:answers='answered' :surveySteps='survey.steps')
33
+        SurveyCompleteView(:answers='answered' :surveySteps='survey.steps' :currentProfileId='currentProfileId')
35
 </template>
34
 </template>
36
 
35
 
37
 <script>
36
 <script>
57
         survey: null,
56
         survey: null,
58
         currentProfileId: null,
57
         currentProfileId: null,
59
         invalidResponse: false,
58
         invalidResponse: false,
60
-        // TODO: CURRENTLY WORKING ON**
61
         authenticator: {},
59
         authenticator: {},
62
         sessionToken: '',
60
         sessionToken: '',
63
         accessToken: '',
61
         accessToken: '',
64
     }),
62
     }),
65
     computed: {
63
     computed: {
66
-        // NOTE: perhaps start this off as returning nothing
67
-        // and then add currentProfile in created()?
68
-        profile: () => currentProfile,
64
+        cP() {
65
+            return currentProfile ? currentProfile : null
66
+        },
69
     },
67
     },
70
     async created() {
68
     async created() {
71
         this.survey = await surveyFactory.createSurvey()
69
         this.survey = await surveyFactory.createSurvey()
74
         if (document.cookie.length) {
72
         if (document.cookie.length) {
75
             // TODO: Remove this this.answered section when:
73
             // TODO: Remove this this.answered section when:
76
             // SurveyCompleteView calls all responses from db
74
             // SurveyCompleteView calls all responses from db
77
-            // BUG: NEEDS BROWSER REFRESH TO BE HIT
78
-            const siimeeAnswers = JSON.parse(
79
-                this.grabCookie(document.cookie, 'siimee_answered'),
80
-            )
81
-            this.sessionToken = this.grabCookie(
75
+            // BUG: NEEDS BROWSER REFRESH TO SEE UPDATED COOKIES
76
+            const siimeeAnswered = this.grabCookie(
82
                 document.cookie,
77
                 document.cookie,
83
-                'siimee_session',
84
-            )
85
-            const sessionTokenIsValid = await this.authenticator.validateJwt(
86
-                this.sessionToken,
78
+                'siimee_answered',
87
             )
79
             )
88
-            this.accessToken = this.grabCookie(document.cookie, 'siimee_access')
89
-            if (sessionTokenIsValid.isValid) {
90
-                this.answered = {
91
-                    name: siimeeAnswers.name,
92
-                    email: siimeeAnswers.email,
93
-                    seeking: siimeeAnswers.seeking,
80
+            if (siimeeAnswered) {
81
+                const siimeeAnswers = JSON.parse(
82
+                    this.grabCookie(document.cookie, 'siimee_answered'),
83
+                )
84
+                this.sessionToken = this.grabCookie(
85
+                    document.cookie,
86
+                    'siimee_session',
87
+                )
88
+                const sessionTokenIsValid =
89
+                    await this.authenticator.validateJwt(this.sessionToken)
90
+                this.accessToken = this.grabCookie(
91
+                    document.cookie,
92
+                    'siimee_access',
93
+                )
94
+                if (sessionTokenIsValid.isValid) {
95
+                    this.answered = {
96
+                        name: siimeeAnswers.name,
97
+                        email: siimeeAnswers.email,
98
+                        seeking: siimeeAnswers.seeking,
99
+                    }
100
+                    this.currentProfileId = siimeeAnswers.profile_id
101
+                    this.goToStep(6)
94
                 }
102
                 }
95
-                this.goToStep(6)
96
             } else this.goToStep(0)
103
             } else this.goToStep(0)
97
         }
104
         }
98
     },
105
     },
106
             }
113
             }
107
             this.currentStep = num
114
             this.currentStep = num
108
         },
115
         },
116
+        // TODO: Refactor to use cookie's max-age attribute instead of network call for jwt auth
109
         async validateAccessToken() {
117
         async validateAccessToken() {
110
             const validatedAccessToken = await this.authenticator.validateJwt(
118
             const validatedAccessToken = await this.authenticator.validateJwt(
111
                 this.accessToken,
119
                 this.accessToken,
138
             return cookieKey in cookies ? cookies[`${cookieKey}`] : undefined
146
             return cookieKey in cookies ? cookies[`${cookieKey}`] : undefined
139
         },
147
         },
140
         async updateAnswers(payload) {
148
         async updateAnswers(payload) {
141
-            // null payload is passed on splash page
142
             if (payload) {
149
             if (payload) {
143
                 // this.invalidResponse = false
150
                 // this.invalidResponse = false
144
                 const k = payload.question.survey_stage
151
                 const k = payload.question.survey_stage
150
                 }
157
                 }
151
 
158
 
152
                 // once validated, don't log password in answered object
159
                 // once validated, don't log password in answered object
153
-                // this.answered[k] = k === 'password' ? undefined : payload.input
160
+                this.answered[k] = k === 'password' ? undefined : payload.input
154
 
161
 
155
                 // formats initial responses for response table
162
                 // formats initial responses for response table
156
                 const response = {}
163
                 const response = {}
174
                 this.goToStep(this.currentStep + 1)
181
                 this.goToStep(this.currentStep + 1)
175
             }
182
             }
176
         },
183
         },
177
-        // NOTE: Brought in from App.vue, might not be necessary...
178
-        // Allows for login after initial email sign up is set
179
-        async setPid(profileId) {
180
-            if (currentProfile.isLoggedIn) {
181
-                currentProfile.logout()
182
-            }
183
-            // ERROR: this._profile is undefinedin login service
184
-            this.profile.id = await currentProfile.login(
185
-                profileId,
186
-                this.$waveui.notify,
187
-            )
188
-            console.log('---')
189
-
190
-            // Change if survey isn't complete...
191
-            // const toRoute = { name: 'HomeView' }
192
-            // this.$router.push(toRoute)
193
-        },
194
     },
184
     },
195
 }
185
 }
196
 </script>
186
 </script>

+ 7
- 6
frontend/src/views/VerifyView.vue View File

5
 </template>
5
 </template>
6
 
6
 
7
 <script>
7
 <script>
8
+// NOTE: If the httponly flag is to be used with these cookies,
9
+// this file will need to be rewritten as an .html file due to the way
10
+// that Hapi sets cookies via the h.state() method
8
 import { Authenticator } from '../services/auth.service.js'
11
 import { Authenticator } from '../services/auth.service.js'
9
 export default {
12
 export default {
10
     name: 'VerifyView',
13
     name: 'VerifyView',
17
         const hashEmail = this.$route.params.email
20
         const hashEmail = this.$route.params.email
18
 
21
 
19
         // TODO: generate a token on the backend here and have it sent over in
22
         // TODO: generate a token on the backend here and have it sent over in
20
-        // the headers intead of setting it directly with document.cookie
23
+        // the headers intead of setting it directly with document.cookie (see note above)
21
 
24
 
22
         const hashesMatch = await this.authenticator.verifyAuthEmail(hashEmail)
25
         const hashesMatch = await this.authenticator.verifyAuthEmail(hashEmail)
23
         const siimeeToken = this.grabToken(document.cookie)
26
         const siimeeToken = this.grabToken(document.cookie)
27
         this.answers = jwt.payload
30
         this.answers = jwt.payload
28
         const accessToken = await this.generateAccessToken()
31
         const accessToken = await this.generateAccessToken()
29
         if (jwt.isValid && hashesMatch) {
32
         if (jwt.isValid && hashesMatch) {
30
-            // TODO: establish session access token cookie here
31
             const siimeeAnswers = JSON.stringify(this.answers)
33
             const siimeeAnswers = JSON.stringify(this.answers)
32
-            document.cookie = `siimee_answered=${siimeeAnswers} ; path=/onboarding; secure`
33
-            // TODO: for session/access cookies, make sure to set http only flag and expiration
34
-            document.cookie = `siimee_session=${siimeeToken} ; path=/onboarding; secure`
35
-            document.cookie = `siimee_access=${accessToken}; path=/onboarding; secure`
34
+            document.cookie = `siimee_answered=${siimeeAnswers}; max-age=360 ; path=/onboarding; secure`
35
+            document.cookie = `siimee_session=${siimeeToken} ; max-age=360 ; path=/onboarding; secure`
36
+            document.cookie = `siimee_access=${accessToken}; max-age=360 ; path=/onboarding; secure`
36
             this.$router.push('/onboarding')
37
             this.$router.push('/onboarding')
37
         }
38
         }
38
         // else {
39
         // else {

Loading…
Cancel
Save