created CollaboratorsHandler

This commit is contained in:
Henry Oswald
2014-04-07 20:46:58 +01:00
parent ff88849444
commit 430cf5cea8
12 changed files with 151 additions and 108 deletions

View File

@@ -1,5 +1,5 @@
ProjectGetter = require "../Project/ProjectGetter"
ProjectHandler = require "../../handlers/ProjectHandler"
CollaboratorsHandler = require "./CollaboratorsHandler"
module.exports = CollaboratorsController =
@@ -17,7 +17,7 @@ module.exports = CollaboratorsController =
user_id = req.session?.user?._id
if !user_id?
return next(new Error("User should be logged in"))
ProjectHandler::removeUserFromProject req.params.project_id, user_id, (error) ->
CollaboratorsHandler.removeUserFromProject req.params.project_id, user_id, (error) ->
return next(error) if error?
res.redirect "/project"

View File

@@ -1,17 +1,82 @@
User = require('../models/User').User
User = require('../../models/User').User
Project = require("../../models/Project").Project
Settings = require('settings-sharelatex')
EmailHandler = require("../Email/EmailHandler")
projectEntityHandler = require '../Project/ProjectEntityHandler'
mimelib = require("mimelib")
logger = require('logger-sharelatex')
async = require("async")
module.exports =
removeUserFromProject: (project_id, user_id, callback = ->)->
logger.log user_id: user_id, project_id: project_id, "removing user"
conditions = _id:project_id
update = $pull:{}
update["$pull"] = collaberator_refs:user_id, readOnly_refs:user_id
Project.update conditions, update, (err)->
if err?
logger.err err: err, "problem removing user from project collaberators"
callback(err)
changeUsersPrivlageLevel: (project_id, user_id, newPrivalageLevel, callback)->
changeUsersPrivilegeLevel: (project_id, user_id, newPrivalageLevel, callback = ->)->
@removeUserFromProject project_id, user_id, =>
User.findById user_id, (err, user)=>
@addUserToProject project_id, user_id, newPrivalageLevel, callback
addUserToProject: (project_id, email, privilegeLevel, callback)->
emails = mimelib.parseAddresses(email)
email = emails[0].address?.toLowerCase()
self = @
User.findOne {'email':email}, (err, user)->
async.waterfall [
(cb)->
if user?
return cb(null, user)
else
self._createHoldingAccount email, cb
(@user, cb)=>
self._updateProjectWithUserPrivileges project_id, user, privilegeLevel, cb
(cb)->
self._notifyUserViaEmail project_id, email, cb
], (err)=>
callback(err, @user)
_createHoldingAccount: (email, callback)->
user = new User 'email':email, holdingAccount:true
user.save (err)->
callback(err, user)
_updateProjectWithUserPrivileges: (project_id, user, privilegeLevel, callback)->
if privilegeLevel == 'readAndWrite'
level = {"collaberator_refs":user}
logger.log privileges: "readAndWrite", user: user, project_id: project_id, "adding user"
else if privilegeLevel == 'readOnly'
level = {"readOnly_refs":user}
logger.log privileges: "readOnly", user: user, project_id: project_id, "adding user"
Project.update {_id: project_id}, {$push:level}, (err)->
callback(err)
_notifyUserViaEmail: (project_id, email, callback)->
Project.findOne(_id: project_id )
.select("name owner_ref")
.populate('owner_ref')
.exec (err, project)->
emailOptions =
to : email
replyTo : project.owner_ref.email
project:
name: project.name
url: "#{Settings.siteUrl}/project/#{project._id}?" + [
"project_name=#{encodeURIComponent(project.name)}"
"user_first_name=#{encodeURIComponent(project.owner_ref.first_name)}"
"new_email=#{encodeURIComponent(email)}"
"r=#{project.owner_ref.referal_id}" # Referal
"rs=ci" # referral source = collaborator invite
].join("&")
owner: project.owner_ref
EmailHandler.sendEmail "projectSharedWithYou", emailOptions, callback

View File

