From 925267ecea68038cbc7f912cfc52c12d025abf65 Mon Sep 17 00:00:00 2001
From: Sebastian <sebastian.mihalache@thinslices.com>
Date: Thu, 19 Apr 2018 09:11:00 +0300
Subject: [PATCH] feat(component-invite): add agree logic for a reviewer

---
 .../routes/collectionsInvitations/patch.js    | 21 ++++++---
 .../collectionsInvitations/patch.test.js      | 43 ++++++++++++++++++-
 .../src/tests/fixtures/collections.js         | 10 ++++-
 .../src/tests/fixtures/userData.js            | 34 ++++++---------
 .../src/tests/fixtures/users.js               | 18 +++++++-
 packages/component-mail-service/src/Mail.js   | 22 ++++++----
 ...handling-editor-agreed.html => agree.html} |  4 +-
 .../{handling-editor-agreed.txt => agree.txt} |  2 +-
 8 files changed, 111 insertions(+), 43 deletions(-)
 rename packages/component-mail-service/src/templates/{handling-editor-agreed.html => agree.html} (98%)
 rename packages/component-mail-service/src/templates/{handling-editor-agreed.txt => agree.txt} (68%)

diff --git a/packages/component-invite/src/routes/collectionsInvitations/patch.js b/packages/component-invite/src/routes/collectionsInvitations/patch.js
index 6850b04fe..19e95891c 100644
--- a/packages/component-invite/src/routes/collectionsInvitations/patch.js
+++ b/packages/component-invite/src/routes/collectionsInvitations/patch.js
@@ -27,19 +27,30 @@ module.exports = models => async (req, res) => {
       })
       return
     }
