2016-03-14 13:06:57 -04:00
|
|
|
sinon = require('sinon')
|
|
|
|
chai = require('chai')
|
|
|
|
should = chai.should()
|
|
|
|
expect = chai.expect
|
|
|
|
modulePath = "../../../../app/js/Features/Authorization/AuthorizationMiddlewear.js"
|
|
|
|
SandboxedModule = require('sandboxed-module')
|
2016-03-18 11:59:03 -04:00
|
|
|
Errors = require "../../../../app/js/Features/Errors/Errors.js"
|
2016-03-14 13:06:57 -04:00
|
|
|
|
|
|
|
describe "AuthorizationMiddlewear", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@user_id = "user-id-123"
|
|
|
|
@project_id = "project-id-123"
|
2017-10-13 06:20:57 -04:00
|
|
|
@token = 'some-token'
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController =
|
|
|
|
getLoggedInUserId: sinon.stub().returns(@user_id)
|
|
|
|
isUserLoggedIn: sinon.stub().returns(true)
|
2016-03-14 13:06:57 -04:00
|
|
|
@AuthorizationMiddlewear = SandboxedModule.require modulePath, requires:
|
|
|
|
"./AuthorizationManager": @AuthorizationManager = {}
|
|
|
|
"logger-sharelatex": {log: () ->}
|
2016-03-18 11:59:03 -04:00
|
|
|
"mongojs": ObjectId: @ObjectId = {}
|
|
|
|
"../Errors/Errors": Errors
|
2016-09-07 11:40:49 -04:00
|
|
|
'../Authentication/AuthenticationController': @AuthenticationController
|
2017-10-13 06:20:57 -04:00
|
|
|
"../TokenAccess/TokenAccessHandler": @TokenAccessHandler =
|
|
|
|
getRequestToken: sinon.stub().returns(@token)
|
2016-03-14 13:06:57 -04:00
|
|
|
@req = {}
|
|
|
|
@res = {}
|
2016-03-18 11:59:03 -04:00
|
|
|
@ObjectId.isValid = sinon.stub()
|
|
|
|
@ObjectId.isValid.withArgs(@project_id).returns true
|
2016-03-14 13:06:57 -04:00
|
|
|
@next = sinon.stub()
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2018-11-14 06:08:15 -05:00
|
|
|
describe "_getUserId", ->
|
|
|
|
beforeEach ->
|
|
|
|
@req = {}
|
|
|
|
|
|
|
|
it "should get the user from session", (done) ->
|
|
|
|
@AuthenticationController.getLoggedInUserId = sinon.stub().returns("1234")
|
|
|
|
@AuthorizationMiddlewear._getUserId @req, (err, user_id) =>
|
|
|
|
expect(err).to.not.exist
|
|
|
|
expect(user_id).to.equal "1234"
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should get oauth_user from request", (done) ->
|
|
|
|
@AuthenticationController.getLoggedInUserId = sinon.stub().returns(null)
|
|
|
|
@req.oauth_user = {_id: "5678"}
|
|
|
|
@AuthorizationMiddlewear._getUserId @req, (err, user_id) =>
|
|
|
|
expect(err).to.not.exist
|
|
|
|
expect(user_id).to.equal "5678"
|
|
|
|
done()
|
|
|
|
|
|
|
|
it "should fall back to null", (done) ->
|
|
|
|
@AuthenticationController.getLoggedInUserId = sinon.stub().returns(null)
|
|
|
|
@req.oauth_user = undefined
|
|
|
|
@AuthorizationMiddlewear._getUserId @req, (err, user_id) =>
|
|
|
|
expect(err).to.not.exist
|
|
|
|
expect(user_id).to.equal null
|
|
|
|
done()
|
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
METHODS_TO_TEST = {
|
|
|
|
"ensureUserCanReadProject": "canUserReadProject"
|
|
|
|
"ensureUserCanWriteProjectSettings": "canUserWriteProjectSettings"
|
|
|
|
"ensureUserCanWriteProjectContent": "canUserWriteProjectContent"
|
|
|
|
"ensureUserCanAdminProject": "canUserAdminProject"
|
|
|
|
}
|
|
|
|
for middlewearMethod, managerMethod of METHODS_TO_TEST
|
|
|
|
do (middlewearMethod, managerMethod) ->
|
|
|
|
describe middlewearMethod, ->
|
|
|
|
beforeEach ->
|
|
|
|
@req.params =
|
|
|
|
project_id: @project_id
|
|
|
|
@AuthorizationManager[managerMethod] = sinon.stub()
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted = sinon.stub()
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
describe "with missing project_id", ->
|
|
|
|
beforeEach ->
|
|
|
|
@req.params = {}
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should return an error to next", ->
|
|
|
|
@AuthorizationMiddlewear[middlewearMethod] @req, @res, @next
|
|
|
|
@next.calledWith(new Error()).should.equal true
|
|
|
|
|
|
|
|
describe "with logged in user", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(@user_id)
|
2016-03-14 13:06:57 -04:00
|
|
|
|
|
|
|
describe "when user has permission", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager[managerMethod]
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(@user_id, @project_id, @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should return next", ->
|
|
|
|
@AuthorizationMiddlewear[middlewearMethod] @req, @res, @next
|
|
|
|
@next.called.should.equal true
|
|
|
|
|
|
|
|
describe "when user doesn't have permission", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager[managerMethod]
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(@user_id, @project_id, @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, false)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should redirect to redirectToRestricted", ->
|
|
|
|
@AuthorizationMiddlewear[middlewearMethod] @req, @res, @next
|
|
|
|
@next.called.should.equal false
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted
|
|
|
|
.calledWith(@req, @res, @next)
|
|
|
|
.should.equal true
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
describe "with anonymous user", ->
|
|
|
|
describe "when user has permission", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(null)
|
2016-03-14 13:06:57 -04:00
|
|
|
@AuthorizationManager[managerMethod]
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(null, @project_id, @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should return next", ->
|
|
|
|
@AuthorizationMiddlewear[middlewearMethod] @req, @res, @next
|
|
|
|
@next.called.should.equal true
|
|
|
|
|
|
|
|
describe "when user doesn't have permission", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(null)
|
2016-03-14 13:06:57 -04:00
|
|
|
@AuthorizationManager[managerMethod]
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(null, @project_id, @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, false)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should redirect to redirectToRestricted", ->
|
|
|
|
@AuthorizationMiddlewear[middlewearMethod] @req, @res, @next
|
|
|
|
@next.called.should.equal false
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted
|
|
|
|
.calledWith(@req, @res, @next)
|
|
|
|
.should.equal true
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-18 11:59:03 -04:00
|
|
|
describe "with malformed project id", ->
|
|
|
|
beforeEach ->
|
|
|
|
@req.params =
|
|
|
|
project_id: "blah"
|
|
|
|
@ObjectId.isValid = sinon.stub().returns false
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-18 11:59:03 -04:00
|
|
|
it "should return a not found error", (done) ->
|
|
|
|
@AuthorizationMiddlewear[middlewearMethod] @req, @res, (error) ->
|
|
|
|
error.should.be.instanceof Errors.NotFoundError
|
|
|
|
done()
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
describe "ensureUserIsSiteAdmin", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager.isUserSiteAdmin = sinon.stub()
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted = sinon.stub()
|
|
|
|
|
|
|
|
describe "with logged in user", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(@user_id)
|
2016-03-14 13:06:57 -04:00
|
|
|
|
|
|
|
describe "when user has permission", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager.isUserSiteAdmin
|
|
|
|
.withArgs(@user_id)
|
|
|
|
.yields(null, true)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should return next", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserIsSiteAdmin @req, @res, @next
|
|
|
|
@next.called.should.equal true
|
|
|
|
|
|
|
|
describe "when user doesn't have permission", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager.isUserSiteAdmin
|
|
|
|
.withArgs(@user_id)
|
|
|
|
.yields(null, false)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should redirect to redirectToRestricted", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserIsSiteAdmin @req, @res, @next
|
|
|
|
@next.called.should.equal false
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted
|
|
|
|
.calledWith(@req, @res, @next)
|
|
|
|
.should.equal true
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
describe "with anonymous user", ->
|
|
|
|
describe "when user has permission", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(null)
|
2016-03-14 13:06:57 -04:00
|
|
|
@AuthorizationManager.isUserSiteAdmin
|
|
|
|
.withArgs(null)
|
|
|
|
.yields(null, true)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should return next", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserIsSiteAdmin @req, @res, @next
|
|
|
|
@next.called.should.equal true
|
|
|
|
|
|
|
|
describe "when user doesn't have permission", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(null)
|
2016-03-14 13:06:57 -04:00
|
|
|
@AuthorizationManager.isUserSiteAdmin
|
|
|
|
.withArgs(null)
|
|
|
|
.yields(null, false)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should redirect to redirectToRestricted", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserIsSiteAdmin @req, @res, @next
|
|
|
|
@next.called.should.equal false
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted
|
|
|
|
.calledWith(@req, @res, @next)
|
|
|
|
.should.equal true
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
describe "ensureUserCanReadMultipleProjects", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager.canUserReadProject = sinon.stub()
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted = sinon.stub()
|
|
|
|
@req.query =
|
|
|
|
project_ids: "project1,project2"
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
describe "with logged in user", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(@user_id)
|
2016-03-14 13:06:57 -04:00
|
|
|
|
|
|
|
describe "when user has permission to access all projects", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(@user_id, "project1", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(@user_id, "project2", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should return next", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserCanReadMultipleProjects @req, @res, @next
|
|
|
|
@next.called.should.equal true
|
|
|
|
|
|
|
|
describe "when user doesn't have permission to access one of the projects", ->
|
|
|
|
beforeEach ->
|
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(@user_id, "project1", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(@user_id, "project2", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, false)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should redirect to redirectToRestricted", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserCanReadMultipleProjects @req, @res, @next
|
|
|
|
@next.called.should.equal false
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted
|
|
|
|
.calledWith(@req, @res, @next)
|
|
|
|
.should.equal true
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
describe "with anonymous user", ->
|
|
|
|
describe "when user has permission", ->
|
|
|
|
describe "when user has permission to access all projects", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(null)
|
2016-03-14 13:06:57 -04:00
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(null, "project1", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(null, "project2", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should return next", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserCanReadMultipleProjects @req, @res, @next
|
|
|
|
@next.called.should.equal true
|
|
|
|
|
|
|
|
describe "when user doesn't have permission to access one of the projects", ->
|
|
|
|
beforeEach ->
|
2016-09-07 11:40:49 -04:00
|
|
|
@AuthenticationController.getLoggedInUserId.returns(null)
|
2016-03-14 13:06:57 -04:00
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(null, "project1", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, true)
|
|
|
|
@AuthorizationManager.canUserReadProject
|
2017-10-13 06:20:57 -04:00
|
|
|
.withArgs(null, "project2", @token)
|
2016-03-14 13:06:57 -04:00
|
|
|
.yields(null, false)
|
2016-09-07 11:40:49 -04:00
|
|
|
|
2016-03-14 13:06:57 -04:00
|
|
|
it "should redirect to redirectToRestricted", ->
|
|
|
|
@AuthorizationMiddlewear.ensureUserCanReadMultipleProjects @req, @res, @next
|
|
|
|
@next.called.should.equal false
|
|
|
|
@AuthorizationMiddlewear.redirectToRestricted
|
|
|
|
.calledWith(@req, @res, @next)
|
|
|
|
.should.equal true
|