Bladeren bron

:recycle: fixing login form | returning profiles for user from api | logging in before setting profile_id

jwt
j 3 jaren geleden
bovenliggende
commit
c6b060a8ad

+ 18
- 10
backend/lib/routes/user/login.js Bestand weergeven

45
         ...pluginConfig.opts,
45
         ...pluginConfig.opts,
46
         handler: async function (request, h) {
46
         handler: async function (request, h) {
47
             try {
47
             try {
48
-                const { userService } = request.services()
48
+                const { userService, profileService } =
49
+                    request.server.services()
49
                 const res = request.payload
50
                 const res = request.payload
50
-
51
                 // Callback to use as transaction
51
                 // Callback to use as transaction
52
                 const login = async txn => {
52
                 const login = async txn => {
53
                     return await userService.login(
53
                     return await userService.login(
60
                 }
60
                 }
61
 
61
 
62
                 // Bound context from your plugin server declaration
62
                 // Bound context from your plugin server declaration
63
-                const user = await h.context.transaction(login)
64
-
65
-                const token = userService.createToken(user)
66
-
63
+                const userAuth = await h.context.transaction(login)
64
+                const token = userService.createToken(userAuth)
67
                 const response = h.response('success')
65
                 const response = h.response('success')
68
-                console.log('response :>> ', response)
69
-                response.header('Authorization', token)
70
-                response.state('token', token, pluginConfig.cookieOpts)
66
+
67
+                const email = userAuth.user_email
68
+                const user = await userService.findByEmail(email)
69
+                const type = user.is_poster == 1 ? 'poster' : 'seeker'
70
+                const profiles = await profileService.getCompleteProfilesFor(
71
+                    user.user_id,
72
+                    type,
73
+                )
71
                 return {
74
                 return {
72
                     ok: true,
75
                     ok: true,
73
                     handler: pluginConfig.handlerType,
76
                     handler: pluginConfig.handlerType,
74
-                    data: { user_email: user.user_email, jwtToken: token },
77
+                    data: {
78
+                        profiles,
79
+                        user_email: user.user_email,
80
+                        jwtToken: token,
81
+                    },
75
                 }
82
                 }
76
             } catch (err) {
83
             } catch (err) {
77
                 console.error(err)
84
                 console.error(err)
91
                     data: Joi.object({
98
                     data: Joi.object({
92
                         user_email: Joi.string(),
99
                         user_email: Joi.string(),
93
                         jwtToken: Joi.string(),
100
                         jwtToken: Joi.string(),
101
+                        profiles: Joi.array(),
94
                     }),
102
                     }),
95
                 }).label('login_res'),
103
                 }).label('login_res'),
96
                 409: Joi.object({
104
                 409: Joi.object({

+ 3
- 3
backend/lib/services/profile/index.js Bestand weergeven

71
     async getCompleteProfilesFor(userId, type) {
71
     async getCompleteProfilesFor(userId, type) {
72
         const { Profile } = this.server.models()
72
         const { Profile } = this.server.models()
73
         await this._setTagLookup()
73
         await this._setTagLookup()
74
-
74
+        console.log('userId :>> ', userId)
75
         const dedupedProfileIds = await this._getProfileIdsForUserId(userId)
75
         const dedupedProfileIds = await this._getProfileIdsForUserId(userId)
76
 
76
 
77
         const profilesEntries = await Profile.query()
77
         const profilesEntries = await Profile.query()
357
         await this._setTagLookup()
357
         await this._setTagLookup()
358
         let associations = groupingId
358
         let associations = groupingId
359
             ? await TagAssociation.query()
359
             ? await TagAssociation.query()
360
-                .where('grouping_id', groupingId)
361
-                .andWhere('profile_id', profileId)
360
+                  .where('grouping_id', groupingId)
361
+                  .andWhere('profile_id', profileId)
362
             : await TagAssociation.query().andWhere('profile_id', profileId)
362
             : await TagAssociation.query().andWhere('profile_id', profileId)
363
         return associations
363
         return associations
364
             .map(assoc => ({
364
             .map(assoc => ({

+ 15
- 1
backend/lib/services/user.js Bestand weergeven

20
         }
20
         }
21
     }
21
     }
22
 
22
 
23
+    /**
24
+     * Use knex to find users with email column
25
+     * @param {string} email
26
+     * @param {*} txn
27
+     * @returns
28
+     */
29
+    async findByEmail(email) {
30
+        const { User } = this.server.models()
31
+
32
+        return await User.query()
33
+            .throwIfNotFound()
34
+            .first()
35
+            .where({ user_email: email })
36
+    }
37
+
23
     /**
38
     /**
24
      * Use knex to find users with id column
39
      * Use knex to find users with id column
25
      * @param {number} id
40
      * @param {number} id
117
      */
132
      */
118
     async login({ email, password }, txn) {
133
     async login({ email, password }, txn) {
119
         const { User, Auth } = this.server.models()
134
         const { User, Auth } = this.server.models()
120
-
121
         const user = await Auth.query(txn)
135
         const user = await Auth.query(txn)
122
             .throwIfNotFound()
136
             .throwIfNotFound()
123
             .first()
137
             .first()

+ 8395
- 10
backend/package-lock.json
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 27
- 7
frontend/src/App.vue Bestand weergeven

1
 <template lang="pug">
1
 <template lang="pug">
2
-w-app 
2
+w-app
3
     TopNav(@on-open='openDrawer = !openDrawer')
3
     TopNav(@on-open='openDrawer = !openDrawer')
4
 
4
 
5
     w-drawer(v-model='openDrawer')
5
     w-drawer(v-model='openDrawer')
40
          * using the login form
40
          * using the login form
41
          */
41
          */
42
         if (DEV_MODE) {
42
         if (DEV_MODE) {
43
+            this.autoLogin()
44
+        }
45
+    },
46
+    methods: {
47
+        async autoLogin() {
43
             console.info('===============================================')
48
             console.info('===============================================')
44
             console.info('-                   SIIMEE                    -')
49
             console.info('-                   SIIMEE                    -')
45
             console.info('-----------------------------------------------')
50
             console.info('-----------------------------------------------')
47
             console.info('[Siimee App]: Starting application...')
52
             console.info('[Siimee App]: Starting application...')
48
             console.info('-----------------------------------------------')
53
             console.info('-----------------------------------------------')
49
             await this.setPid(DEV_PID)
54
             await this.setPid(DEV_PID)
50
-        }
51
-    },
52
-    methods: {
55
+        },
53
         /**
56
         /**
54
          * Sync up this components state with
57
          * Sync up this components state with
55
          * the currentProfile handler
58
          * the currentProfile handler
56
          */
59
          */
57
-        async setPid(profileId) {
60
+        async setPid(form) {
58
             if (currentProfile.isLoggedIn) {
61
             if (currentProfile.isLoggedIn) {
59
                 currentProfile.logout()
62
                 currentProfile.logout()
60
             }
63
             }
61
 
64
 
62
-            await currentProfile.login(profileId, this.$waveui.notify)
63
             console.log('---')
65
             console.log('---')
66
+            const { profiles } = await currentProfile.login(
67
+                form.email,
68
+                form.password,
69
+            )
64
 
70
 
65
             /**
71
             /**
66
              * Default to the HomeView and alter as needed (side-effects!)
72
              * Default to the HomeView and alter as needed (side-effects!)
67
              */
73
              */
68
-            const toRoute = { name: 'HomeView' }
74
+            let toRoute = { name: 'HomeView' }
75
+
76
+            if (profiles.length) {
77
+                const profile = profiles[0]
78
+                await currentProfile.setup(
79
+                    profile.profile_id,
80
+                    this.$waveui.notify,
81
+                )
82
+            } else {
83
+                console.warn(
84
+                    `[Login] No profiles associated with ${form.email}`,
85
+                )
86
+                toRoute = { name: 'OnboardingView' }
87
+            }
88
+
69
             this.$router.push(toRoute)
89
             this.$router.push(toRoute)
70
         },
90
         },
71
     },
91
     },

+ 1
- 1
frontend/src/entities/survey/survey.js Bestand weergeven

35
         /**  Fields */
35
         /**  Fields */
36
         this.steps = [...questionSteps] // ! required
36
         this.steps = [...questionSteps] // ! required
37
         this.aspectQuestions = _formatAspectQuestions(this.steps)
37
         this.aspectQuestions = _formatAspectQuestions(this.steps)
38
-        console.log('this.aspectQuestions: ', JSON.stringify(this.aspectQuestions))
38
+        // console.log('this.aspectQuestions: ', JSON.stringify(this.aspectQuestions))
39
     }
39
     }
40
 
40
 
41
     isValid() {
41
     isValid() {

+ 7
- 7
frontend/src/router/guards.js Bestand weergeven

2
 
2
 
3
 const DEV_MODE = import.meta.env.VITE_DEV == 'true'
3
 const DEV_MODE = import.meta.env.VITE_DEV == 'true'
4
 
4
 
5
-async function log(to) {
5
+const log = async to => {
6
     if (DEV_MODE) {
6
     if (DEV_MODE) {
7
         if (!currentProfile.isLoggedIn || !currentProfile.isComplete) {
7
         if (!currentProfile.isLoggedIn || !currentProfile.isComplete) {
8
             console.info(
8
             console.info(
17
     log(destination)
17
     log(destination)
18
     if (DEV_MODE) {
18
     if (DEV_MODE) {
19
         nextCb()
19
         nextCb()
20
-    } else if (
21
-        destination.meta.requiresCompleteProfile &&
22
-        !currentProfile.isLoggedIn &&
23
-        !currentProfile.isComplete
24
-    ) {
25
-        nextCb('onboarding')
26
     } else if (
20
     } else if (
27
         destination.meta.requiresCompleteProfile &&
21
         destination.meta.requiresCompleteProfile &&
28
         destination.meta.requiresAuth &&
22
         destination.meta.requiresAuth &&
29
         !currentProfile.isLoggedIn
23
         !currentProfile.isLoggedIn
30
     ) {
24
     ) {
31
         nextCb('login')
25
         nextCb('login')
26
+    } else if (
27
+        destination.meta.requiresCompleteProfile &&
28
+        !currentProfile.isLoggedIn &&
29
+        !currentProfile.isComplete
30
+    ) {
31
+        nextCb('onboarding')
32
     } else {
32
     } else {
33
         nextCb()
33
         nextCb()
34
     }
34
     }

+ 11
- 4
frontend/src/services/login.service.js Bestand weergeven

7
     fetchProfileByProfileId,
7
     fetchProfileByProfileId,
8
     Chatter,
8
     Chatter,
9
     StonkAlert,
9
     StonkAlert,
10
+    loginUser,
10
 } from '../services/index.js'
11
 } from '../services/index.js'
11
 import { surveyFactory } from '../utils/index.js'
12
 import { surveyFactory } from '../utils/index.js'
12
 
13
 
76
      * @param {number} profileId
77
      * @param {number} profileId
77
      * @returns {number} stored reactive id
78
      * @returns {number} stored reactive id
78
      */
79
      */
79
-    async login(profileId, cb) {
80
-        this._loading.value = true
80
+    async login(email, password) {
81
         // First check if profile exists
81
         // First check if profile exists
82
-        console.warn('[Login Service warn]: Logging in:', profileId)
83
-
82
+        console.warn('[Login Service warn]: Logging in:', email)
83
+        const res = await loginUser({ email, password })
84
+        if (res) {
85
+            console.warn(`[Login Service warn] Logging in: Succeeded!`)
86
+        }
87
+        return res
88
+    }
89
+    async setup(profileId, cb) {
84
         // TODO: You can probably use this call to get responses, groupings and tags
90
         // TODO: You can probably use this call to get responses, groupings and tags
91
+        this._loading.value = true
85
         this._profile = await fetchProfileByProfileId(profileId)
92
         this._profile = await fetchProfileByProfileId(profileId)
86
         this.id.value = this._profile.profile_id
93
         this.id.value = this._profile.profile_id
87
 
94
 

+ 6
- 2
frontend/src/services/user.service.js Bestand weergeven

1
 import { db } from '../utils/db.js'
1
 import { db } from '../utils/db.js'
2
+const SERVICE = 'user'
2
 
3
 
3
 /**
4
 /**
4
  * Signup a new user
5
  * Signup a new user
10
         user_email: user.email,
11
         user_email: user.email,
11
         is_poster: user.seeking == 'position' ? 0 : 1,
12
         is_poster: user.seeking == 'position' ? 0 : 1,
12
     }
13
     }
13
-    return await db.post(`/user/signup`, payload)
14
+    return await db.post(`/${SERVICE}/signup`, payload)
14
 }
15
 }
15
 
16
 
16
-export { signupUser }
17
+const loginUser = async ({ email, password }) => {
18
+    return await db.post(`/${SERVICE}/login`, { user_email: email, password })
19
+}
20
+export { signupUser, loginUser }

+ 9
- 1
frontend/src/utils/db.js Bestand weergeven

1
 const domain = 'localhost'
1
 const domain = 'localhost'
2
+const gui_port = 3000
2
 const port = 3001
3
 const port = 3001
3
 const httpProtocol = `http`
4
 const httpProtocol = `http`
4
 const prefix = 'api'
5
 const prefix = 'api'
5
-const remote = `${httpProtocol}://${domain}:${port}/${prefix}`
6
+const backend_host = `${domain}:${port}`
7
+const host = `${domain}:${gui_port}`
8
+const origin = `${httpProtocol}://${host}/`
9
+const remote = `${httpProtocol}://${backend_host}/${prefix}`
10
+const referrer = origin
6
 
11
 
7
 const headerTemplate = {
12
 const headerTemplate = {
8
     method: null,
13
     method: null,
14
         // 'Content-Type': 'application/x-www-form-urlencoded',
19
         // 'Content-Type': 'application/x-www-form-urlencoded',
15
     },
20
     },
16
     redirect: 'manual', // manual, *follow, error
21
     redirect: 'manual', // manual, *follow, error
22
+    host,
23
+    origin,
24
+    referrer,
17
     referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
25
     referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
18
     body: null, // body data type must match "Content-Type" header
26
     body: null, // body data type must match "Content-Type" header
19
 }
27
 }

+ 6
- 4
frontend/src/utils/survey.js Bestand weergeven

18
     image: 'FormInput',
18
     image: 'FormInput',
19
     // distance: 'FormInput',
19
     // distance: 'FormInput',
20
     blurb: 'FormInput',
20
     blurb: 'FormInput',
21
-    aspects: 'Aspects'
21
+    aspects: 'Aspects',
22
 }
22
 }
23
 /**
23
 /**
24
  * Make a step from match or step information
24
  * Make a step from match or step information
63
             }
63
             }
64
             const responseKeyLike = formatStep(match, step)
64
             const responseKeyLike = formatStep(match, step)
65
             const withComponent = associateWithComponent(responseKeyLike)
65
             const withComponent = associateWithComponent(responseKeyLike)
66
-            console.log('withComponent :>> ', withComponent)
66
+            // console.log('withComponent :>> ', withComponent)
67
             return withComponent
67
             return withComponent
68
         })
68
         })
69
-        // temporary extra condition in filter 
69
+        // temporary extra condition in filter
70
         let unseen = this.questionsFromDb.filter(
70
         let unseen = this.questionsFromDb.filter(
71
-            q => !seenIds.includes(q.response_key_id) && [1,2,3,4,5,6].includes(q.response_key_id),
71
+            q =>
72
+                !seenIds.includes(q.response_key_id) &&
73
+                [1, 2, 3, 4, 5, 6].includes(q.response_key_id),
72
         )
74
         )
73
         return [...stepsInCommon, ...unseen]
75
         return [...stepsInCommon, ...unseen]
74
     }
76
     }

+ 20
- 5
frontend/src/views/LoginView.vue Bestand weergeven

1
 <template lang="pug">
1
 <template lang="pug">
2
 main.view--login
2
 main.view--login
3
-
4
     article.pa12
3
     article.pa12
5
         form
4
         form
6
-            w-input.mb4(label="User E-mail" tile outline v-model="form.profileId" inner-icon-left='icon-envelope')
7
-            w-input(label="Password" type="password" tile outline inner-icon-left='icon-eye')
5
+            w-input.mb4(
6
+                inner-icon-left='icon-envelope'
7
+                label='User E-mail'
8
+                outline
9
+                tile
10
+                v-model='form.email'
11
+            )
12
+            w-input(
13
+                inner-icon-left='icon-eye'
14
+                label='Password'
15
+                outline
16
+                tile
17
+                v-model='form.password'
18
+            )
8
 
19
 
9
             //- Emit up an event so we can sync App pid with currentProfile.id
20
             //- Emit up an event so we can sync App pid with currentProfile.id
10
-            w-button.xs12.mt12(@click="$emit('updatePid', form.profileId)" type="submit") submit
21
+            w-button.xs12.mt12(
22
+                @click.prevent.stop='$emit("updatePid", form)'
23
+                type='submit'
24
+            ) submit
11
 </template>
25
 </template>
12
 
26
 
13
 <script>
27
 <script>
14
 export default {
28
 export default {
15
     data: () => ({
29
     data: () => ({
16
         form: {
30
         form: {
17
-            profileId: null,
31
+            email: null,
32
+            password: null,
18
         },
33
         },
19
     }),
34
     }),
20
 }
35
 }

Laden…
Annuleren
Opslaan