Shane Kilkelly 10 лет назад
Родитель
Сommit
ab2c1e82fb
22 измененных файлов с 394 добавлено и 361 удалено
  1. 2 2
      services/web/app/coffee/Features/Analytics/AnalyticsController.coffee
  2. 75 64
      services/web/app/coffee/Features/Authentication/AuthenticationController.coffee
  3. 12 15
      services/web/app/coffee/Features/Authorization/AuthorizationMiddlewear.coffee
  4. 6 2
      services/web/app/coffee/Features/Chat/ChatController.coffee
  5. 66 61
      services/web/app/coffee/Features/Collaborators/CollaboratorsInviteController.coffee
  6. 31 31
      services/web/app/coffee/Features/Compile/CompileController.coffee
  7. 22 23
      services/web/app/coffee/Features/Contacts/ContactController.coffee
  8. 5 3
      services/web/app/coffee/Features/Notifications/NotificationsController.coffee
  9. 64 59
      services/web/app/coffee/Features/Project/ProjectController.coffee
  10. 4 2
      services/web/app/coffee/Features/Referal/ReferalController.coffee
  11. 4 3
      services/web/app/coffee/Features/Referal/ReferalMiddleware.coffee
  12. 6 8
      services/web/app/coffee/Features/Security/RateLimiterMiddlewear.coffee
  13. 3 1
      services/web/app/coffee/Features/Spelling/SpellingController.coffee
  14. 3 2
      services/web/app/coffee/Features/StaticPages/HomeController.coffee
  15. 2 2
      services/web/app/coffee/Features/Subscription/SubscriptionController.coffee
  16. 22 18
      services/web/app/coffee/Features/Subscription/SubscriptionGroupController.coffee
  17. 12 11
      services/web/app/coffee/Features/Tags/TagsController.coffee
  18. 13 14
      services/web/app/coffee/Features/TrackChanges/TrackChangesController.coffee
  19. 4 6
      services/web/app/coffee/Features/Uploads/ProjectUploadController.coffee
  20. 17 14
      services/web/app/coffee/Features/User/UserController.coffee
  21. 6 4
      services/web/app/coffee/Features/User/UserPagesController.coffee
  22. 15 16
      services/web/app/coffee/infrastructure/ExpressLocals.coffee

+ 2 - 2
services/web/app/coffee/Features/Analytics/AnalyticsController.coffee

@@ -1,7 +1,7 @@
-AnalyticsManager = require "./AnalyticsManager"
+AnalyticsManager = equire "./AnalyticsManager"
 
 module.exports = AnalyticsController =
 	recordEvent: (req, res, next) ->
 		AnalyticsManager.recordEvent req.session?.user?._id, req.params.event, req.body, (error) ->
 			return next(error) if error?
-			res.send 204
+			res.send 204

+ 75 - 64
services/web/app/coffee/Features/Authentication/AuthenticationController.coffee

@@ -14,8 +14,8 @@ Analytics = require "../Analytics/AnalyticsManager"
 
 module.exports = AuthenticationController =
 
-	login: (req, res, next = (error) ->) ->
-		AuthenticationController.doLogin req.body, req, res, next
+	# login: (req, res, next = (error) ->) ->
+	# 	AuthenticationController.doLogin req.body, req, res, next
 
 	serializeUser: (user, callback) ->
 		console.log ">> serialize", user._id
@@ -65,60 +65,38 @@ module.exports = AuthenticationController =
 					logger.log email: email, "failed log in"
 					return done(null, false, {message: req.i18n.translate("email_or_password_wrong_try_again"), type: 'error'})
 
+	isUserLoggedIn: (req) ->
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		return user_id?
 
-	doLogin: (options, req, res, next) ->
-		dienow
-		email = options.email?.toLowerCase()
-		password = options.password
-		redir = Url.parse(options.redir or "/project").path
-		LoginRateLimiter.processLoginRequest email, (err, isAllowed)->
-			if !isAllowed
-				logger.log email:email, "too many login requests"
-				res.statusCode = 429
-				return res.send
-					message:
-						text: req.i18n.translate("to_many_login_requests_2_mins"),
-						type: 'error'
-			AuthenticationManager.authenticate email: email, password, (error, user) ->
-				return next(error) if error?
-				if user?
-					UserHandler.setupLoginData user, ->
-					LoginRateLimiter.recordSuccessfulLogin email
-					AuthenticationController._recordSuccessfulLogin user._id
-					AuthenticationController.establishUserSession req, user, (error) ->
-						return next(error) if error?
-						req.session.justLoggedIn = true
-						logger.log email: email, user_id: user._id.toString(), "successful log in"
-						Analytics.recordEvent user._id, "user-logged-in"
-						res.json redir: redir
-				else
-					AuthenticationController._recordFailedLogin()
-					logger.log email: email, "failed log in"
-					res.json message:
-						text: req.i18n.translate("email_or_password_wrong_try_again"),
-						type: 'error'
-
-	getLoggedInUserId: (req, callback = (error, user_id) ->) ->
+	# TODO: perhaps should produce an error if the current user is not present
+	getLoggedInUserId: (req) ->
+		# old sessions
 		if req?.session?.user?._id?
-			callback null, req.session.user._id.toString()
+			return req.session.user._id.toString()
+		# new passport sessions
+		else if req?.session?.passport?.user?._id?
+			return req.session.passport.user._id.toString()
+		# neither
 		else
-			callback null, null
+			return null
 
+	# TODO: perhaps should produce an error if the current user is not present
 	getLoggedInUser: (req, callback = (error, user) ->) ->
 		if req.session?.user?._id?
 			query = req.session.user._id
 		else
 			return callback null, null
 
-		UserGetter.getUser query, callback
+		# omit sensitive information
+		UserGetter.getUser query, {hashedPassword: false, refProviders: false}, callback
 
 	requireLogin: () ->
 		doRequest = (req, res, next = (error) ->) ->
 			console.log ">>>>", req.currentUser()
-			if !req.session.user?
+			if !AuthenticationController.isUserLoggedIn()?
 				AuthenticationController._redirectToLoginOrRegisterPage(req, res)
 			else
-				req.user = req.session.user
 				return next()
 
 		return doRequest
@@ -133,7 +111,7 @@ module.exports = AuthenticationController =
 
 		if req.headers['authorization']?
 			return AuthenticationController.httpAuth(req, res, next)
-		else if req.session.user?
+		else if AuthenticationController.isUserLoggedIn()?
 			return next()
 		else
 			logger.log url:req.url, "user trying to access endpoint not in global whitelist"
@@ -179,26 +157,59 @@ module.exports = AuthenticationController =
 		Metrics.inc "user.login.failed"
 		callback()
 
