From 4773d6d22f15a249c33d605f793e739bbb67428f Mon Sep 17 00:00:00 2001 From: Henry Oswald Date: Wed, 27 May 2015 20:50:16 +0100 Subject: [PATCH] added tests around new endpoints for joining groups --- .../SubscriptionGroupController.coffee | 34 +++--- .../SubscriptionGroupHandler.coffee | 22 +++- .../PasswordResetHandlerTests.coffee | 2 +- .../SubscriptionGroupControllerTests.coffee | 110 +++++++++++++++++- .../SubscriptionGroupHandlerTests.coffee | 55 +++++++++ 5 files changed, 204 insertions(+), 19 deletions(-) diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionGroupController.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionGroupController.coffee index 2cafcb2a24..e60e4e4600 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionGroupController.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionGroupController.coffee @@ -2,9 +2,9 @@ SubscriptionGroupHandler = require("./SubscriptionGroupHandler") logger = require("logger-sharelatex") SubscriptionLocator = require("./SubscriptionLocator") +ErrorsController = require("../Errors/ErrorController") settings = require("settings-sharelatex") -OneTimeTokenHandler = require("../Security/OneTimeTokenHandler") -EmailHandler = require("../Email/EmailHandler") + SubscriptionDomainAllocator = require("./SubscriptionDomainAllocator") _ = require("underscore") @@ -43,6 +43,8 @@ module.exports = subscription_id = req.params.subscription_id user_id = req.session.user._id licence = SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId(subscription_id) + if !licence? + return ErrorsController.notFound(req, res) SubscriptionGroupHandler.isUserPartOfGroup user_id, licence.subscription_id, (err, partOfGroup)-> if partOfGroup return res.redirect("/user/subscription/custom_account") @@ -57,28 +59,28 @@ module.exports = user_id = req.session.user._id licence = SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId(subscription_id) if !licence? - res.send 500 - OneTimeTokenHandler.getNewToken subscription_id, (err, token)-> - opts = - to : req.session.user.email - group_name: licence.name - completeJoinUrl: "#{settings.siteUrl}/user/subscription/#{subscription_id}/group/complete-join?token=#{token}" - EmailHandler.sendEmail "completeJoinGroupAccount", opts, -> + return ErrorsController.notFound(req, res) + SubscriptionGroupHandler.sendVerificationEmail subscription_id, licence.name, req.session.user.email, (err)-> + if err? + res.send 500 + else res.send 200 completeJoin: (req, res)-> subscription_id = req.params.subscription_id - OneTimeTokenHandler.getValueFromTokenAndExpire req.query.token, (err, token_subscription_id)-> - console.log token_subscription_id - if err? or subscription_id != token_subscription_id - return res.send 403 - SubscriptionLocator.getSubscription subscription_id, (err, subscription)-> - SubscriptionGroupHandler.addUserToGroup subscription.admin_id, req.user.email, (err, user)-> - res.redirect "#{settings.siteUrl}/user/subscription/#{subscription_id}/group/successful-join" + if !SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId(subscription_id)? + return ErrorsController.notFound(req, res) + SubscriptionGroupHandler.processGroupVerification req.session.user.email, subscription_id, req.query.token, (err)-> + if err? + res.send 500 + else + res.redirect "/user/subscription/#{subscription_id}/group/successful-join" renderSuccessfulJoinPage: (req, res)-> subscription_id = req.params.subscription_id licence = SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId(subscription_id) + if !SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId(subscription_id)? + return ErrorsController.notFound(req, res) res.render "subscriptions/group/successful_join", title: "Sucessfully joined group" licenceName:licence.name diff --git a/services/web/app/coffee/Features/Subscription/SubscriptionGroupHandler.coffee b/services/web/app/coffee/Features/Subscription/SubscriptionGroupHandler.coffee index bc05bd36dd..c816b5271c 100644 --- a/services/web/app/coffee/Features/Subscription/SubscriptionGroupHandler.coffee +++ b/services/web/app/coffee/Features/Subscription/SubscriptionGroupHandler.coffee @@ -6,8 +6,11 @@ SubscriptionLocator = require("./SubscriptionLocator") UserLocator = require("../User/UserLocator") LimitationsManager = require("./LimitationsManager") logger = require("logger-sharelatex") +OneTimeTokenHandler = require("../Security/OneTimeTokenHandler") +EmailHandler = require("../Email/EmailHandler") +settings = require("settings-sharelatex") -module.exports = +module.exports = SubscriptionGroupHandler = addUserToGroup: (adminUser_id, newEmail, callback)-> UserCreator.getUserOrCreateHoldingAccount newEmail, (err, user)-> @@ -47,6 +50,23 @@ module.exports = callback(err, partOfGroup) + sendVerificationEmail: (subscription_id, licenceName, email, callback)-> + OneTimeTokenHandler.getNewToken subscription_id, (err, token)-> + opts = + to : email + group_name: licenceName + completeJoinUrl: "#{settings.siteUrl}/user/subscription/#{subscription_id}/group/complete-join?token=#{token}" + EmailHandler.sendEmail "completeJoinGroupAccount", opts, callback + + processGroupVerification: (userEmail, subscription_id, token, callback)-> + OneTimeTokenHandler.getValueFromTokenAndExpire token, (err, token_subscription_id)-> + if err? or subscription_id != token_subscription_id + logger.err userEmail:userEmail, token:token, "token value not found for processing group verification" + return callback("token not found") + SubscriptionLocator.getSubscription subscription_id, (err, subscription)-> + SubscriptionGroupHandler.addUserToGroup subscription.admin_id, userEmail, callback + + buildUserViewModel = (user)-> u = email: user.email diff --git a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee index 67a4688c58..47fa4f2836 100644 --- a/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/PasswordReset/PasswordResetHandlerTests.coffee @@ -23,7 +23,7 @@ describe "PasswordResetHandler", -> setUserPassword:sinon.stub() @PasswordResetHandler = SandboxedModule.require modulePath, requires: "../User/UserGetter": @UserGetter - "./OneTimeTokenHandler": @OneTimeTokenHandler + "../Security/OneTimeTokenHandler": @OneTimeTokenHandler "../Email/EmailHandler":@EmailHandler "../Authentication/AuthenticationManager":@AuthenticationManager "settings-sharelatex": @settings diff --git a/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupControllerTests.coffee b/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupControllerTests.coffee index 28279a1296..828657a1e1 100644 --- a/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupControllerTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupControllerTests.coffee @@ -13,16 +13,42 @@ describe "Subscription Group Controller", -> @GroupHandler = addUserToGroup: sinon.stub().callsArgWith(2, null, @user) removeUserFromGroup: sinon.stub().callsArgWith(2) + isUserPartOfGroup: sinon.stub() + sendVerificationEmail:sinon.stub() + processGroupVerification:sinon.stub() + @SubscriptionLocator = getUsersSubscription: sinon.stub().callsArgWith(1, null, @subscription) + @SubscriptionDomainAllocator = + findDomainLicenceBySubscriptionId:sinon.stub() + + @OneTimeTokenHandler = + getValueFromTokenAndExpire:sinon.stub() + + + @ErrorsController = + notFound:sinon.stub() + @Controller = SandboxedModule.require modulePath, requires: "./SubscriptionGroupHandler":@GroupHandler "logger-sharelatex": log:-> "./SubscriptionLocator": @SubscriptionLocator + "./SubscriptionDomainAllocator":@SubscriptionDomainAllocator + "../Errors/ErrorController":@ErrorsController + @adminUserId = "123jlkj" + @subscription_id = "123434325412" + @user_email = "bob@gmail.com" @req = session: - user: _id: @adminUserId + user: + _id: @adminUserId + email:@user_email + params: + subscription_id:@subscription_id + query:{} + + @token = "super-secret-token" describe "addUserToGroup", -> @@ -59,3 +85,85 @@ describe "Subscription Group Controller", -> path.should.equal("/") done() @Controller.renderSubscriptionGroupAdminPage @req, res + + + describe "renderGroupInvitePage", -> + describe "with a valid licence", -> + beforeEach -> + @SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId.returns({subscription_id:@subscription_id, adminUser_id:@adminUserId}) + + it "should render subscriptions/group/invite if not part of group", (done)-> + @GroupHandler.isUserPartOfGroup.callsArgWith(2, null, false) + res = + render : (pageName)=> + pageName.should.equal "subscriptions/group/invite" + done() + @Controller.renderGroupInvitePage @req, res + + it "should redirect to custom page if is already part of group", (done)-> + @GroupHandler.isUserPartOfGroup.callsArgWith(2, null, true) + res = + redirect : (location)=> + location.should.equal "/user/subscription/custom_account" + done() + @Controller.renderGroupInvitePage @req, res + + describe "without a valid licence", -> + beforeEach -> + @SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId.returns(undefined) + + it "should send a 500", (done)-> + @Controller.renderGroupInvitePage @req, {} + @ErrorsController.notFound.called.should.equal true + done() + + + + describe "beginJoinGroup", -> + describe "with a valid licence", -> + beforeEach -> + @licenceName = "get amazing licence" + @SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId.returns({name:@licenceName}) + @GroupHandler.sendVerificationEmail.callsArgWith(3) + + it "should ask the SubscriptionGroupHandler to send the verification email", (done)-> + res = + send : (statusCode)=> + statusCode.should.equal 200 + @GroupHandler.sendVerificationEmail.calledWith(@subscription_id, @licenceName, @user_email).should.equal true + done() + @Controller.beginJoinGroup @req, res + + describe "without a valid licence", -> + beforeEach -> + @SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId.returns(undefined) + + it "should send a 500", (done)-> + @Controller.beginJoinGroup @req, {} + @ErrorsController.notFound.called.should.equal true + done() + + + describe "completeJoin", -> + describe "with a valid licence", -> + beforeEach -> + @GroupHandler.processGroupVerification.callsArgWith(3) + @SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId.returns({name:@licenceName}) + + it "should redirect to the success page upon processGroupVerification", (done)-> + @req.query.token = @token + res = + redirect : (location)=> + @GroupHandler.processGroupVerification.calledWith(@user_email, @subscription_id, @token).should.equal true + location.should.equal "/user/subscription/#{@subscription_id}/group/successful-join" + done() + @Controller.completeJoin @req, res + + describe "without a valid licence", -> + beforeEach -> + @SubscriptionDomainAllocator.findDomainLicenceBySubscriptionId.returns(undefined) + + it "should send a 500", (done)-> + @Controller.completeJoin @req, {} + @ErrorsController.notFound.called.should.equal true + done() \ No newline at end of file diff --git a/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupHandlerTests.coffee b/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupHandlerTests.coffee index ddc51a154a..03af764442 100644 --- a/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupHandlerTests.coffee +++ b/services/web/test/UnitTests/coffee/Subscription/SubscriptionGroupHandlerTests.coffee @@ -16,6 +16,7 @@ describe "Subscription Group Handler", -> @SubscriptionLocator = getUsersSubscription: sinon.stub() getSubscriptionByMemberIdAndId: sinon.stub() + getSubscription: sinon.stub() @UserCreator = getUserOrCreateHoldingAccount: sinon.stub().callsArgWith(1, null, @user) @@ -30,6 +31,16 @@ describe "Subscription Group Handler", -> @LimitationsManager = hasGroupMembersLimitReached: sinon.stub() + @OneTimeTokenHandler = + getValueFromTokenAndExpire:sinon.stub() + getNewToken:sinon.stub() + + @EmailHandler = + sendEmail:sinon.stub() + + @settings = + siteUrl:"http://www.sharelatex.com" + @Handler = SandboxedModule.require modulePath, requires: "logger-sharelatex": log:-> "../User/UserCreator": @UserCreator @@ -37,6 +48,13 @@ describe "Subscription Group Handler", -> "./SubscriptionLocator": @SubscriptionLocator "../User/UserLocator": @UserLocator "./LimitationsManager": @LimitationsManager + "../Security/OneTimeTokenHandler":@OneTimeTokenHandler + "../Email/EmailHandler":@EmailHandler + "settings-sharelatex":@settings + "logger-sharelatex": + err:-> + log:-> + describe "addUserToGroup", -> it "should find or create the user", (done)-> @@ -119,3 +137,40 @@ describe "Subscription Group Handler", -> done() + describe "sendVerificationEmail", -> + beforeEach -> + @token = "secret token" + @subscription_id = "123ed13123" + @licenceName = "great licnece" + @email = "bob@smith.com" + @OneTimeTokenHandler.getNewToken.callsArgWith(1, null, @token) + @EmailHandler.sendEmail.callsArgWith(2) + + it "should put a one time token into the email", (done)-> + @Handler.sendVerificationEmail @subscription_id, @licenceName, @email, (err)=> + emailOpts = @EmailHandler.sendEmail.args[0][1] + emailOpts.completeJoinUrl.should.equal "#{@settings.siteUrl}/user/subscription/#{@subscription_id}/group/complete-join?token=#{@token}" + emailOpts.to.should.equal @email + emailOpts.group_name.should.equal @licenceName + done() + + describe "processGroupVerification", -> + beforeEach -> + @token = "31dDAd2Da" + @subscription_id = "31DSd1123D" + @admin_id = "eDSda1ew" + @OneTimeTokenHandler.getValueFromTokenAndExpire.callsArgWith(1, null, @subscription_id) + @SubscriptionLocator.getSubscription.callsArgWith(1, null, {admin_id:@admin_id}) + @Handler.addUserToGroup = sinon.stub().callsArgWith(2) + + it "should addUserToGroup", (done)-> + @Handler.processGroupVerification @email, @subscription_id, @token, (err)=> + @Handler.addUserToGroup.calledWith(@admin_id, @email).should.equal true + done() + + + + + + +