Selaa lähdekoodia

:construction: Cleaned up logic from created into methods on Auth and Verification

tags/0.0.3^2
tomit4 3 vuotta sitten
vanhempi
commit
536fb847f7

+ 1
- 0
backend/lib/routes/user/signup.js Näytä tiedosto

@@ -69,6 +69,7 @@ module.exports = {
69 69
                     })
70 70
                     .code(201)
71 71
             } catch (err) {
72
+                console.error('ERROR :=>', err)
72 73
                 return h
73 74
                     .response({
74 75
                         ok: false,

+ 1
- 1
backend/lib/routes/user/validatesession.js Näytä tiedosto

@@ -37,7 +37,7 @@ module.exports = {
37 37
                 return {
38 38
                     ok: false,
39 39
                     handler: pluginConfig.handlerType,
40
-                    data: err.message,
40
+                    data: { error: err.message },
41 41
                 }
42 42
             }
43 43
         },

+ 16
- 13
backend/lib/services/profile/index.js Näytä tiedosto

@@ -135,21 +135,24 @@ module.exports = class ProfileService extends Schmervice.Service {
135 135
      */
136 136
     async saveResponsesCreateProfileFor(userId, responses, txn) {
137 137
         const { Profile, Response } = this.server.models()
138
-
139
-        const profile = await Profile.query(txn).insert({
140
-            user_id: userId,
141
-        })
142
-        for (const responseToSave of responses) {
143
-            const convertedResponse = this._convertResponse(responseToSave)
144
-            const responseInfo = {
145
-                profile_id: profile.id,
146
-                response_key_id: convertedResponse.response_key_id,
147
-                val: convertedResponse.val,
138
+        try {
139
+            const profile = await Profile.query(txn).insert({
140
+                user_id: userId,
141
+            })
142
+            for (const responseToSave of responses) {
143
+                const convertedResponse = this._convertResponse(responseToSave)
144
+                const responseInfo = {
145
+                    profile_id: profile.id,
146
+                    response_key_id: convertedResponse.response_key_id,
147
+                    val: convertedResponse.val,
148
+                }
149
+                await Response.query(txn).insert(responseInfo)
148 150
             }
149
-            await Response.query(txn).insert(responseInfo)
151
+            //** Work around for HAPI returning profile_id as id */
152
+            return { user_id: profile.user_id, profile_id: profile.id }
153
+        } catch (err) {
154
+            throw new Error(err)
150 155
         }
151
-        //** Work around for HAPI returning profile_id as id */
152
-        return { user_id: profile.user_id, profile_id: profile.id }
153 156
     }
154 157
 
155 158
     /** Update responses in place

+ 42
- 23
frontend/src/components/onboarding/Auth.vue Näytä tiedosto

@@ -2,9 +2,6 @@
2 2
 .wait-message
3 3
     p.verify-message Thanks for signing up!
4 4
     p.verify-message We'll just need you to verify your email address to continue. Please check your email!
5
-    w-button.ma1.grow(
6
-        @click='handleSubmit'
7
-    ) TEST BUTTON
8 5
 </template>
9 6
 
10 7
 <script>
@@ -17,16 +14,16 @@ export default {
17 14
     props: {
18 15
         question: {
19 16
             required: true,
20
-            type: String,
21
-            default: 'authenticated question!!',
17
+            type: Object,
18
+            default: () => {},
22 19
         },
23 20
         answered: {
24
-            type: String,
25
-            default: '',
21
+            type: Object,
22
+            default: () => {},
26 23
         },
27 24
         responses: {
28
-            type: String,
29
-            default: '',
25
+            type: Object,
26
+            default: () => {},
30 27
         },
31 28
         survey: {
32 29
             required: true,
@@ -41,33 +38,55 @@ export default {
41 38
     async created() {
42 39
         // Establishes New User And Sends Auth Email
43 40
         this.authenticator = new Authenticator()
44
-        if (this.survey.hasMinResponsesToCreateProfile(this.responses)) {
41
+        try {
42
+            this.doesUserHaveMinResponses(this.responses)
45 43
             const userPass = this.responses.find(
46 44
                 response => response.response_key_id === 9,
47 45
             )
48
-            const newUser = await signupUser({
46
+            const newUserId = await this.signupNewUser({
49 47
                 ...this.answered,
50 48
                 password: userPass.val,
51 49
             })
52
-            const newUserId = newUser.user_id
53
-            await createProfileForUserId(newUserId, this.responses)
54
-            const jwt = await this.authenticator.getJwt({
50
+            await this.createProfileForNewUser(newUserId, this.responses)
51
+            const sessionToken = await this.getSessionToken({
55 52
                 ...this.answered,
56
-                expires: 60 * 3,
57 53
             })
58
-            document.cookie = `siimee_session=${jwt}; max-age=600; path=/; secure`
54
+            document.cookie = `siimee_session=${sessionToken}; max-age=600; path=/; secure`
59 55
             await this.authenticator.sendAuthEmail(this.answered)
60
-        } else {
61
-            console.error('ERROR :=>')
56
+        } catch (err) {
57
+            // TODO: redirect to an error page displaying which
58
+            // error occurred and how to reach out to staff??
59
+            console.error('ERROR :=>', err)
62 60
         }
63 61
     },
64 62
     methods: {
65
-        // TODO: remove test button above and use a watcher instead to emit this
66
-        handleSubmit() {
67
-            const payload = {
68
-                question: this.question,
63
+        doesUserHaveMinResponses(responses) {
64
+            if (!this.survey.hasMinResponsesToCreateProfile(responses))
65
+                throw new Error(
66
+                    'User has not answered minimum amount of questions to create profile',
67
+                )
68
+        },
69
+        async getSessionToken(payload) {
70
+            return await this.authenticator.getJwt({
71
+                payload,
72
+                expires: 60 * 3,
73
+            })
74
+        },
75
+        async signupNewUser(userInfo) {
76
+            const newUser = await signupUser(userInfo)
77
+            if (!newUser || newUser.error) {
78
+                throw new Error(
79
+                    'Error occured when signing up new User :=>',
80
+                    newUser.error,
81
+                )
82
+            } else return newUser.user_id
83
+        },
84
+        async createProfileForNewUser(userId, responses) {
85
+            try {
86
+                await createProfileForUserId(userId, responses)
87
+            } catch (err) {
88
+                throw new Error(err)
69 89
             }
70
-            this.$emit('update-answers', payload)
71 90
         },
72 91
     },
73 92
 }

+ 1
- 1
frontend/src/components/onboarding/QuestionResponse.vue Näytä tiedosto

@@ -24,7 +24,7 @@ export default {
24 24
             type: Object,
25 25
             required: true,
26 26
         },
27
-        currentSteps: {
27
+        currentStep: {
28 28
             type: Number,
29 29
             required: true,
30 30
         },

+ 2
- 32
frontend/src/services/auth.service.js Näytä tiedosto

@@ -19,40 +19,10 @@ class Authenticator {
19 19
         const isVerified = await db.get(`/user/verify/${hashedEmail}`)
20 20
         return isVerified.hashesMatch
21 21
     }
22
-
23 22
     async getJwt(req) {
24
-        // TODO: Clean up, should be able to use TOJ's db.post function,
25
-        // may need custon db.postWithHeaders() func or something like that...
26
-        const response = await fetch('http://localhost:3001/api/user/getjwt', {
27
-            method: 'POST',
28
-            mode: 'cors',
29
-            cache: 'no-cache',
30
-            credentials: 'omit',
31
-            headers: {
32
-                'Content-Type': 'application/json',
33
-            },
34
-            redirect: 'manual',
35
-            referrerPolicy: 'no-referrer',
36
-            body: JSON.stringify({ payload: req, expires: 600 }),
37
-        }).then(response => {
38
-            return response
39
-        })
40
-        console.log('response.headers :=>', response.headers)
41
-        // TODO: consider cleaner way to convert headers into JS Object
42
-        const getHeaders = headers => {
43
-            const headerObj = {}
44
-            const keys = headers.keys()
45
-            let header = keys.next()
46
-            while (header.value) {
47
-                headerObj[header.value] = headers.get(header.value)
48
-                header = keys.next()
49
-            }
50
-            return headerObj
51
-        }
52
-        const headerObj = getHeaders(response.headers)
53
-        return headerObj['authorization']
23
+        const responseHeaders = await db.post('/user/getjwt', req, true)
24
+        return responseHeaders
54 25
     }
55
-
56 26
     async validateSession(sessionToken) {
57 27
         const validateSession = await db.get(
58 28
             `/user/validatesession/${sessionToken}`,

+ 9
- 4
frontend/src/utils/db.js Näytä tiedosto

@@ -35,14 +35,18 @@ class Connector {
35 35
         }
36 36
         return header
37 37
     }
38
-    async _tryFetch({ endpoint, header }) {
38
+    async _tryFetch({ endpoint, header }, returnHeaders = false) {
39 39
         try {
40 40
             const res = await fetch(`${remote}${endpoint}`, header)
41 41
             if (!res.ok) {
42 42
                 throw Error(res.statusText)
43 43
             }
44
-            const jsonRes = await res.json()
45
-            return jsonRes.data
44
+            if (returnHeaders) {
45
+                return res.headers
46
+            } else {
47
+                const jsonRes = await res.json()
48
+                return jsonRes.data
49
+            }
46 50
         } catch (error) {
47 51
             console.error(`[API Util]: ${error}\nroute:`, endpoint)
48 52
         }
@@ -53,10 +57,11 @@ class Connector {
53 57
             header: this._makeHeader({ method: this._verbs.get }),
54 58
         })
55 59
     }
56
-    async post(endpoint, payload = {}) {
60
+    async post(endpoint, payload = {}, returnHeaders = false) {
57 61
         return await this._tryFetch({
58 62
             endpoint,
59 63
             header: this._makeHeader({ method: this._verbs.post, payload }),
64
+            returnHeaders,
60 65
         })
61 66
     }
62 67
     async patch(endpoint, payload = {}) {

+ 1
- 1
frontend/src/views/OnboardingView.vue Näytä tiedosto

@@ -87,7 +87,7 @@ export default {
87 87
         }
88 88
         // if (sessionData && !accessToken) {
89 89
         if (sessionData) {
90
-            this.userEmail = sessionData.email
90
+            this.userEmail = sessionData.payload.email
91 91
             this.emailIsRegistered =
92 92
                 await this.authenticator.checkIfEmailIsRegistered(
93 93
                     this.userEmail,

+ 43
- 39
frontend/src/views/VerifyView.vue Näytä tiedosto

@@ -11,42 +11,27 @@ export default {
11 11
     data: () => ({
12 12
         authenticator: {},
13 13
         answers: {},
14
+        hash: undefined,
15
+        sessionToken: undefined,
16
+        accessToken: undefined,
14 17
     }),
15 18
     async created() {
16 19
         this.authenticator = new Authenticator()
17
-        const hashEmail = this.$route.params.email
18
-
19
-        const hashesMatch = await this.authenticator.verifyAuthEmail(hashEmail)
20
-        const sessionToken = this.grabCookie('siimee_session')
21
-        // TODO: Refactor, see methods below
22
-        // if (!hashesMatch) {
23
-        //     throw new Error('no record of hashed email in cache')
24
-        //     this.$router.push('/onboarding')
25
-        // }
26
-
27
-        // TODO: THIS NEEDS TO BE SENT OVER TO verifyAuthEmail(hashEmail) in the headers
28
-        // TODO: Refactor, see methods below
29
-        // if (!sessionToken) {
30
-        //     throw new Error('token doesn't exist)
31
-        //     this.$router.push('/onboarding')
32
-        // } else {}
33
-
34
-        // TODO: Refactor to not nest, use try/catch/throw
35
-        if (sessionToken) {
36
-            const validatedSessionToken =
37
-                await this.authenticator.validateSession(sessionToken)
38
-            if (validatedSessionToken && hashesMatch) {
39
-                // TODO: What payload does accessToken need in first param to getJwt?
40
-                const accessToken = await this.authenticator.getJwt({
41
-                    ...sessionToken,
42
-                    expires: 60 * 3,
43
-                })
44
-                document.cookie = `siimee_access=${accessToken}; max-age=600; path=/; secure`
45
-                this.$router.push('/onboarding')
46
-            }
47
-        } else {
48
-            console.error('ERROR :=>')
20
+        this.hash = this.$route.params.email
21
+        this.sessionToken = this.grabCookie('siimee_session')
22
+        try {
23
+            this.isHashInUrl(this.hash)
24
+            this.doesEmailMatch(this.hash)
25
+            this.doesSessionTokenExist(this.sessionToken)
26
+            const sessionTokenIsValid = this.isSessionTokenValid(
27
+                this.sessionToken,
28
+            )
29
+            if (sessionTokenIsValid)
30
+                document.cookie = `siimee_access=${this.accessToken}; max-age=600; path=/; secure`
31
+        } catch (err) {
32
+            console.error(err)
49 33
         }
34
+        this.$router.push('/onboarding')
50 35
     },
51 36
     methods: {
52 37
         grabCookie(cookieKey) {
@@ -61,16 +46,35 @@ export default {
61 46
                 ? cookies[`${cookieKey}`]
62 47
                 : undefined
63 48
         },
64
-        async generateAccessToken() {
65
-            const accessJwt = await this.authenticator.getJwt({
66
-                ...this.answers,
49
+        async getAccessToken(payload) {
50
+            return await this.authenticator.getJwt({
51
+                payload,
67 52
                 expires: 60 * 3,
68 53
             })
69
-            return accessJwt
70 54
         },
71
-        // async doesEmailMatch() {},
72
-        // async doesTokenExist() {},
73
-        // async isTokenValid() {},
55
+        isHashInUrl(hash) {
56
+            if (!hash) throw new Error('URL contains no hash!')
57
+        },
58
+        async doesEmailMatch(hashEmail) {
59
+            const hashesMatch = await this.authenticator.verifyAuthEmail(
60
+                hashEmail,
61
+            )
62
+            if (!hashesMatch) throw new Error('Hash is not in registry!')
63
+        },
64
+        async doesSessionTokenExist(sessionToken) {
65
+            if (!sessionToken)
66
+                throw new Error('sessionToken not in cookie store!')
67
+        },
68
+        async isSessionTokenValid(sessionToken) {
69
+            const sessionTokenIsValid =
70
+                await this.authenticator.validateSession(sessionToken)
71
+            if (sessionTokenIsValid.error) {
72
+                throw new Error(sessionTokenIsValid.error)
73
+            } else {
74
+                // TODO: Does accessToken need sessionToken data?
75
+                this.accessToken = await this.getAccessToken(this.sessionToken)
76
+            }
77
+        },
74 78
     },
75 79
 }
76 80
 </script>

Loading…
Peruuta
Tallenna