Ensure that a user can only be added to project once

This commit is contained in:
James Allen 2015-11-02 15:21:41 +00:00
parent 7359fc16ee
commit c46f62cfc1
3 changed files with 53 additions and 23 deletions

View file

@ -30,26 +30,34 @@ module.exports = CollaboratorsHandler =
return callback null, user._id
addUserIdToProject: (project_id, adding_user_id, user_id, privilegeLevel, callback = (error) ->)->
if privilegeLevel == 'readAndWrite'
level = {"collaberator_refs":user_id}
logger.log {privileges: "readAndWrite", user_id, project_id}, "adding user"
else if privilegeLevel == 'readOnly'
level = {"readOnly_refs":user_id}
logger.log {privileges: "readOnly", user_id, project_id}, "adding user"
else
return callback(new Error("unknown privilegeLevel: #{privilegeLevel}"))
# Do these in the background
UserGetter.getUser user_id, {email: 1}, (error, user) ->
if error?
logger.error {err: error, project_id, user_id}, "error getting user while adding to project"
CollaboratorsEmailHandler.notifyUserOfProjectShare project_id, user.email
ContactManager.addContact adding_user_id, user_id
Project.update { _id: project_id }, { $push:level }, (error) ->
Project.findOne { _id: project_id }, { collaberator_refs: 1, readOnly_refs: 1 }, (error, project) ->
return callback(error) if error?
# Flush to TPDS in background to add files to collaborator's Dropbox
ProjectEntityHandler.flushProjectToThirdPartyDataStore project_id, (error) ->
existing_users = (project.collaberator_refs or [])
existing_users = existing_users.concat(project.readOnly_refs or [])
existing_users = existing_users.map (u) -> u.toString()
if existing_users.indexOf(user_id.toString()) > -1
return callback null # User already in Project
if privilegeLevel == 'readAndWrite'
level = {"collaberator_refs":user_id}
logger.log {privileges: "readAndWrite", user_id, project_id}, "adding user"
else if privilegeLevel == 'readOnly'
level = {"readOnly_refs":user_id}
logger.log {privileges: "readOnly", user_id, project_id}, "adding user"
else
return callback(new Error("unknown privilegeLevel: #{privilegeLevel}"))
# Do these in the background
UserGetter.getUser user_id, {email: 1}, (error, user) ->
if error?
logger.error {err: error, project_id, user_id}, "error flushing to TPDS after adding collaborator"
callback()
logger.error {err: error, project_id, user_id}, "error getting user while adding to project"
CollaboratorsEmailHandler.notifyUserOfProjectShare project_id, user.email
ContactManager.addContact adding_user_id, user_id
Project.update { _id: project_id }, { $addToSet: level }, (error) ->
return callback(error) if error?
# Flush to TPDS in background to add files to collaborator's Dropbox
ProjectEntityHandler.flushProjectToThirdPartyDataStore project_id, (error) ->
if error?
logger.error {err: error, project_id, user_id}, "error flushing to TPDS after adding collaborator"
callback()

View file

@ -38,9 +38,15 @@ define [
else
# Must be a group
contact.display = contact.name
getCurrentMemberEmails = () ->
$scope.project.members.map (u) -> u.email
$scope.filterAutocompleteUsers = ($query) ->
currentMemberEmails = getCurrentMemberEmails()
return $scope.autocompleteContacts.filter (contact) ->
if contact.email? and contact.email in currentMemberEmails
return false
for text in [contact.name, contact.email]
if text?.toLowerCase().indexOf($query.toLowerCase()) > -1
return true
@ -55,6 +61,7 @@ define [
$scope.state.error = null
$scope.state.inflight = true
currentMemberEmails = getCurrentMemberEmails()
do addNextMember = () ->
if members.length == 0 or !$scope.canAddCollaborators
$scope.state.inflight = false
@ -62,10 +69,16 @@ define [
return
member = members.shift()
if !member.type? and member.display in currentMemberEmails
# Skip this existing member
return addNextMember()
if member.type == "user"
request = projectMembers.addMember(member.email, $scope.inputs.privileges)
else if member.type == "group"
request = projectMembers.addGroup(member.id, $scope.inputs.privileges)
else # Not an auto-complete object, so email == display
request = projectMembers.addMember(member.display, $scope.inputs.privileges)
request
.success (data) ->

View file

@ -40,6 +40,7 @@ describe "CollaboratorsHandler", ->
describe "addUserToProject", ->
beforeEach ->
@Project.update = sinon.stub().callsArg(2)
@Project.findOne = sinon.stub().callsArgWith(2, null, @project = {})
@ProjectEntityHandler.flushProjectToThirdPartyDataStore = sinon.stub().callsArg(1)
@CollaboratorHandler.addEmailToProject = sinon.stub().callsArgWith(4, null, @user_id)
@UserGetter.getUser = sinon.stub().callsArgWith(2, null, @user = { _id: @user_id, email: @email })
@ -55,7 +56,7 @@ describe "CollaboratorsHandler", ->
.calledWith({
_id: @project_id
}, {
"$push":{ readOnly_refs: @user_id }
"$addToSet":{ readOnly_refs: @user_id }
})
.should.equal true
@ -83,7 +84,7 @@ describe "CollaboratorsHandler", ->
.calledWith({
_id: @project_id
}, {
"$push":{ collaberator_refs: @user_id }
"$addToSet":{ collaberator_refs: @user_id }
})
.should.equal true
@ -98,6 +99,14 @@ describe "CollaboratorsHandler", ->
it "should call the callback with an error", ->
@callback.calledWith(new Error()).should.equal true
describe "when user already exists as a collaborator", ->
beforeEach ->
@project.collaberator_refs = [@user_id]
@CollaboratorHandler.addUserIdToProject @project_id, @adding_user_id, @user_id, "readAndWrite", @callback
it "should not add the user again", ->
@Project.update.called.should.equal false
describe "addEmailToProject", ->
beforeEach ->