-	establishUserSession: (req, user, callback = (error) ->) ->
-		dienow
-		lightUser =
-			_id: user._id
-			first_name: user.first_name
-			last_name: user.last_name
-			isAdmin: user.isAdmin
-			email: user.email
-			referal_id: user.referal_id
-			session_created: (new Date()).toISOString()
-			ip_address: req.ip
-		# Regenerate the session to get a new sessionID (cookie value) to
-		# protect against session fixation attacks
-		oldSession = req.session
-		req.session.destroy()
-		req.sessionStore.generate(req)
-		for key, value of oldSession
-			req.session[key] = value
-
-		req.session.user = lightUser
-
-		UserSessionsManager.trackSession(user, req.sessionID, () ->)
-		callback()
+	# establishUserSession: (req, user, callback = (error) ->) ->
+	# 	dienow
+	# 	lightUser =
+	# 		_id: user._id
+	# 		first_name: user.first_name
+	# 		last_name: user.last_name
+	# 		isAdmin: user.isAdmin
+	# 		email: user.email
+	# 		referal_id: user.referal_id
+	# 		session_created: (new Date()).toISOString()
+	# 		ip_address: req.ip
+	# 	# Regenerate the session to get a new sessionID (cookie value) to
+	# 	# protect against session fixation attacks
+	# 	oldSession = req.session
+	# 	req.session.destroy()
+	# 	req.sessionStore.generate(req)
+	# 	for key, value of oldSession
+	# 		req.session[key] = value
+
+	# 	req.session.user = lightUser
+
+	# 	UserSessionsManager.trackSession(user, req.sessionID, () ->)
+	# 	callback()
+
+
+	# doLogin: (options, req, res, next) ->
+	# 	dienow
+	# 	email = options.email?.toLowerCase()
+	# 	password = options.password
+	# 	redir = Url.parse(options.redir or "/project").path
+	# 	LoginRateLimiter.processLoginRequest email, (err, isAllowed)->
+	# 		if !isAllowed
+	# 			logger.log email:email, "too many login requests"
+	# 			res.statusCode = 429
+	# 			return res.send
+	# 				message:
+	# 					text: req.i18n.translate("to_many_login_requests_2_mins"),
+	# 					type: 'error'
+	# 		AuthenticationManager.authenticate email: email, password, (error, user) ->
+	# 			return next(error) if error?
+	# 			if user?
+	# 				UserHandler.setupLoginData user, ->
+	# 				LoginRateLimiter.recordSuccessfulLogin email
+	# 				AuthenticationController._recordSuccessfulLogin user._id
+	# 				AuthenticationController.establishUserSession req, user, (error) ->
+	# 					return next(error) if error?
+	# 					req.session.justLoggedIn = true
+	# 					logger.log email: email, user_id: user._id.toString(), "successful log in"
+	# 					Analytics.recordEvent user._id, "user-logged-in"
+	# 					res.json redir: redir
+	# 			else
+	# 				AuthenticationController._recordFailedLogin()
+	# 				logger.log email: email, "failed log in"
+	# 				res.json message:
+	# 					text: req.i18n.translate("email_or_password_wrong_try_again"),
+	# 					type: 'error'

+ 12 - 15
services/web/app/coffee/Features/Authorization/AuthorizationMiddlewear.coffee

@@ -3,6 +3,7 @@ async = require "async"
 logger = require "logger-sharelatex"
 ObjectId = require("mongojs").ObjectId
 Errors = require "../Errors/Errors"
+AuthenticationController = require "../Authentication/AuthenticationController"
 
 module.exports = AuthorizationMiddlewear =
 	ensureUserCanReadMultipleProjects: (req, res, next) ->
@@ -20,7 +21,7 @@ module.exports = AuthorizationMiddlewear =
 					AuthorizationMiddlewear.redirectToRestricted req, res, next
 				else
 					next()
-		
+
 	ensureUserCanReadProject: (req, res, next) ->
 		AuthorizationMiddlewear._getUserAndProjectId req, (error, user_id, project_id) ->
 			return next(error) if error?
@@ -32,7 +33,7 @@ module.exports = AuthorizationMiddlewear =
 				else
 					logger.log {user_id, project_id}, "denying user read access to project"
 					AuthorizationMiddlewear.redirectToRestricted req, res, next
-		
+
 	ensureUserCanWriteProjectSettings: (req, res, next) ->
 		AuthorizationMiddlewear._getUserAndProjectId req, (error, user_id, project_id) ->
 			return next(error) if error?
@@ -44,7 +45,7 @@ module.exports = AuthorizationMiddlewear =
 				else
 					logger.log {user_id, project_id}, "denying user write access to project settings"
 					AuthorizationMiddlewear.redirectToRestricted req, res, next
-		
+
 	ensureUserCanWriteProjectContent: (req, res, next) ->
 		AuthorizationMiddlewear._getUserAndProjectId req, (error, user_id, project_id) ->
 			return next(error) if error?
@@ -56,7 +57,7 @@ module.exports = AuthorizationMiddlewear =
 				else
 					logger.log {user_id, project_id}, "denying user write access to project settings"
 					AuthorizationMiddlewear.redirectToRestricted req, res, next
-		
+
 	ensureUserCanAdminProject: (req, res, next) ->
 		AuthorizationMiddlewear._getUserAndProjectId req, (error, user_id, project_id) ->
 			return next(error) if error?
@@ -68,7 +69,7 @@ module.exports = AuthorizationMiddlewear =
 				else
 					logger.log {user_id, project_id}, "denying user admin access to project"
 					AuthorizationMiddlewear.redirectToRestricted req, res, next
-		
+
 	ensureUserIsSiteAdmin: (req, res, next) ->
 		AuthorizationMiddlewear._getUserId req, (error, user_id) ->
 			return next(error) if error?
@@ -90,22 +91,18 @@ module.exports = AuthorizationMiddlewear =
 		AuthorizationMiddlewear._getUserId req, (error, user_id) ->
 			return callback(error) if error?
 			callback(null, user_id, project_id)
-	
+
 	_getUserId: (req, callback = (error, user_id) ->) ->
-		if req.session?.user?._id?
-			user_id = req.session.user._id
-		else
-			user_id = null
-		callback null, user_id
-		
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		return callback(null, user_id)
+
 	redirectToRestricted: (req, res, next) ->
 		res.redirect "/restricted"
-	
+
 	restricted : (req, res, next)->
-		if req.session.user?
+		if AuthenticationController.isUserLoggedIn()?
 			res.render 'user/restricted',
 				title:'restricted'
 		else
 			logger.log "user not logged in and trying to access #{req.url}, being redirected to login"
 			res.redirect '/register'
-		

+ 6 - 2
services/web/app/coffee/Features/Chat/ChatController.coffee

@@ -1,14 +1,18 @@
 ChatHandler = require("./ChatHandler")
 EditorRealTimeController = require("../Editor/EditorRealTimeController")
 logger = require("logger-sharelatex")
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 module.exports =
 
 
-	sendMessage: (req, res)->
+	sendMessage: (req, res, next)->
 		project_id = req.params.Project_id
-		user_id = req.session.user._id
 		messageContent = req.body.content
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		if !user_id?
+			err = new Error('no logged-in user')
+			return next(err)
 		ChatHandler.sendMessage project_id, user_id, messageContent, (err, builtMessge)->
 			if err?
 				logger.err err:err, project_id:project_id, user_id:user_id, messageContent:messageContent, "problem sending message to chat api"

+ 66 - 61
services/web/app/coffee/Features/Collaborators/CollaboratorsInviteController.coffee

@@ -8,6 +8,7 @@ EmailHelper = require "../Helpers/EmailHelper"
 EditorRealTimeController = require("../Editor/EditorRealTimeController")
 NotificationsBuilder = require("../Notifications/NotificationsBuilder")
 AnalyticsManger = require("../Analytics/AnalyticsManager")
+AuthenticationController = require("../Authentication/AuthenticationController")
 
 module.exports = CollaboratorsInviteController =
 
@@ -23,26 +24,27 @@ module.exports = CollaboratorsInviteController =
 	inviteToProject: (req, res, next) ->
 		projectId = req.params.Project_id
 		email = req.body.email
