Shane Kilkelly 10 лет назад
Родитель
Сommit
a5ddcc3df7

+ 10 - 0
services/web/app/coffee/Features/Collaborators/CollaboratorsInviteController.coffee

@@ -50,6 +50,16 @@ module.exports = CollaboratorsInviteController =
 				return next(err)
 			res.sendStatus(201)
 
+	resendInvite: (req, res, next) ->
+		projectId = req.params.Project_id
+		inviteId = req.params.invite_id
+		logger.log {projectId, inviteId}, "resending invite"
+		CollaboratorsInviteHandler.resendInvite projectId, inviteId, (err) ->
+			if err?
+				logger.err {projectId, inviteId}, "error revoking invite"
+				return next(err)
+			res.sendStatus(201)
+
 	viewInvite: (req, res, next) ->
 		projectId = req.params.Project_id
 		token = req.params.token

+ 12 - 0
services/web/app/coffee/Features/Collaborators/CollaboratorsInviteHandler.coffee

@@ -54,6 +54,18 @@ module.exports = CollaboratorsInviteHandler =
 				return callback(err)
 			callback(null)
 
+	resendInvite: (projectId, inviteId, callback=(err)->) ->
+		logger.log {projectId, inviteId}, "resending invite email"
+		ProjectInvite.findOne {_id: inviteId, projectId: projectId}, (err, invite) ->
+			if err?
+				logger.err {err, projectId, inviteId}, "error finding invite"
+				return callback(err)
+			if !invite?
+				logger.err {err, projectId, inviteId}, "no invite found, nothing to resend"
+				return callback(null)
+			CollaboratorsEmailHandler.notifyUserOfProjectInvite projectId, invite.email, invite
+			callback(null)
+
 	getInviteByToken: (projectId, tokenString, callback=(err,invite)->) ->
 		logger.log {projectId, tokenString}, "fetching invite by token"
 		ProjectInvite.findOne {projectId: projectId, token: tokenString}, (err, invite) ->

+ 6 - 0
services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee

@@ -29,6 +29,12 @@ module.exports =
 			CollaboratorsInviteController.revokeInvite
 		)
 
