mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-29 21:03:39 -05:00
Add option to restrict invites to existing user accounts.
This commit is contained in:
parent
3a8a12fcb3
commit
259c589076
6 changed files with 217 additions and 18 deletions
|
@ -4,6 +4,7 @@ UserGetter = require "../User/UserGetter"
|
||||||
CollaboratorsHandler = require('./CollaboratorsHandler')
|
CollaboratorsHandler = require('./CollaboratorsHandler')
|
||||||
CollaboratorsInviteHandler = require('./CollaboratorsInviteHandler')
|
CollaboratorsInviteHandler = require('./CollaboratorsInviteHandler')
|
||||||
logger = require('logger-sharelatex')
|
logger = require('logger-sharelatex')
|
||||||
|
Settings = require('settings-sharelatex')
|
||||||
EmailHelper = require "../Helpers/EmailHelper"
|
EmailHelper = require "../Helpers/EmailHelper"
|
||||||
EditorRealTimeController = require("../Editor/EditorRealTimeController")
|
EditorRealTimeController = require("../Editor/EditorRealTimeController")
|
||||||
NotificationsBuilder = require("../Notifications/NotificationsBuilder")
|
NotificationsBuilder = require("../Notifications/NotificationsBuilder")
|
||||||
|
@ -21,6 +22,16 @@ module.exports = CollaboratorsInviteController =
|
||||||
return next(err)
|
return next(err)
|
||||||
res.json({invites: invites})
|
res.json({invites: invites})
|
||||||
|
|
||||||
|
_checkShouldInviteEmail: (email, callback=(err, shouldAllowInvite)->) ->
|
||||||
|
if Settings.restrictInvitesToExistingAccounts == true
|
||||||
|
logger.log {email}, "checking if user exists with this email"
|
||||||
|
UserGetter.getUser {email: email}, {_id: 1}, (err, user) ->
|
||||||
|
return callback(err) if err?
|
||||||
|
userExists = user? and user?._id?
|
||||||
|
callback(null, userExists)
|
||||||
|
else
|
||||||
|
callback(null, true)
|
||||||
|
|
||||||
inviteToProject: (req, res, next) ->
|
inviteToProject: (req, res, next) ->
|
||||||
projectId = req.params.Project_id
|
projectId = req.params.Project_id
|
||||||
email = req.body.email
|
email = req.body.email
|
||||||
|
@ -37,6 +48,13 @@ module.exports = CollaboratorsInviteController =
|
||||||
if !email? or email == ""
|
if !email? or email == ""
|
||||||
logger.log {projectId, email, sendingUserId}, "invalid email address"
|
logger.log {projectId, email, sendingUserId}, "invalid email address"
|
||||||
return res.sendStatus(400)
|
return res.sendStatus(400)
|
||||||
|
CollaboratorsInviteController._checkShouldInviteEmail email, (err, shouldAllowInvite)->
|
||||||
|
if err?
|
||||||
|
logger.err {err, email, projectId, sendingUserId}, "error checking if we can invite this email address"
|
||||||
|
return next(err)
|
||||||
|
if !shouldAllowInvite
|
||||||
|
logger.log {email, projectId, sendingUserId}, "not allowed to send an invite to this email address"
|
||||||
|
return res.json {invite: null, error: 'cannot_invite_non_user'}
|
||||||
CollaboratorsInviteHandler.inviteToProject projectId, sendingUser, email, privileges, (err, invite) ->
|
CollaboratorsInviteHandler.inviteToProject projectId, sendingUser, email, privileges, (err, invite) ->
|
||||||
if err?
|
if err?
|
||||||
logger.err {projectId, email, sendingUserId}, "error creating project invite"
|
logger.err {projectId, email, sendingUserId}, "error creating project invite"
|
||||||
|
|
|
@ -137,10 +137,15 @@ script(type='text/ng-template', id='shareProjectModalTemplate')
|
||||||
p.small(ng-show="startedFreeTrial")
|
p.small(ng-show="startedFreeTrial")
|
||||||
| #{translate("refresh_page_after_starting_free_trial")}.
|
| #{translate("refresh_page_after_starting_free_trial")}.
|
||||||
|
|
||||||
.modal-footer
|
.modal-footer.modal-footer-share
|
||||||
.modal-footer-left
|
.modal-footer-left
|
||||||
i.fa.fa-refresh.fa-spin(ng-show="state.inflight")
|
i.fa.fa-refresh.fa-spin(ng-show="state.inflight")
|
||||||
span.text-danger.error(ng-show="state.error") #{translate("generic_something_went_wrong")}
|
span.text-danger.error(ng-show="state.error")
|
||||||
|
span(ng-switch="state.errorReason")
|
||||||
|
span(ng-switch-when="cannot_invite_non_user")
|
||||||
|
| #{translate("cannot_invite_non_user")}
|
||||||
|
span(ng-switch-default)
|
||||||
|
| #{translate("generic_something_went_wrong")}
|
||||||
button.btn.btn-default(
|
button.btn.btn-default(
|
||||||
ng-click="done()"
|
ng-click="done()"
|
||||||
) #{translate("close")}
|
) #{translate("close")}
|
||||||
|
|
|
@ -276,6 +276,10 @@ module.exports = settings =
|
||||||
# Cookie max age (in milliseconds). Set to false for a browser session.
|
# Cookie max age (in milliseconds). Set to false for a browser session.
|
||||||
cookieSessionLength: 5 * 24 * 60 * 60 * 1000 # 5 days
|
cookieSessionLength: 5 * 24 * 60 * 60 * 1000 # 5 days
|
||||||
|
|
||||||
|
# When true, only allow invites to be sent to email addresses that
|
||||||
|
# already have user accounts
|
||||||
|
restrictInvitesToExistingAccounts: false
|
||||||
|
|
||||||
# Should we allow access to any page without logging in? This includes
|
# Should we allow access to any page without logging in? This includes
|
||||||
# public projects, /learn, /templates, about pages, etc.
|
# public projects, /learn, /templates, about pages, etc.
|
||||||
allowPublicAccess: if process.env["SHARELATEX_ALLOW_PUBLIC_ACCESS"] == 'true' then true else false
|
allowPublicAccess: if process.env["SHARELATEX_ALLOW_PUBLIC_ACCESS"] == 'true' then true else false
|
||||||
|
|
|
@ -8,6 +8,7 @@ define [
|
||||||
}
|
}
|
||||||
$scope.state = {
|
$scope.state = {
|
||||||
error: null
|
error: null
|
||||||
|
errorReason: null
|
||||||
inflight: false
|
inflight: false
|
||||||
startedFreeTrial: false
|
startedFreeTrial: false
|
||||||
invites: []
|
invites: []
|
||||||
|
@ -69,7 +70,8 @@ define [
|
||||||
|
|
||||||
members = $scope.inputs.contacts
|
members = $scope.inputs.contacts
|
||||||
$scope.inputs.contacts = []
|
$scope.inputs.contacts = []
|
||||||
$scope.state.error = null
|
$scope.state.error = false
|
||||||
|
$scope.state.errorReason = null
|
||||||
$scope.state.inflight = true
|
$scope.state.inflight = true
|
||||||
|
|
||||||
if !$scope.project.invites?
|
if !$scope.project.invites?
|
||||||
|
@ -101,6 +103,11 @@ define [
|
||||||
|
|
||||||
request
|
request
|
||||||
.success (data) ->
|
.success (data) ->
|
||||||
|
if data.error
|
||||||
|
$scope.state.error = true
|
||||||
|
$scope.state.errorReason = "#{data.error}"
|
||||||
|
$scope.state.inflight = false
|
||||||
|
else
|
||||||
if data.invite
|
if data.invite
|
||||||
invite = data.invite
|
invite = data.invite
|
||||||
$scope.project.invites.push invite
|
$scope.project.invites.push invite
|
||||||
|
@ -121,6 +128,7 @@ define [
|
||||||
.error () ->
|
.error () ->
|
||||||
$scope.state.inflight = false
|
$scope.state.inflight = false
|
||||||
$scope.state.error = true
|
$scope.state.error = true
|
||||||
|
$scope.state.errorReason = null
|
||||||
|
|
||||||
$timeout addMembers, 50 # Give email list a chance to update
|
$timeout addMembers, 50 # Give email list a chance to update
|
||||||
|
|
||||||
|
|
|
@ -48,3 +48,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.modal-footer-share {
|
||||||
|
.modal-footer-left {
|
||||||
|
max-width: 70%;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ describe "CollaboratorsInviteController", ->
|
||||||
"../Notifications/NotificationsBuilder": @NotificationsBuilder = {}
|
"../Notifications/NotificationsBuilder": @NotificationsBuilder = {}
|
||||||
"../Analytics/AnalyticsManager": @AnalyticsManger
|
"../Analytics/AnalyticsManager": @AnalyticsManger
|
||||||
'../Authentication/AuthenticationController': @AuthenticationController
|
'../Authentication/AuthenticationController': @AuthenticationController
|
||||||
|
'settings-sharelatex': @settings = {}
|
||||||
@res = new MockResponse()
|
@res = new MockResponse()
|
||||||
@req = new MockRequest()
|
@req = new MockRequest()
|
||||||
|
|
||||||
|
@ -103,9 +104,15 @@ describe "CollaboratorsInviteController", ->
|
||||||
describe 'when all goes well', ->
|
describe 'when all goes well', ->
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@_checkShouldInviteEmail = sinon.stub(
|
||||||
|
@CollaboratorsInviteController, '_checkShouldInviteEmail'
|
||||||
|
).callsArgWith(1, null, true)
|
||||||
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, null, true)
|
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, null, true)
|
||||||
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
@_checkShouldInviteEmail.restore()
|
||||||
|
|
||||||
it 'should produce json response', ->
|
it 'should produce json response', ->
|
||||||
@res.json.callCount.should.equal 1
|
@res.json.callCount.should.equal 1
|
||||||
({invite: @invite}).should.deep.equal(@res.json.firstCall.args[0])
|
({invite: @invite}).should.deep.equal(@res.json.firstCall.args[0])
|
||||||
|
@ -114,6 +121,10 @@ describe "CollaboratorsInviteController", ->
|
||||||
@LimitationsManager.canAddXCollaborators.callCount.should.equal 1
|
@LimitationsManager.canAddXCollaborators.callCount.should.equal 1
|
||||||
@LimitationsManager.canAddXCollaborators.calledWith(@project_id).should.equal true
|
@LimitationsManager.canAddXCollaborators.calledWith(@project_id).should.equal true
|
||||||
|
|
||||||
|
it 'should have called _checkShouldInviteEmail', ->
|
||||||
|
@_checkShouldInviteEmail.callCount.should.equal 1
|
||||||
|
@_checkShouldInviteEmail.calledWith(@targetEmail).should.equal true
|
||||||
|
|
||||||
it 'should have called inviteToProject', ->
|
it 'should have called inviteToProject', ->
|
||||||
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 1
|
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 1
|
||||||
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user,@targetEmail,@privileges).should.equal true
|
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user,@targetEmail,@privileges).should.equal true
|
||||||
|
@ -125,37 +136,63 @@ describe "CollaboratorsInviteController", ->
|
||||||
describe 'when the user is not allowed to add more collaborators', ->
|
describe 'when the user is not allowed to add more collaborators', ->
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@_checkShouldInviteEmail = sinon.stub(
|
||||||
|
@CollaboratorsInviteController, '_checkShouldInviteEmail'
|
||||||
|
).callsArgWith(1, null, true)
|
||||||
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, null, false)
|
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, null, false)
|
||||||
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
@_checkShouldInviteEmail.restore()
|
||||||
|
|
||||||
it 'should produce json response without an invite', ->
|
it 'should produce json response without an invite', ->
|
||||||
@res.json.callCount.should.equal 1
|
@res.json.callCount.should.equal 1
|
||||||
({invite: null}).should.deep.equal(@res.json.firstCall.args[0])
|
({invite: null}).should.deep.equal(@res.json.firstCall.args[0])
|
||||||
|
|
||||||
|
it 'should not have called _checkShouldInviteEmail', ->
|
||||||
|
@_checkShouldInviteEmail.callCount.should.equal 0
|
||||||
|
@_checkShouldInviteEmail.calledWith(@targetEmail).should.equal false
|
||||||
|
|
||||||
it 'should not have called inviteToProject', ->
|
it 'should not have called inviteToProject', ->
|
||||||
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 0
|
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 0
|
||||||
|
|
||||||
describe 'when canAddXCollaborators produces an error', ->
|
describe 'when canAddXCollaborators produces an error', ->
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@_checkShouldInviteEmail = sinon.stub(
|
||||||
|
@CollaboratorsInviteController, '_checkShouldInviteEmail'
|
||||||
|
).callsArgWith(1, null, true)
|
||||||
@err = new Error('woops')
|
@err = new Error('woops')
|
||||||
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, @err)
|
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, @err)
|
||||||
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
@_checkShouldInviteEmail.restore()
|
||||||
|
|
||||||
it 'should call next with an error', ->
|
it 'should call next with an error', ->
|
||||||
@next.callCount.should.equal 1
|
@next.callCount.should.equal 1
|
||||||
@next.calledWith(@err).should.equal true
|
@next.calledWith(@err).should.equal true
|
||||||
|
|
||||||
|
it 'should not have called _checkShouldInviteEmail', ->
|
||||||
|
@_checkShouldInviteEmail.callCount.should.equal 0
|
||||||
|
@_checkShouldInviteEmail.calledWith(@targetEmail).should.equal false
|
||||||
|
|
||||||
it 'should not have called inviteToProject', ->
|
it 'should not have called inviteToProject', ->
|
||||||
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 0
|
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 0
|
||||||
|
|
||||||
describe 'when inviteToProject produces an error', ->
|
describe 'when inviteToProject produces an error', ->
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@_checkShouldInviteEmail = sinon.stub(
|
||||||
|
@CollaboratorsInviteController, '_checkShouldInviteEmail'
|
||||||
|
).callsArgWith(1, null, true)
|
||||||
@err = new Error('woops')
|
@err = new Error('woops')
|
||||||
@CollaboratorsInviteHandler.inviteToProject = sinon.stub().callsArgWith(4, @err)
|
@CollaboratorsInviteHandler.inviteToProject = sinon.stub().callsArgWith(4, @err)
|
||||||
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
@_checkShouldInviteEmail.restore()
|
||||||
|
|
||||||
it 'should call next with an error', ->
|
it 'should call next with an error', ->
|
||||||
@next.callCount.should.equal 1
|
@next.callCount.should.equal 1
|
||||||
@next.calledWith(@err).should.equal true
|
@next.calledWith(@err).should.equal true
|
||||||
|
@ -164,10 +201,60 @@ describe "CollaboratorsInviteController", ->
|
||||||
@LimitationsManager.canAddXCollaborators.callCount.should.equal 1
|
@LimitationsManager.canAddXCollaborators.callCount.should.equal 1
|
||||||
@LimitationsManager.canAddXCollaborators.calledWith(@project_id).should.equal true
|
@LimitationsManager.canAddXCollaborators.calledWith(@project_id).should.equal true
|
||||||
|
|
||||||
|
it 'should have called _checkShouldInviteEmail', ->
|
||||||
|
@_checkShouldInviteEmail.callCount.should.equal 1
|
||||||
|
@_checkShouldInviteEmail.calledWith(@targetEmail).should.equal true
|
||||||
|
|
||||||
it 'should have called inviteToProject', ->
|
it 'should have called inviteToProject', ->
|
||||||
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 1
|
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 1
|
||||||
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user,@targetEmail,@privileges).should.equal true
|
@CollaboratorsInviteHandler.inviteToProject.calledWith(@project_id,@current_user,@targetEmail,@privileges).should.equal true
|
||||||
|
|
||||||
|
describe 'when _checkShouldInviteEmail disallows the invite', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@_checkShouldInviteEmail = sinon.stub(
|
||||||
|
@CollaboratorsInviteController, '_checkShouldInviteEmail'
|
||||||
|
).callsArgWith(1, null, false)
|
||||||
|
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, null, true)
|
||||||
|
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
@_checkShouldInviteEmail.restore()
|
||||||
|
|
||||||
|
it 'should produce json response with no invite, and an error property', ->
|
||||||
|
@res.json.callCount.should.equal 1
|
||||||
|
({invite: null, error: 'cannot_invite_non_user'}).should.deep.equal(@res.json.firstCall.args[0])
|
||||||
|
|
||||||
|
it 'should have called _checkShouldInviteEmail', ->
|
||||||
|
@_checkShouldInviteEmail.callCount.should.equal 1
|
||||||
|
@_checkShouldInviteEmail.calledWith(@targetEmail).should.equal true
|
||||||
|
|
||||||
|
it 'should not have called inviteToProject', ->
|
||||||
|
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 0
|
||||||
|
|
||||||
|
describe 'when _checkShouldInviteEmail produces an error', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@_checkShouldInviteEmail = sinon.stub(
|
||||||
|
@CollaboratorsInviteController, '_checkShouldInviteEmail'
|
||||||
|
).callsArgWith(1, new Error('woops'))
|
||||||
|
@LimitationsManager.canAddXCollaborators = sinon.stub().callsArgWith(2, null, true)
|
||||||
|
@CollaboratorsInviteController.inviteToProject @req, @res, @next
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
@_checkShouldInviteEmail.restore()
|
||||||
|
|
||||||
|
it 'should call next with an error', ->
|
||||||
|
@next.callCount.should.equal 1
|
||||||
|
@next.calledWith(@err).should.equal true
|
||||||
|
|
||||||
|
it 'should have called _checkShouldInviteEmail', ->
|
||||||
|
@_checkShouldInviteEmail.callCount.should.equal 1
|
||||||
|
@_checkShouldInviteEmail.calledWith(@targetEmail).should.equal true
|
||||||
|
|
||||||
|
it 'should not have called inviteToProject', ->
|
||||||
|
@CollaboratorsInviteHandler.inviteToProject.callCount.should.equal 0
|
||||||
|
|
||||||
describe "viewInvite", ->
|
describe "viewInvite", ->
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
|
@ -579,3 +666,74 @@ describe "CollaboratorsInviteController", ->
|
||||||
|
|
||||||
it 'should have called acceptInvite', ->
|
it 'should have called acceptInvite', ->
|
||||||
@CollaboratorsInviteHandler.acceptInvite.callCount.should.equal 1
|
@CollaboratorsInviteHandler.acceptInvite.callCount.should.equal 1
|
||||||
|
|
||||||
|
describe '_checkShouldInviteEmail', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@email = 'user@example.com'
|
||||||
|
@call = (callback) =>
|
||||||
|
@CollaboratorsInviteController._checkShouldInviteEmail @email, callback
|
||||||
|
|
||||||
|
describe 'when we should be restricting to existing accounts', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@settings.restrictInvitesToExistingAccounts = true
|
||||||
|
|
||||||
|
describe 'when user account is present', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@user = {_id: ObjectId().toString()}
|
||||||
|
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user)
|
||||||
|
|
||||||
|
it 'should callback with `true`', (done) ->
|
||||||
|
@call (err, shouldAllow) =>
|
||||||
|
expect(err).to.equal null
|
||||||
|
expect(shouldAllow).to.equal true
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'when user account is absent', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@user = null
|
||||||
|
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user)
|
||||||
|
|
||||||
|
it 'should callback with `false`', (done) ->
|
||||||
|
@call (err, shouldAllow) =>
|
||||||
|
expect(err).to.equal null
|
||||||
|
expect(shouldAllow).to.equal false
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should have called getUser', (done) ->
|
||||||
|
@call (err, shouldAllow) =>
|
||||||
|
@UserGetter.getUser.callCount.should.equal 1
|
||||||
|
@UserGetter.getUser.calledWith({email: @email}, {_id: 1}).should.equal true
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'when getUser produces an error', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@user = null
|
||||||
|
@UserGetter.getUser = sinon.stub().callsArgWith(2, new Error('woops'))
|
||||||
|
|
||||||
|
it 'should callback with an error', (done) ->
|
||||||
|
@call (err, shouldAllow) =>
|
||||||
|
expect(err).to.not.equal null
|
||||||
|
expect(err).to.be.instanceof Error
|
||||||
|
expect(shouldAllow).to.equal undefined
|
||||||
|
done()
|
||||||
|
|
||||||
|
describe 'when we should not be restricting', ->
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
@settings.restrictInvitesToExistingAccounts = false
|
||||||
|
|
||||||
|
it 'should callback with `true`', (done) ->
|
||||||
|
@call (err, shouldAllow) =>
|
||||||
|
expect(err).to.equal null
|
||||||
|
expect(shouldAllow).to.equal true
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'should not have called getUser', (done) ->
|
||||||
|
@call (err, shouldAllow) =>
|
||||||
|
@UserGetter.getUser.callCount.should.equal 0
|
||||||
|
done()
|
||||||
|
|
Loading…
Reference in a new issue