-		sendingUser = req.session.user
-		sendingUserId = sendingUser._id
-		logger.log {projectId, email, sendingUserId}, "inviting to project"
-		LimitationsManager.canAddXCollaborators projectId, 1, (error, allowed) =>
-			return next(error) if error?
-			if !allowed
-				logger.log {projectId, email, sendingUserId}, "not allowed to invite more users to project"
-				return res.json {invite: null}
-			{email, privileges} = req.body
-			email = EmailHelper.parseEmail(email)
-			if !email? or email == ""
-				logger.log {projectId, email, sendingUserId}, "invalid email address"
-				return res.sendStatus(400)
-			CollaboratorsInviteHandler.inviteToProject projectId, sendingUser, email, privileges, (err, invite) ->
-				if err?
-					logger.err {projectId, email, sendingUserId}, "error creating project invite"
-					return next(err)
-				logger.log {projectId, email, sendingUserId}, "invite created"
-				EditorRealTimeController.emitToRoom(projectId, 'project:membership:changed', {invites: true})
-				return res.json {invite: invite}
+		AuthenticationController.getLoggedInUser req, (err, sendingUser) ->
+			return callback(err) if err?
+			sendingUserId = sendingUser._id
+			logger.log {projectId, email, sendingUserId}, "inviting to project"
+			LimitationsManager.canAddXCollaborators projectId, 1, (error, allowed) =>
+				return next(error) if error?
+				if !allowed
+					logger.log {projectId, email, sendingUserId}, "not allowed to invite more users to project"
+					return res.json {invite: null}
+				{email, privileges} = req.body
+				email = EmailHelper.parseEmail(email)
+				if !email? or email == ""
+					logger.log {projectId, email, sendingUserId}, "invalid email address"
+					return res.sendStatus(400)
+				CollaboratorsInviteHandler.inviteToProject projectId, sendingUser, email, privileges, (err, invite) ->
+					if err?
+						logger.err {projectId, email, sendingUserId}, "error creating project invite"
+						return next(err)
+					logger.log {projectId, email, sendingUserId}, "invite created"
+					EditorRealTimeController.emitToRoom(projectId, 'project:membership:changed', {invites: true})
+					return res.json {invite: invite}
 
 	revokeInvite: (req, res, next) ->
 		projectId = req.params.Project_id
@@ -58,67 +60,70 @@ module.exports = CollaboratorsInviteController =
 	resendInvite: (req, res, next) ->
 		projectId = req.params.Project_id
 		inviteId = req.params.invite_id
-		sendingUser = req.session.user
 		logger.log {projectId, inviteId}, "resending invite"
-		CollaboratorsInviteHandler.resendInvite projectId, sendingUser, inviteId, (err) ->
-			if err?
-				logger.err {projectId, inviteId}, "error resending invite"
-				return next(err)
-			res.sendStatus(201)
+		AuthenticationController.getLoggedInUser req, (err, sendingUser) ->
+			return callback(err) if err?
+			CollaboratorsInviteHandler.resendInvite projectId, sendingUser, inviteId, (err) ->
+				if err?
+					logger.err {projectId, inviteId}, "error resending invite"
+					return next(err)
+				res.sendStatus(201)
 
 	viewInvite: (req, res, next) ->
 		projectId = req.params.Project_id
 		token = req.params.token
-		currentUser = req.session.user
 		_renderInvalidPage = () ->
 			logger.log {projectId, token}, "invite not valid, rendering not-valid page"
 			res.render "project/invite/not-valid", {title: "Invalid Invite"}
 		# check if the user is already a member of the project
-		CollaboratorsHandler.isUserMemberOfProject currentUser._id, projectId, (err, isMember, _privilegeLevel) ->
-			if err?
-				logger.err {err, projectId}, "error checking if user is member of project"
-				return next(err)
-			if isMember
-				logger.log {projectId, userId: currentUser._id}, "user is already a member of this project, redirecting"
-				return res.redirect "/project/#{projectId}"
-			# get the invite
-			CollaboratorsInviteHandler.getInviteByToken projectId, token, (err, invite) ->
+		AuthenticationController.getLoggedInUser req, (err, currentUser) ->
+			return callback(err) if err?
+			CollaboratorsHandler.isUserMemberOfProject currentUser._id, projectId, (err, isMember, _privilegeLevel) ->
 				if err?
-					logger.err {projectId, token}, "error getting invite by token"
+					logger.err {err, projectId}, "error checking if user is member of project"
 					return next(err)
-				# check if invite is gone, or otherwise non-existent
-				if !invite?
-					logger.log {projectId, token}, "no invite found for this token"
-					return _renderInvalidPage()
-				# check the user who sent the invite exists
-				UserGetter.getUser {_id: invite.sendingUserId}, {email: 1, first_name: 1, last_name: 1}, (err, owner) ->
+				if isMember
+					logger.log {projectId, userId: currentUser._id}, "user is already a member of this project, redirecting"
+					return res.redirect "/project/#{projectId}"
+				# get the invite
+				CollaboratorsInviteHandler.getInviteByToken projectId, token, (err, invite) ->
 					if err?
-						logger.err {err, projectId}, "error getting project owner"
+						logger.err {projectId, token}, "error getting invite by token"
 						return next(err)
-					if !owner?
-						logger.log {projectId}, "no project owner found"
+					# check if invite is gone, or otherwise non-existent
+					if !invite?
+						logger.log {projectId, token}, "no invite found for this token"
 						return _renderInvalidPage()
-					# fetch the project name
-					ProjectGetter.getProject projectId, {}, (err, project) ->
+					# check the user who sent the invite exists
+					UserGetter.getUser {_id: invite.sendingUserId}, {email: 1, first_name: 1, last_name: 1}, (err, owner) ->
 						if err?
-							logger.err {err, projectId}, "error getting project"
+							logger.err {err, projectId}, "error getting project owner"
 							return next(err)
-						if !project?
-							logger.log {projectId}, "no project found"
+						if !owner?
+							logger.log {projectId}, "no project owner found"
 							return _renderInvalidPage()
-						# finally render the invite
-						res.render "project/invite/show", {invite, project, owner, title: "Project Invite"}
+						# fetch the project name
+						ProjectGetter.getProject projectId, {}, (err, project) ->
+							if err?
+								logger.err {err, projectId}, "error getting project"
+								return next(err)
+							if !project?
+								logger.log {projectId}, "no project found"
+								return _renderInvalidPage()
+							# finally render the invite
+							res.render "project/invite/show", {invite, project, owner, title: "Project Invite"}
 
 	acceptInvite: (req, res, next) ->
 		projectId = req.params.Project_id
 		inviteId = req.params.invite_id
 		{token} = req.body
-		currentUser = req.session.user
 		logger.log {projectId, inviteId, userId: currentUser._id}, "accepting invite"
-		CollaboratorsInviteHandler.acceptInvite projectId, inviteId, token, currentUser, (err) ->
-			if err?
-				logger.err {projectId, inviteId}, "error accepting invite by token"
-				return next(err)
-			EditorRealTimeController.emitToRoom projectId, 'project:membership:changed', {invites: true, members: true}
-			AnalyticsManger.recordEvent(currentUser._id, "project-invite-accept", {inviteId:inviteId, projectId:projectId})
-			res.redirect "/project/#{projectId}"
+		AuthenticationController.getLoggedInUser req, (err, currentUser) ->
+			return callback(err) if err?
+			CollaboratorsInviteHandler.acceptInvite projectId, inviteId, token, currentUser, (err) ->
+				if err?
+					logger.err {projectId, inviteId}, "error accepting invite by token"
+					return next(err)
+				EditorRealTimeController.emitToRoom projectId, 'project:membership:changed', {invites: true, members: true}
+				AnalyticsManger.recordEvent(currentUser._id, "project-invite-accept", {inviteId:inviteId, projectId:projectId})
+				res.redirect "/project/#{projectId}"

+ 31 - 31
services/web/app/coffee/Features/Compile/CompileController.coffee