@@ -7,7 +7,7 @@ ProjectOptionsHandler = require('../Project/ProjectOptionsHandler')
ProjectDetailsHandler = require('../Project/ProjectDetailsHandler')
ProjectDeleter = require("../Project/ProjectDeleter")
ProjectGetter = require('../Project/ProjectGetter')
ProjectHandler = new (require('../../handlers/ProjectHandler'))()
CollaboratorsHandler = require("../Collaborators/CollaboratorsHandler")
DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
LimitationsManager = require("../Subscription/LimitationsManager")
AuthorizationManager = require("../Security/AuthorizationManager")
@@ -124,7 +124,7 @@ module.exports = EditorController =
cursorData.name = "Anonymous"
EditorRealTimeController.emitToRoom(project_id, "clientTracking.clientUpdated", cursorData)
addUserToProject: (project_id, email, privlages, callback = (error, collaborator_added)->)->
addUserToProject: (project_id, email, privileges, callback = (error, collaborator_added)->)->
email = email.toLowerCase()
LimitationsManager.isCollaboratorLimitReached project_id, (error, limit_reached) =>
if error?
@@ -134,12 +134,13 @@ module.exports = EditorController =
if limit_reached
callback null, false
else
ProjectHandler.addUserToProject project_id, email, privlages, (user)=>
EditorRealTimeController.emitToRoom(project_id, 'userAddedToProject', user, privlages)
CollaboratorsHandler.addUserToProject project_id, email, privileges, (err, user)=>
ProjectEntityHandler.flushProjectToThirdPartyDataStore project_id, "", ->
EditorRealTimeController.emitToRoom(project_id, 'userAddedToProject', user, privileges)
callback null, true
removeUserFromProject: (project_id, user_id, callback)->
ProjectHandler.removeUserFromProject project_id, user_id, =>
CollaboratorsHandler.removeUserFromProject project_id, user_id, =>
EditorRealTimeController.emitToRoom(project_id, 'userRemovedFromProject', user_id)
if callback?
callback()
@@ -241,7 +242,6 @@ module.exports = EditorController =
deleteProject: (project_id, callback)->
Metrics.inc "editor.delete-project"
logger.log project_id:project_id, "recived message to delete project"
console.log ProjectDeleter
ProjectDeleter.deleteProject project_id, callback
renameEntity: (project_id, entity_id, entityType, newName, callback)->

View File

@@ -38,8 +38,6 @@ module.exports =
buildViewModel : ->
plans = Settings.plans
console.log plans
console.log(typeof(plans))
allPlans = {}
plans.forEach (plan)->
allPlans[plan.planCode] = plan

View File

@@ -124,7 +124,7 @@ module.exports = class ProjectController
else
anonymous = false
SubscriptionLocator.getUsersSubscription user?._id, (err, subscription)->
SecurityManager.userCanAccessProject user, project, (canAccess, privlageLevel)->
SecurityManager.userCanAccessProject user, project, (canAccess, privilegeLevel)->
allowedFreeTrial = true
if subscription? and subscription.freeTrial? and subscription.freeTrial.expiresAt?
allowedFreeTrial = !!subscription.freeTrial.allowed
@@ -160,7 +160,7 @@ module.exports = class ProjectController
siteUrl: Settings.siteUrl,
jsPath: res.locals.jsPath
})
privlageLevel: privlageLevel
privilegeLevel: privilegeLevel
userCanSeeDropbox: user.featureSwitches.dropbox and project.owner_ref._id+"" == user._id+""
loadPdfjs: (user.ace.pdfViewer == "pdfjs")
chatUrl: Settings.apis.chat.url

View File

@@ -20,58 +20,3 @@ tagsHandler = require('../Features/Tags/TagsHandler')
module.exports = class ProjectHandler
addUserToProject: (project_id, email, privlages, callback)->
if email != ''
doAdd = (user)=>
Project.findOne(_id: project_id )
.select("name owner_ref")
.populate('owner_ref')
.exec (err, project)->
emailOptions =
to : email
replyTo : project.owner_ref.email
project:
name: project.name
url: "#{Settings.siteUrl}/project/#{project._id}?" + [
"project_name=#{encodeURIComponent(project.name)}"
"user_first_name=#{encodeURIComponent(project.owner_ref.first_name)}"
"new_email=#{encodeURIComponent(email)}"
"r=#{project.owner_ref.referal_id}" # Referal
"rs=ci" # referral source = collaborator invite
].join("&")
owner: project.owner_ref
EmailHandler.sendEmail "projectSharedWithYou", emailOptions, ->
if privlages == 'readAndWrite'
level = {"collaberator_refs":user}
logger.log privileges: "readAndWrite", user: user, project: project, "adding user"
else if privlages == 'readOnly'
level = {"readOnly_refs":user}
logger.log privileges: "readOnly", user: user, project: project, "adding user"
Project.update {_id: project_id}, {$push:level},{},(err)->
projectEntityHandler.flushProjectToThirdPartyDataStore project_id, "", ->
if callback?
callback(user)
emails = mimelib.parseAddresses(email)
email = emails[0].address
User.findOne {'email':email}, (err, user)->
if(!user)
user = new User 'email':email, holdingAccount:true
user.save (err)->
logger.log user: user, 'creating new empty user'
doAdd user
else
doAdd user
removeUserFromProject: (project_id, user_id, callback)->
logger.log user_id: user_id, project_id: project_id, "removing user"
conditions = _id:project_id
update = $pull:{}
update["$pull"] = collaberator_refs:user_id, readOnly_refs:user_id
Project.update conditions, update, {}, (err)->
if err?
logger.err err: err, "problem removing user from project collaberators"
if callback?
callback()