-
-    await collectionHelper.updateHandlingEditor(collection, isAccepted)
+    if (invitation.userId !== user.id) {
+      res.status(403).json({
+        error: `User ${user.email} is not allowed to modify invitation ${
+          invitation.id
+        }`,
+      })
+      return
+    }
+    if (invitation.role === 'handlingEditor')
+      await collectionHelper.updateHandlingEditor(collection, isAccepted)
     invitation.timestamp = Date.now()
     invitation.hasAnswer = true
     const eic = await userHelper.getEditorInChief(models.User)
     if (isAccepted === true) {
       invitation.isAccepted = true
+      let toEmail = eic.email
+      if (invitation.role === 'reviewer')
+        toEmail = collection.handlingEditor.email
       await collection.save()
       try {
-        await mailService.setupHandlingEditorAgreedEmail(
-          eic.email,
+        await mailService.setupAgreeEmail(
+          toEmail,
           user,
-          'handling-editor-agreed',
+          invitation.role,
           `${req.protocol}://${req.get('host')}`,
           collection.customId,
         )
diff --git a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
index 3a1bec6bb..62c4332bd 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
@@ -9,7 +9,7 @@ const cloneDeep = require('lodash/cloneDeep')
 const models = Model.build()
 jest.mock('pubsweet-component-mail-service', () => ({
   setupAssignEmail: jest.fn(),
-  setupHandlingEditorAgreedEmail: jest.fn(),
+  setupAgreeEmail: jest.fn(),
   setupDeclineEmail: jest.fn(),
 }))
 
@@ -32,7 +32,26 @@ describe('Patch collections invitations route handler', () => {
     })
     req.user = handlingEditor.id
     req.params.collectionId = collection.id
-    req.params.invitationId = collection.invitations[0].id
+    const heInv = collection.invitations.find(
+      inv => inv.role === 'handlingEditor',
+    )
+    req.params.invitationId = heInv.id
+    const res = httpMocks.createResponse()
+    await require(patchPath)(models)(req, res)
+    expect(res.statusCode).toBe(200)
+  })
+  it('should return success when the reviewer agrees work on a collection', async () => {
+    const { reviewer } = testFixtures.users
+    const { collection } = testFixtures.collections
+    const req = httpMocks.createRequest({
+      body,
+    })
+    req.user = reviewer.id
+    req.params.collectionId = collection.id
+    const reviewerInv = collection.invitations.find(
+      inv => inv.role === 'reviewer',
+    )
+    req.params.invitationId = reviewerInv.id
     const res = httpMocks.createResponse()
     await require(patchPath)(models)(req, res)
     expect(res.statusCode).toBe(200)
@@ -99,4 +118,24 @@ describe('Patch collections invitations route handler', () => {
     const data = JSON.parse(res._getData())
     expect(data.error).toEqual('Invitation invalid-id not found')
   })
+  it("should return an error when a user tries to patch another user's invitation", async () => {
+    const { reviewer } = testFixtures.users
+    const { collection } = testFixtures.collections
+    const req = httpMocks.createRequest({
+      body,
+    })
+    req.user = reviewer.id
+    req.params.collectionId = collection.id
+    const inv = collection.invitations.find(
+      inv => inv.role === 'handlingEditor',
+    )
+    req.params.invitationId = inv.id
+    const res = httpMocks.createResponse()
+    await require(patchPath)(models)(req, res)
+    expect(res.statusCode).toBe(403)
+    const data = JSON.parse(res._getData())
+    expect(data.error).toEqual(
+      `User ${reviewer.email} is not allowed to modify invitation ${inv.id}`,
+    )
+  })
 })
diff --git a/packages/component-invite/src/tests/fixtures/collections.js b/packages/component-invite/src/tests/fixtures/collections.js
index b0dba9b45..78920b4aa 100644
--- a/packages/component-invite/src/tests/fixtures/collections.js
+++ b/packages/component-invite/src/tests/fixtures/collections.js
@@ -1,5 +1,5 @@
 const Chance = require('chance')
-const { user, handlingEditor, author } = require('./userData')
+const { user, handlingEditor, author, reviewer } = require('./userData')
 const { fragment } = require('./fragments')
 
 const chance = new Chance()
@@ -27,6 +27,14 @@ const collections = {
         userId: handlingEditor.id,
         timestamp: chance.timestamp(),
       },
+      {
+        id: chance.guid(),
+        role: 'reviewer',
+        hasAnswer: false,
+        isAccepted: false,
+        userId: reviewer.id,
+        timestamp: chance.timestamp(),
+      },
     ],
     handlingEditor: {
       id: handlingEditor.id,
diff --git a/packages/component-invite/src/tests/fixtures/userData.js b/packages/component-invite/src/tests/fixtures/userData.js
index de7459c0d..a7046079c 100644
--- a/packages/component-invite/src/tests/fixtures/userData.js
+++ b/packages/component-invite/src/tests/fixtures/userData.js
@@ -1,27 +1,17 @@
 const Chance = require('chance')
 
 const chance = new Chance()
+const generateUserData = () => ({
+  id: chance.guid(),
+  email: chance.email(),
+  firstName: chance.first(),
+  lastName: chance.last(),
+})
+
 module.exports = {
-  handlingEditor: {
-    id: chance.guid(),
-    email: chance.email(),
-    firstName: chance.first(),
-    lastName: chance.last(),
-  },
-  user: {
-    id: chance.guid(),
-    email: chance.email(),
-    firstName: chance.first(),
-    lastName: chance.last(),
-  },
-  admin: {
-    id: chance.guid(),
-    email: chance.email(),
-  },
-  author: {
-    id: chance.guid(),
-    email: chance.email(),
-    firstName: chance.first(),
-    lastName: chance.last(),
-  },
+  handlingEditor: generateUserData(),
+  user: generateUserData(),
+  admin: generateUserData(),
+  author: generateUserData(),
+  reviewer: generateUserData(),
 }
diff --git a/packages/component-invite/src/tests/fixtures/users.js b/packages/component-invite/src/tests/fixtures/users.js
index c36f0a74c..c474cfc7a 100644
--- a/packages/component-invite/src/tests/fixtures/users.js
+++ b/packages/component-invite/src/tests/fixtures/users.js
@@ -1,5 +1,5 @@
 const { heTeamID } = require('./teamIDs')
-const { handlingEditor, user, admin, author } = require('./userData')
+const { handlingEditor, user, admin, author, reviewer } = require('./userData')
 const Chance = require('chance')
 
 const chance = new Chance()
@@ -8,6 +8,8 @@ const users = {
     type: 'user',
     username: 'admin',
     email: admin.email,
+    firstName: admin.firstName,
+    lastName: admin.lastName,
     password: 'test',
     admin: true,
     id: admin.id,
@@ -71,6 +73,20 @@ const users = {
     save: jest.fn(() => users.author),
     isConfirmed: true,
   },
+  reviewer: {
+    type: 'user',
+    username: chance.word(),
+    email: reviewer.email,
+    password: 'password',
+    admin: false,
+    id: reviewer.id,
+    firstName: reviewer.firstName,
+    lastName: reviewer.lastName,
+    affiliation: chance.company(),
+    title: 'Mr',
+    save: jest.fn(() => users.reviewer),
+    isConfirmed: true,
+  },
 }
 
 module.exports = users
diff --git a/packages/component-mail-service/src/Mail.js b/packages/component-mail-service/src/Mail.js
index 6e53819af..3f051acb6 100644
--- a/packages/component-mail-service/src/Mail.js
+++ b/packages/component-mail-service/src/Mail.js
@@ -91,22 +91,24 @@ module.exports = {
     }
     return Email.send(mailData)
   },