+		webRouter.post(
+			'/project/:Project_id/invite/:invite_id/resend',
+			AuthorizationMiddlewear.ensureUserCanAdminProject,
+			CollaboratorsInviteController.resendInvite
+		)
+
 		webRouter.get(
 			'/project/:Project_id/invite/token/:token',
 			AuthenticationController.requireLogin(),

+ 9 - 1
services/web/public/coffee/ide/share/controllers/ShareProjectModalController.coffee

@@ -136,7 +136,15 @@ define [
 					$scope.state.error = "Sorry, something went wrong :("
 
 		$scope.resendInvite = (invite) ->
-			console.log ">> resend"
+			$scope.state.error = null
+			$scope.state.inflight = true
+			projectInvites
+				.resendInvite(invite._id)
+				.success () ->
+					$scope.state.inflight = false
+				.error () ->
+					$scope.state.inflight = false
+					$scope.state.error = "Sorry, something went wrong resending the invite :("
 
 		$scope.openMakePublicModal = () ->
 			$modal.open {

+ 5 - 0
services/web/public/coffee/ide/share/services/projectInvites.coffee

@@ -19,6 +19,11 @@ define [
 						"X-Csrf-Token": window.csrfToken
 				})
 
+			resendInvite: (inviteId, privileges) ->
+				$http.post("/project/#{ide.project_id}/invite/#{inviteId}/resend", {
+					_csrf: window.csrfToken
+				})
+
 			getInvites: () ->
 				$http.get("/project/#{ide.project_id}/invite", {
 					json: true

+ 44 - 0
services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteControllerTests.coffee

@@ -429,6 +429,50 @@ describe "CollaboratorsInviteController", ->
 			it 'should call ProjectGetter.getProject', ->
 				@ProjectGetter.getProject.callCount.should.equal 1
 
+	describe "resendInvite", ->
+
+		beforeEach ->
+			@req.params =
+				Project_id: @project_id
+				invite_id: @invite_id = "thuseoautoh"
+			@req.session =
+				user: _id: @current_user_id = "current-user-id"
+			@res.render = sinon.stub()
+			@res.sendStatus = sinon.stub()
+			@CollaboratorsInviteHandler.resendInvite = sinon.stub().callsArgWith(2, null)
+			@callback = sinon.stub()
+			@next = sinon.stub()
+
+		describe 'when resendInvite does not produce an error', ->
+
+			beforeEach ->
+				@CollaboratorsInviteController.resendInvite @req, @res, @next
+
+			it 'should produce a 201 response', ->
+				@res.sendStatus.callCount.should.equal 1
+				@res.sendStatus.calledWith(201).should.equal true
+
+			it 'should have called resendInvite', ->
+				@CollaboratorsInviteHandler.resendInvite.callCount.should.equal 1
+
+		describe 'when resendInvite produces an error', ->
+
+			beforeEach ->
+				@err = new Error('woops')
+				@CollaboratorsInviteHandler.resendInvite = sinon.stub().callsArgWith(2, @err)
+				@CollaboratorsInviteController.resendInvite @req, @res, @next
+
+			it 'should not produce a 201 response', ->
+				@res.sendStatus.callCount.should.equal 0
+
+			it 'should call next with the error', ->
+				@next.callCount.should.equal 1
+				@next.calledWith(@err).should.equal true
+
+			it 'should have called resendInvite', ->
+				@CollaboratorsInviteHandler.resendInvite.callCount.should.equal 1
+
+
 	describe "revokeInvite", ->
 
 		beforeEach ->

+ 61 - 0
services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteHandlerTests.coffee

@@ -209,6 +209,67 @@ describe "CollaboratorsInviteHandler", ->
 					expect(err).to.be.instanceof Error
 					done()
 
+	describe 'resendInvite', ->
+
+		beforeEach ->
+			@ProjectInvite.findOne.callsArgWith(1, null, @fakeInvite)
+			@CollaboratorsEmailHandler.notifyUserOfProjectInvite = sinon.stub()
+			@call = (callback) =>
+				@CollaboratorsInviteHandler.resendInvite @projectId, @inviteId, callback
+
+		describe 'when all goes well', ->
+
+			beforeEach ->
+
+			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 ProjectInvite.findOne', (done) ->
+				@call (err, invite) =>
+					@ProjectInvite.findOne.callCount.should.equal 1
+					@ProjectInvite.findOne.calledWith({_id: @inviteId, projectId: @projectId}).should.equal true
+					done()
+
+			it 'should have called CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
+				@call (err, invite) =>
+					@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 1
+					@CollaboratorsEmailHandler.notifyUserOfProjectInvite.calledWith(@projectId, @email).should.equal true
+					done()
+
+		describe 'when findOne produces an error', ->
+
+			beforeEach ->
+				@ProjectInvite.findOne.callsArgWith(1, new Error('woops'))
+
+			it 'should produce an error', (done) ->
+				@call (err, invite) =>
+					expect(err).to.be.instanceof Error
+					done()
+
+			it 'should not have called CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
+				@call (err, invite) =>
+					@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 0
+					done()
+
+		describe 'when findOne does not find an invite', ->
+
+			beforeEach ->
+				@ProjectInvite.findOne.callsArgWith(1, null, null)
+
+			it 'should not produce an error', (done) ->
+				@call (err, invite) =>
+					expect(err).to.not.be.instanceof Error
+					expect(err).to.be.oneOf [null, undefined]
+					done()
+
+			it 'should not have called CollaboratorsEmailHandler.notifyUserOfProjectInvite', (done) ->
+				@call (err, invite) =>
+					@CollaboratorsEmailHandler.notifyUserOfProjectInvite.callCount.should.equal 0
+					done()
+
 	describe 'getInviteByToken', ->
 
 		beforeEach ->