View File

@@ -54,9 +54,9 @@ module.exports = (app)->
next()
app.use (req, res, next)->
res.locals.formatProjectPublicAccessLevel = (privlageLevel)->
formatedPrivlages = private:"Private", readOnly:"Public: Read Only", readAndWrite:"Public: Read and Write"
return formatedPrivlages[privlageLevel] || "Private"
res.locals.formatProjectPublicAccessLevel = (privilegeLevel)->
formatedPrivileges = private:"Private", readOnly:"Public: Read Only", readAndWrite:"Public: Read and Write"
return formatedPrivileges[privilegeLevel] || "Private"
next()
app.use (req, res, next)->

View File

@@ -198,7 +198,7 @@ module.exports = class Router
app.get '/test', (req, res) ->
res.render "tests",
privlageLevel: "owner"
privilegeLevel: "owner"
project:
name: "test"
date: Date.now()
@@ -314,9 +314,9 @@ module.exports = class Router
AuthorizationManager.ensureClientCanViewProject client, (error, project_id) =>
CompileManager.compile(project_id, user._id, opts, callback)
client.on 'changeUsersPrivlageLevel', (user_id, newPrivalageLevel)->
client.on 'changeUsersPrivilegeLevel', (user_id, newPrivalageLevel)->
AuthorizationManager.ensureClientCanAdminProject client, (error, project_id) =>
projectHandler.changeUsersPrivlageLevel project_id, user_id, newPrivalageLevel
projectHandler.changeUsersPrivilegeLevel project_id, user_id, newPrivalageLevel
client.on 'enableversioningController', (callback)->
AuthorizationManager.ensureClientCanEditProject client, (error, project_id) =>

View File

@@ -16,7 +16,7 @@
.tab-content.form-horizontal
.tab-pane#generalProjectSettings.form.form-horizontal.active
if privlageLevel == 'owner' || privlageLevel == 'readAndWrite'
if privilegeLevel == 'owner' || privilegeLevel == 'readAndWrite'
.control-group
label(for='xlInput').control-label Project Name
.controls
@@ -54,7 +54,7 @@
else
span You do not have permission to modify these settings.
if privlageLevel == 'owner'
if privilegeLevel == 'owner'
.control-group
label(for='select').control-label Public Access
.controls
@@ -69,7 +69,7 @@
a.btn(href='/project/'+project._id+'/clone').cloneProject Clone Project
.tab-pane#deleteProjectTab
if privlageLevel == 'owner'
if privilegeLevel == 'owner'
button#deleteProject.btn.btn-danger Delete Project
else
span You do not have permission to modify these settings.

View File

@@ -11,9 +11,11 @@ ObjectId = require("mongojs").ObjectId
describe "CollaboratorsController", ->
beforeEach ->
@CollaboratorsHandler =
removeUserFromProject:sinon.stub()
@CollaboratorsController = SandboxedModule.require modulePath, requires:
"../Project/ProjectGetter": @ProjectGetter = {}
"../../handlers/ProjectHandler": @ProjectHandler = class ProjectHandler
"./CollaboratorsHandler": @CollaboratorsHandler
@res = new MockResponse()
@req = new MockRequest()
@@ -54,12 +56,12 @@ describe "CollaboratorsController", ->
user: _id: @user_id = "user-id-123"
destroy:->
@req.params = project_id: @project_id
@ProjectHandler::removeUserFromProject = sinon.stub().callsArg(2)
@CollaboratorsHandler.removeUserFromProject = sinon.stub().callsArg(2)
@CollaboratorsController.removeSelfFromProject(@req, @res)
it "should remove the logged in user from the project", ->
@ProjectHandler::removeUserFromProject.calledWith(@project_id, @user_id)
@CollaboratorsHandler.removeUserFromProject.calledWith(@project_id, @user_id)
it "should redirect to the project page", ->
@res.redirectedTo.should.equal "/project"

