ソースを参照

:sparkles: renaming migrations | creating memberships and groupings

master
TOJ 5年前
コミット
1f89954f6f

+ 1
- 1
backend/README.md ファイルの表示

35
 Since we can't unseed the database, it's best to destroy the `dev` database and rebuild it.
35
 Since we can't unseed the database, it's best to destroy the `dev` database and rebuild it.
36
 
36
 
37
 1. Stop the database by navigating to the project root directory `cd ../` and running `docker-compose down`
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
 3. Restart the database while still at the project root with `docker-compose --env-file ./backend/server/.env up -d`
39
 3. Restart the database while still at the project root with `docker-compose --env-file ./backend/server/.env up -d`
40
 4. Recreate schemas and tables but navigating to `./backend` and running `npm run migrate`
40
 4. Recreate schemas and tables but navigating to `./backend` and running `npm run migrate`
41
 5. Reseed the dummy data with `npm run seed`
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 ファイルの表示


backend/db/migrations/20210527174440_create_groupings_table.js → backend/db/migrations/20210527174440_create_memberships_table.js ファイルの表示


+ 3
- 1
backend/lib/models/grouping.js ファイルの表示

5
     static get tableName() { return 'groupings' }
5
     static get tableName() { return 'groupings' }
6
     static get joiSchema() {
6
     static get joiSchema() {
7
         return Joi.object({
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 ファイルの表示

5
     static get tableName() { return 'memberships' }
5
     static get tableName() { return 'memberships' }
6
     static get joiSchema() {
6
     static get joiSchema() {
7
         return Joi.object({
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 ファイルの表示

12
 
12
 
13
 const validators = {
13
 const validators = {
14
     join: {
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
         ...pluginConfig.docs,
29
         ...pluginConfig.docs,
24
         tags: ['api'],
30
         tags: ['api'],
25
         auth: false,
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
         handler: async function (request, h) {
39
         handler: async function (request, h) {
27
             try {
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
                 return {
59
                 return {
29
                     ok: true,
60
                     ok: true,
30
                     handler: pluginConfig.handlerType,
61
                     handler: pluginConfig.handlerType,
31
-                    data: { foo: 'bar' }
62
+                    data: { membership }
32
                 }
63
                 }
33
             }
64
             }
34
             catch(err) {
65
             catch(err) {
44
             schema: Joi.object({
75
             schema: Joi.object({
45
                 ok: Joi.bool(),
76
                 ok: Joi.bool(),
46
                 handler: Joi.string(),
77
                 handler: Joi.string(),
47
-                data: validators.join
78
+                data: Joi.object()
48
             }),
79
             }),
49
             failAction: 'log'
80
             failAction: 'log'
50
         }
81
         }

+ 14
- 6
backend/lib/services/display.js ファイルの表示

8
         return { ...user, token }
8
         return { ...user, token }
9
     }
9
     }
10
 
10
 
11
+    /**
12
+     * List all memberships
13
+     * @returns
14
+     */
11
     membershipList() {
15
     membershipList() {
12
         const { Membership } = this.server.models()
16
         const { Membership } = this.server.models()
13
         const memberships = Membership.query()
17
         const memberships = Membership.query()
14
         server.log(Membership)
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
         const { User } = this.server.models()
30
         const { User } = this.server.models()
23
         const { toProfile } = internals
31
         const { toProfile } = internals
24
 
32
 
25
         const result = await User.fetchGraph(user, `[
33
         const result = await User.fetchGraph(user, `[
26
             followedBy(currentUser) as following
34
             followedBy(currentUser) as following
27
         ]`, {
35
         ]`, {
28
-            transaction
36
+            txn
29
         }).modifiers({
37
         }).modifiers({
30
             currentUser: (builder) => builder.where('Users.id', currentUserId)
38
             currentUser: (builder) => builder.where('Users.id', currentUserId)
31
         })
39
         })

+ 99
- 12
backend/lib/services/membership.js ファイルの表示

2
 
2
 
3
 const Schmervice = require('@hapipal/schmervice');
3
 const Schmervice = require('@hapipal/schmervice');
4
 
4
 
5
+
5
 module.exports = class MembershipService extends Schmervice.Service {
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
         /** Grab just the Groupings this id has a Membership for */
64
         /** Grab just the Groupings this id has a Membership for */
24
         return await Grouping.query()
65
         return await Grouping.query()
25
             .throwIfNotFound()
66
             .throwIfNotFound()
26
             .whereIn('grouping_id', dedupedGroupings)
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 ファイルの表示

116
             aud: 'urn:audience:test',
116
             aud: 'urn:audience:test',
117
             iss: 'urn:issuer:test',
117
             iss: 'urn:issuer:test',
118
             email: user.user_email
118
             email: user.user_email
119
-        },
120
-        {
119
+        }, {
121
             key: key,
120
             key: key,
122
             algorithm: 'HS256'
121
             algorithm: 'HS256'
123
         }, {
122
         }, {

+ 5
- 1
backend/server/index.js ファイルの表示

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

読み込み中…
キャンセル
保存