Henry Oswald 12 лет назад
Родитель
Сommit
430cf5cea8

+ 2 - 2
services/web/app/coffee/Features/Collaborators/CollaboratorsController.coffee

@@ -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"
 

+ 70 - 5
services/web/app/coffee/Features/Collaborators/CollaboratorsHandler.coffee

@@ -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
+
+
+

+ 6 - 6
services/web/app/coffee/Features/Editor/EditorController.coffee

@@ -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)->

+ 0 - 2
services/web/app/coffee/Features/Subscription/SubscriptionViewModelBuilder.coffee

@@ -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

+ 2 - 2
services/web/app/coffee/controllers/ProjectController.coffee

@@ -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

+ 0 - 55
services/web/app/coffee/handlers/ProjectHandler.coffee

@@ -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()

+ 3 - 3
services/web/app/coffee/infrastructure/ExpressLocals.coffee

@@ -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)-> 

+ 3 - 3
services/web/app/coffee/router.coffee

@@ -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) =>

+ 3 - 3
services/web/app/views/project/partials/manage.jade

@@ -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.

+ 5 - 3
services/web/test/UnitTests/coffee/Collaborators/CollaboratorsControllerTests.coffee

@@ -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"

+ 26 - 4
services/web/test/UnitTests/coffee/Collaborators/CollaboratorsHandlerTests.coffee

@@ -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()
+
+
+
+
+

+ 31 - 20
services/web/test/UnitTests/coffee/Editor/EditorControllerTests.coffee

@@ -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()