@@ -16,53 +16,53 @@ module.exports = CompileController =
 		res.setTimeout(5 * 60 * 1000)
 		project_id = req.params.Project_id
 		isAutoCompile = !!req.query?.auto_compile
-		AuthenticationController.getLoggedInUserId req, (error, user_id) ->
+		user_id = AuthenticationController.getLoggedInUserId req
+		options = {
+			isAutoCompile: isAutoCompile
+		}
+		if req.body?.rootDoc_id?
+			options.rootDoc_id = req.body.rootDoc_id
+		else if req.body?.settingsOverride?.rootDoc_id? # Can be removed after deploy
+			options.rootDoc_id = req.body.settingsOverride.rootDoc_id
+		if req.body?.compiler
+			options.compiler = req.body.compiler
+		if req.body?.draft
+			options.draft = req.body.draft
+		if req.body?.check in ['validate', 'error', 'silent']
+			options.check = req.body.check
+		logger.log {options:options, project_id:project_id, user_id:user_id}, "got compile request"
+		CompileManager.compile project_id, user_id, options, (error, status, outputFiles, clsiServerId, limits, validationProblems) ->
 			return next(error) if error?
-			options = {
-				isAutoCompile: isAutoCompile
+			res.contentType("application/json")
+			res.status(200).send JSON.stringify {
+				status: status
+				outputFiles: outputFiles
+				compileGroup: limits?.compileGroup
+				clsiServerId:clsiServerId
+				validationProblems:validationProblems
 			}
-			if req.body?.rootDoc_id?
-				options.rootDoc_id = req.body.rootDoc_id
-			else if req.body?.settingsOverride?.rootDoc_id? # Can be removed after deploy
-				options.rootDoc_id = req.body.settingsOverride.rootDoc_id
-			if req.body?.compiler
-				options.compiler = req.body.compiler
-			if req.body?.draft
-				options.draft = req.body.draft
-			if req.body?.check in ['validate', 'error', 'silent']
-				options.check = req.body.check
-			logger.log {options:options, project_id:project_id, user_id:user_id}, "got compile request"
-			CompileManager.compile project_id, user_id, options, (error, status, outputFiles, clsiServerId, limits, validationProblems) ->
-				return next(error) if error?
-				res.contentType("application/json")
-				res.status(200).send JSON.stringify {
-					status: status
-					outputFiles: outputFiles
-					compileGroup: limits?.compileGroup
-					clsiServerId:clsiServerId
-					validationProblems:validationProblems
-				}
 
 	stopCompile: (req, res, next = (error) ->) ->
 		project_id = req.params.Project_id
-		AuthenticationController.getLoggedInUserId req, (error, user_id) ->
+		user_id = AuthenticationController.getLoggedInUserId req
+		logger.log {project_id:project_id, user_id:user_id}, "stop compile request"
+		CompileManager.stopCompile project_id, user_id, (error) ->
 			return next(error) if error?
-			logger.log {project_id:project_id, user_id:user_id}, "stop compile request"
-			CompileManager.stopCompile project_id, user_id, (error) ->
-				return next(error) if error?
-				res.status(200).send()
+			res.status(200).send()
 
 	_compileAsUser: (req, callback) ->
 		# callback with user_id if per-user, undefined otherwise
 		if not Settings.disablePerUserCompiles
-			AuthenticationController.getLoggedInUserId req, callback # -> (error, user_id)
+			user_id = AuthenticationController.getLoggedInUserId req
+			return callback(null, user_id)
 		else
 			callback() # do a per-project compile, not per-user
 
 	_downloadAsUser: (req, callback) ->
 		# callback with user_id if per-user, undefined otherwise
 		if not Settings.disablePerUserCompiles
-			AuthenticationController.getLoggedInUserId req, callback # -> (error, user_id)
+			user_id = AuthenticationController.getLoggedInUserId req
+			return callback(null, user_id)
 		else
 			callback() # do a per-project compile, not per-user
 

+ 22 - 23
services/web/app/coffee/Features/Contacts/ContactController.coffee

@@ -6,33 +6,32 @@ Modules = require "../../infrastructure/Modules"
 
 module.exports = ContactsController =
 	getContacts: (req, res, next) ->
-		AuthenticationController.getLoggedInUserId req, (error, user_id) ->
+		user_id = AuthenticationController.getLoggedInUserId req
+		ContactManager.getContactIds user_id, {limit: 50}, (error, contact_ids) ->
 			return next(error) if error?
-			ContactManager.getContactIds user_id, {limit: 50}, (error, contact_ids) ->
+			UserGetter.getUsers contact_ids, {
+				email: 1, first_name: 1, last_name: 1, holdingAccount: 1
+			}, (error, contacts) ->
 				return next(error) if error?
-				UserGetter.getUsers contact_ids, {
-					email: 1, first_name: 1, last_name: 1, holdingAccount: 1
-				}, (error, contacts) ->
+
+				# UserGetter.getUsers may not preserve order so put them back in order
+				positions = {}
+				for contact_id, i in contact_ids
+					positions[contact_id] = i
+				contacts.sort (a,b) -> positions[a._id?.toString()] - positions[b._id?.toString()]
+
+				# Don't count holding accounts to discourage users from repeating mistakes (mistyped or wrong emails, etc)
+				contacts = contacts.filter (c) -> !c.holdingAccount
+
+				contacts = contacts.map(ContactsController._formatContact)
+
+				Modules.hooks.fire "getContacts", user_id, contacts, (error, additional_contacts) ->
 					return next(error) if error?
-					
-					# UserGetter.getUsers may not preserve order so put them back in order
-					positions = {}
-					for contact_id, i in contact_ids
-						positions[contact_id] = i
-					contacts.sort (a,b) -> positions[a._id?.toString()] - positions[b._id?.toString()]
+					contacts = contacts.concat(additional_contacts...)
+					res.send({
+						contacts: contacts
+					})
 
-					# Don't count holding accounts to discourage users from repeating mistakes (mistyped or wrong emails, etc)
-					contacts = contacts.filter (c) -> !c.holdingAccount
-					
-					contacts = contacts.map(ContactsController._formatContact)
-					
-					Modules.hooks.fire "getContacts", user_id, contacts, (error, additional_contacts) ->
-						return next(error) if error?
-						contacts = contacts.concat(additional_contacts...)
-						res.send({
-							contacts: contacts
-						})
-	
 	_formatContact: (contact) ->
 		return  {
 			id: contact._id?.toString()

+ 5 - 3
services/web/app/coffee/Features/Notifications/NotificationsController.coffee

@@ -1,18 +1,20 @@
 NotificationsHandler = require("./NotificationsHandler")
+AuthenticationController = require("../Authentication/AuthenticationController")
 logger = require("logger-sharelatex")
 _ = require("underscore")
 
 module.exports =
 
 	getAllUnreadNotifications: (req, res)->
-		NotificationsHandler.getUserNotifications req.session.user._id, (err, unreadNotifications)->
-			unreadNotifications = _.map unreadNotifications, (notification)-> 
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		NotificationsHandler.getUserNotifications user_id, (err, unreadNotifications)->
+			unreadNotifications = _.map unreadNotifications, (notification)->
 				notification.html = req.i18n.translate(notification.templateKey, notification.messageOpts)
 				return notification
 			res.send(unreadNotifications)
 
 	markNotificationAsRead: (req, res)->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		notification_id = req.params.notification_id
 		NotificationsHandler.markAsRead user_id, notification_id, ->
 			res.send()

+ 64 - 59
services/web/app/coffee/Features/Project/ProjectController.coffee

@@ -18,6 +18,7 @@ InactiveProjectManager = require("../InactiveData/InactiveProjectManager")
 ProjectUpdateHandler = require("./ProjectUpdateHandler")
 ProjectGetter = require("./ProjectGetter")
 PrivilegeLevels = require("../Authorization/PrivilegeLevels")
+AuthenticationController = require("../Authentication/AuthenticationController")
 
 module.exports = ProjectController =
 
@@ -88,32 +89,34 @@ module.exports = ProjectController =
 		project_id = req.params.Project_id
 		projectName = req.body.projectName
 		logger.log project_id:project_id, projectName:projectName, "cloning project"
-		if !req.session.user?
+		if !AuthenticationController.isUserLoggedIn()?
 			return res.send redir:"/register"
-		projectDuplicator.duplicate req.session.user, project_id, projectName, (err, project)->
-			if err?
-				logger.error err:err, project_id: project_id, user_id: req.session.user._id, "error cloning project"
-				return next(err)
-			res.send(project_id:project._id)
+		AuthenticationController.getLoggedInUser req, (err, currentUser) ->
+			return next(err) if err?
+			projectDuplicator.duplicate currentUser, project_id, projectName, (err, project)->
+				if err?
+					logger.error err:err, project_id: project_id, user_id: currentUser._id, "error cloning project"
+					return next(err)
+				res.send(project_id:project._id)
 
 
 	newProject: (req, res)->
-		user = req.session.user
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		projectName = req.body.projectName?.trim()
 		template = req.body.template
-		logger.log user: user, projectType: template, name: projectName, "creating project"
+		logger.log user: user_id, projectType: template, name: projectName, "creating project"
 		async.waterfall [
 			(cb)->
 				if template == 'example'
-					projectCreationHandler.createExampleProject user._id, projectName, cb
+					projectCreationHandler.createExampleProject user_id, projectName, cb
 				else
-					projectCreationHandler.createBasicProject user._id, projectName, cb
+					projectCreationHandler.createBasicProject user_id, projectName, cb
 		], (err, project)->
 			if err?
-				logger.error err: err, project: project, user: user, name: projectName, templateType: template, "error creating project"
+				logger.error err: err, project: project, user: user_id, name: projectName, templateType: template, "error creating project"
 				res.sendStatus 500
 			else
-				logger.log project: project, user: user, name: projectName, templateType: template, "created project"
+				logger.log project: project, user: user_id, name: projectName, templateType: template, "created project"
 				res.send {project_id:project._id}
 
 
@@ -131,51 +134,53 @@ module.exports = ProjectController =
 
 	projectListPage: (req, res, next)->
 		timer = new metrics.Timer("project-list")
-		user_id = req.session.user._id
-		async.parallel {
-			tags: (cb)->
-				TagsHandler.getAllTags user_id, cb
-			notifications: (cb)->
-				NotificationsHandler.getUserNotifications user_id, cb
-			projects: (cb)->
-				ProjectGetter.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel archived owner_ref', cb
-			hasSubscription: (cb)->
-				LimitationsManager.userHasSubscriptionOrIsGroupMember req.session.user, cb
-			user: (cb) ->
-				User.findById user_id, "featureSwitches", cb
-			}, (err, results)->
-				if err?
-					logger.err err:err, "error getting data for project list page"
-					return next(err)
-				logger.log results:results, user_id:user_id, "rendering project list"
-				tags = results.tags[0]
-				notifications = require("underscore").map results.notifications, (notification)->
-					notification.html = req.i18n.translate(notification.templateKey, notification.messageOpts)
-					return notification
-				projects = ProjectController._buildProjectList results.projects[0], results.projects[1], results.projects[2]
-				user = results.user
-				ProjectController._injectProjectOwners projects, (error, projects) ->
-					return next(error) if error?
-
-					viewModel = {
-						title:'your_projects'
-						priority_title: true
-						projects: projects
-						tags: tags
-						notifications: notifications or []
-						user: user
-						hasSubscription: results.hasSubscription[0]
-					}
-
-					if Settings?.algolia?.app_id? and Settings?.algolia?.read_only_api_key?
-						viewModel.showUserDetailsArea = true
-						viewModel.algolia_api_key = Settings.algolia.read_only_api_key
-						viewModel.algolia_app_id = Settings.algolia.app_id
-					else
-						viewModel.showUserDetailsArea = false
-
-					res.render 'project/list', viewModel
-					timer.done()
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		AuthenticationController.getLoggedInUser req, (err, currentUser) ->
+			return next(err) if err?
+			async.parallel {
+				tags: (cb)->
+					TagsHandler.getAllTags user_id, cb
+				notifications: (cb)->
+					NotificationsHandler.getUserNotifications user_id, cb
+				projects: (cb)->
+					ProjectGetter.findAllUsersProjects user_id, 'name lastUpdated publicAccesLevel archived owner_ref', cb
+				hasSubscription: (cb)->
+					LimitationsManager.userHasSubscriptionOrIsGroupMember currentUser, cb
+				user: (cb) ->
+					User.findById user_id, "featureSwitches", cb
+				}, (err, results)->
+					if err?
+						logger.err err:err, "error getting data for project list page"
+						return next(err)
+					logger.log results:results, user_id:user_id, "rendering project list"
+					tags = results.tags[0]
+					notifications = require("underscore").map results.notifications, (notification)->
+						notification.html = req.i18n.translate(notification.templateKey, notification.messageOpts)
+						return notification
+					projects = ProjectController._buildProjectList results.projects[0], results.projects[1], results.projects[2]
+					user = results.user
+					ProjectController._injectProjectOwners projects, (error, projects) ->
+						return next(error) if error?
+
+						viewModel = {
+							title:'your_projects'
+							priority_title: true
+							projects: projects
+							tags: tags
+							notifications: notifications or []
+							user: user
+							hasSubscription: results.hasSubscription[0]
+						}
+
+						if Settings?.algolia?.app_id? and Settings?.algolia?.read_only_api_key?
+							viewModel.showUserDetailsArea = true
+							viewModel.algolia_api_key = Settings.algolia.read_only_api_key
+							viewModel.algolia_app_id = Settings.algolia.app_id
+						else
+							viewModel.showUserDetailsArea = false
+
+						res.render 'project/list', viewModel
+						timer.done()
 
 
 	loadEditor: (req, res, next)->
@@ -183,8 +188,8 @@ module.exports = ProjectController =
 		if !Settings.editorIsOpen
 			return res.render("general/closed", {title:"updating_site"})
 
-		if req.session.user?
-			user_id = req.session.user._id
+		if AuthenticationController.isUserLoggedIn(req)?
+			user_id = AuthenticationController.getLoggedInUserId(req)
 			anonymous = false
 		else
 			anonymous = true

+ 4 - 2
services/web/app/coffee/Features/Referal/ReferalController.coffee

@@ -1,9 +1,11 @@
 logger = require('logger-sharelatex')
 ReferalHandler = require('./ReferalHandler')
+AuthenticationController = require('../Authentication/AuthenticationController')
 
-module.exports = 
+module.exports =
 	bonus: (req, res)->
-		ReferalHandler.getReferedUserIds req.session.user._id, (err, refered_users)->
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		ReferalHandler.getReferedUserIds user_id, (err, refered_users)->
 			res.render "referal/bonus",
 				title: "bonus_please_recommend_us"
 				refered_users: refered_users

+ 4 - 3
services/web/app/coffee/Features/Referal/ReferalMiddleware.coffee

@@ -1,11 +1,12 @@
 User = require("../../models/User").User
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 module.exports = RefererMiddleware =
 	getUserReferalId: (req, res, next) ->
-		if req.session? and req.session.user?
-			User.findById req.session.user._id, (error, user) ->
+		if AuthenticationController.isUserLoggedIn()?
+			AuthenticationController.getLoggedInUser req, (error, user) ->
 				return next(error) if error?
-				req.session.user.referal_id = user.referal_id
+				req.user.referal_id = user.referal_id
 				next()
 		else
 			next()

+ 6 - 8
services/web/app/coffee/Features/Security/RateLimiterMiddlewear.coffee

@@ -1,24 +1,22 @@
 RateLimiter = require "../../infrastructure/RateLimiter"
 logger = require "logger-sharelatex"
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 module.exports = RateLimiterMiddlewear =
 	###
 	Do not allow more than opts.maxRequests from a single client in
 	opts.timeInterval. Pass an array of opts.params to segment this based on
 	parameters in the request URL, e.g.:
-	
+
 	    app.get "/project/:project_id", RateLimiterMiddlewear.rateLimit(endpointName: "open-editor", params: ["project_id"])
-	
+
 	will rate limit each project_id separately.
-	
+
 	Unique clients are identified by user_id if logged in, and IP address if not.
 	###
 	rateLimit: (opts) ->
 		return (req, res, next) ->
-			if req.session?.user?
-				user_id = req.session.user._id
-			else
-				user_id = req.ip
+			user_id = AuthenticationController.getLoggedInUserId(req) || req.ip
 			params = (opts.params or []).map (p) -> req.params[p]
 			params.push user_id
 			if !opts.endpointName?
@@ -37,4 +35,4 @@ module.exports = RateLimiterMiddlewear =
 					logger.warn options, "rate limit exceeded"
 					res.status(429) # Too many requests
 					res.write("Rate limit reached, please try again later")
-					res.end()
+					res.end()

+ 3 - 1
services/web/app/coffee/Features/Spelling/SpellingController.coffee

@@ -1,13 +1,15 @@
 request = require 'request'
 Settings = require 'settings-sharelatex'
 logger = require 'logger-sharelatex'
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 TEN_SECONDS = 1000 * 10
 
 module.exports = SpellingController =
 	proxyRequestToSpellingApi: (req, res, next) ->
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		url = req.url.slice("/spelling".length)
-		url = "/user/#{req.session.user._id}#{url}"
+		url = "/user/#{user_id}#{url}"
 		req.headers["Host"] = Settings.apis.spelling.host
 		request(url: Settings.apis.spelling.url + url, method: req.method, headers: req.headers, json: req.body, timeout:TEN_SECONDS)
 		.on "error", (error) ->

+ 3 - 2
services/web/app/coffee/Features/StaticPages/HomeController.coffee

@@ -5,12 +5,13 @@ Path = require "path"
 fs = require "fs"
 
 ErrorController = require "../Errors/ErrorController"
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 homepageExists = fs.existsSync Path.resolve(__dirname + "/../../../views/external/home.jade")
 
 module.exports = HomeController =
 	index : (req,res)->
-		if req.session.user
+		if AuthenticationController.isUserLoggedIn(req)?
 			if req.query.scribtex_path?
 				res.redirect "/project?scribtex_path=#{req.query.scribtex_path}"
 			else
@@ -33,4 +34,4 @@ module.exports = HomeController =
 					res.render "external/#{page}.jade",
 						title: title
 				else
-					ErrorController.notFound(req, res, next)
+					ErrorController.notFound(req, res, next)

+ 2 - 2
services/web/app/coffee/Features/Subscription/SubscriptionController.coffee

@@ -13,7 +13,7 @@ module.exports = SubscriptionController =
 
 	plansPage: (req, res, next) ->
 		plans = SubscriptionViewModelBuilder.buildViewModel()
-		if !req.session.user?
+		if AuthenticationController.isUserLoggedIn(req)?
 			baseUrl = "/register?redir="
 		else
 			baseUrl = ""
@@ -134,7 +134,7 @@ module.exports = SubscriptionController =
 							successURL : "#{Settings.siteUrl}/user/subscription/billing-details/update"
 							user       :
 								id : user._id
-	
+
 	updateBillingDetails: (req, res, next) ->
 		res.redirect "/user/subscription?saved_billing_details=true"
 

+ 22 - 18
services/web/app/coffee/Features/Subscription/SubscriptionGroupController.coffee

@@ -3,27 +3,28 @@ logger = require("logger-sharelatex")
 SubscriptionLocator = require("./SubscriptionLocator")
 ErrorsController = require("../Errors/ErrorController")
 SubscriptionDomainHandler = require("./SubscriptionDomainHandler")
+AuthenticationController = require('../Authentication/AuthenticationController')
 _ = require("underscore")
 async = require("async")
 
 module.exports =
 
 	addUserToGroup: (req, res)->
-		adminUserId = req.session.user._id
+		adminUserId = AuthenticationController.getLoggedInUserId(req)
 		newEmail = req.body?.email?.toLowerCase()?.trim()
 		logger.log adminUserId:adminUserId, newEmail:newEmail, "adding user to group subscription"
 		SubscriptionGroupHandler.addUserToGroup adminUserId, newEmail, (err, user)->
 			if err?
 				logger.err err:err, newEmail:newEmail, adminUserId:adminUserId, "error adding user from group"
 				return res.sendStatus 500
-			result = 
+			result =
 				user:user
 			if err and err.limitReached
 				result.limitReached = true
 			res.json(result)
 
 	removeUserFromGroup: (req, res)->
-		adminUserId = req.session.user._id
+		adminUserId = AuthenticationController.getLoggedInUserId(req)
 		userToRemove_id = req.params.user_id
 		logger.log adminUserId:adminUserId, userToRemove_id:userToRemove_id, "removing user from group subscription"
 		SubscriptionGroupHandler.removeUserFromGroup adminUserId, userToRemove_id, (err)->
@@ -31,10 +32,10 @@ module.exports =
 				logger.err err:err, adminUserId:adminUserId, userToRemove_id:userToRemove_id, "error removing user from group"
 				return res.sendStatus 500
 			res.send()
-			
+
 	removeSelfFromGroup: (req, res)->
 		adminUserId = req.query.admin_user_id
-		userToRemove_id = req.session.user._id
+		userToRemove_id = AuthenticationController.getLoggedInUserId(req)
 		logger.log adminUserId:adminUserId, userToRemove_id:userToRemove_id, "removing user from group subscription after self request"
 		SubscriptionGroupHandler.removeUserFromGroup adminUserId, userToRemove_id, (err)->
 			if err?
@@ -43,7 +44,7 @@ module.exports =
 			res.send()
 
 	renderSubscriptionGroupAdminPage: (req, res)->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		SubscriptionLocator.getUsersSubscription user_id, (err, subscription)->
 			if !subscription.groupPlan
 				return res.redirect("/")
@@ -55,11 +56,11 @@ module.exports =
 
 	renderGroupInvitePage: (req, res)->
 		group_subscription_id = req.params.subscription_id
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		licence = SubscriptionDomainHandler.findDomainLicenceBySubscriptionId(group_subscription_id)
 		if !licence?
 			return ErrorsController.notFound(req, res)
-		jobs = 
+		jobs =
 			partOfGroup: (cb)->
 				SubscriptionGroupHandler.isUserPartOfGroup user_id, licence.group_subscription_id, cb
 			subscription: (cb)->
@@ -77,15 +78,18 @@ module.exports =
 
 	beginJoinGroup: (req, res)->
 		subscription_id = req.params.subscription_id
-		user_id = req.session.user._id
-		licence = SubscriptionDomainHandler.findDomainLicenceBySubscriptionId(subscription_id)
-		if !licence?
-			return ErrorsController.notFound(req, res)
-		SubscriptionGroupHandler.sendVerificationEmail subscription_id, licence.name, req.session.user.email, (err)->
+		AuthenticationController.getLoggedInUser req, (err, currentUser) ->
 			if err?
-				res.sendStatus 500
-			else
-				res.sendStatus 200
+				logger.err {subscription_id}, "error getting current user"
+				return res.sendStatus 500
+			licence = SubscriptionDomainHandler.findDomainLicenceBySubscriptionId(subscription_id)
+			if !licence?
+				return ErrorsController.notFound(req, res)
+			SubscriptionGroupHandler.sendVerificationEmail subscription_id, licence.name, currentUser.email, (err)->
+				if err?
+					res.sendStatus 500
+				else
+					res.sendStatus 200
 
 	completeJoin: (req, res)->
 		subscription_id = req.params.subscription_id
@@ -109,10 +113,10 @@ module.exports =
 			return ErrorsController.notFound(req, res)
 		res.render "subscriptions/group/successful_join",
 			title: "Sucessfully joined group"
-			licenceName:licence.name	
+			licenceName:licence.name
 
 	exportGroupCsv: (req, res)->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		logger.log user_id: user_id, "exporting group csv"
 		SubscriptionLocator.getUsersSubscription user_id, (err, subscription)->
 			if !subscription.groupPlan

+ 12 - 11
services/web/app/coffee/Features/Tags/TagsController.coffee

@@ -1,48 +1,49 @@
 TagsHandler = require("./TagsHandler")
 logger = require("logger-sharelatex")
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 module.exports =
 	getAllTags: (req, res, next)->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		logger.log {user_id}, "getting tags"
 		TagsHandler.getAllTags user_id, (error, allTags)->
 			return next(error) if error?
 			res.json(allTags)
-	
+
 	createTag: (req, res, next) ->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		name = req.body.name
 		logger.log {user_id, name}, "creating tag"
 		TagsHandler.createTag user_id, name, (error, tag) ->
 			return next(error) if error?
 			res.json(tag)
-	
+
 	addProjectToTag: (req, res, next) ->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		{tag_id, project_id} = req.params
 		logger.log {user_id, tag_id, project_id}, "adding tag to project"
 		TagsHandler.addProjectToTag user_id, tag_id, project_id, (error) ->
 			return next(error) if error?
 			res.status(204).end()
-	
+
 	removeProjectFromTag: (req, res, next) ->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		{tag_id, project_id} = req.params
 		logger.log {user_id, tag_id, project_id}, "removing tag from project"
 		TagsHandler.removeProjectFromTag user_id, tag_id, project_id, (error) ->
 			return next(error) if error?
 			res.status(204).end()
-	
+
 	deleteTag: (req, res, next) ->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		tag_id = req.params.tag_id
 		logger.log {user_id, tag_id}, "deleting tag"
 		TagsHandler.deleteTag user_id, tag_id, (error) ->
 			return next(error) if error?
 			res.status(204).end()
-	
+
 	renameTag: (req, res, next) ->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		tag_id = req.params.tag_id
 		name = req.body?.name
 		if !name?

+ 13 - 14
services/web/app/coffee/Features/TrackChanges/TrackChangesController.coffee

@@ -5,17 +5,16 @@ AuthenticationController = require "../Authentication/AuthenticationController"
 
 module.exports = TrackChangesController =
 	proxyToTrackChangesApi: (req, res, next = (error) ->) ->
-		AuthenticationController.getLoggedInUserId req, (error, user_id) ->
-			return next(error) if error?
-			url = settings.apis.trackchanges.url + req.url
-			logger.log url: url, "proxying to track-changes api"
-			getReq = request(
-				url: url
-				method: req.method
-				headers:
-					"X-User-Id": user_id
-			)
-			getReq.pipe(res)
-			getReq.on "error", (error) ->
-				logger.error err: error, "track-changes API error"
-				next(error)
+		user_id = AuthenticationController.getLoggedInUserId req
+		url = settings.apis.trackchanges.url + req.url
+		logger.log url: url, "proxying to track-changes api"
+		getReq = request(
+			url: url
+			method: req.method
+			headers:
+				"X-User-Id": user_id
+		)
+		getReq.pipe(res)
+		getReq.on "error", (error) ->
+			logger.error err: error, "track-changes API error"
+			next(error)

+ 4 - 6
services/web/app/coffee/Features/Uploads/ProjectUploadController.coffee

@@ -4,11 +4,12 @@ fs      = require "fs"
 Path    = require "path"
 FileSystemImportManager = require "./FileSystemImportManager"
 ProjectUploadManager    = require "./ProjectUploadManager"
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 module.exports = ProjectUploadController =
 	uploadProject: (req, res, next) ->
 		timer = new metrics.Timer("project-upload")
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		{originalname, path} = req.files.qqfile
 		name = Path.basename(originalname, ".zip")
 		ProjectUploadManager.createProjectFromZipArchive user_id, name, path, (error, project) ->
@@ -24,7 +25,7 @@ module.exports = ProjectUploadController =
 					project: project._id, file_path: path, file_name: name,
 					"uploaded project"
 				res.send success: true, project_id: project._id
-	
+
 	uploadFile: (req, res, next) ->
 		timer = new metrics.Timer("file-upload")
 		name = req.files.qqfile?.originalname
@@ -35,7 +36,7 @@ module.exports = ProjectUploadController =
 			logger.err project_id:project_id, name:name, "bad name when trying to upload file"
 			return res.send success: false
 		logger.log folder_id:folder_id, project_id:project_id, "getting upload file request"
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		FileSystemImportManager.addEntity user_id, project_id, folder_id, name, path, true, (error, entity) ->
 			fs.unlink path, ->
 			timer.done()
@@ -50,6 +51,3 @@ module.exports = ProjectUploadController =
 					project_id: project_id, file_path: path, file_name: name, folder_id: folder_id
 					"uploaded file"
 				res.send success: true, entity_id: entity?._id
-
-
-

+ 17 - 14
services/web/app/coffee/Features/User/UserController.coffee

@@ -8,6 +8,7 @@ logger = require("logger-sharelatex")
 metrics = require("../../infrastructure/Metrics")
 Url = require("url")
 AuthenticationManager = require("../Authentication/AuthenticationManager")
+AuthenticationController = require('../Authentication/AuthenticationController')
 UserSessionsManager = require("./UserSessionsManager")
 UserUpdater = require("./UserUpdater")
 settings = require "settings-sharelatex"
@@ -15,20 +16,21 @@ settings = require "settings-sharelatex"
 module.exports = UserController =
 
 	deleteUser: (req, res)->
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
 		UserDeleter.deleteUser user_id, (err)->
 			if !err?
 				req.session?.destroy()
 			res.sendStatus(200)
 
 	unsubscribe: (req, res)->
-		UserLocator.findById req.session.user._id, (err, user)->
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		UserLocator.findById user_id, (err, user)->
 			newsLetterManager.unsubscribe user, ->
 				res.send()
 
 	updateUserSettings : (req, res)->
-		logger.log user: req.session.user, "updating account settings"
-		user_id = req.session.user._id
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		logger.log user: user_id, "updating account settings"
 		User.findById user_id, (err, user)->
 			if err? or !user?
 				logger.err err:err, user_id:user_id, "problem updaing user settings"
@@ -73,7 +75,7 @@ module.exports = UserController =
 							if err?
 								logger.err err:err, user_id:user_id, "error getting user for email update"
 								return res.send 500
-							req.session.user.email = user.email
+							req.user.email = user.email
 							UserHandler.populateGroupLicenceInvite user, (err)-> #need to refresh this in the background
 								if err?
 									logger.err err:err, "error populateGroupLicenceInvite"
@@ -83,13 +85,13 @@ module.exports = UserController =
 		metrics.inc "user.logout"
 		logger.log user: req?.session?.user, "logging out"
 		sessionId = req.sessionID
-		user = req?.session?.user
-		req.logout?()  # passport logout
-		req.session.destroy (err)->
-			if err
-				logger.err err: err, 'error destorying session'
-			UserSessionsManager.untrackSession(user, sessionId)
-			res.redirect '/login'
+		AuthenticationController.getLoggedInUser req, (err, user) ->
+			req.logout?()  # passport logout
+			req.session.destroy (err)->
+				if err
+					logger.err err: err, 'error destorying session'
+				UserSessionsManager.untrackSession(user, sessionId)
+				res.redirect '/login'
 
 	register : (req, res, next = (error) ->)->
 		email = req.body.email
@@ -106,10 +108,11 @@ module.exports = UserController =
 	changePassword : (req, res, next = (error) ->)->
 		metrics.inc "user.password-change"
 		oldPass = req.body.currentPassword
-		AuthenticationManager.authenticate {_id:req.session.user._id}, oldPass, (err, user)->
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		AuthenticationManager.authenticate {_id:user_id}, oldPass, (err, user)->
 			return next(err) if err?
 			if(user)
-				logger.log user: req.session.user, "changing password"
+				logger.log user: user._id, "changing password"
 				newPassword1 = req.body.newPassword1
 				newPassword2 = req.body.newPassword2
 				if newPassword1 != newPassword2

+ 6 - 4
services/web/app/coffee/Features/User/UserPagesController.coffee

@@ -4,6 +4,7 @@ ErrorController = require("../Errors/ErrorController")
 logger = require("logger-sharelatex")
 Settings = require("settings-sharelatex")
 fs = require('fs')
+AuthenticationController = require('../Authentication/AuthenticationController')
 
 module.exports =
 
@@ -22,14 +23,14 @@ module.exports =
 			sharedProjectData: sharedProjectData
 			newTemplateData: newTemplateData
 			new_email:req.query.new_email || ""
-	
+
 	activateAccountPage: (req, res) ->
 		# An 'activation' is actually just a password reset on an account that
 		# was set with a random password originally.
 		logger.log query:req.query, "activiate account page called"
 		if !req.query?.user_id? or !req.query?.token?
 			return ErrorController.notFound(req, res)
-			
+
 		UserGetter.getUser req.query.user_id, {email: 1, loginCount: 1}, (error, user) ->
 			return next(error) if error?
 			if !user
@@ -53,8 +54,9 @@ module.exports =
 			email: req.query.email
 
 	settingsPage : (req, res, next)->
-		logger.log user: req.session.user, "loading settings page"
-		UserLocator.findById req.session.user._id, (err, user)->
+		user_id = AuthenticationController.getLoggedInUserId(req)
+		logger.log user: user_id, "loading settings page"
+		UserLocator.findById user_id, (err, user)->
 			return next(err) if err?
 			res.render 'user/settings',
 				title:'account_settings'

+ 15 - 16
services/web/app/coffee/infrastructure/ExpressLocals.coffee

@@ -5,6 +5,7 @@ Settings = require('settings-sharelatex')
 SubscriptionFormatters = require('../Features/Subscription/SubscriptionFormatters')
 querystring = require('querystring')
 SystemMessageManager = require("../Features/SystemMessages/SystemMessageManager")
+AuthenticationController = require("../Features/Authentication/AuthenticationController")
 _ = require("underscore")
 Modules = require "./Modules"
 Url = require "url"
@@ -59,7 +60,7 @@ module.exports = (app, webRouter, apiRouter)->
 		res.locals.session = req.session
 		next()
 
-	webRouter.use (req, res, next)-> 
+	webRouter.use (req, res, next)->
 
 		cdnBlocked = req.query.nocdn == 'true' or req.session.cdnBlocked
 
@@ -77,7 +78,7 @@ module.exports = (app, webRouter, apiRouter)->
 			staticFilesBase = Settings.cdn?.web?.darkHost
 		else
 			staticFilesBase = ""
-		
+
 		res.locals.jsPath = jsPath
 		res.locals.fullJsPath = Url.resolve(staticFilesBase, jsPath)
 
@@ -86,7 +87,7 @@ module.exports = (app, webRouter, apiRouter)->
 			path = Path.join(jsPath, jsFile)
 
 			doFingerPrint = opts.fingerprint != false
-			
+
 			if !opts.qs?
 				opts.qs = {}
 
@@ -95,7 +96,7 @@ module.exports = (app, webRouter, apiRouter)->
 
 			if opts.cdn != false
 				path = Url.resolve(staticFilesBase, path)
-				
+
 			qs = querystring.stringify(opts.qs)
 
 			if qs? and qs.length > 0
@@ -115,7 +116,7 @@ module.exports = (app, webRouter, apiRouter)->
 
 
 
-	webRouter.use (req, res, next)-> 
+	webRouter.use (req, res, next)->
 		res.locals.settings = Settings
 		next()
 
@@ -143,7 +144,7 @@ module.exports = (app, webRouter, apiRouter)->
 			return formatedPrivileges[privilegeLevel] || "Private"
 		next()
 
-	webRouter.use (req, res, next)-> 
+	webRouter.use (req, res, next)->
 		res.locals.buildReferalUrl = (referal_medium) ->
 			url = Settings.siteUrl
 			if req.session? and req.session.user? and req.session.user.referal_id?
@@ -167,7 +168,7 @@ module.exports = (app, webRouter, apiRouter)->
 			return ""
 
 		res.locals.getLoggedInUserId = ->
-			return req.session.user?._id
+			return AuthenticationController.getLoggedInUserId(req)
 		next()
 
 	webRouter.use (req, res, next) ->
@@ -179,11 +180,11 @@ module.exports = (app, webRouter, apiRouter)->
 			return req.query?[field]
 		next()
 
-	webRouter.use (req, res, next)-> 
+	webRouter.use (req, res, next)->
 		res.locals.fingerprint = getFingerprint
 		next()
 
-	webRouter.use (req, res, next)-> 
+	webRouter.use (req, res, next)->
 		res.locals.formatPrice = SubscriptionFormatters.formatPrice
 		next()
 
@@ -193,11 +194,11 @@ module.exports = (app, webRouter, apiRouter)->
 		next()
 
 	webRouter.use (req, res, next)->
-		if req.session.user?
+		if req.user?
 			res.locals.user =
-				email: req.session.user.email
-				first_name: req.session.user.first_name
-				last_name: req.session.user.last_name
+				email: req.user.email
+				first_name: req.user.first_name
+				last_name: req.user.last_name
 			if req.session.justRegistered
 				res.locals.justRegistered = true
 				delete req.session.justRegistered
@@ -223,7 +224,7 @@ module.exports = (app, webRouter, apiRouter)->
 			res.locals.nav[key] = _.clone(Settings.nav[key])
 		res.locals.templates = Settings.templateLinks
 		next()
-		
+
 	webRouter.use (req, res, next) ->
 		SystemMessageManager.getMessages (error, messages = []) ->
 			res.locals.systemMessages = messages
@@ -246,5 +247,3 @@ module.exports = (app, webRouter, apiRouter)->
 		res.locals.moduleIncludes = Modules.moduleIncludes
 		res.locals.moduleIncludesAvailable = Modules.moduleIncludesAvailable
 		next()
-
-