Skip to content
Snippets Groups Projects
patch.js 3.34 KiB
Newer Older
  authsome: authsomeHelper,
} = require('pubsweet-component-helper-service')

const Job = require('pubsweet-component-jobs')
const notifications = require('./emails/notifications')

module.exports = models => async (req, res) => {
  const { collectionId, invitationId, fragmentId } = req.params
  const { isAccepted, reason } = req.body

  const UserModel = models.User
  const user = await UserModel.find(req.user)
  try {
    const collection = await models.Collection.find(collectionId)
    if (!collection.fragments.includes(fragmentId))
      return res.status(400).json({
        error: `Fragment ${fragmentId} does not match collection ${collectionId}`,
      })
    const fragment = await models.Fragment.find(fragmentId)
    fragment.invitations = fragment.invitations || []
    const invitation = await fragment.invitations.find(
      invitation => invitation.id === invitationId,
    )

    const invitationHelper = new Invitation({
      userId: user.id,
      role: 'reviewer',
      invitation,
    })
    const invitationValidation = invitationHelper.validateInvitation()
    if (invitationValidation.error)
      return res.status(invitationValidation.status).json({
        error: invitationValidation.error,
      })

    const authsome = authsomeHelper.getAuthsome(models)
    const canPatch = await authsome.can(req.user, 'PATCH', invitation)
    if (!canPatch)
      return res.status(403).json({
        error: 'Unauthorized.',
      })

    await Job.cancelQueue(`reminders-${user.id}-${invitation.id}`)
    await Job.cancelQueue(`removal-${user.id}-${invitation.id}`)
    const collectionHelper = new Collection({ collection })
    const baseUrl = services.getBaseUrl(req)

    invitation.respondedOn = Date.now()
    invitation.hasAnswer = true
      if (collection.status === 'reviewersInvited') {
        collectionHelper.updateStatus({ newStatus: 'underReview' })
      }
      fragment.save()
    } else {
      if (reason) invitation.reason = reason
      collectionHelper.updateStatusByNumberOfReviewers({
        invitations: fragment.invitations,

      const teamHelper = new Team({
        fragmentId,
        collectionId,
        TeamModel: models.Team,
      })

      const reviewerTeam = await teamHelper.getTeam({
        role: 'reviewer',
        objectType: 'fragment',
      })

      await teamHelper.removeTeamMember({
        teamId: reviewerTeam.id,
        userId: user.id,
      })

      user.teams = user.teams.filter(
        userTeamId => reviewerTeam.id !== userTeamId,
      )
      await user.save()
    notifications.sendHandlingEditorEmail({
      baseUrl,
      fragment,
      collection,
      reviewer: user,
      UserModel: models.User,
      emailType:
        isAccepted === true ? 'reviewer-accepted' : 'reviewer-declined',
    if (isAccepted) {
      notifications.sendReviewerEmail({
        baseUrl,
        fragment,
        collection,
        reviewer: user,
        isCanceled: false,
        UserModel: models.User,
      })
    }

    return res.status(200).json(invitation)
  } catch (e) {
    const notFoundError = await services.handleNotFoundError(e, 'Item')
    return res.status(notFoundError.status).json({
      error: notFoundError.message,
    })
  }
}