Procházet zdrojové kódy

:sparkles: renaming migrations | creating memberships and groupings

master
TOJ před 5 roky
rodič
revize
1f89954f6f

+ 1
- 1
backend/README.md Zobrazit soubor

@@ -35,7 +35,7 @@ Migrating tracks changes in schema. Migration steps are contained in the `./db/m
35 35
 Since we can't unseed the database, it's best to destroy the `dev` database and rebuild it.
36 36
 
37 37
 1. Stop the database by navigating to the project root directory `cd ../` and running `docker-compose down`
38
-2. Destroy the database volume `docker volume rm siimee_db`. BE CAREFUL.
38
+2. Destroy the database volume `docker volume rm siimee_siimee_db`. BE CAREFUL.
39 39
 3. Restart the database while still at the project root with `docker-compose --env-file ./backend/server/.env up -d`
40 40
 4. Recreate schemas and tables but navigating to `./backend` and running `npm run migrate`
41 41
 5. Reseed the dummy data with `npm run seed`

backend/db/migrations/20210527174434_create_memberships_table.js → backend/db/migrations/20210527174434_create_groupings_table.js Zobrazit soubor


backend/db/migrations/20210527174440_create_groupings_table.js → backend/db/migrations/20210527174440_create_memberships_table.js Zobrazit soubor


+ 3
- 1
backend/lib/models/grouping.js Zobrazit soubor

@@ -5,7 +5,9 @@ module.exports = class Grouping extends Schwifty.Model {
5 5
     static get tableName() { return 'groupings' }
6 6
     static get joiSchema() {
7 7
         return Joi.object({
8
-            grouping_id: Joi.number().required(),
8
+            grouping_id: Joi.number(),
9
+            grouping_name: Joi.string().required(),
10
+            grouping_type: Joi.string().required(),
9 11
         })
10 12
     }
11 13
 }

+ 5
- 1
backend/lib/models/membership.js Zobrazit soubor

@@ -5,7 +5,11 @@ module.exports = class Membership extends Schwifty.Model {
5 5
     static get tableName() { return 'memberships' }
6 6
     static get joiSchema() {
7 7
         return Joi.object({
8
-            membership_id: Joi.number().required(),
8
+            membership_id: Joi.number(),
9
+            user_id: Joi.number().required(),
10
+            grouping_id: Joi.number().allow(null),
11
+            membership_type: Joi.string().required(),
12
+            can_edit: Joi.boolean().required(),
9 13
         })
10 14
     }
11 15
 }

+ 34
- 3
backend/lib/routes/membership/join.js Zobrazit soubor

@@ -12,7 +12,13 @@ const pluginConfig = {
12 12
 
13 13
 const validators = {
14 14
     join: {
15
-        payload: Joi.object()
15
+        payload: Joi.object({
16
+            user_id: Joi.number().required(),
17
+            grouping_id: Joi.number().allow(null),
18
+            grouping_name: Joi.string().allow(null),
19
+            grouping_type: Joi.string().allow(null),
20
+            role: Joi.string(),
21
+        })
16 22
     }
17 23
 }
18 24
 
@@ -23,12 +29,37 @@ module.exports = {
23 29
         ...pluginConfig.docs,
24 30
         tags: ['api'],
25 31
         auth: false,
32
+
33
+        /**
34
+         * Join a grouping by creating a membership record
35
+         * @param {*} request
36
+         * @param {*} h
37
+         * @returns {object}
38
+         */
26 39
         handler: async function (request, h) {
27 40
             try {
41
+                const { membershipService } = request.services()
42
+
43
+                /** Grab payload info */
44
+                const res = request.payload
45
+                const groupingToWrite = {
46
+                    grouping_id: res.grouping_id,
47
+                    grouping_name: res.grouping_name,
48
+                    grouping_type: res.grouping_type
49
+                }
50
+                /** Check if the grouping exists and if NOT creat it */
51
+                const groupingId = await membershipService.findOrCreateGrouping(groupingToWrite)
52
+
53
+                /** Default to participant role */
54
+                const role = res.role ? res.role : 'participant'
55
+
56
+                /** User membership service method to create membership */
57
+                const membership = await membershipService.joinGrouping(res.user_id, groupingId, role)
58
+
28 59
                 return {
29 60
                     ok: true,
30 61
                     handler: pluginConfig.handlerType,
31
-                    data: { foo: 'bar' }
62
+                    data: { membership }
32 63
                 }
33 64
             }
34 65
             catch(err) {
@@ -44,7 +75,7 @@ module.exports = {
44 75
             schema: Joi.object({
45 76
                 ok: Joi.bool(),
46 77
                 handler: Joi.string(),
47
-                data: validators.join
78
+                data: Joi.object()
48 79
             }),
49 80
             failAction: 'log'
50 81
         }

+ 14
- 6
backend/lib/services/display.js Zobrazit soubor

@@ -8,24 +8,32 @@ module.exports = class DisplayService extends Schmervice.Service {
8 8
         return { ...user, token }
9 9
     }
10 10
 
11
+    /**
12
+     * List all memberships
13
+     * @returns
14
+     */
11 15
     membershipList() {
12 16
         const { Membership } = this.server.models()
13 17
         const memberships = Membership.query()
14 18
         server.log(Membership)
15
-        return [
16
-            { foo: 'bar', membership_type: 'baz' },
17
-            { foo: 'buz', membership_type: 'biz' },
18
-        ]
19
+        return memberships
19 20
     }
20 21
 
21
-    async profile(currentUserId, user, transaction)  {
22
+    /**
23
+     *
24
+     * @param {number} currentUserId
25
+     * @param {User} user
26
+     * @param {*} txn
27
+     * @returns
28
+     */
29
+    async profile(currentUserId, user, txn)  {
22 30
         const { User } = this.server.models()
23 31
         const { toProfile } = internals
24 32
 
25 33
         const result = await User.fetchGraph(user, `[
26 34
             followedBy(currentUser) as following
27 35
         ]`, {
28
-            transaction
36
+            txn
29 37
         }).modifiers({
30 38
             currentUser: (builder) => builder.where('Users.id', currentUserId)
31 39
         })

+ 99
- 12
backend/lib/services/membership.js Zobrazit soubor

@@ -2,27 +2,114 @@
2 2
 
3 3
 const Schmervice = require('@hapipal/schmervice');
4 4
 
5
+
5 6
 module.exports = class MembershipService extends Schmervice.Service {
6
-    constructor(...args) {
7
-        super(...args)
7
+    constructor(...args) { super(...args) }
8
+
9
+    /**
10
+     * Internal method to get list of grouping_ids for this user
11
+     * @param {number} userId
12
+     * @returns {Array} List of all grouping_ids for user
13
+     */
14
+    async _getGroupIdsForUserId(userId) {
15
+        const { Membership } = this.server.models()
16
+
17
+            /** Grab every Membership associated with this id */
18
+            const allMemberships = await Membership.query()
19
+                .where('user_id', userId)
20
+
21
+            /** Copy a list of the just the Groupings */
22
+            const groupingIdsToGrab = allMemberships.map(membership => membership.grouping_id)
23
+
24
+            /** Uncomment to dedupe the list just in case */
25
+            return [...new Set(groupingIdsToGrab)]
8 26
     }
9
-    async findGroupingsById(id) {
10
-        const { Membership, Grouping } = this.server.models()
11 27
 
12
-        /** Grab every Membership associated with this id */
13
-        const allMemberships = await Membership.query()
14
-            .throwIfNotFound()
15
-            .where('user_id', id)
28
+    /**
29
+     * Internal method to create a new grouping
30
+     * @param {*} groupingToTry
31
+     * @param {*} txn
32
+     * @returns
33
+     */
34
+    async _createGrouping(groupingToTry, txn) {
35
+        const { Grouping } = this.server.models()
36
+        const groupingInfo = {
37
+            grouping_name: groupingToTry.grouping_name,
38
+            grouping_type: groupingToTry.grouping_type,
39
+        }
40
+        return await Grouping.query(txn)
41
+            .insert(groupingInfo)
42
+    }
16 43
 
17
-        /** Copy a list of the just the Groupings */
18
-        const groupingIdsToGrab = allMemberships.map(membership => membership.grouping_id)
44
+    async findOrCreateGrouping(groupingToTry) {
45
+        let idToReturn = groupingToTry.grouping_id
46
+        if(!idToReturn) {
47
+            /** ?: For some reason this returns the key id */
48
+            const grouping = await this._createGrouping(groupingToTry)
49
+            idToReturn = grouping.id
50
+        }
51
+        return idToReturn
52
+    }
19 53
 
20
-        /** Uncomment to dedupe the list just in case */
21
-        const dedupedGroupings = [...new Set(groupingIdsToGrab)]
54
+    /**
55
+     * Get a list of groupings for user
56
+     * @param {number} userId
57
+     * @returns {Array}
58
+     */
59
+    async findGroupingsById(userId) {
60
+        const { Grouping } = this.server.models()
61
+
62
+        const dedupedGroupings = await this._getGroupIdsForUserId(userId)
22 63
 
23 64
         /** Grab just the Groupings this id has a Membership for */
24 65
         return await Grouping.query()
25 66
             .throwIfNotFound()
26 67
             .whereIn('grouping_id', dedupedGroupings)
27 68
     }
69
+
70
+    /**
71
+     * Check for grouping membership then add membership record
72
+     * @param {number} userId
73
+     * @param {number} groupingId
74
+     * @param {string} role
75
+     * @returns
76
+     */
77
+    async joinGrouping(userId, groupingId, role, txn) {
78
+        const { Membership } = this.server.models()
79
+
80
+        const dedupedGroupings = await this._getGroupIdsForUserId(userId)
81
+
82
+        /** Do NOTHING if already in Grouping */
83
+        if(dedupedGroupings.includes(groupingId)) return
84
+
85
+        console.log(dedupedGroupings)
86
+        const membershipInfo = {
87
+            user_id: userId,
88
+            grouping_id: groupingId,
89
+            membership_type: role,
90
+            can_edit: false
91
+        }
92
+        console.log(membershipInfo)
93
+        return await Membership.query(txn)
94
+            .insert(membershipInfo)
95
+    }
96
+
97
+    /**
98
+     * Remove membership record based on grouping_id
99
+     * @param {number} userId
100
+     * @param {number} groupingId
101
+     * @returns
102
+     */
103
+    async leaveGrouping(userId, groupingId) {
104
+        const { Membership } = this.server.models()
105
+
106
+        const dedupedGroupings = await this._getGroupIdsForUserId(userId)
107
+
108
+        /** Do NOTHING if NOT in Grouping */
109
+        if(!dedupedGroupings.includes(groupingId)) return
110
+
111
+        return await Membership.query()
112
+            .delete()
113
+            .where('grouping_id', groupingId)
114
+    }
28 115
 }

+ 1
- 2
backend/lib/services/user.js Zobrazit soubor

@@ -116,8 +116,7 @@ module.exports = class UserService extends Schmervice.Service {
116 116
             aud: 'urn:audience:test',
117 117
             iss: 'urn:issuer:test',
118 118
             email: user.user_email
119
-        },
120
-        {
119
+        }, {
121 120
             key: key,
122 121
             algorithm: 'HS256'
123 122
         }, {

+ 5
- 1
backend/server/index.js Zobrazit soubor

@@ -1,7 +1,11 @@
1 1
 const Glue = require('@hapi/glue');
2 2
 const Exiting = require('exiting');
3 3
 const Manifest = require('./manifest');
4
-
4
+/**
5
+ * Our main app server
6
+ * @param {boolean} start
7
+ * @returns {Server}
8
+ */
5 9
 exports.deployment = async ({ start } = {}) => {
6 10
     const manifest = Manifest.get('/', process.env)
7 11
     const server = await Glue.compose(manifest, { relativeTo: __dirname })

Načítá se…
Zrušit
Uložit