View File

@@ -14,26 +14,48 @@ describe "CollaboratorsHandler", ->
email:"bob@bob.com"
@UserModel =
findById:sinon.stub().callsArgWith(1, null, @user)
update: sinon.stub()
@settings = {}
@ProjectModel =
update: sinon.stub().callsArgWith(1)
@CollaboratorHandler = SandboxedModule.require modulePath, requires:
"settings-sharelatex":@settings
"logger-sharelatex": log:->
'../models/User': User:@UserModel
"logger-sharelatex":
log:->
err:->
'../../models/User': User:@UserModel
"../../models/Project": Project:@ProjectModel
@project_id = "123l2j13lkj"
@user_id = "132kj1lk2j"
describe "changeUsersPrivlageLevel", ->
describe "changeUsersPrivilegeLevel", ->
it "should call removeUserFromProject then addUserToProject", (done)->
@CollaboratorHandler.removeUserFromProject = sinon.stub().callsArgWith(2)
@CollaboratorHandler.addUserToProject = sinon.stub().callsArgWith(3)
newPrivalageLevel = "readAndWrite"
@CollaboratorHandler.changeUsersPrivlageLevel @project_id, @user_id, newPrivalageLevel, =>
@CollaboratorHandler.changeUsersPrivilegeLevel @project_id, @user_id, newPrivalageLevel, =>
@CollaboratorHandler.removeUserFromProject.calledWith(@project_id, @user_id).should.equal true
@CollaboratorHandler.addUserToProject.calledWith(@project_id, @user_id, newPrivalageLevel)
done()
describe "removeUserFromProject", ->
beforeEach ->
@ProjectModel.update.callsArgWith(2)
it "should remove the user from mongo", (done)->
@CollaboratorHandler.removeUserFromProject @project_id, @user_id, =>
update = @ProjectModel.update.args[0][1]
assert.deepEqual update, "$pull":{collaberator_refs:@user_id, readOnly_refs:@user_id}
done()

View File

