diff --git a/packages/component-invite/src/routes/collectionsInvitations/patch.js b/packages/component-invite/src/routes/collectionsInvitations/patch.js
index 19e95891cbedfb9e8ec0f0309986e78fe404803b..dcfde76b44eb1915df3db8f7aa1a6caabeec257b 100644
--- a/packages/component-invite/src/routes/collectionsInvitations/patch.js
+++ b/packages/component-invite/src/routes/collectionsInvitations/patch.js
@@ -21,20 +21,21 @@ module.exports = models => async (req, res) => {
     const invitation = await collection.invitations.find(
       invitation => invitation.id === invitationId,
     )
-    if (invitation === undefined) {
-      res.status(404).json({
+    if (invitation === undefined)
+      return res.status(404).json({
         error: `Invitation ${invitationId} not found`,
       })
-      return
-    }
-    if (invitation.userId !== user.id) {
-      res.status(403).json({
+    if (invitation.hasAnswer)
+      return res
+        .status(400)
+        .json({ error: `${invitation.id} has already been answered` })
+    if (invitation.userId !== user.id)
+      return 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()
diff --git a/packages/component-invite/src/tests/collectionsInvitations/delete.test.js b/packages/component-invite/src/tests/collectionsInvitations/delete.test.js
index 8b8b78eaad94c4ea18994dc4acd9e47a096c38e0..38ca5f0f27a654940ee63b22411a73e2b2b6bbac 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/delete.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/delete.test.js
@@ -11,12 +11,13 @@ jest.mock('pubsweet-component-mail-service', () => ({
 }))
 
 const deletePath = '../../routes/collectionsInvitations/delete'
-const models = Model.build()
 
 describe('Delete Collections Invitations route handler', () => {
   let testFixtures = {}
+  let models
   beforeEach(() => {
     testFixtures = cloneDeep(fixtures)
+    models = Model.build(testFixtures)
   })
   it('should return an error when the collection does not exist', async () => {
     const { editorInChief } = testFixtures.users
diff --git a/packages/component-invite/src/tests/collectionsInvitations/get.test.js b/packages/component-invite/src/tests/collectionsInvitations/get.test.js
index b594ef52666a89e8e619b7e63862c2e6eb3ea49e..7d64dcf8bfb2344606bbfb1bbbb7410194549662 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/get.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/get.test.js
@@ -9,8 +9,10 @@ const cloneDeep = require('lodash/cloneDeep')
 const getPath = '../../routes/collectionsInvitations/get'
 describe('Get collection invitations route handler', () => {
   let testFixtures = {}
+  let models
   beforeEach(() => {
     testFixtures = cloneDeep(fixtures)
+    models = Model.build(testFixtures)
   })
   it('should return success when the request data is correct', async () => {
     const { editorInChief, handlingEditor } = testFixtures.users
@@ -23,7 +25,6 @@ describe('Get collection invitations route handler', () => {
     req.params.collectionId = collection.id
     req.user = editorInChief.id
     const res = httpMocks.createResponse()
-    const models = Model.build()
     await require(getPath)(models)(req, res)
 
     expect(res.statusCode).toBe(200)
@@ -36,7 +37,6 @@ describe('Get collection invitations route handler', () => {
     req.query = {}
     req.user = editorInChief.id
     const res = httpMocks.createResponse()
-    const models = Model.build()
     await require(getPath)(models)(req, res)
     expect(res.statusCode).toBe(400)
     const data = JSON.parse(res._getData())
@@ -53,7 +53,6 @@ describe('Get collection invitations route handler', () => {
     req.params.collectionId = 'invalid-id'
     req.user = editorInChief.id
     const res = httpMocks.createResponse()
-    const models = Model.build()
     await require(getPath)(models)(req, res)
     expect(res.statusCode).toBe(404)
     const data = JSON.parse(res._getData())
@@ -70,7 +69,6 @@ describe('Get collection invitations route handler', () => {
     req.params.collectionId = collection.id
     req.user = editorInChief.id
     const res = httpMocks.createResponse()
-    const models = Model.build()
     await require(getPath)(models)(req, res)
     expect(res.statusCode).toBe(400)
     const data = JSON.parse(res._getData())
@@ -88,7 +86,6 @@ describe('Get collection invitations route handler', () => {
     req.params.collectionId = collection.id
     req.user = editorInChief.id
     const res = httpMocks.createResponse()
-    const models = Model.build()
     await require(getPath)(models)(req, res)
     expect(res.statusCode).toBe(400)
     const data = JSON.parse(res._getData())
diff --git a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
index 62c4332bd2fbadaba33ceda8f3cfa2a98c6eed90..5bd2442091472233b2e08a0f0cb2e2c139db545c 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
@@ -6,7 +6,6 @@ const fixtures = require('./../fixtures/fixtures')
 const Model = require('./../helpers/Model')
 const cloneDeep = require('lodash/cloneDeep')
 
-const models = Model.build()
 jest.mock('pubsweet-component-mail-service', () => ({
   setupAssignEmail: jest.fn(),
   setupAgreeEmail: jest.fn(),
@@ -20,9 +19,11 @@ const patchPath = '../../routes/collectionsInvitations/patch'
 describe('Patch collections invitations route handler', () => {
   let testFixtures = {}
   let body = {}
+  let models
   beforeEach(() => {
     testFixtures = cloneDeep(fixtures)
     body = cloneDeep(reqBody)
+    models = Model.build(testFixtures)
   })
   it('should return success when the handling editor accepts work on a collection', async () => {
     const { handlingEditor } = testFixtures.users
@@ -33,7 +34,7 @@ describe('Patch collections invitations route handler', () => {
     req.user = handlingEditor.id
     req.params.collectionId = collection.id
     const heInv = collection.invitations.find(
-      inv => inv.role === 'handlingEditor',
+      inv => inv.role === 'handlingEditor' && inv.hasAnswer === false,
     )
     req.params.invitationId = heInv.id
     const res = httpMocks.createResponse()
@@ -65,7 +66,10 @@ 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' && inv.hasAnswer == false,
+    )
+    req.params.invitationId = heInv.id
     const res = httpMocks.createResponse()
     await require(patchPath)(models)(req, res)
 
@@ -127,7 +131,7 @@ describe('Patch collections invitations route handler', () => {
     req.user = reviewer.id
     req.params.collectionId = collection.id
     const inv = collection.invitations.find(
-      inv => inv.role === 'handlingEditor',
+      inv => inv.role === 'handlingEditor' && inv.hasAnswer === false,
     )
     req.params.invitationId = inv.id
     const res = httpMocks.createResponse()
@@ -138,4 +142,20 @@ describe('Patch collections invitations route handler', () => {
       `User ${reviewer.email} is not allowed to modify invitation ${inv.id}`,
     )
   })
+  it('should return an error when the invitation is already answered', async () => {
+    const { handlingEditor } = testFixtures.users
+    const { collection } = testFixtures.collections
+    const req = httpMocks.createRequest({
+      body,
+    })
+    req.user = handlingEditor.id
+    req.params.collectionId = collection.id
+    const inv = collection.invitations.find(inv => inv.hasAnswer)
+    req.params.invitationId = inv.id
+    const res = httpMocks.createResponse()
+    await require(patchPath)(models)(req, res)
+    expect(res.statusCode).toBe(400)
+    const data = JSON.parse(res._getData())
+    expect(data.error).toEqual(`${inv.id} has already been answered`)
+  })
 })
diff --git a/packages/component-invite/src/tests/collectionsInvitations/post.test.js b/packages/component-invite/src/tests/collectionsInvitations/post.test.js
index 14573ae7393e4f03910742ce25e2fc2975f024ba..5378ad0e6b6b0e81858874106ad58aeeab28a0b6 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/post.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/post.test.js
@@ -11,7 +11,6 @@ const cloneDeep = require('lodash/cloneDeep')
 
 const configRoles = config.get('roles')
 
-const models = Model.build()
 jest.mock('pubsweet-component-mail-service', () => ({
   setupInviteEmail: jest.fn(),
   setupAssignEmail: jest.fn(),
@@ -34,9 +33,11 @@ const postPath = '../../routes/collectionsInvitations/post'
 describe('Post collections invitations route handler', () => {
   let testFixtures = {}
   let body = {}
+  let models
   beforeEach(() => {
     testFixtures = cloneDeep(fixtures)
     body = cloneDeep(reqBody)
+    models = Model.build(testFixtures)
   })
   it('should return an error params are missing', async () => {
     const { admin } = testFixtures.users
diff --git a/packages/component-invite/src/tests/fixtures/collections.js b/packages/component-invite/src/tests/fixtures/collections.js
index 78920b4aa04df9a88ae59d850cf3daa0fb95d4bb..9331af1e1f653959caaf886ea8cc0e51c59b9324 100644
--- a/packages/component-invite/src/tests/fixtures/collections.js
+++ b/packages/component-invite/src/tests/fixtures/collections.js
@@ -35,6 +35,14 @@ const collections = {
         userId: reviewer.id,
         timestamp: chance.timestamp(),
       },
+      {
+        id: chance.guid(),
+        role: 'handlingEditor',
+        hasAnswer: true,
+        isAccepted: false,
+        userId: handlingEditor.id,
+        timestamp: chance.timestamp(),
+      },
     ],
     handlingEditor: {
       id: handlingEditor.id,
diff --git a/packages/component-invite/src/tests/helpers/Model.js b/packages/component-invite/src/tests/helpers/Model.js
index c1ded2c8e9866d90df89faa05d681b49dd207311..7337e1aa65d689787330b3996571b22c5c39504c 100644
--- a/packages/component-invite/src/tests/helpers/Model.js
+++ b/packages/component-invite/src/tests/helpers/Model.js
@@ -1,4 +1,4 @@
-const fixtures = require('../fixtures/fixtures')
+// const fixtures = require('../fixtures/fixtures')
 
 const UserMock = require('../mocks/User')
 const TeamMock = require('../mocks/Team')
@@ -7,23 +7,23 @@ const notFoundError = new Error()
 notFoundError.name = 'NotFoundError'
 notFoundError.status = 404
 
-const build = () => {
+const build = fixtures => {
   const models = {
     User: {},
     Collection: {
-      find: jest.fn(id => findMock(id, 'collections')),
+      find: jest.fn(id => findMock(id, 'collections', fixtures)),
     },
     Team: {},
     Fragment: {
-      find: jest.fn(id => findMock(id, 'fragments')),
+      find: jest.fn(id => findMock(id, 'fragments', fixtures)),
     },
   }
-  UserMock.find = jest.fn(id => findMock(id, 'users'))
-  UserMock.findByEmail = jest.fn(email => findByEmailMock(email))
+  UserMock.find = jest.fn(id => findMock(id, 'users', fixtures))
+  UserMock.findByEmail = jest.fn(email => findByEmailMock(email, fixtures))
   UserMock.all = jest.fn(() => Object.values(fixtures.users))
-  TeamMock.find = jest.fn(id => findMock(id, 'teams'))
+  TeamMock.find = jest.fn(id => findMock(id, 'teams', fixtures))
   TeamMock.updateProperties = jest.fn(team =>
-    updatePropertiesMock(team, 'teams'),
+    updatePropertiesMock(team, 'teams', fixtures),
   )
   TeamMock.all = jest.fn(() => Object.values(fixtures.teams))
 
@@ -32,7 +32,7 @@ const build = () => {
   return models
 }
 
-const findMock = (id, type) => {
+const findMock = (id, type, fixtures) => {
   const foundObj = Object.values(fixtures[type]).find(
     fixtureObj => fixtureObj.id === id,
   )
@@ -41,7 +41,7 @@ const findMock = (id, type) => {
   return Promise.resolve(foundObj)
 }
 
-const findByEmailMock = email => {
+const findByEmailMock = (email, fixtures) => {
   const foundUser = Object.values(fixtures.users).find(
     fixtureUser => fixtureUser.email === email,
   )
@@ -50,7 +50,7 @@ const findByEmailMock = email => {
   return Promise.resolve(foundUser)
 }
 
-const updatePropertiesMock = (obj, type) => {
+const updatePropertiesMock = (obj, type, fixtures) => {
   const foundObj = Object.values(fixtures[type]).find(
     fixtureObj => fixtureObj === obj,
   )
diff --git a/packages/component-mail-service/src/Mail.js b/packages/component-mail-service/src/Mail.js
index e5e4bbbd209e1cf81e098cc74e83f8de2decf83f..d0cd73a98305e197cb38d923b02b51979fddcd41 100644
--- a/packages/component-mail-service/src/Mail.js
+++ b/packages/component-mail-service/src/Mail.js
@@ -161,7 +161,9 @@ module.exports = {
         email: invitedUser.email,
         token: invitedUser.passwordResetToken,
         collectionId: collection.id,
+        fragmentId,
         agree: true,
+        invitationId,
       })}`
     }
 
diff --git a/packages/component-user-manager/src/helpers/Collection.js b/packages/component-user-manager/src/helpers/Collection.js
index 40cf70f3bd2965e1e6d5b2bc86d3b30372391a3d..85853a987c05a85f28010d59a9579ee503969dd4 100644
--- a/packages/component-user-manager/src/helpers/Collection.js
+++ b/packages/component-user-manager/src/helpers/Collection.js
@@ -13,6 +13,11 @@ module.exports = {
     collection.authors = collection.authors || []
     const author = {
       userId: user.id,
+      firstName: user.firstName || '',
+      lastName: user.lastName || '',
+      email: user.email,
+      title: user.title || '',
+      affiliation: user.affiliation || '',
       isSubmitting,
       isCorresponding,
     }
diff --git a/packages/component-user-manager/src/routes/collectionsUsers/get.js b/packages/component-user-manager/src/routes/collectionsUsers/get.js
index 7f11e412a000edc026e8b7ce336b2ec39fb46ed3..1d6b395dd79dfeaa3e5b38f8c00a4b29d6c5716b 100644
--- a/packages/component-user-manager/src/routes/collectionsUsers/get.js
+++ b/packages/component-user-manager/src/routes/collectionsUsers/get.js
@@ -2,7 +2,7 @@ const helpers = require('../../helpers/helpers')
 const teamHelper = require('../../helpers/Team')
 
 module.exports = models => async (req, res) => {
-  // TO DO: add authsom
+  // TO DO: add authsome
   const { collectionId } = req.params
   try {
     const collection = await models.Collection.find(collectionId)
diff --git a/packages/components-faraday/src/components/Dashboard/DashboardCard.js b/packages/components-faraday/src/components/Dashboard/DashboardCard.js
index dc6058df1952753ac83d84766fcbecb644ce7204..d291f88149fbee610b0d3a9efadb861e9360efed 100644
--- a/packages/components-faraday/src/components/Dashboard/DashboardCard.js
+++ b/packages/components-faraday/src/components/Dashboard/DashboardCard.js
@@ -108,14 +108,14 @@ const DashboardCard = ({
         <DetailsView>
           <Top>
             <AuthorList>
-              {version.authors.map(
+              {project.authors.map(
                 (
                   {
                     affiliation,
                     firstName,
                     lastName,
-                    middleName,
                     email,
+                    userId,
                     isSubmitting,
                     isCorresponding,
                   },
@@ -124,16 +124,15 @@ const DashboardCard = ({
                 ) => (
                   <AuthorTooltip
                     affiliation={affiliation}
-                    authorName={`${firstName} ${lastName}`}
+                    authorName={`${firstName || ''} ${lastName || ''}`}
+                    currentUser={currentUser}
                     email={email}
                     isCorresponding={isCorresponding}
                     isSubmitting={isSubmitting}
-                    key={email}
+                    key={userId}
                   >
                     <Author>
-                      <AuthorName>
-                        {firstName} {middleName} {lastName}
-                      </AuthorName>
+                      <AuthorName>{`${firstName} ${lastName}`}</AuthorName>
                       {isSubmitting && <AuthorStatus>SA</AuthorStatus>}
                       {isCorresponding && <AuthorStatus>CA</AuthorStatus>}
                       {arr.length - 1 === index ? '' : ','}
@@ -224,6 +223,7 @@ const AuthorList = styled.span`
 const AuthorName = styled.span`
   text-decoration: underline;
   padding-left: 2px;
+  cursor: default;
 `
 const Author = styled.div`
   padding-right: ${th('subGridUnit')};
diff --git a/packages/xpub-faraday-server/src/AuthorBackend.js b/packages/xpub-faraday-server/src/AuthorBackend.js
index 3c0fbcc1dab501f51fb9080d8612ada06746fcde..d05bb8349c8ae0e5dcc051102e710c9c2196871c 100644
--- a/packages/xpub-faraday-server/src/AuthorBackend.js
+++ b/packages/xpub-faraday-server/src/AuthorBackend.js
@@ -40,7 +40,7 @@ const AuthorBackend = app => {
           if (submittingAuthors.length > 0) {
             res
               .status(400)
-              .json({ error: 'There can only be one sumbitting author' })
+              .json({ error: 'There can only be one submitting author' })
             return
           }
         }
diff --git a/packages/xpub-faraday-server/src/AuthorBackend.test.js b/packages/xpub-faraday-server/src/AuthorBackend.test.js
index 697e0b8237acb26da5f79904d80b2bf6e01b543b..ab4ee126dd3f531778bcfb68f9fc19ee43e2cd35 100644
--- a/packages/xpub-faraday-server/src/AuthorBackend.test.js
+++ b/packages/xpub-faraday-server/src/AuthorBackend.test.js
@@ -130,7 +130,7 @@ describe('Author Backend API', () => {
       .post(createAuthorUrl)
       .set('Authorization', 'Bearer 123')
       .send(testFixtures.authors.newSubmittingAuthor)
-      .expect(400, '{"error":"There can only be one sumbitting author"}')
+      .expect(400, '{"error":"There can only be one submitting author"}')
   })
 
   it('should return success when saving a new author', () => {