From e15976be21b119b6f6c369509ab9bc209574f2ad Mon Sep 17 00:00:00 2001 From: James Allen Date: Thu, 22 Sep 2016 17:24:06 +0100 Subject: [PATCH] Use token in URL to force its precense when invite and allow easy dynamic notifications --- .../CollaboratorsInviteController.coffee | 11 +++++------ .../Collaborators/CollaboratorsInviteHandler.coffee | 8 ++++---- .../Collaborators/CollaboratorsRouter.coffee | 2 +- services/web/app/views/project/invite/show.jade | 2 +- .../project-list/notifications-controller.coffee | 2 +- .../CollaboratorsInviteControllerTests.coffee | 12 ++++++------ .../CollaboratorsInviteHandlerTests.coffee | 2 +- 7 files changed, 19 insertions(+), 20 deletions(-) diff --git a/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteController.coffee b/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteController.coffee index 051518a957..7cbd09c28a 100644 --- a/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteController.coffee +++ b/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteController.coffee @@ -111,16 +111,15 @@ module.exports = CollaboratorsInviteController = acceptInvite: (req, res, next) -> projectId = req.params.Project_id - inviteId = req.params.invite_id - {token} = req.body + token = req.params.token currentUser = req.session.user - logger.log {projectId, inviteId, userId: currentUser._id}, "accepting invite" - CollaboratorsInviteHandler.acceptInvite projectId, inviteId, token, currentUser, (err) -> + logger.log {projectId, userId: currentUser._id, token}, "got request to accept invite" + CollaboratorsInviteHandler.acceptInvite projectId, token, currentUser, (err) -> if err? - logger.err {projectId, inviteId}, "error accepting invite by token" + logger.err {projectId, token}, "error accepting invite by token" return next(err) EditorRealTimeController.emitToRoom projectId, 'project:membership:changed', {invites: true, members: true} - AnalyticsManger.recordEvent(currentUser._id, "project-invite-accept", {inviteId:inviteId, projectId:projectId}) + AnalyticsManger.recordEvent(currentUser._id, "project-invite-accept", {projectId:projectId, userId:currentUser._id}) if req.xhr res.sendStatus 204 # Done async via project page notification else diff --git a/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteHandler.coffee b/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteHandler.coffee index 1ece15bf85..960bcff5c3 100644 --- a/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteHandler.coffee +++ b/services/web/app/coffee/Features/Collaborators/CollaboratorsInviteHandler.coffee @@ -119,15 +119,15 @@ module.exports = CollaboratorsInviteHandler = return callback(null, null) callback(null, invite) - acceptInvite: (projectId, inviteId, tokenString, user, callback=(err)->) -> - logger.log {projectId, inviteId, userId: user._id}, "accepting invite" + acceptInvite: (projectId, tokenString, user, callback=(err)->) -> + logger.log {projectId, userId: user._id, tokenString}, "accepting invite" CollaboratorsInviteHandler.getInviteByToken projectId, tokenString, (err, invite) -> if err? - logger.err {err, projectId, inviteId}, "error finding invite" + logger.err {err, projectId, tokenString}, "error finding invite" return callback(err) if !invite err = new Errors.NotFoundError("no matching invite found") - logger.log {err, projectId, inviteId, tokenString}, "no matching invite found" + logger.log {err, projectId, tokenString}, "no matching invite found" return callback(err) inviteId = invite._id CollaboratorsHandler.addUserIdToProject projectId, invite.sendingUserId, user._id, invite.privileges, (err) -> diff --git a/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee b/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee index 7fc4722ef2..4c7cc8c76a 100644 --- a/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee +++ b/services/web/app/coffee/Features/Collaborators/CollaboratorsRouter.coffee @@ -66,7 +66,7 @@ module.exports = ) webRouter.post( - '/project/:Project_id/invite/:invite_id/accept', + '/project/:Project_id/invite/token/:token/accept', AuthenticationController.requireLogin(), CollaboratorsInviteController.acceptInvite ) diff --git a/services/web/app/views/project/invite/show.jade b/services/web/app/views/project/invite/show.jade index 833e75085e..eed30d3d19 100644 --- a/services/web/app/views/project/invite/show.jade +++ b/services/web/app/views/project/invite/show.jade @@ -20,7 +20,7 @@ block content form.form( name="acceptForm", method="POST", - action="/project/#{invite.projectId}/invite/#{invite._id}/accept" + action="/project/#{invite.projectId}/invite/token/#{invite.token}/accept" ) input(name='_csrf', type='hidden', value=csrfToken) input(name='token', type='hidden', value="#{invite.token}") diff --git a/services/web/public/coffee/main/project-list/notifications-controller.coffee b/services/web/public/coffee/main/project-list/notifications-controller.coffee index e3ec2f4c02..c9f2d0c68b 100644 --- a/services/web/public/coffee/main/project-list/notifications-controller.coffee +++ b/services/web/public/coffee/main/project-list/notifications-controller.coffee @@ -24,7 +24,7 @@ define [ $scope.accept = () -> $scope.notification.inflight = true $http({ - url: "/project/#{$scope.notification.messageOpts.projectId}/invite/#{$scope.notification.messageOpts.token}/accept" + url: "/project/#{$scope.notification.messageOpts.projectId}/invite/token/#{$scope.notification.messageOpts.token}/accept" method: "POST" headers: "X-Csrf-Token": window.csrfToken diff --git a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteControllerTests.coffee b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteControllerTests.coffee index 0144583f05..f1e1634ca1 100644 --- a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteControllerTests.coffee @@ -531,14 +531,12 @@ describe "CollaboratorsInviteController", -> beforeEach -> @req.params = Project_id: @project_id - invite_id: @invite_id = "thuseoautoh" + token: @token = "mock-token" @req.session = user: _id: @current_user_id = "current-user-id" - @req.body = - token: "thsueothaueotauahsuet" @res.render = sinon.stub() @res.redirect = sinon.stub() - @CollaboratorsInviteHandler.acceptInvite = sinon.stub().callsArgWith(4, null) + @CollaboratorsInviteHandler.acceptInvite = sinon.stub().callsArgWith(3, null) @callback = sinon.stub() @next = sinon.stub() @@ -552,7 +550,9 @@ describe "CollaboratorsInviteController", -> @res.redirect.calledWith("/project/#{@project_id}").should.equal true it 'should have called acceptInvite', -> - @CollaboratorsInviteHandler.acceptInvite.callCount.should.equal 1 + @CollaboratorsInviteHandler.acceptInvite + .calledWith(@project_id, @token) + .should.equal true it 'should have called emitToRoom', -> @EditorRealTimeController.emitToRoom.callCount.should.equal 1 @@ -562,7 +562,7 @@ describe "CollaboratorsInviteController", -> beforeEach -> @err = new Error('woops') - @CollaboratorsInviteHandler.acceptInvite = sinon.stub().callsArgWith(4, @err) + @CollaboratorsInviteHandler.acceptInvite = sinon.stub().callsArgWith(3, @err) @CollaboratorsInviteController.acceptInvite @req, @res, @next it 'should not redirect to project page', -> diff --git a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteHandlerTests.coffee b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteHandlerTests.coffee index d4ae9a4229..ac94fcf10d 100644 --- a/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Collaborators/CollaboratorsInviteHandlerTests.coffee @@ -404,7 +404,7 @@ describe "CollaboratorsInviteHandler", -> @CollaboratorsInviteHandler._tryCancelInviteNotification = sinon.stub().callsArgWith(1, null) @ProjectInvite.remove.callsArgWith(1, null) @call = (callback) => - @CollaboratorsInviteHandler.acceptInvite @projectId, @inviteId, @token, @user, callback + @CollaboratorsInviteHandler.acceptInvite @projectId, @token, @user, callback afterEach -> @_getInviteByToken.restore()