diff --git a/packages/component-user-manager/src/helpers/Collection.js b/packages/component-user-manager/src/helpers/Collection.js index 875f65740c5f6b9be2f455d060e1ed179afffbbe..40cf70f3bd2965e1e6d5b2bc86d3b30372391a3d 100644 --- a/packages/component-user-manager/src/helpers/Collection.js +++ b/packages/component-user-manager/src/helpers/Collection.js @@ -2,7 +2,22 @@ const mailService = require('pubsweet-component-mail-service') const logger = require('@pubsweet/logger') module.exports = { - addAuthor: async (collection, user, res, url) => { + addAuthor: async ( + collection, + user, + res, + url, + isSubmitting, + isCorresponding, + ) => { + collection.authors = collection.authors || [] + const author = { + userId: user.id, + isSubmitting, + isCorresponding, + } + collection.authors.push(author) + await collection.save() if (collection.owners.includes(user.id)) { return res.status(200).json(user) } diff --git a/packages/component-user-manager/src/routes/collectionsUsers/delete.js b/packages/component-user-manager/src/routes/collectionsUsers/delete.js index d504eda36ea13e8187a97137947a2856c94e94f2..db4cdb7c444ac488ad5eebbeed85d5823d96a59a 100644 --- a/packages/component-user-manager/src/routes/collectionsUsers/delete.js +++ b/packages/component-user-manager/src/routes/collectionsUsers/delete.js @@ -14,6 +14,9 @@ module.exports = models => async (req, res) => { models.Team, ) + collection.authors = collection.authors.filter( + author => author.userId !== userId, + ) await collection.save() await teamHelper.removeTeamMember(team.id, userId, models.Team) user.teams = user.teams.filter(userTeamId => team.id !== userTeamId) diff --git a/packages/component-user-manager/src/routes/collectionsUsers/get.js b/packages/component-user-manager/src/routes/collectionsUsers/get.js index cc97ce38bdd8e997eb711ec6b8568309fccb28a5..3ef86406b0ae21590f2223d0b83c89c12bb9be2c 100644 --- a/packages/component-user-manager/src/routes/collectionsUsers/get.js +++ b/packages/component-user-manager/src/routes/collectionsUsers/get.js @@ -5,7 +5,7 @@ module.exports = models => async (req, res) => { // TO DO: add authsom const { collectionId } = req.params try { - await models.Collection.find(collectionId) + const collection = await models.Collection.find(collectionId) const members = await teamHelper.getTeamMembersByCollection( collectionId, 'author', @@ -18,8 +18,17 @@ module.exports = models => async (req, res) => { }) return } - - const membersData = members.map(async member => models.User.find(member)) + const membersData = members.map(async member => { + const user = await models.User.find(member) + const matchingAuthor = collection.authors.find( + author => author.userId === user.id, + ) + return { + ...user, + isSubmitting: matchingAuthor.isSubmitting, + isCorresponding: matchingAuthor.isCorresponding, + } + }) const resBody = await Promise.all(membersData) res.status(200).json(resBody) diff --git a/packages/component-user-manager/src/routes/collectionsUsers/post.js b/packages/component-user-manager/src/routes/collectionsUsers/post.js index 822ddc8f06aaef0f9cd96405c609cf903d388665..36ed33c0203adf6e0c4154b3682d46ec89af1375 100644 --- a/packages/component-user-manager/src/routes/collectionsUsers/post.js +++ b/packages/component-user-manager/src/routes/collectionsUsers/post.js @@ -6,9 +6,11 @@ const teamHelper = require('../../helpers/Team') const userHelper = require('../../helpers/User') module.exports = models => async (req, res) => { - const { email, role } = req.body + const { email, role, isSubmitting, isCorresponding } = req.body - if (!helpers.checkForUndefinedParams(email, role)) { + if ( + !helpers.checkForUndefinedParams(email, role, isSubmitting, isCorresponding) + ) { res.status(400).json({ error: 'Email and role are required' }) logger.error('Email and role are missing') return @@ -29,12 +31,28 @@ module.exports = models => async (req, res) => { try { let user = await models.User.findByEmail(email) - await teamHelper.setupManuscriptTeam(models, user, collectionId, role) - - // get updated user from DB - user = await models.User.find(user.id) if (role === 'author') { - return collectionHelper.addAuthor(collection, user, res, url) + await teamHelper.setupManuscriptTeam(models, user, collectionId, role) + // get updated user from DB + user = await models.User.find(user.id) + if (collection.authors !== undefined) { + const match = collection.authors.find( + author => author.userId === user.id, + ) + if (match) { + return res.status(400).json({ + error: `User ${user.email} is already an author`, + }) + } + } + return await collectionHelper.addAuthor( + collection, + user, + res, + url, + isSubmitting, + isCorresponding, + ) } return res.status(400).json({ error: `${role} is not defined`, @@ -61,7 +79,14 @@ module.exports = models => async (req, res) => { }) } await teamHelper.setupManuscriptTeam(models, newUser, collectionId, role) - return res.status(200).json(newUser) + return collectionHelper.addAuthor( + collection, + newUser, + res, + url, + isSubmitting, + isCorresponding, + ) } return res.status(e.status).json({ error: 'Something went wrong', diff --git a/packages/component-user-manager/src/tests/collectionsUsers/get.test.js b/packages/component-user-manager/src/tests/collectionsUsers/get.test.js index 6ac3af3a81d64ec76323fe830379d298c1b727ef..b5975b4ed8d941cd760c22b4df9ec729c41e8ab7 100644 --- a/packages/component-user-manager/src/tests/collectionsUsers/get.test.js +++ b/packages/component-user-manager/src/tests/collectionsUsers/get.test.js @@ -21,6 +21,8 @@ describe('Get collections users route handler', () => { expect(res.statusCode).toBe(200) const data = JSON.parse(res._getData()) expect(data).toHaveLength(1) + expect(data[0].isSubmitting).toBeDefined() + expect(data[0].type).toBe('user') }) it('should return an error when the collection does not exist', async () => { const req = httpMocks.createRequest() diff --git a/packages/component-user-manager/src/tests/collectionsUsers/post.test.js b/packages/component-user-manager/src/tests/collectionsUsers/post.test.js index 6e2333d117a045e8c4e01a804f7a7b8022668e3c..2d3e09c16d627f75f28591b605dbe7dbb1892c80 100644 --- a/packages/component-user-manager/src/tests/collectionsUsers/post.test.js +++ b/packages/component-user-manager/src/tests/collectionsUsers/post.test.js @@ -23,6 +23,8 @@ const postPath = '../../routes/collectionsUsers/post' const body = { email: chance.email(), role: 'author', + isSubmitting: true, + isCorresponding: false, } describe('Post collections users route handler', () => { it('should return success when an author adds a new user to a collection', async () => { @@ -38,6 +40,10 @@ describe('Post collections users route handler', () => { const data = JSON.parse(res._getData()) expect(data.email).toEqual(body.email) expect(data.invitations).toBeUndefined() + const matchingAuthor = standardCollection.authors.find( + author => author.userId === data.id, + ) + expect(matchingAuthor).toBeDefined() }) it('should return success when an author adds an existing user as co author to a collection', async () => { body.email = author.email @@ -52,6 +58,26 @@ describe('Post collections users route handler', () => { expect(res.statusCode).toBe(200) const data = JSON.parse(res._getData()) expect(data.email).toEqual(body.email) + const matchingAuthor = standardCollection.authors.find( + auth => auth.userId === author.id, + ) + expect(matchingAuthor).toBeDefined() + }) + it('should return an error when the an author is added to the same collection', async () => { + body.email = submittingAuthor.email + const req = httpMocks.createRequest({ + body, + }) + req.user = submittingAuthor.id + req.params.collectionId = standardCollection.id + const res = httpMocks.createResponse() + await require(postPath)(models)(req, res) + + expect(res.statusCode).toBe(400) + const data = JSON.parse(res._getData()) + expect(data.error).toEqual( + `User ${submittingAuthor.email} is already an author`, + ) }) it('should return an error when params are missing', async () => { delete body.email diff --git a/packages/component-user-manager/src/tests/fixtures/collections.js b/packages/component-user-manager/src/tests/fixtures/collections.js index 761f952759486c25406fe7071a820ef1f69f315a..b52062a067bb7e8375023b0856f18da55e63c719 100644 --- a/packages/component-user-manager/src/tests/fixtures/collections.js +++ b/packages/component-user-manager/src/tests/fixtures/collections.js @@ -10,6 +10,13 @@ module.exports = { fragments: [], owners: [submittingAuthor.id], save: jest.fn(), + authors: [ + { + userId: submittingAuthor.id, + isSubmitting: true, + isCorresponding: false, + }, + ], }, authorsCollection: { id: chance.guid(), diff --git a/packages/component-user-manager/src/tests/fixtures/teams.js b/packages/component-user-manager/src/tests/fixtures/teams.js index 8839ea58a2c31169bdc030c541ee363ad4880e97..410b999e3f98f3b196eb28feb5512c744e5b61ea 100644 --- a/packages/component-user-manager/src/tests/fixtures/teams.js +++ b/packages/component-user-manager/src/tests/fixtures/teams.js @@ -3,7 +3,7 @@ const collections = require('./collections') const { authorTeamID } = require('./teamIDs') const { standardCollection } = collections -const { author } = users +const { submittingAuthor } = users const teams = { authorTeam: { teamType: { @@ -16,7 +16,7 @@ const teams = { type: 'collection', id: standardCollection.id, }, - members: [author.id], + members: [submittingAuthor.id], save: jest.fn(() => teams.authorTeam), updateProperties: jest.fn(() => teams.authorTeam), id: authorTeamID, diff --git a/packages/xpub-faraday/config/validations.js b/packages/xpub-faraday/config/validations.js index 5064bd743ded07f3d8fcdf3f977e39c77a9b3dfa..f6a6f09a3f3497f5ab5552d710f29314bacf8145 100644 --- a/packages/xpub-faraday/config/validations.js +++ b/packages/xpub-faraday/config/validations.js @@ -9,7 +9,8 @@ module.exports = { status: Joi.string(), reviewers: Joi.array(), customId: Joi.string(), - assignedPeople: Joi.array(), + authors: Joi.array(), + invitations: Joi.array(), }, fragment: [ { @@ -95,7 +96,6 @@ module.exports = { lastName: Joi.string().allow(''), affiliation: Joi.string().allow(''), title: Joi.string().allow(''), - invitations: Joi.array(), teams: Joi.array(), editorInChief: Joi.boolean(), handlingEditor: Joi.boolean(),