-  setupHandlingEditorAgreedEmail: async (
-    toEmail,
-    user,
-    emailType,
-    url,
-    collectionId,
-  ) => {
-    const { htmlBody, textBody } = getEmailBody(emailType, {
+  setupAgreeEmail: async (toEmail, user, invRole, url, collectionId) => {
+    let role = 'Handling Editor'
+    let subject = 'Handling Editor Agreed'
+    if (invRole === 'reviewer') {
+      subject = 'Reviewer Agreed'
+      role = 'Reviewer'
+    }
+    const { htmlBody, textBody } = getEmailBody('agree', {
       url,
+      role,
       name: `${user.firstName} ${user.lastName}`,
       collectionId,
     })
+
     const mailData = {
       from: config.get('mailer.from'),
       to: toEmail,
-      subject: 'Handling Editor Agreed',
+      subject,
       text: textBody,
       html: htmlBody,
     }
@@ -152,6 +154,8 @@ module.exports = {
       agreeUrl = `${baseUrl}${resetPath}?${querystring.encode({
         email: invitedUser.email,
         token: invitedUser.passwordResetToken,
+        collectionId: collection.id,
+        agree: true,
       })}`
     }
 
diff --git a/packages/component-mail-service/src/templates/handling-editor-agreed.html b/packages/component-mail-service/src/templates/agree.html
similarity index 98%
rename from packages/component-mail-service/src/templates/handling-editor-agreed.html
rename to packages/component-mail-service/src/templates/agree.html
index 3f24b1f42..edf453b48 100644
--- a/packages/component-mail-service/src/templates/handling-editor-agreed.html
+++ b/packages/component-mail-service/src/templates/agree.html
@@ -145,7 +145,7 @@
                                 width="100%" style="display: none !important; mso-hide: all; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">
                                 <tr>
                                   <td role="module-content">
-                                    <p>handling editor agreed</p>
+                                    <p>a user has agreed</p>
                                   </td>
                                 </tr>
                               </table>
@@ -163,7 +163,7 @@
                               <table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
                                 <tr>
                                   <td style="padding:30px 23px 0px 23px;background-color:#ffffff;" height="100%" valign="top" bgcolor="#ffffff">
-                                    <h1 style="text-align: center;">{{ name }} has agreed to be Handling Editor on manuscript {{ collectionId }}</h1>
+                                    <h1 style="text-align: center;">{{ name }} has agreed to be a {{ role }} on manuscript {{ collectionId }}.</h1>
 
                                     <div style="text-align: center;">Please click on the link below to access your dashboard.</div>
 
diff --git a/packages/component-mail-service/src/templates/handling-editor-agreed.txt b/packages/component-mail-service/src/templates/agree.txt
similarity index 68%
rename from packages/component-mail-service/src/templates/handling-editor-agreed.txt
rename to packages/component-mail-service/src/templates/agree.txt
index 550581b44..ea941f3dd 100644
--- a/packages/component-mail-service/src/templates/handling-editor-agreed.txt
+++ b/packages/component-mail-service/src/templates/agree.txt
@@ -1,4 +1,4 @@
-{{ name }} has agreed to be Handling Editor on manuscript {{ collectionId }}
+{{ name }} has agreed to be a {{ role }} on manuscript {{ collectionId }}
 Please click on the link below to access your dashboard
 {{ url }} VIEW DASHBOARD
 Hindawi Publishing Corporation
-- 
GitLab