@@ -30,10 +30,10 @@ describe "EditorController", ->
@ProjectOptionsHandler =
setCompiler : sinon.spy()
setSpellCheckLanguage: sinon.spy()
@ProjectEntityHandler = {}
@ProjectEntityHandler =
flushProjectToThirdPartyDataStore:sinon.stub()
@ProjectEditorHandler =
buildProjectModelView : sinon.stub().returns(@projectModelView)
@ProjectHandler = class ProjectHandler
@Project =
findPopulatedById: sinon.stub().callsArgWith(1, null, @project)
@LimitationsManager = {}
@@ -51,17 +51,24 @@ describe "EditorController", ->
@TpdsPollingBackgroundTasks = {}
@ProjectDetailsHandler =
setProjectDescription:sinon.stub()
@CollaboratorsHandler =
removeUserFromProject: sinon.stub().callsArgWith(2)
addUserToProject: sinon.stub().callsArgWith(3)
@ProjectDeleter =
deleteProject: sinon.stub()
@EditorController = SandboxedModule.require modulePath, requires:
"../../infrastructure/Server" : io : @io
'../Project/ProjectEditorHandler' : @ProjectEditorHandler
'../Project/ProjectEntityHandler' : @ProjectEntityHandler
'../Project/ProjectOptionsHandler' : @ProjectOptionsHandler
'../Project/ProjectDetailsHandler': @ProjectDetailsHandler
'../Project/ProjectDeleter' : @ProjectDeleter
'../Project/ProjectGetter' : @ProjectGetter = {}
'../Collaborators/CollaboratorsHandler': @CollaboratorsHandler
'../DocumentUpdater/DocumentUpdaterHandler' : @DocumentUpdaterHandler
'../Subscription/LimitationsManager' : @LimitationsManager
'../Security/AuthorizationManager' : @AuthorizationManager
'../../handlers/ProjectHandler' : @ProjectHandler
"../Versioning/AutomaticSnapshotManager" : @AutomaticSnapshotManager
"../Versioning/VersioningApiHandler" : @VersioningApiHandler
'../../models/Project' : Project: @Project
@@ -293,25 +300,29 @@ describe "EditorController", ->
@email = "Jane.Doe@example.com"
@priveleges = "readOnly"
@addedUser = { _id: "added-user" }
@ProjectHandler::addUserToProject = sinon.stub().callsArgWith(3, @addedUser)
@CollaboratorsHandler.addUserToProject = sinon.stub().callsArgWith(3, null, @addedUser)
@EditorRealTimeController.emitToRoom = sinon.stub()
@callback = sinon.stub()
describe "when the project can accept more collaborators", ->
beforeEach ->
@LimitationsManager.isCollaboratorLimitReached = sinon.stub().callsArgWith(1, null, false)
@EditorController.addUserToProject(@project_id, @email, @priveleges, @callback)
it "should add the user to the project", ->
@ProjectHandler::addUserToProject
.calledWith(@project_id, @email.toLowerCase(), @priveleges)
.should.equal true
it "should add the user to the project", (done)->
@EditorController.addUserToProject @project_id, @email, @priveleges, =>
@CollaboratorsHandler.addUserToProject.calledWith(@project_id, @email.toLowerCase(), @priveleges).should.equal true
done()
it "should emit a userAddedToProject event", ->
@EditorRealTimeController.emitToRoom.calledWith(@project_id, "userAddedToProject", @addedUser).should.equal true
it "should emit a userAddedToProject event", (done)->
@EditorController.addUserToProject @project_id, @email, @priveleges, =>
@EditorRealTimeController.emitToRoom.calledWith(@project_id, "userAddedToProject", @addedUser).should.equal true
done()
it "should return true to the callback", (done)->
@EditorController.addUserToProject @project_id, @email, @priveleges, (err, result)=>
result.should.equal true
done()
it "should return true to the callback", ->
@callback.calledWith(null, true).should.equal true
describe "when the project cannot accept more collaborators", ->
beforeEach ->
@@ -319,7 +330,7 @@ describe "EditorController", ->
@EditorController.addUserToProject(@project_id, @email, @priveleges, @callback)
it "should not add the user to the project", ->
@ProjectHandler::addUserToProject.called.should.equal false
@CollaboratorsHandler.addUserToProject.called.should.equal false
it "should not emit a userAddedToProject event", ->
@EditorRealTimeController.emitToRoom.called.should.equal false
@@ -331,13 +342,13 @@ describe "EditorController", ->
describe "removeUserFromProject", ->
beforeEach ->
@removed_user_id = "removed-user-id"
@ProjectHandler::removeUserFromProject = sinon.stub().callsArgWith(2)
@CollaboratorsHandler.removeUserFromProject = sinon.stub().callsArgWith(2)
@EditorRealTimeController.emitToRoom = sinon.stub()
@EditorController.removeUserFromProject(@project_id, @removed_user_id)
it "remove the user from the project", ->
@ProjectHandler::removeUserFromProject
@CollaboratorsHandler.removeUserFromProject
.calledWith(@project_id, @removed_user_id)
.should.equal true
@@ -613,12 +624,12 @@ describe "EditorController", ->
beforeEach ->
@err = "errro"
@ProjectHandler::deleteProject = sinon.stub().callsArgWith(1, @err)
@ProjectDeleter.deleteProject = sinon.stub().callsArgWith(1, @err)
it "should call the project handler", (done)->
@EditorController.deleteProject @project_id, (err)=>
err.should.equal @err
@ProjectHandler::deleteProject.calledWith(@project_id).should.equal true
@ProjectDeleter.deleteProject.calledWith(@project_id).should.equal true
done()
@@ -673,7 +684,7 @@ describe "EditorController", ->
@ProjectDetailsHandler.renameProject = sinon.stub().callsArgWith(2, @err)
@EditorRealTimeController.emitToRoom = sinon.stub()
it "should call the ProjectHandler", (done)->
it "should call the EditorController", (done)->
@EditorController.renameProject @project_id, @newName, =>
@ProjectDetailsHandler.renameProject.calledWith(@project_id, @newName).should.equal true
done()
@@ -693,7 +704,7 @@ describe "EditorController", ->
@ProjectDetailsHandler.setPublicAccessLevel = sinon.stub().callsArgWith(2, @err)
@EditorRealTimeController.emitToRoom = sinon.stub()
it "should call the ProjectHandler", (done)->
it "should call the EditorController", (done)->
@EditorController.setPublicAccessLevel @project_id, @newAccessLevel, =>
@ProjectDetailsHandler.setPublicAccessLevel.calledWith(@project_id, @newAccessLevel).should.equal true
done()