From f5899e9340825a0671b9dee1c8ac898ae611e06e Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Mon, 20 Jul 2020 21:08:59 -0400 Subject: [PATCH 01/19] #26 Add Group PATCH --- src/pages/api/group/[id].js | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/pages/api/group/[id].js b/src/pages/api/group/[id].js index c47cc729..bf6a4965 100644 --- a/src/pages/api/group/[id].js +++ b/src/pages/api/group/[id].js @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ import nc from 'next-connect'; import { ObjectID } from 'mongodb'; import middleware from '../../../middlewares/middleware'; @@ -32,6 +33,38 @@ const handler = nc() } }, ); + .patch( + async (req, res) => { + const token = await jwt.getJwt({ req, secret }); + if (token && token.exp > 0) { + const memberQuery = (process.env.NODE_ENV === 'development') ? [{ members: ObjectID(token.user.id) }, { members: getObjectId('FakeUserReplaceMe') }] : [{ members: ObjectID(token.user.id) }]; + const fieldsToSet = req.body.name ? { name: req.body.name } : {}; + const membersToPush = req.body.addedUserId ? { members: ObjectID(req.body.addedUserId) } : {}; + const membersToPull = req.body.removedUserId ? { members: ObjectID(req.body.removedUserId) } : {}; + await req.db + .collection('groups') + .findOneAndUpdate( + { + _id: ObjectID(req.query.id), + $or: memberQuery, + }, + { + $set: fieldsToSet, + $push: membersToPush, + $pull: membersToPull, + $currentDate: { + updatedAt: true, + }, + }, + { + returnOriginal: false, + }, + (err, doc) => { + if (err) throw err; + res.status(200).json(doc); + }, + ); + } else res.status(403).json({ error: '403 Invalid or expired token' }); }, ); From 1a4cd3f19e9522ab553bf97367448fb3f9cbff16 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 21 Jul 2020 12:30:10 -0400 Subject: [PATCH 02/19] #26 fix line lengths --- src/pages/api/group/[id].js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/pages/api/group/[id].js b/src/pages/api/group/[id].js index 6ec10c7b..c6a2d0db 100644 --- a/src/pages/api/group/[id].js +++ b/src/pages/api/group/[id].js @@ -1,5 +1,5 @@ -/* eslint-disable max-len */ import nc from 'next-connect'; +import { getObjectId } from 'mongo-seeding'; import { ObjectID } from 'mongodb'; import jwt from 'next-auth/jwt'; import middleware from '../../../middlewares/middleware'; @@ -39,16 +39,25 @@ const handler = nc() } else { res.status(404).json({ error: '404 Not Found' }); } - }, - ) + }, + ); + } + }, + ) .patch( async (req, res) => { const token = await jwt.getJwt({ req, secret }); if (token && token.exp > 0) { - const memberQuery = (process.env.NODE_ENV === 'development') ? [{ members: ObjectID(token.user.id) }, { members: getObjectId('FakeUserReplaceMe') }] : [{ members: ObjectID(token.user.id) }]; + const memberQuery = (process.env.NODE_ENV === 'development') + ? [{ members: ObjectID(token.user.id) }, { members: getObjectId('FakeUserReplaceMe') }] + : [{ members: ObjectID(token.user.id) }]; const fieldsToSet = req.body.name ? { name: req.body.name } : {}; - const membersToPush = req.body.addedUserId ? { members: ObjectID(req.body.addedUserId) } : {}; - const membersToPull = req.body.removedUserId ? { members: ObjectID(req.body.removedUserId) } : {}; + const membersToPush = req.body.addedUserId + ? { members: ObjectID(req.body.addedUserId) } + : {}; + const membersToPull = req.body.removedUserId + ? { members: ObjectID(req.body.removedUserId) } + : {}; await req.db .collection('groups') .findOneAndUpdate( From 315f200cd8725985211774e2e7c9b0916f748958 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 21 Jul 2020 20:00:43 -0400 Subject: [PATCH 03/19] #26 update eslint to ES9 to support spread operator --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 615d50ee..9016cce4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,7 +2,7 @@ "extends": ["airbnb", "plugin:testing-library/react"], "plugins": ["jest","testing-library"], "parserOptions": { - "ecmaVersion": 8, + "ecmaVersion": 9, "sourceType": "module", "ecmaFeatures": { "jsx": true From 50e3e52d9dceda5c580ba1c8dd629e7aa4e6bdef Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 21 Jul 2020 20:07:47 -0400 Subject: [PATCH 04/19] #26 update seeds with embedded docs (#2) --- src/seeds/1-groups/groups.js | 13 +++++++++++-- src/seeds/2-documents/documents.js | 9 ++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/seeds/1-groups/groups.js b/src/seeds/1-groups/groups.js index 535b83e3..e31bd52f 100644 --- a/src/seeds/1-groups/groups.js +++ b/src/seeds/1-groups/groups.js @@ -8,8 +8,17 @@ const dateCreated = new Date(Date.now()); const group = { id: getObjectId(name), name, - members: [getObjectId('FakeUserReplaceMe')], - documents: [getObjectId(docTitle)], + members: [{ + id: getObjectId('FakeUserReplaceMe'), + name: 'Fake User', + email: 'fake.user@email.com', + role: 'owner', + }], + documents: [{ + id: getObjectId(docTitle), + name: docTitle, + slug: 'afterward', + }], createdAt: dateCreated, updatedAt: dateCreated, }; diff --git a/src/seeds/2-documents/documents.js b/src/seeds/2-documents/documents.js index 3b3797dc..644aaa36 100644 --- a/src/seeds/2-documents/documents.js +++ b/src/seeds/2-documents/documents.js @@ -13,7 +13,14 @@ const documents = [{ title, slug: 'afterward', owner: getObjectId('FakeUserReplaceMe'), - groups: [getObjectId(groupName)], + groups: [{ + id: getObjectId(groupName), + name: groupName, + members: [{ + id: getObjectId('FakeUserReplaceMe'), + name: 'Fake User', + }], + }], resourceType: 'Book Section', authors: ['Edith Wharton'], publisher: '(MacMillan and Co.) Project Gutenberg', From 1493a51024bd8578ccd4344a0594d523293be6c8 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 21 Jul 2020 20:51:18 -0400 Subject: [PATCH 05/19] #26 logic for handling various PATCH operations --- src/pages/api/group/[id].js | 42 ++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/pages/api/group/[id].js b/src/pages/api/group/[id].js index c6a2d0db..844a958c 100644 --- a/src/pages/api/group/[id].js +++ b/src/pages/api/group/[id].js @@ -1,10 +1,10 @@ import nc from 'next-connect'; -import { getObjectId } from 'mongo-seeding'; import { ObjectID } from 'mongodb'; import jwt from 'next-auth/jwt'; import middleware from '../../../middlewares/middleware'; const secret = process.env.AUTH_SECRET; +const fakeUserID = ObjectID('7b639ae33efb36eaf6447c55'); const handler = nc() .use(middleware) @@ -17,7 +17,7 @@ const handler = nc() .findOne( { _id: ObjectID(req.query.id), - members: token.user.id, + 'members.id': token.user.id, }, (err, doc) => { if (doc) { @@ -49,14 +49,31 @@ const handler = nc() const token = await jwt.getJwt({ req, secret }); if (token && token.exp > 0) { const memberQuery = (process.env.NODE_ENV === 'development') - ? [{ members: ObjectID(token.user.id) }, { members: getObjectId('FakeUserReplaceMe') }] - : [{ members: ObjectID(token.user.id) }]; - const fieldsToSet = req.body.name ? { name: req.body.name } : {}; - const membersToPush = req.body.addedUserId - ? { members: ObjectID(req.body.addedUserId) } + ? [{ 'members.id': ObjectID(token.user.id) }, { 'members.id': fakeUserID }] + : [{ 'members.id': ObjectID(token.user.id) }]; + const nameToUpdate = req.body.name + ? { name: req.body.name } : {}; - const membersToPull = req.body.removedUserId - ? { members: ObjectID(req.body.removedUserId) } + let documentToUpdate = {}; + let documentByID = {}; + if (req.body.updatedDocument) { + documentByID = { 'documents.id': req.body.updatedDocument.id }; + documentToUpdate = { + 'documents.$.slug': req.body.updatedDocument.slug, + 'documents.$.name': req.body.updatedDocument.name, + }; + } + const memberToPush = req.body.addedUser + ? { members: req.body.addedUser } + : {}; + const documentToPush = req.body.addedDoc + ? { documents: req.body.addedDoc } + : {}; + const memberToPull = req.body.removedUserID + ? { 'members.id': ObjectID(req.body.removedUserID) } + : {}; + const documentToPull = req.body.removedDocumentID + ? { 'documents.id': ObjectID(req.body.removedDocumentID) } : {}; await req.db .collection('groups') @@ -64,11 +81,12 @@ const handler = nc() { _id: ObjectID(req.query.id), $or: memberQuery, + ...documentByID, }, { - $set: fieldsToSet, - $push: membersToPush, - $pull: membersToPull, + $set: { ...nameToUpdate, ...documentToUpdate }, + $push: { ...memberToPush, ...documentToPush }, + $pull: { ...memberToPull, ...documentToPull }, $currentDate: { updatedAt: true, }, From 3d712a67532d06c644f63fe455b2d0492c2d2780 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 10:19:22 -0400 Subject: [PATCH 06/19] #26 secure document API route by group membership, Fixes #24 --- src/pages/api/document/[id].js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/api/document/[id].js b/src/pages/api/document/[id].js index 468ae51f..5b78cc26 100644 --- a/src/pages/api/document/[id].js +++ b/src/pages/api/document/[id].js @@ -14,7 +14,10 @@ const handler = nc() await req.db .collection('documents') .findOne( - { _id: ObjectID(req.query.id) }, + { + _id: ObjectID(req.query.id), + 'groups.members.id': ObjectID(token.user.id), + }, (err, doc) => { if (doc) { const { From ecc1f14439cc3e24aac8f828f5ccc9a497b9101d Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 10:24:47 -0400 Subject: [PATCH 07/19] #26 Wrap ID queries in ObjectID function --- src/pages/api/group/[id].js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/api/group/[id].js b/src/pages/api/group/[id].js index 844a958c..a82e9be8 100644 --- a/src/pages/api/group/[id].js +++ b/src/pages/api/group/[id].js @@ -17,7 +17,7 @@ const handler = nc() .findOne( { _id: ObjectID(req.query.id), - 'members.id': token.user.id, + 'members.id': ObjectID(token.user.id), }, (err, doc) => { if (doc) { @@ -57,7 +57,7 @@ const handler = nc() let documentToUpdate = {}; let documentByID = {}; if (req.body.updatedDocument) { - documentByID = { 'documents.id': req.body.updatedDocument.id }; + documentByID = { 'documents.id': ObjectID(req.body.updatedDocument.id) }; documentToUpdate = { 'documents.$.slug': req.body.updatedDocument.slug, 'documents.$.name': req.body.updatedDocument.name, From 6424a18ee5771314327ed6753d69d1814350e599 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 12:04:02 -0400 Subject: [PATCH 08/19] #26 Add Group POST route --- src/pages/api/group/index.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/pages/api/group/index.js diff --git a/src/pages/api/group/index.js b/src/pages/api/group/index.js new file mode 100644 index 00000000..2a2381da --- /dev/null +++ b/src/pages/api/group/index.js @@ -0,0 +1,35 @@ +import nc from 'next-connect'; +import { ObjectID } from 'mongodb'; +import jwt from 'next-auth/jwt'; +import middleware from '../../../middlewares/middleware'; + +const secret = process.env.AUTH_SECRET; + +const handler = nc() + .use(middleware) + .post( + async (req, res) => { + const token = await jwt.getJwt({ req, secret }); + if (token && token.exp > 0) { + const { name } = req.body; + const members = [{ + id: ObjectID(token.user.id), + name: token.user.name, + email: token.user.email, + role: 'owner', + }]; + const documents = [{}]; + await req.db + .collection('groups') + .insertOne( + { name, members, documents }, + (err, doc) => { + if (err) throw err; + res.status(200).json(doc); + }, + ); + } else res.status(403).json({ error: '403 Invalid or expired token' }); + }, + ); + +export default handler; From 498fadc577196c9aca1eff2d2f1e5602fd51aed3 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 21 Jul 2020 20:00:43 -0400 Subject: [PATCH 09/19] #26 update eslint to ES9 to support spread operator --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index 615d50ee..9016cce4 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,7 +2,7 @@ "extends": ["airbnb", "plugin:testing-library/react"], "plugins": ["jest","testing-library"], "parserOptions": { - "ecmaVersion": 8, + "ecmaVersion": 9, "sourceType": "module", "ecmaFeatures": { "jsx": true From a260455b15d4fb2152de534e03638daf3942b345 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 21 Jul 2020 20:07:47 -0400 Subject: [PATCH 10/19] #26 update seeds with embedded docs (#2) --- src/seeds/1-groups/groups.js | 13 +++++++++++-- src/seeds/2-documents/documents.js | 9 ++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/seeds/1-groups/groups.js b/src/seeds/1-groups/groups.js index 535b83e3..e31bd52f 100644 --- a/src/seeds/1-groups/groups.js +++ b/src/seeds/1-groups/groups.js @@ -8,8 +8,17 @@ const dateCreated = new Date(Date.now()); const group = { id: getObjectId(name), name, - members: [getObjectId('FakeUserReplaceMe')], - documents: [getObjectId(docTitle)], + members: [{ + id: getObjectId('FakeUserReplaceMe'), + name: 'Fake User', + email: 'fake.user@email.com', + role: 'owner', + }], + documents: [{ + id: getObjectId(docTitle), + name: docTitle, + slug: 'afterward', + }], createdAt: dateCreated, updatedAt: dateCreated, }; diff --git a/src/seeds/2-documents/documents.js b/src/seeds/2-documents/documents.js index 3b3797dc..644aaa36 100644 --- a/src/seeds/2-documents/documents.js +++ b/src/seeds/2-documents/documents.js @@ -13,7 +13,14 @@ const documents = [{ title, slug: 'afterward', owner: getObjectId('FakeUserReplaceMe'), - groups: [getObjectId(groupName)], + groups: [{ + id: getObjectId(groupName), + name: groupName, + members: [{ + id: getObjectId('FakeUserReplaceMe'), + name: 'Fake User', + }], + }], resourceType: 'Book Section', authors: ['Edith Wharton'], publisher: '(MacMillan and Co.) Project Gutenberg', From 2bd3dc31483f682318d01f208cb3c45fdc79dc2c Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Tue, 21 Jul 2020 20:51:18 -0400 Subject: [PATCH 11/19] #26 logic for handling various PATCH operations --- src/pages/api/group/[id].js | 41 +++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src/pages/api/group/[id].js b/src/pages/api/group/[id].js index 6ec10c7b..2972a622 100644 --- a/src/pages/api/group/[id].js +++ b/src/pages/api/group/[id].js @@ -5,6 +5,7 @@ import jwt from 'next-auth/jwt'; import middleware from '../../../middlewares/middleware'; const secret = process.env.AUTH_SECRET; +const fakeUserID = ObjectID('7b639ae33efb36eaf6447c55'); const handler = nc() .use(middleware) @@ -17,7 +18,7 @@ const handler = nc() .findOne( { _id: ObjectID(req.query.id), - members: token.user.id, + 'members.id': token.user.id, }, (err, doc) => { if (doc) { @@ -45,21 +46,45 @@ const handler = nc() async (req, res) => { const token = await jwt.getJwt({ req, secret }); if (token && token.exp > 0) { - const memberQuery = (process.env.NODE_ENV === 'development') ? [{ members: ObjectID(token.user.id) }, { members: getObjectId('FakeUserReplaceMe') }] : [{ members: ObjectID(token.user.id) }]; - const fieldsToSet = req.body.name ? { name: req.body.name } : {}; - const membersToPush = req.body.addedUserId ? { members: ObjectID(req.body.addedUserId) } : {}; - const membersToPull = req.body.removedUserId ? { members: ObjectID(req.body.removedUserId) } : {}; + const memberQuery = (process.env.NODE_ENV === 'development') + ? [{ 'members.id': ObjectID(token.user.id) }, { 'members.id': fakeUserID }] + : [{ 'members.id': ObjectID(token.user.id) }]; + const nameToUpdate = req.body.name + ? { name: req.body.name } + : {}; + let documentToUpdate = {}; + let documentByID = {}; + if (req.body.updatedDocument) { + documentByID = { 'documents.id': req.body.updatedDocument.id }; + documentToUpdate = { + 'documents.$.slug': req.body.updatedDocument.slug, + 'documents.$.name': req.body.updatedDocument.name, + }; + } + const memberToPush = req.body.addedUser + ? { members: req.body.addedUser } + : {}; + const documentToPush = req.body.addedDoc + ? { documents: req.body.addedDoc } + : {}; + const memberToPull = req.body.removedUserID + ? { 'members.id': ObjectID(req.body.removedUserID) } + : {}; + const documentToPull = req.body.removedDocumentID + ? { 'documents.id': ObjectID(req.body.removedDocumentID) } + : {}; await req.db .collection('groups') .findOneAndUpdate( { _id: ObjectID(req.query.id), $or: memberQuery, + ...documentByID, }, { - $set: fieldsToSet, - $push: membersToPush, - $pull: membersToPull, + $set: { ...nameToUpdate, ...documentToUpdate }, + $push: { ...memberToPush, ...documentToPush }, + $pull: { ...memberToPull, ...documentToPull }, $currentDate: { updatedAt: true, }, From 1fcfe9fcb07e01ce512c5d8737ffe929164a6813 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 10:19:22 -0400 Subject: [PATCH 12/19] #26 secure document API route by group membership, Fixes #24 --- src/pages/api/document/[id].js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/api/document/[id].js b/src/pages/api/document/[id].js index 468ae51f..5b78cc26 100644 --- a/src/pages/api/document/[id].js +++ b/src/pages/api/document/[id].js @@ -14,7 +14,10 @@ const handler = nc() await req.db .collection('documents') .findOne( - { _id: ObjectID(req.query.id) }, + { + _id: ObjectID(req.query.id), + 'groups.members.id': ObjectID(token.user.id), + }, (err, doc) => { if (doc) { const { From 461c681418baff39180747cfe6c9937d2bffc0f8 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 10:24:47 -0400 Subject: [PATCH 13/19] #26 Wrap ID queries in ObjectID function --- src/pages/api/group/[id].js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/api/group/[id].js b/src/pages/api/group/[id].js index 2972a622..f4401b5a 100644 --- a/src/pages/api/group/[id].js +++ b/src/pages/api/group/[id].js @@ -18,7 +18,7 @@ const handler = nc() .findOne( { _id: ObjectID(req.query.id), - 'members.id': token.user.id, + 'members.id': ObjectID(token.user.id), }, (err, doc) => { if (doc) { @@ -55,7 +55,7 @@ const handler = nc() let documentToUpdate = {}; let documentByID = {}; if (req.body.updatedDocument) { - documentByID = { 'documents.id': req.body.updatedDocument.id }; + documentByID = { 'documents.id': ObjectID(req.body.updatedDocument.id) }; documentToUpdate = { 'documents.$.slug': req.body.updatedDocument.slug, 'documents.$.name': req.body.updatedDocument.name, From 894ae5576305d844496e1899746cecad0c192277 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 12:04:02 -0400 Subject: [PATCH 14/19] #26 Add Group POST route --- src/pages/api/group/index.js | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/pages/api/group/index.js diff --git a/src/pages/api/group/index.js b/src/pages/api/group/index.js new file mode 100644 index 00000000..2a2381da --- /dev/null +++ b/src/pages/api/group/index.js @@ -0,0 +1,35 @@ +import nc from 'next-connect'; +import { ObjectID } from 'mongodb'; +import jwt from 'next-auth/jwt'; +import middleware from '../../../middlewares/middleware'; + +const secret = process.env.AUTH_SECRET; + +const handler = nc() + .use(middleware) + .post( + async (req, res) => { + const token = await jwt.getJwt({ req, secret }); + if (token && token.exp > 0) { + const { name } = req.body; + const members = [{ + id: ObjectID(token.user.id), + name: token.user.name, + email: token.user.email, + role: 'owner', + }]; + const documents = [{}]; + await req.db + .collection('groups') + .insertOne( + { name, members, documents }, + (err, doc) => { + if (err) throw err; + res.status(200).json(doc); + }, + ); + } else res.status(403).json({ error: '403 Invalid or expired token' }); + }, + ); + +export default handler; From 4caf0ff07366fc21ac04494239573336c334f415 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 15:35:19 -0400 Subject: [PATCH 15/19] #26 Allow owner access to document (#24) --- src/pages/api/document/[id].js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/api/document/[id].js b/src/pages/api/document/[id].js index 5b78cc26..fd5ddd5d 100644 --- a/src/pages/api/document/[id].js +++ b/src/pages/api/document/[id].js @@ -16,7 +16,7 @@ const handler = nc() .findOne( { _id: ObjectID(req.query.id), - 'groups.members.id': ObjectID(token.user.id), + $or: [{ 'groups.members.id': ObjectID(token.user.id) }, { owner: ObjectID(token.user.id) }], }, (err, doc) => { if (doc) { From 8c785ce9b387aa5953d1350d7504646c67d8096d Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 16:06:29 -0400 Subject: [PATCH 16/19] #26 Document POST api route --- src/pages/api/document/[id].js | 6 +++ src/pages/api/document/index.js | 83 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 src/pages/api/document/index.js diff --git a/src/pages/api/document/[id].js b/src/pages/api/document/[id].js index fd5ddd5d..9560bd60 100644 --- a/src/pages/api/document/[id].js +++ b/src/pages/api/document/[id].js @@ -22,6 +22,7 @@ const handler = nc() if (doc) { const { title, + slug, owner, groups, resourceType, @@ -44,11 +45,14 @@ const handler = nc() issue, pageNumbers, publication, + series, + sesiesNumber, notes, } = doc; if (err) throw err; res.status(200).json({ title, + slug, owner, groups, resourceType, @@ -71,6 +75,8 @@ const handler = nc() issue, pageNumbers, publication, + series, + sesiesNumber, notes, }); } else { diff --git a/src/pages/api/document/index.js b/src/pages/api/document/index.js new file mode 100644 index 00000000..37f0979e --- /dev/null +++ b/src/pages/api/document/index.js @@ -0,0 +1,83 @@ +import nc from 'next-connect'; +import { ObjectID } from 'mongodb'; +import jwt from 'next-auth/jwt'; +import middleware from '../../../middlewares/middleware'; + +const secret = process.env.AUTH_SECRET; + +const handler = nc() + .use(middleware) + .post( + async (req, res) => { + const token = await jwt.getJwt({ req, secret }); + if (token && token.exp > 0) { + const dateCreated = new Date(Date.now()); + const { + title, + groups, + resourceType, + authors, + publisher, + publicationDate, + bookTitle, + edition, + url, + accessed, + rightsStatus, + location, + state, + text, + uploadContentType, + editors, + volume, + issue, + pageNumbers, + publication, + series, + sesiesNumber, + notes, + } = req.body; + const metadata = { + title, + groups, + resourceType, + authors, + publisher, + publicationDate, + bookTitle, + edition, + url, + accessed, + rightsStatus, + location, + state, + text, + uploadContentType, + editors, + volume, + issue, + pageNumbers, + publication, + series, + sesiesNumber, + notes, + }; + await req.db + .collection('documents') + .insert( + { + owner: ObjectID(token.user.id), + createdAt: dateCreated, + updatedAt: dateCreated, + ...metadata, + }, + (err, doc) => { + if (err) throw err; + res.status(200).json(doc); + }, + ); + } else res.status(403).json({ error: '403 Invalid or expired token' }); + }, + ); + +export default handler; From 09c343ea394215dfabf1445bd3d5c428ef95c93b Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 17:54:38 -0400 Subject: [PATCH 17/19] #26 Add Document PATCH route --- src/pages/api/document/[id].js | 106 +++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/src/pages/api/document/[id].js b/src/pages/api/document/[id].js index 9560bd60..6bae088d 100644 --- a/src/pages/api/document/[id].js +++ b/src/pages/api/document/[id].js @@ -86,6 +86,112 @@ const handler = nc() ); } else res.status(403).json({ error: '403 Invalid or expired token' }); }, + ) + .patch( + async (req, res) => { + const token = await jwt.getJwt({ req, secret }); + if (token && token.exp > 0) { + const { + title, + slug, + resourceType, + authors, + publisher, + publicationDate, + bookTitle, + edition, + url, + accessed, + rightsStatus, + location, + state, + text, + editors, + volume, + issue, + pageNumbers, + publication, + series, + sesiesNumber, + notes, + } = req.body; + const fieldsToSet = { + title, + slug, + resourceType, + authors, + publisher, + publicationDate, + bookTitle, + edition, + url, + accessed, + rightsStatus, + location, + state, + text, + editors, + volume, + issue, + pageNumbers, + publication, + series, + sesiesNumber, + notes, + }; + Object.keys(fieldsToSet).forEach((key) => { + if (fieldsToSet[key] === undefined) { + delete fieldsToSet[key]; + } + }); + const groupToPush = req.body.addedGroup + ? { groups: req.body.addedGroup } + : {}; + const groupToPull = req.body.removedGroupId + ? { 'groups.id': ObjectID(req.body.removedGroupId) } + : {}; + let groupById = {}; + let groupFieldsToSet = {}; + let memberToPush = {}; + let memberToPull = {}; + if (req.body.updatedGroup) { + groupById = { 'groups.id': ObjectID(req.body.updatedGroup.id) }; + if (req.body.updatedGroup.name) { + groupFieldsToSet = { 'groups.$.name': req.body.updatedGroup.name }; + } + if (req.body.addedUser) { + memberToPush = { 'groups.$.members': req.body.addedUser }; + } + if (req.body.removedUserId) { + memberToPull = { 'groups.$.members.id': ObjectID(req.body.removedUserId) }; + } + } + await req.db + .collection('documents') + .findOneAndUpdate( + { + _id: ObjectID(req.query.id), + owner: ObjectID(token.user.id), + ...groupById, + }, + { + $set: { ...fieldsToSet, ...groupFieldsToSet }, + $push: { ...memberToPush, ...groupToPush }, + $pull: { ...memberToPull, ...groupToPull }, + $currentDate: { + updatedAt: true, + }, + }, + { + returnOriginal: false, + }, + (err, doc) => { + if (err) throw err; + res.status(200).json(doc); + }, + ); + } else res.status(403).json({ error: '403 Invalid or expired token' }); + }, ); export default handler; From 22d6b1d551f0df66534177706204d232774366a5 Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 17:55:21 -0400 Subject: [PATCH 18/19] #26 don't add undefined fields to Document in POST --- src/pages/api/document/index.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pages/api/document/index.js b/src/pages/api/document/index.js index 37f0979e..b1a367e7 100644 --- a/src/pages/api/document/index.js +++ b/src/pages/api/document/index.js @@ -14,6 +14,7 @@ const handler = nc() const dateCreated = new Date(Date.now()); const { title, + slug, groups, resourceType, authors, @@ -39,6 +40,7 @@ const handler = nc() } = req.body; const metadata = { title, + slug, groups, resourceType, authors, @@ -62,6 +64,11 @@ const handler = nc() sesiesNumber, notes, }; + Object.keys(metadata).forEach((key) => { + if (metadata[key] === undefined) { + delete metadata[key]; + } + }); await req.db .collection('documents') .insert( From c093251eb49e0fc77aeb94dc098e7d2630ddf20d Mon Sep 17 00:00:00 2001 From: Ben Silverman Date: Wed, 22 Jul 2020 17:55:32 -0400 Subject: [PATCH 19/19] #26 Camel-casing variable names --- src/pages/api/group/[id].js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/pages/api/group/[id].js b/src/pages/api/group/[id].js index a82e9be8..3772902e 100644 --- a/src/pages/api/group/[id].js +++ b/src/pages/api/group/[id].js @@ -4,7 +4,7 @@ import jwt from 'next-auth/jwt'; import middleware from '../../../middlewares/middleware'; const secret = process.env.AUTH_SECRET; -const fakeUserID = ObjectID('7b639ae33efb36eaf6447c55'); +const fakeUserId = ObjectID('7b639ae33efb36eaf6447c55'); const handler = nc() .use(middleware) @@ -49,15 +49,15 @@ const handler = nc() const token = await jwt.getJwt({ req, secret }); if (token && token.exp > 0) { const memberQuery = (process.env.NODE_ENV === 'development') - ? [{ 'members.id': ObjectID(token.user.id) }, { 'members.id': fakeUserID }] + ? [{ 'members.id': ObjectID(token.user.id) }, { 'members.id': fakeUserId }] : [{ 'members.id': ObjectID(token.user.id) }]; const nameToUpdate = req.body.name ? { name: req.body.name } : {}; let documentToUpdate = {}; - let documentByID = {}; + let documentById = {}; if (req.body.updatedDocument) { - documentByID = { 'documents.id': ObjectID(req.body.updatedDocument.id) }; + documentById = { 'documents.id': ObjectID(req.body.updatedDocument.id) }; documentToUpdate = { 'documents.$.slug': req.body.updatedDocument.slug, 'documents.$.name': req.body.updatedDocument.name, @@ -66,14 +66,14 @@ const handler = nc() const memberToPush = req.body.addedUser ? { members: req.body.addedUser } : {}; - const documentToPush = req.body.addedDoc - ? { documents: req.body.addedDoc } + const documentToPush = req.body.addedDocument + ? { documents: req.body.addedDocument } : {}; - const memberToPull = req.body.removedUserID - ? { 'members.id': ObjectID(req.body.removedUserID) } + const memberToPull = req.body.removedUserId + ? { 'members.id': ObjectID(req.body.removedUserId) } : {}; - const documentToPull = req.body.removedDocumentID - ? { 'documents.id': ObjectID(req.body.removedDocumentID) } + const documentToPull = req.body.removedDocumentId + ? { 'documents.id': ObjectID(req.body.removedDocumentId) } : {}; await req.db .collection('groups') @@ -81,7 +81,7 @@ const handler = nc() { _id: ObjectID(req.query.id), $or: memberQuery, - ...documentByID, + ...documentById, }, { $set: { ...nameToUpdate, ...documentToUpdate },