mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Refactor. Handle republishing of notifications on resend.
This commit is contained in:
parent
85f49d6c9c
commit
ece0491e3d
7 changed files with 331 additions and 232 deletions
|
@ -20,27 +20,6 @@ module.exports = CollaboratorsInviteController =
|
|||
return next(err)
|
||||
res.json({invites: invites})
|
||||
|
||||
_trySendInviteNotification: (projectId, sendingUser, invite, callback=(err)->) ->
|
||||
email = invite.email
|
||||
UserGetter.getUser {email: email}, {_id: 1}, (err, existingUser) ->
|
||||
if err?
|
||||
logger.err {projectId, email}, "error checking if user exists"
|
||||
return callback(err)
|
||||
if !existingUser?
|
||||
logger.log {projectId, email}, "no existing user found, returning"
|
||||
return callback(null)
|
||||
ProjectGetter.getProject projectId, {_id: 1, name: 1}, (err, project) ->
|
||||
if err?
|
||||
logger.err {projectId, email}, "error getting project"
|
||||
return callback(err)
|
||||
if !project?
|
||||
logger.log {projectId}, "no project found while sending notification, returning"
|
||||
return callback(null)
|
||||
NotificationsBuilder.projectInvite(invite, project, sendingUser, existingUser).create(callback)
|
||||
|
||||
_tryCancelInviteNotification: (inviteId, currentUser, callback=()->) ->
|
||||
NotificationsBuilder.projectInvite({_id: inviteId}, null, null, currentUser).read(callback)
|
||||
|
||||
inviteToProject: (req, res, next) ->
|
||||
projectId = req.params.Project_id
|
||||
email = req.body.email
|
||||
|
@ -57,14 +36,12 @@ module.exports = CollaboratorsInviteController =
|
|||
if !email? or email == ""
|
||||
logger.log {projectId, email, sendingUserId}, "invalid email address"
|
||||
return res.sendStatus(400)
|
||||
CollaboratorsInviteHandler.inviteToProject projectId, sendingUserId, email, privileges, (err, invite) ->
|
||||
CollaboratorsInviteHandler.inviteToProject projectId, sendingUser, email, privileges, (err, invite) ->
|
||||
if err?
|
||||
logger.err {projectId, email, sendingUserId}, "error creating project invite"
|
||||
return next(err)
|
||||
logger.log {projectId, email, sendingUserId}, "invite created"
|
||||
EditorRealTimeController.emitToRoom projectId, 'project:membership:changed', {invites: true}
|
||||
# async check if email is for an existing user, send a notification
|
||||
CollaboratorsInviteController._trySendInviteNotification(projectId, sendingUser, invite, ()->)
|
||||
EditorRealTimeController.emitToRoom(projectId, 'project:membership:changed', {invites: true})
|
||||
return res.json {invite: invite}
|
||||
|
||||
revokeInvite: (req, res, next) ->
|
||||
|
@ -81,8 +58,9 @@ module.exports = CollaboratorsInviteController =
|
|||
resendInvite: (req, res, next) ->
|
||||
projectId = req.params.Project_id
|
||||
inviteId = req.params.invite_id
|
||||
sendingUser = req.session.user
|
||||
logger.log {projectId, inviteId}, "resending invite"
|
||||
CollaboratorsInviteHandler.resendInvite projectId, inviteId, (err) ->
|
||||
CollaboratorsInviteHandler.resendInvite projectId, sendingUser, inviteId, (err) ->
|
||||
if err?
|
||||
logger.err {projectId, inviteId}, "error resending invite"
|
||||
return next(err)
|
||||
|
@ -142,5 +120,4 @@ module.exports = CollaboratorsInviteController =
|
|||
logger.err {projectId, inviteId}, "error accepting invite by token"
|
||||
return next(err)
|
||||
EditorRealTimeController.emitToRoom projectId, 'project:membership:changed', {invites: true, members: true}
|
||||
CollaboratorsInviteController._tryCancelInviteNotification inviteId, currentUser, () ->
|
||||
res.redirect "/project/#{projectId}"
|
||||
|
|
|
@ -2,10 +2,13 @@ ProjectInvite = require("../../models/ProjectInvite").ProjectInvite
|
|||
logger = require('logger-sharelatex')
|
||||
CollaboratorsEmailHandler = require "./CollaboratorsEmailHandler"
|
||||
CollaboratorsHandler = require "./CollaboratorsHandler"
|
||||
UserGetter = require "../User/UserGetter"
|
||||
ProjectGetter = require "../Project/ProjectGetter"
|
||||
Async = require "async"
|
||||
PrivilegeLevels = require "../Authorization/PrivilegeLevels"
|
||||
Errors = require "../Errors/Errors"
|
||||
Crypto = require 'crypto'
|
||||
NotificationsBuilder = require("../Notifications/NotificationsBuilder")
|
||||
|
||||
|
||||
module.exports = CollaboratorsInviteHandler =
|
||||
|
@ -27,26 +30,57 @@ module.exports = CollaboratorsInviteHandler =
|
|||
return callback(err)
|
||||
callback(null, count)
|
||||
|
||||
inviteToProject: (projectId, sendingUserId, email, privileges, callback=(err,invite)->) ->
|
||||
logger.log {projectId, sendingUserId, email, privileges}, "adding invite"
|
||||
_trySendInviteNotification: (projectId, sendingUser, invite, callback=(err)->) ->
|
||||
email = invite.email
|
||||
UserGetter.getUser {email: email}, {_id: 1}, (err, existingUser) ->
|
||||
if err?
|
||||
logger.err {projectId, email}, "error checking if user exists"
|
||||
return callback(err)
|
||||
if !existingUser?
|
||||
logger.log {projectId, email}, "no existing user found, returning"
|
||||
return callback(null)
|
||||
ProjectGetter.getProject projectId, {_id: 1, name: 1}, (err, project) ->
|
||||
if err?
|
||||
logger.err {projectId, email}, "error getting project"
|
||||
return callback(err)
|
||||
if !project?
|
||||
logger.log {projectId}, "no project found while sending notification, returning"
|
||||
return callback(null)
|
||||
NotificationsBuilder.projectInvite(invite, project, sendingUser, existingUser).create(callback)
|
||||
|
||||
_tryCancelInviteNotification: (inviteId, callback=()->) ->
|
||||
NotificationsBuilder.projectInvite({_id: inviteId}, null, null, null).read(callback)
|
||||
|
||||
_sendMessages: (projectId, sendingUser, invite, callback=(err)->) ->
|
||||
logger.log {projectId, inviteId: invite._id}, "sending notification and email for invite"
|
||||
CollaboratorsEmailHandler.notifyUserOfProjectInvite projectId, invite.email, invite, (err)->
|
||||
return callback(err) if err?
|
||||
CollaboratorsInviteHandler._trySendInviteNotification projectId, sendingUser, invite, (err)->
|
||||
return callback(err) if err?
|
||||
callback()
|
||||
|
||||
inviteToProject: (projectId, sendingUser, email, privileges, callback=(err,invite)->) ->
|
||||
logger.log {projectId, sendingUserId: sendingUser._id, email, privileges}, "adding invite"
|
||||
Crypto.randomBytes 24, (err, buffer) ->
|
||||
if err?
|
||||
logger.err {err, projectId, sendingUserId, email}, "error generating random token"
|
||||
logger.err {err, projectId, sendingUserId: sendingUser._id, email}, "error generating random token"
|
||||
return callback(err)
|
||||
token = buffer.toString('hex')
|
||||
invite = new ProjectInvite {
|
||||
email: email
|
||||
token: token
|
||||
sendingUserId: sendingUserId
|
||||
sendingUserId: sendingUser._id
|
||||
projectId: projectId
|
||||
privileges: privileges
|
||||
}
|
||||
invite.save (err, invite) ->
|
||||
if err?
|
||||
logger.err {err, projectId, sendingUserId, email}, "error saving token"
|
||||
logger.err {err, projectId, sendingUserId: sendingUser._id, email}, "error saving token"
|
||||
return callback(err)
|
||||
CollaboratorsEmailHandler.notifyUserOfProjectInvite projectId, email, invite
|
||||
callback(null, invite)
|
||||
CollaboratorsInviteHandler._sendMessages projectId, sendingUser, invite, (err) ->
|
||||
if err?
|
||||
logger.err {projectId, email}, "error sending messages for invite"
|
||||
callback(err, invite)
|
||||
|
||||
revokeInvite: (projectId, inviteId, callback=(err)->) ->
|
||||
logger.log {projectId, inviteId}, "removing invite"
|
||||
|
@ -54,9 +88,10 @@ module.exports = CollaboratorsInviteHandler =
|
|||
if err?
|
||||
logger.err {err, projectId, inviteId}, "error removing invite"
|
||||
return callback(err)
|
||||
CollaboratorsInviteHandler._tryCancelInviteNotification(inviteId, ()->)
|
||||
callback(null)
|
||||
|
||||
resendInvite: (projectId, inviteId, callback=(err)->) ->
|
||||
resendInvite: (projectId, sendingUser, inviteId, callback=(err)->) ->
|
||||
logger.log {projectId, inviteId}, "resending invite email"
|
||||
ProjectInvite.findOne {_id: inviteId, projectId: projectId}, (err, invite) ->
|
||||
if err?
|
||||
|
@ -65,8 +100,11 @@ module.exports = CollaboratorsInviteHandler =
|
|||
if !invite?
|
||||
logger.err {err, projectId, inviteId}, "no invite found, nothing to resend"
|
||||
return callback(null)
|
||||
CollaboratorsEmailHandler.notifyUserOfProjectInvite projectId, invite.email, invite
|
||||
callback(null)
|
||||
CollaboratorsInviteHandler._sendMessages projectId, sendingUser, invite, (err) ->
|
||||
if err?
|
||||
logger.err {projectid, inviteId}, "error resending invite messages"
|
||||
return callback(err)
|
||||
callback(null)
|
||||
|
||||
getInviteByToken: (projectId, tokenString, callback=(err,invite)->) ->
|
||||
logger.log {projectId, tokenString}, "fetching invite by token"
|
||||
|
@ -100,4 +138,5 @@ module.exports = CollaboratorsInviteHandler =
|
|||
if err?
|
||||
logger.err {err, projectId, inviteId}, "error removing invite"
|
||||
return callback(err)
|
||||
CollaboratorsInviteHandler._tryCancelInviteNotification inviteId, ()->
|
||||
callback()
|
||||
|
|
|
@ -12,7 +12,7 @@ module.exports =
|
|||
groupName: licence.name
|
||||
subscription_id: licence.subscription_id
|
||||
logger.log user_id:user._id, key:key, "creating notification key for user"
|
||||
NotificationsHandler.createNotification user._id, @key, "notification_group_invite", messageOpts, null, callback
|
||||
NotificationsHandler.createNotification user._id, @key, "notification_group_invite", messageOpts, null, false, callback
|
||||
|
||||
read: (callback = ->)->
|
||||
NotificationsHandler.markAsReadWithKey user._id, @key, callback
|
||||
|
@ -26,6 +26,6 @@ module.exports =
|
|||
projectId: project._id.toString()
|
||||
token: invite.token
|
||||
logger.log {user_id: user._id, project_id: project._id, invite_id: invite._id, key: @key}, "creating project invite notification for user"
|
||||
NotificationsHandler.createNotification user._id, @key, "notification_project_invite", messageOpts, invite.expires, callback
|
||||
NotificationsHandler.createNotification user._id, @key, "notification_project_invite", messageOpts, invite.expires, true, callback
|
||||
read: (callback=()->) ->
|
||||
NotificationsHandler.markAsReadByKeyOnly @key, callback
|
||||
|
|
|
@ -29,7 +29,7 @@ module.exports =
|
|||
unreadNotifications = []
|
||||
callback(null, unreadNotifications)
|
||||
|
||||
createNotification: (user_id, key, templateKey, messageOpts, expiryDateTime, callback)->
|
||||
createNotification: (user_id, key, templateKey, messageOpts, expiryDateTime, forceCreate, callback)->
|
||||
payload = {
|
||||
key:key
|
||||
messageOpts:messageOpts
|
||||
|
@ -37,6 +37,8 @@ module.exports =
|
|||
}
|
||||
if expiryDateTime?
|
||||
payload.expires = expiryDateTime
|
||||
if forceCreate
|
||||
payload.forceCreate = true
|
||||
opts =
|
||||
uri: "#{settings.apis.notifications?.url}/user/#{user_id}"
|
||||
timeout: oneSecond
|
||||
|
|
|
@ -26,166 +26,6 @@ describe "CollaboratorsInviteController", ->
|
|||
@project_id = "project-id-123"
|
||||
@callback = sinon.stub()
|
||||
|
||||
describe '_tryCancelInviteNotification', ->
|
||||
beforeEach ->
|
||||
@inviteId = ObjectId()
|
||||
@currentUser = {_id: ObjectId()}
|
||||
@notification = {read: sinon.stub().callsArgWith(0, null)}
|
||||
@NotificationsBuilder.projectInvite = sinon.stub().returns(@notification)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteController._tryCancelInviteNotification @inviteId, @currentUser, callback
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should call notification.read', (done) ->
|
||||
@call (err) =>
|
||||
@notification.read.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
describe 'when notification.read produces an error', ->
|
||||
beforeEach ->
|
||||
@notification = {read: sinon.stub().callsArgWith(0, new Error('woops'))}
|
||||
@NotificationsBuilder.projectInvite = sinon.stub().returns(@notification)
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
describe "_trySendInviteNotification", ->
|
||||
|
||||
beforeEach ->
|
||||
@invite =
|
||||
_id: ObjectId(),
|
||||
token: "some_token",
|
||||
sendingUserId: ObjectId(),
|
||||
projectId: @project_id,
|
||||
targetEmail: 'user@example.com'
|
||||
createdAt: new Date(),
|
||||
@sendingUser =
|
||||
_id: ObjectId()
|
||||
first_name: "jim"
|
||||
@existingUser = {_id: ObjectId()}
|
||||
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @existingUser)
|
||||
@fakeProject =
|
||||
_id: @project_id
|
||||
name: "some project"
|
||||
@ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, @fakeProject)
|
||||
@notification = {create: sinon.stub().callsArgWith(0, null)}
|
||||
@NotificationsBuilder.projectInvite = sinon.stub().returns(@notification)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteController._trySendInviteNotification @project_id, @sendingUser, @invite, callback
|
||||
|
||||
describe 'when the user exists', ->
|
||||
|
||||
beforeEach ->
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should call getUser', (done) ->
|
||||
@call (err) =>
|
||||
@UserGetter.getUser.callCount.should.equal 1
|
||||
@UserGetter.getUser.calledWith({email: @invite.email}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should call getProject', (done) ->
|
||||
@call (err) =>
|
||||
@ProjectGetter.getProject.callCount.should.equal 1
|
||||
@ProjectGetter.getProject.calledWith(@project_id).should.equal true
|
||||
done()
|
||||
|
||||
it 'should call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 1
|
||||
@notification.create.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
describe 'when getProject produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@ProjectGetter.getProject.callsArgWith(2, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
it 'should not call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 0
|
||||
@notification.create.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'when projectInvite.create produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@notification.create.callsArgWith(0, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
describe 'when the user does not exist', ->
|
||||
|
||||
beforeEach ->
|
||||
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, null)
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should call getUser', (done) ->
|
||||
@call (err) =>
|
||||
@UserGetter.getUser.callCount.should.equal 1
|
||||
@UserGetter.getUser.calledWith({email: @invite.email}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should not call getProject', (done) ->
|
||||
@call (err) =>
|
||||
@ProjectGetter.getProject.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
it 'should not call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 0
|
||||
@notification.create.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'when the getUser produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@UserGetter.getUser = sinon.stub().callsArgWith(2, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
it 'should call getUser', (done) ->
|
||||
@call (err) =>
|
||||
@UserGetter.getUser.callCount.should.equal 1
|
||||
@UserGetter.getUser.calledWith({email: @invite.email}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should not call getProject', (done) ->
|
||||
@call (err) =>
|
||||
@ProjectGetter.getProject.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
it 'should not call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 0
|
||||
@notification.create.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'getAllInvites', ->
|
||||
|
||||
beforeEach ->
|
||||
|
@ -231,8 +71,10 @@ describe "CollaboratorsInviteController", ->
|
|||
@targetEmail = "user@example.com"
|
||||
@req.params =
|
||||
Project_id: @project_id
|
||||
@current_user =
|
||||
_id: @current_user_id = "current-user-id"
|
||||
@req.session =
|
||||
user: _id: @current_user_id = "current-user-id"
|
||||
user: @current_user
|
||||
@req.body =
|
||||
email: @targetEmail
|
||||
privileges: @privileges = "readAndWrite"
|
||||
|
@ -248,7 +90,6 @@ describe "CollaboratorsInviteController", ->
|
|||
}
|
||||
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, null, true)
|
||||
@CollaboratorsInviteHandler.inviteToProject = sinon.stub().callsArgWith(4, null, @invite)
|
||||
@CollaboratorsInviteController._trySendInviteNotification = sinon.stub()
|
||||
@callback = sinon.stub()
|
||||
@next = sinon.stub()
|
||||
|
||||
|
@ -268,15 +109,12 @@ describe "CollaboratorsInviteController", ->
|
|||
|
||||
it 'should have called inviteToProject', ->
|
||||
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 1
|
||||
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user_id,@targetEmail,@privileges).should.equal true
|
||||
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user,@targetEmail,@privileges).should.equal true
|
||||
|
||||
it 'should have called emitToRoom', ->
|
||||
@EditorRealTimeController.emitToRoom.callCount.should.equal 1
|
||||
@EditorRealTimeController.emitToRoom.calledWith(@project_id, 'project:membership:changed').should.equal true
|
||||
|
||||
it 'should call _trySendInviteNotification', ->
|
||||
@CollaboratorsInviteController._trySendInviteNotification.callCount.should.equal 1
|
||||
|
||||
describe 'when the user is not allowed to add more collaborators', ->
|
||||
|
||||
beforeEach ->
|
||||
|
@ -321,7 +159,7 @@ describe "CollaboratorsInviteController", ->
|
|||
|
||||
it 'should have called inviteToProject', ->
|
||||
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 1
|
||||
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user_id,@targetEmail,@privileges).should.equal true
|
||||
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user,@targetEmail,@privileges).should.equal true
|
||||
|
||||
describe "viewInvite", ->
|
||||
|
||||
|
@ -604,7 +442,7 @@ describe "CollaboratorsInviteController", ->
|
|||
user: _id: @current_user_id = "current-user-id"
|
||||
@res.render = sinon.stub()
|
||||
@res.sendStatus = sinon.stub()
|
||||
@CollaboratorsInviteHandler.resendInvite = sinon.stub().callsArgWith(2, null)
|
||||
@CollaboratorsInviteHandler.resendInvite = sinon.stub().callsArgWith(3, null)
|
||||
@callback = sinon.stub()
|
||||
@next = sinon.stub()
|
||||
|
||||
|
@ -624,7 +462,7 @@ describe "CollaboratorsInviteController", ->
|
|||
|
||||
beforeEach ->
|
||||
@err = new Error('woops')
|
||||
@CollaboratorsInviteHandler.resendInvite = sinon.stub().callsArgWith(2, @err)
|
||||
@CollaboratorsInviteHandler.resendInvite = sinon.stub().callsArgWith(3, @err)
|
||||
@CollaboratorsInviteController.resendInvite @req, @res, @next
|
||||
|
||||
it 'should not produce a 201 response', ->
|
||||
|
@ -637,15 +475,16 @@ describe "CollaboratorsInviteController", ->
|
|||
it 'should have called resendInvite', ->
|
||||
@CollaboratorsInviteHandler.resendInvite.callCount.should.equal 1
|
||||
|
||||
|
||||
describe "revokeInvite", ->
|
||||
|
||||
beforeEach ->
|
||||
@req.params =
|
||||
Project_id: @project_id
|
||||
invite_id: @invite_id = "thuseoautoh"
|
||||
@current_user =
|
||||
_id: @current_user_id = "current-user-id"
|
||||
@req.session =
|
||||
user: _id: @current_user_id = "current-user-id"
|
||||
user: @current_user
|
||||
@res.render = sinon.stub()
|
||||
@res.sendStatus = sinon.stub()
|
||||
@CollaboratorsInviteHandler.revokeInvite = sinon.stub().callsArgWith(2, null)
|
||||
|
@ -698,7 +537,6 @@ describe "CollaboratorsInviteController", ->
|
|||
@res.render = sinon.stub()
|
||||
@res.redirect = sinon.stub()
|
||||
@CollaboratorsInviteHandler.acceptInvite = sinon.stub().callsArgWith(4, null)
|
||||
@CollaboratorsInviteController._tryCancelInviteNotification = sinon.stub()
|
||||
@callback = sinon.stub()
|
||||
@next = sinon.stub()
|
||||
|
||||
|
@ -718,9 +556,6 @@ describe "CollaboratorsInviteController", ->
|
|||
@EditorRealTimeController.emitToRoom.callCount.should.equal 1
|
||||
@EditorRealTimeController.emitToRoom.calledWith(@project_id, 'project:membership:changed').should.equal true
|
||||
|
||||
it 'should call _tryCancelInviteNotification', ->
|
||||
@CollaboratorsInviteController._tryCancelInviteNotification.callCount.should.equal 1
|
||||
|
||||
describe 'when revokeInvite produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
|
|
|
@ -24,14 +24,20 @@ describe "CollaboratorsInviteHandler", ->
|
|||
@Crypto = Crypto
|
||||
@CollaboratorsInviteHandler = SandboxedModule.require modulePath, requires:
|
||||
'settings-sharelatex': @settings = {}
|
||||
'../../models/ProjectInvite': {ProjectInvite: @ProjectInvite}
|
||||
'logger-sharelatex': @logger = {err: sinon.stub(), error: sinon.stub(), log: sinon.stub()}
|
||||
'./CollaboratorsEmailHandler': @CollaboratorsEmailHandler = {}
|
||||
"./CollaboratorsHandler": @CollaboratorsHandler = {addUserIdToProject: sinon.stub()}
|
||||
'../../models/ProjectInvite': {ProjectInvite: @ProjectInvite}
|
||||
'../User/UserGetter': @UserGetter = {getUser: sinon.stub()}
|
||||
"../Project/ProjectGetter": @ProjectGetter = {}
|
||||
"../Notifications/NotificationsBuilder": @NotificationsBuilder = {}
|
||||
'crypto': @Crypto
|
||||
|
||||
@projectId = ObjectId()
|
||||
@sendingUserId = ObjectId()
|
||||
@sendingUser =
|
||||
_id: @sendingUserId
|
||||
name: "Bob"
|
||||
@email = "user@example.com"
|
||||
@userId = ObjectId()
|
||||
@user =
|
||||
|
@ -125,9 +131,9 @@ describe "CollaboratorsInviteHandler", ->
|
|||
beforeEach ->
|
||||
@ProjectInvite::save = sinon.spy (cb) -> cb(null, this)
|
||||
@randomBytesSpy = sinon.spy(@Crypto, 'randomBytes')
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite = sinon.stub()
|
||||
@CollaboratorsInviteHandler._sendMessages = sinon.stub().callsArgWith(3, null)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteHandler.inviteToProject @projectId, @sendingUserId, @email, @privileges, callback
|
||||
@CollaboratorsInviteHandler.inviteToProject @projectId, @sendingUser, @email, @privileges, callback
|
||||
|
||||
afterEach ->
|
||||
@randomBytesSpy.restore()
|
||||
|
@ -160,10 +166,10 @@ describe "CollaboratorsInviteHandler", ->
|
|||
@ProjectInvite::save.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
it 'should have called CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
|
||||
it 'should have called _sendMessages', (done) ->
|
||||
@call (err, invite) =>
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 1
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.calledWith(@projectId, @email).should.equal true
|
||||
@CollaboratorsInviteHandler._sendMessages.callCount.should.equal 1
|
||||
@CollaboratorsInviteHandler._sendMessages.calledWith(@projectId, @sendingUser).should.equal true
|
||||
done()
|
||||
|
||||
describe 'when saving model produces an error', ->
|
||||
|
@ -176,10 +182,64 @@ describe "CollaboratorsInviteHandler", ->
|
|||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
describe '_sendMessages', ->
|
||||
|
||||
beforeEach ->
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite = sinon.stub().callsArgWith(3, null)
|
||||
@CollaboratorsInviteHandler._trySendInviteNotification = sinon.stub().callsArgWith(3, null)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteHandler._sendMessages @projectId, @sendingUser, @fakeInvite, callback
|
||||
|
||||
describe 'when all goes well', ->
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.not.be.instanceof Error
|
||||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should call CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
|
||||
@call (err) =>
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 1
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.calledWith(@projectId, @fakeInvite.email, @fakeInvite).should.equal true
|
||||
done()
|
||||
|
||||
it 'should call _trySendInviteNotification', (done) ->
|
||||
@call (err) =>
|
||||
@CollaboratorsInviteHandler._trySendInviteNotification.callCount.should.equal 1
|
||||
@CollaboratorsInviteHandler._trySendInviteNotification.calledWith(@projectId, @sendingUser, @fakeInvite).should.equal true
|
||||
done()
|
||||
|
||||
describe 'when CollaboratorsEmailHandler.notifyUserOfProjectInvite produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite = sinon.stub().callsArgWith(3, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err, invite) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
it 'should not call _trySendInviteNotification', (done) ->
|
||||
@call (err) =>
|
||||
@CollaboratorsInviteHandler._trySendInviteNotification.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'when _trySendInviteNotification produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@CollaboratorsInviteHandler._trySendInviteNotification = sinon.stub().callsArgWith(3, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err, invite) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
describe 'revokeInvite', ->
|
||||
|
||||
beforeEach ->
|
||||
@ProjectInvite.remove.callsArgWith(1, null)
|
||||
@CollaboratorsInviteHandler._tryCancelInviteNotification = sinon.stub().callsArgWith(1, null)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteHandler.revokeInvite @projectId, @inviteId, callback
|
||||
|
||||
|
@ -199,6 +259,12 @@ describe "CollaboratorsInviteHandler", ->
|
|||
@ProjectInvite.remove.calledWith({projectId: @projectId, _id: @inviteId}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should call _tryCancelInviteNotification', (done) ->
|
||||
@call (err) =>
|
||||
@CollaboratorsInviteHandler._tryCancelInviteNotification.callCount.should.equal 1
|
||||
@CollaboratorsInviteHandler._tryCancelInviteNotification.calledWith(@inviteId).should.equal true
|
||||
done()
|
||||
|
||||
describe 'when remove produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
|
@ -213,9 +279,9 @@ describe "CollaboratorsInviteHandler", ->
|
|||
|
||||
beforeEach ->
|
||||
@ProjectInvite.findOne.callsArgWith(1, null, @fakeInvite)
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite = sinon.stub()
|
||||
@CollaboratorsInviteHandler._sendMessages = sinon.stub().callsArgWith(3, null)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteHandler.resendInvite @projectId, @inviteId, callback
|
||||
@CollaboratorsInviteHandler.resendInvite @projectId, @sendingUser, @inviteId, callback
|
||||
|
||||
describe 'when all goes well', ->
|
||||
|
||||
|
@ -233,10 +299,10 @@ describe "CollaboratorsInviteHandler", ->
|
|||
@ProjectInvite.findOne.calledWith({_id: @inviteId, projectId: @projectId}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should have called CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
|
||||
it 'should have called _sendMessages', (done) ->
|
||||
@call (err, invite) =>
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 1
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.calledWith(@projectId, @email).should.equal true
|
||||
@CollaboratorsInviteHandler._sendMessages.callCount.should.equal 1
|
||||
@CollaboratorsInviteHandler._sendMessages.calledWith(@projectId, @sendingUser, @fakeInvite).should.equal true
|
||||
done()
|
||||
|
||||
describe 'when findOne produces an error', ->
|
||||
|
@ -249,9 +315,9 @@ describe "CollaboratorsInviteHandler", ->
|
|||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
it 'should not have called CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
|
||||
it 'should not have called _sendMessages', (done) ->
|
||||
@call (err, invite) =>
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 0
|
||||
@CollaboratorsInviteHandler._sendMessages.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'when findOne does not find an invite', ->
|
||||
|
@ -265,9 +331,9 @@ describe "CollaboratorsInviteHandler", ->
|
|||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should not have called CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
|
||||
it 'should not have called _sendMessages', (done) ->
|
||||
@call (err, invite) =>
|
||||
@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 0
|
||||
@CollaboratorsInviteHandler._sendMessages.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'getInviteByToken', ->
|
||||
|
@ -335,6 +401,7 @@ describe "CollaboratorsInviteHandler", ->
|
|||
@CollaboratorsHandler.addUserIdToProject.callsArgWith(4, null)
|
||||
@_getInviteByToken = sinon.stub(@CollaboratorsInviteHandler, 'getInviteByToken')
|
||||
@_getInviteByToken.callsArgWith(2, null, @fakeInvite)
|
||||
@CollaboratorsInviteHandler._tryCancelInviteNotification = sinon.stub().callsArgWith(1, null)
|
||||
@ProjectInvite.remove.callsArgWith(1, null)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteHandler.acceptInvite @projectId, @inviteId, @token, @user, callback
|
||||
|
@ -494,3 +561,163 @@ describe "CollaboratorsInviteHandler", ->
|
|||
@call (err) =>
|
||||
@ProjectInvite.remove.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
describe '_tryCancelInviteNotification', ->
|
||||
beforeEach ->
|
||||
@inviteId = ObjectId()
|
||||
@currentUser = {_id: ObjectId()}
|
||||
@notification = {read: sinon.stub().callsArgWith(0, null)}
|
||||
@NotificationsBuilder.projectInvite = sinon.stub().returns(@notification)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteHandler._tryCancelInviteNotification @inviteId, callback
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should call notification.read', (done) ->
|
||||
@call (err) =>
|
||||
@notification.read.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
describe 'when notification.read produces an error', ->
|
||||
beforeEach ->
|
||||
@notification = {read: sinon.stub().callsArgWith(0, new Error('woops'))}
|
||||
@NotificationsBuilder.projectInvite = sinon.stub().returns(@notification)
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
describe "_trySendInviteNotification", ->
|
||||
|
||||
beforeEach ->
|
||||
@invite =
|
||||
_id: ObjectId(),
|
||||
token: "some_token",
|
||||
sendingUserId: ObjectId(),
|
||||
projectId: @project_id,
|
||||
targetEmail: 'user@example.com'
|
||||
createdAt: new Date(),
|
||||
@sendingUser =
|
||||
_id: ObjectId()
|
||||
first_name: "jim"
|
||||
@existingUser = {_id: ObjectId()}
|
||||
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @existingUser)
|
||||
@fakeProject =
|
||||
_id: @project_id
|
||||
name: "some project"
|
||||
@ProjectGetter.getProject = sinon.stub().callsArgWith(2, null, @fakeProject)
|
||||
@notification = {create: sinon.stub().callsArgWith(0, null)}
|
||||
@NotificationsBuilder.projectInvite = sinon.stub().returns(@notification)
|
||||
@call = (callback) =>
|
||||
@CollaboratorsInviteHandler._trySendInviteNotification @project_id, @sendingUser, @invite, callback
|
||||
|
||||
describe 'when the user exists', ->
|
||||
|
||||
beforeEach ->
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should call getUser', (done) ->
|
||||
@call (err) =>
|
||||
@UserGetter.getUser.callCount.should.equal 1
|
||||
@UserGetter.getUser.calledWith({email: @invite.email}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should call getProject', (done) ->
|
||||
@call (err) =>
|
||||
@ProjectGetter.getProject.callCount.should.equal 1
|
||||
@ProjectGetter.getProject.calledWith(@project_id).should.equal true
|
||||
done()
|
||||
|
||||
it 'should call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 1
|
||||
@notification.create.callCount.should.equal 1
|
||||
done()
|
||||
|
||||
describe 'when getProject produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@ProjectGetter.getProject.callsArgWith(2, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
it 'should not call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 0
|
||||
@notification.create.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'when projectInvite.create produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@notification.create.callsArgWith(0, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
describe 'when the user does not exist', ->
|
||||
|
||||
beforeEach ->
|
||||
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, null)
|
||||
|
||||
it 'should not produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.oneOf [null, undefined]
|
||||
done()
|
||||
|
||||
it 'should call getUser', (done) ->
|
||||
@call (err) =>
|
||||
@UserGetter.getUser.callCount.should.equal 1
|
||||
@UserGetter.getUser.calledWith({email: @invite.email}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should not call getProject', (done) ->
|
||||
@call (err) =>
|
||||
@ProjectGetter.getProject.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
it 'should not call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 0
|
||||
@notification.create.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
describe 'when the getUser produces an error', ->
|
||||
|
||||
beforeEach ->
|
||||
@UserGetter.getUser = sinon.stub().callsArgWith(2, new Error('woops'))
|
||||
|
||||
it 'should produce an error', (done) ->
|
||||
@call (err) =>
|
||||
expect(err).to.be.instanceof Error
|
||||
done()
|
||||
|
||||
it 'should call getUser', (done) ->
|
||||
@call (err) =>
|
||||
@UserGetter.getUser.callCount.should.equal 1
|
||||
@UserGetter.getUser.calledWith({email: @invite.email}).should.equal true
|
||||
done()
|
||||
|
||||
it 'should not call getProject', (done) ->
|
||||
@call (err) =>
|
||||
@ProjectGetter.getProject.callCount.should.equal 0
|
||||
done()
|
||||
|
||||
it 'should not call NotificationsBuilder.projectInvite.create', (done) ->
|
||||
@call (err) =>
|
||||
@NotificationsBuilder.projectInvite.callCount.should.equal 0
|
||||
@notification.create.callCount.should.equal 0
|
||||
done()
|
||||
|
|
|
@ -61,9 +61,10 @@ describe 'NotificationsHandler', ->
|
|||
@messageOpts = {value:12344}
|
||||
@templateKey = "renderThisHtml"
|
||||
@expiry = null
|
||||
@forceCreate = false
|
||||
|
||||
it "should post the message over", (done)->
|
||||
@handler.createNotification user_id, @key, @templateKey, @messageOpts, @expiry, =>
|
||||
@handler.createNotification user_id, @key, @templateKey, @messageOpts, @expiry, @forceCreate, =>
|
||||
args = @request.args[0][0]
|
||||
args.uri.should.equal "#{notificationUrl}/user/#{user_id}"
|
||||
args.timeout.should.equal 1000
|
||||
|
@ -77,9 +78,10 @@ describe 'NotificationsHandler', ->
|
|||
@messageOpts = {value:12344}
|
||||
@templateKey = "renderThisHtml"
|
||||
@expiry = new Date()
|
||||
@forceCreate = false
|
||||
|
||||
it 'should post the message over with expiry field', (done) ->
|
||||
@handler.createNotification user_id, @key, @templateKey, @messageOpts, @expiry, =>
|
||||
@handler.createNotification user_id, @key, @templateKey, @messageOpts, @expiry, @forceCreate, =>
|
||||
args = @request.args[0][0]
|
||||
args.uri.should.equal "#{notificationUrl}/user/#{user_id}"
|
||||
args.timeout.should.equal 1000
|
||||
|
@ -87,6 +89,23 @@ describe 'NotificationsHandler', ->
|
|||
assert.deepEqual(args.json, expectedJson)
|
||||
done()
|
||||
|
||||
describe 'when forceCreate is true', ->
|
||||
beforeEach ->
|
||||
@key = "some key here"
|
||||
@messageOpts = {value:12344}
|
||||
@templateKey = "renderThisHtml"
|
||||
@expiry = null
|
||||
@forceCreate = true
|
||||
|
||||
it 'should add a forceCreate=true flag to the payload', (done) ->
|
||||
@handler.createNotification user_id, @key, @templateKey, @messageOpts, @expiry, @forceCreate, =>
|
||||
args = @request.args[0][0]
|
||||
args.uri.should.equal "#{notificationUrl}/user/#{user_id}"
|
||||
args.timeout.should.equal 1000
|
||||
expectedJson = {key:@key, templateKey:@templateKey, messageOpts:@messageOpts, forceCreate: @forceCreate}
|
||||
assert.deepEqual(args.json, expectedJson)
|
||||
done()
|
||||
|
||||
describe "markAsReadByKeyOnly", ->
|
||||
beforeEach ->
|
||||
@key = "some key here"
|
||||
|
|
Loading…
Reference in a new issue