Delete SecurityManager and replace with (unwritten) AuthorizationManager
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
module.exports =
|
||||
getPrivilegeLevelForProject: (user_id, project_id, callback = (error, canAccess, privilegeLevel) ->) ->
|
||||
return callback(null, true, "readAndWrite")
|
||||
|
||||
canUserReadProject: (user_id, project_id, callback = (error, canRead) ->) ->
|
||||
|
||||
canUserWriteProjectSettings: (user_id, project_id, callback = (error, canWriteSettings) ->) ->
|
||||
|
||||
canUserAdminProject: (user_id, project_id, callback = (error, canAdmin) ->) ->
|
||||
|
||||
isUserSiteAdmin: (user_id, callback = (error, isAdmin) ->) ->
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
module.exports =
|
||||
ensureUserCanReadMultipleProjects: (req, res, next) ->
|
||||
next()
|
||||
|
||||
ensureUserCanReadProject: (req, res, next) ->
|
||||
next()
|
||||
|
||||
ensureUserCanWriteProjectSettings: (req, res, next) ->
|
||||
next()
|
||||
|
||||
ensureUserCanWriteProjectContent: (req, res, next) ->
|
||||
next()
|
||||
|
||||
ensureUserCanAdminProject: (req, res, next) ->
|
||||
next()
|
||||
|
||||
ensureUserIsSiteAdmin: (req, res, next) ->
|
||||
next()
|
||||
|
||||
restricted : (req, res, next)->
|
||||
if req.session.user?
|
||||
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'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
CollaboratorsController = require('./CollaboratorsController')
|
||||
SecurityManager = require('../../managers/SecurityManager')
|
||||
AuthenticationController = require('../Authentication/AuthenticationController')
|
||||
AuthorizationMiddlewear = require('../Authorization/AuthorizationMiddlewear')
|
||||
|
||||
module.exports =
|
||||
apply: (webRouter, apiRouter) ->
|
||||
webRouter.post '/project/:Project_id/leave', AuthenticationController.requireLogin(), CollaboratorsController.removeSelfFromProject
|
||||
|
||||
webRouter.post '/project/:Project_id/users', SecurityManager.requestIsOwner, CollaboratorsController.addUserToProject
|
||||
webRouter.delete '/project/:Project_id/users/:user_id', SecurityManager.requestIsOwner, CollaboratorsController.removeUserFromProject
|
||||
webRouter.post '/project/:Project_id/users', AuthorizationMiddlewear.ensureUserCanAdminProject, CollaboratorsController.addUserToProject
|
||||
webRouter.delete '/project/:Project_id/users/:user_id', AuthorizationMiddlewear.ensureUserCanAdminProject, CollaboratorsController.removeUserFromProject
|
||||
|
||||
@@ -5,7 +5,7 @@ EditorRealTimeController = require "./EditorRealTimeController"
|
||||
EditorController = require "./EditorController"
|
||||
ProjectGetter = require('../Project/ProjectGetter')
|
||||
UserGetter = require('../User/UserGetter')
|
||||
AuthorizationManager = require("../Security/AuthorizationManager")
|
||||
AuthorizationManager = require("../Authorization/AuthorizationManager")
|
||||
ProjectEditorHandler = require('../Project/ProjectEditorHandler')
|
||||
Metrics = require('../../infrastructure/Metrics')
|
||||
CollaboratorsHandler = require("../Collaborators/CollaboratorsHandler")
|
||||
@@ -34,7 +34,7 @@ module.exports = EditorHttpController =
|
||||
return callback(error) if error?
|
||||
UserGetter.getUser user_id, { isAdmin: true }, (error, user) ->
|
||||
return callback(error) if error?
|
||||
AuthorizationManager.getPrivilegeLevelForProject project, user, (error, canAccess, privilegeLevel) ->
|
||||
AuthorizationManager.getPrivilegeLevelForProject user_id, project_id, (error, canAccess, privilegeLevel) ->
|
||||
return callback(error) if error?
|
||||
if !canAccess
|
||||
callback null, null, false
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
EditorHttpController = require('./EditorHttpController')
|
||||
SecurityManager = require('../../managers/SecurityManager')
|
||||
AuthenticationController = require "../Authentication/AuthenticationController"
|
||||
AuthorizationMiddlewear = require('../Authorization/AuthorizationMiddlewear')
|
||||
|
||||
module.exports =
|
||||
apply: (webRouter, apiRouter) ->
|
||||
webRouter.post '/project/:Project_id/doc', SecurityManager.requestCanModifyProject, EditorHttpController.addDoc
|
||||
webRouter.post '/project/:Project_id/folder', SecurityManager.requestCanModifyProject, EditorHttpController.addFolder
|
||||
webRouter.post '/project/:Project_id/doc', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.addDoc
|
||||
webRouter.post '/project/:Project_id/folder', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.addFolder
|
||||
|
||||
webRouter.post '/project/:Project_id/:entity_type/:entity_id/rename', SecurityManager.requestCanModifyProject, EditorHttpController.renameEntity
|
||||
webRouter.post '/project/:Project_id/:entity_type/:entity_id/move', SecurityManager.requestCanModifyProject, EditorHttpController.moveEntity
|
||||
webRouter.post '/project/:Project_id/:entity_type/:entity_id/rename', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.renameEntity
|
||||
webRouter.post '/project/:Project_id/:entity_type/:entity_id/move', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.moveEntity
|
||||
|
||||
webRouter.delete '/project/:Project_id/file/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteFile
|
||||
webRouter.delete '/project/:Project_id/doc/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteDoc
|
||||
webRouter.delete '/project/:Project_id/folder/:entity_id', SecurityManager.requestCanModifyProject, EditorHttpController.deleteFolder
|
||||
webRouter.delete '/project/:Project_id/file/:entity_id', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.deleteFile
|
||||
webRouter.delete '/project/:Project_id/doc/:entity_id', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.deleteDoc
|
||||
webRouter.delete '/project/:Project_id/folder/:entity_id', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.deleteFolder
|
||||
|
||||
webRouter.post '/project/:Project_id/doc/:doc_id/restore', SecurityManager.requestCanModifyProject, EditorHttpController.restoreDoc
|
||||
webRouter.post '/project/:Project_id/doc/:doc_id/restore', AuthorizationMiddlewear.ensureUserCanWriteProjectContent, EditorHttpController.restoreDoc
|
||||
|
||||
# Called by the real-time API to load up the current project state.
|
||||
# This is a post request because it's more than just a getting of data. We take actions
|
||||
|
||||
@@ -13,7 +13,7 @@ NotificationsHandler = require("../Notifications/NotificationsHandler")
|
||||
LimitationsManager = require("../Subscription/LimitationsManager")
|
||||
_ = require("underscore")
|
||||
Settings = require("settings-sharelatex")
|
||||
SecurityManager = require("../../managers/SecurityManager")
|
||||
AuthorizationManager = require("../Authorization/AuthorizationManager")
|
||||
fs = require "fs"
|
||||
InactiveProjectManager = require("../InactiveData/InactiveProjectManager")
|
||||
ProjectUpdateHandler = require("./ProjectUpdateHandler")
|
||||
@@ -225,7 +225,8 @@ module.exports = ProjectController =
|
||||
daysSinceLastUpdated = (new Date() - project.lastUpdated) /86400000
|
||||
logger.log project_id:project_id, daysSinceLastUpdated:daysSinceLastUpdated, "got db results for loading editor"
|
||||
|
||||
SecurityManager.userCanAccessProject user, project, (canAccess, privilegeLevel)->
|
||||
AuthorizationManager.getPrivilegeLevelForProject user_id, project_id, (error, canAccess, privilegeLevel)->
|
||||
return next(error) if error?
|
||||
if !canAccess
|
||||
return res.sendStatus 401
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
SecurityManager = require '../../managers/SecurityManager'
|
||||
|
||||
module.exports = AuthorizationManager =
|
||||
getPrivilegeLevelForProject: (
|
||||
project, user,
|
||||
callback = (error, canAccess, privilegeLevel)->
|
||||
) ->
|
||||
# This is not tested because eventually this function should be brought into
|
||||
# this module.
|
||||
SecurityManager.userCanAccessProject user, project, (canAccess, privilegeLevel) ->
|
||||
if canAccess
|
||||
callback null, true, privilegeLevel
|
||||
else
|
||||
callback null, false
|
||||
|
||||
setPrivilegeLevelOnClient: (client, privilegeLevel) ->
|
||||
client.set("privilege_level", privilegeLevel)
|
||||
|
||||
ensureClientCanViewProject: (client, callback = (error, project_id)->) ->
|
||||
@ensureClientHasPrivilegeLevelForProject client, ["owner", "readAndWrite", "readOnly"], callback
|
||||
|
||||
ensureClientCanEditProject: (client, callback = (error, project_id)->) ->
|
||||
@ensureClientHasPrivilegeLevelForProject client, ["owner", "readAndWrite"], callback
|
||||
|
||||
ensureClientCanAdminProject: (client, callback = (error, project_id)->) ->
|
||||
@ensureClientHasPrivilegeLevelForProject client, ["owner"], callback
|
||||
|
||||
ensureClientHasPrivilegeLevelForProject: (client, levels, callback = (error, project_id)->) ->
|
||||
client.get "privilege_level", (error, level) ->
|
||||
return callback(error) if error?
|
||||
if level?
|
||||
client.get "project_id", (error, project_id) ->
|
||||
return callback(error) if error?
|
||||
if project_id?
|
||||
if levels.indexOf(level) > -1
|
||||
callback null, project_id
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SecurityManager = require '../../managers/SecurityManager'
|
||||
AuthenticationController = require '../Authentication/AuthenticationController'
|
||||
SubscriptionHandler = require './SubscriptionHandler'
|
||||
PlansLocator = require("./PlansLocator")
|
||||
SubscriptionFormatters = require("./SubscriptionFormatters")
|
||||
@@ -32,7 +32,7 @@ module.exports = SubscriptionController =
|
||||
|
||||
#get to show the recurly.js page
|
||||
paymentPage: (req, res, next) ->
|
||||
SecurityManager.getCurrentUser req, (error, user) =>
|
||||
AuthenticationController.getLoggedInUser req, (error, user) =>
|
||||
return next(error) if error?
|
||||
plan = PlansLocator.findLocalPlanInSettings(req.query.planCode)
|
||||
LimitationsManager.userHasSubscription user, (err, hasSubscription)->
|
||||
@@ -81,7 +81,7 @@ module.exports = SubscriptionController =
|
||||
|
||||
|
||||
userSubscriptionPage: (req, res, next) ->
|
||||
SecurityManager.getCurrentUser req, (error, user) =>
|
||||
AuthenticationController.getLoggedInUser req, (error, user) =>
|
||||
return next(error) if error?
|
||||
LimitationsManager.userHasSubscriptionOrIsGroupMember user, (err, hasSubOrIsGroupMember, subscription)->
|
||||
groupLicenceInviteUrl = SubscriptionDomainHandler.getDomainLicencePage(user)
|
||||
@@ -110,7 +110,7 @@ module.exports = SubscriptionController =
|
||||
|
||||
|
||||
userCustomSubscriptionPage: (req, res, next)->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
LimitationsManager.userHasSubscriptionOrIsGroupMember user, (err, hasSubOrIsGroupMember, subscription)->
|
||||
res.render "subscriptions/custom_account",
|
||||
title: "your_subscription"
|
||||
@@ -118,7 +118,7 @@ module.exports = SubscriptionController =
|
||||
|
||||
|
||||
editBillingDetailsPage: (req, res, next) ->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
return next(error) if error?
|
||||
LimitationsManager.userHasSubscription user, (err, hasSubscription)->
|
||||
if !hasSubscription
|
||||
@@ -139,7 +139,7 @@ module.exports = SubscriptionController =
|
||||
id : user.id
|
||||
|
||||
createSubscription: (req, res, next)->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
return callback(error) if error?
|
||||
recurly_token_id = req.body.recurly_token_id
|
||||
subscriptionDetails = req.body.subscriptionDetails
|
||||
@@ -151,14 +151,14 @@ module.exports = SubscriptionController =
|
||||
res.sendStatus 201
|
||||
|
||||
successful_subscription: (req, res)->
|
||||
SecurityManager.getCurrentUser req, (error, user) =>
|
||||
AuthenticationController.getLoggedInUser req, (error, user) =>
|
||||
SubscriptionViewModelBuilder.buildUsersSubscriptionViewModel user, (error, subscription) ->
|
||||
res.render "subscriptions/successful_subscription",
|
||||
title: "thank_you"
|
||||
subscription:subscription
|
||||
|
||||
cancelSubscription: (req, res, next) ->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
logger.log user_id:user._id, "canceling subscription"
|
||||
return next(error) if error?
|
||||
SubscriptionHandler.cancelSubscription user, (err)->
|
||||
@@ -167,7 +167,7 @@ module.exports = SubscriptionController =
|
||||
res.redirect "/user/subscription"
|
||||
|
||||
updateSubscription: (req, res)->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
return next(error) if error?
|
||||
planCode = req.body.plan_code
|
||||
logger.log planCode: planCode, user_id:user._id, "updating subscription"
|
||||
@@ -177,7 +177,7 @@ module.exports = SubscriptionController =
|
||||
res.redirect "/user/subscription"
|
||||
|
||||
reactivateSubscription: (req, res)->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
logger.log user_id:user._id, "reactivating subscription"
|
||||
return next(error) if error?
|
||||
SubscriptionHandler.reactivateSubscription user, (err)->
|
||||
@@ -196,7 +196,7 @@ module.exports = SubscriptionController =
|
||||
res.sendStatus 200
|
||||
|
||||
renderUpgradeToAnnualPlanPage: (req, res)->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
LimitationsManager.userHasSubscription user, (err, hasSubscription, subscription)->
|
||||
planCode = subscription?.planCode.toLowerCase()
|
||||
if planCode?.indexOf("annual") != -1
|
||||
@@ -213,7 +213,7 @@ module.exports = SubscriptionController =
|
||||
planName: planName
|
||||
|
||||
processUpgradeToAnnualPlan: (req, res)->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
{planName} = req.body
|
||||
coupon_code = Settings.coupon_codes.upgradeToAnnualPromo[planName]
|
||||
annualPlanName = "#{planName}-annual"
|
||||
@@ -226,7 +226,7 @@ module.exports = SubscriptionController =
|
||||
res.sendStatus 200
|
||||
|
||||
extendTrial: (req, res)->
|
||||
SecurityManager.getCurrentUser req, (error, user) ->
|
||||
AuthenticationController.getLoggedInUser req, (error, user) ->
|
||||
LimitationsManager.userHasSubscription user, (err, hasSubscription, subscription)->
|
||||
SubscriptionHandler.extendTrial subscription, 14, (err)->
|
||||
if err?
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SecurityManager = require('../../managers/SecurityManager')
|
||||
AuthorizationMiddlewear = require('../Authorization/AuthorizationMiddlewear')
|
||||
AuthenticationController = require('../Authentication/AuthenticationController')
|
||||
ProjectUploadController = require "./ProjectUploadController"
|
||||
RateLimiterMiddlewear = require('../Security/RateLimiterMiddlewear')
|
||||
@@ -16,6 +16,6 @@ module.exports =
|
||||
maxRequests: 200
|
||||
timeInterval: 60 * 30
|
||||
}),
|
||||
SecurityManager.requestCanModifyProject,
|
||||
AuthorizationMiddlewear.ensureUserCanWriteProjectContent,
|
||||
ProjectUploadController.uploadFile
|
||||
|
||||
|
||||
@@ -1,194 +0,0 @@
|
||||
logger = require('logger-sharelatex')
|
||||
crypto = require 'crypto'
|
||||
Assert = require 'assert'
|
||||
Settings = require 'settings-sharelatex'
|
||||
User = require('../models/User').User
|
||||
Project = require('../models/Project').Project
|
||||
ErrorController = require("../Features/Errors/ErrorController")
|
||||
AuthenticationController = require("../Features/Authentication/AuthenticationController")
|
||||
_ = require('underscore')
|
||||
metrics = require('../infrastructure/Metrics')
|
||||
querystring = require('querystring')
|
||||
async = require "async"
|
||||
|
||||
module.exports = SecurityManager =
|
||||
restricted : (req, res, next)->
|
||||
if req.session.user?
|
||||
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'
|
||||
|
||||
getCurrentUser: (req, callback) ->
|
||||
if req.session.user?
|
||||
User.findById req.session.user._id, callback
|
||||
else
|
||||
callback null, null
|
||||
|
||||
requestCanAccessMultipleProjects: (req, res, next) ->
|
||||
project_ids = req.query.project_ids?.split(",")
|
||||
jobs = []
|
||||
for project_id in project_ids or []
|
||||
do (project_id) ->
|
||||
jobs.push (callback) ->
|
||||
# This is a bit hacky - better to have an abstracted method
|
||||
# that we can pass project_id to, but this whole file needs
|
||||
# a serious refactor ATM.
|
||||
req.params.Project_id = project_id
|
||||
SecurityManager.requestCanAccessProject req, res, (error) ->
|
||||
delete req.params.Project_id
|
||||
callback(error)
|
||||
async.series jobs, next
|
||||
|
||||
requestCanAccessProject : (req, res, next)->
|
||||
doRequest = (req, res, next) ->
|
||||
getRequestUserAndProject req, res, {allow_auth_token: options?.allow_auth_token}, (err, user, project)->
|
||||
if !project? or project.archived
|
||||
return ErrorController.notFound(req, res, next)
|
||||
userCanAccessProject user, project, (canAccess, permissionLevel)->
|
||||
if canAccess
|
||||
next()
|
||||
else if user?
|
||||
logger.log "user_id: #{user._id} email: #{user.email} trying to access restricted page #{req.path}"
|
||||
res.redirect('/restricted')
|
||||
else
|
||||
logger.log "user not logged in and trying to access #{req.url}, being redirected to login"
|
||||
AuthenticationController._redirectToLoginOrRegisterPage(req, res)
|
||||
if arguments.length > 1
|
||||
options =
|
||||
allow_auth_token: false
|
||||
doRequest.apply(this, arguments)
|
||||
else
|
||||
options = req
|
||||
return doRequest
|
||||
|
||||
requestCanModifyProject : (req, res, next)->
|
||||
getRequestUserAndProject req, res, {}, (err, user, project)=>
|
||||
userCanModifyProject user, project, (canModify)->
|
||||
if canModify
|
||||
next()
|
||||
else
|
||||
logger.log "user_id: #{user?._id} email: #{user?.email} can not modify project redirecting to restricted page"
|
||||
res.redirect('/restricted')
|
||||
|
||||
userCanModifyProject : userCanModifyProject = (user, project, callback)->
|
||||
if !user? or !project?
|
||||
callback false
|
||||
else if userIsOwner user, project
|
||||
callback true
|
||||
else if userIsCollaberator user, project
|
||||
callback true
|
||||
else if project.publicAccesLevel == "readAndWrite"
|
||||
callback true
|
||||
else if user.isAdmin
|
||||
callback true
|
||||
else
|
||||
callback false
|
||||
|
||||
|
||||
requestIsOwner : (req, res, next)->
|
||||
getRequestUserAndProject req, res, {}, (err, user, project)->
|
||||
if !user?
|
||||
return res.redirect('/restricted')
|
||||
else if userIsOwner user, project || user.isAdmin
|
||||
next()
|
||||
else
|
||||
logger.log user_id: user?._id, email: user?.email, "user is not owner of project redirecting to restricted page"
|
||||
res.redirect('/restricted')
|
||||
|
||||
requestIsAdmin : isAdmin = (req, res, next)->
|
||||
logger.log "checking if user is admin"
|
||||
user = req.session.user
|
||||
if(user? && user.isAdmin)
|
||||
logger.log user: user, "User is admin"
|
||||
next()
|
||||
else
|
||||
res.redirect('/restricted')
|
||||
logger.log user:user, "is not admin redirecting to restricted page"
|
||||
|
||||
userCanAccessProject : userCanAccessProject = (user, project, callback)=>
|
||||
if !user?
|
||||
user = {_id:'anonymous-user'}
|
||||
if !project?
|
||||
callback false
|
||||
logger.log user:user, project:project, "Checking if can access"
|
||||
if userIsOwner user, project
|
||||
callback true, "owner"
|
||||
else if userIsCollaberator user, project
|
||||
callback true, "readAndWrite"
|
||||
else if userIsReadOnly user, project
|
||||
callback true, "readOnly"
|
||||
else if user.isAdmin
|
||||
logger.log user:user, project:project, "user is admin and can access project"
|
||||
callback true, "owner"
|
||||
else if project.publicAccesLevel == "readAndWrite"
|
||||
logger.log user:user, project:project, "project is a public read and write project"
|
||||
callback true, "readAndWrite"
|
||||
else if project.publicAccesLevel == "readOnly"
|
||||
logger.log user:user, project:project, "project is a public read only project"
|
||||
callback true, "readOnly"
|
||||
else
|
||||
metrics.inc "security.denied"
|
||||
logger.log user:user, project:project, "Security denied - user can not enter project"
|
||||
callback false
|
||||
|
||||
userIsOwner : userIsOwner = (user, project)->
|
||||
if !user?
|
||||
return false
|
||||
else
|
||||
userId = user._id+''
|
||||
ownerRef = getProjectIdFromRef(project.owner_ref)
|
||||
if userId == ownerRef
|
||||
true
|
||||
else
|
||||
false
|
||||
|
||||
userIsCollaberator : userIsCollaberator = (user, project)->
|
||||
if !user?
|
||||
return false
|
||||
else
|
||||
userId = user._id+''
|
||||
result = false
|
||||
_.each project.collaberator_refs, (colabRef)->
|
||||
colabRef = getProjectIdFromRef(colabRef)
|
||||
if colabRef == userId
|
||||
result = true
|
||||
return result
|
||||
|
||||
userIsReadOnly : userIsReadOnly = (user, project)->
|
||||
if !user?
|
||||
return false
|
||||
else
|
||||
userId = user._id+''
|
||||
result = false
|
||||
_.each project.readOnly_refs, (readOnlyRef)->
|
||||
readOnlyRef = getProjectIdFromRef(readOnlyRef)
|
||||
|
||||
if readOnlyRef == userId
|
||||
result = true
|
||||
return result
|
||||
|
||||
getRequestUserAndProject = (req, res, options, callback)->
|
||||
project_id = req.params.Project_id
|
||||
if !project_id?
|
||||
logger.log project_id:project_id, options:options, url:req?.url, "no project_id trying to getRequestUserAndProject"
|
||||
return res.send 422
|
||||
Project.findById project_id, 'name owner_ref readOnly_refs collaberator_refs publicAccesLevel archived', (err, project)=>
|
||||
if err?
|
||||
logger.err err:err, "error getting project for security check"
|
||||
return callback err
|
||||
AuthenticationController.getLoggedInUser req, options, (err, user)=>
|
||||
if err?
|
||||
logger.err err:err, "error getting last logged in user for security check"
|
||||
callback err, user, project
|
||||
|
||||
getProjectIdFromRef = (ref)->
|
||||
if !ref?
|
||||
return null
|
||||
else if ref._id?
|
||||
return ref._id+''
|
||||
else
|
||||
return ref+''
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ ErrorController = require('./Features/Errors/ErrorController')
|
||||
ProjectController = require("./Features/Project/ProjectController")
|
||||
ProjectApiController = require("./Features/Project/ProjectApiController")
|
||||
SpellingController = require('./Features/Spelling/SpellingController')
|
||||
SecurityManager = require('./managers/SecurityManager')
|
||||
AuthorizationManager = require('./Features/Security/AuthorizationManager')
|
||||
EditorController = require("./Features/Editor/EditorController")
|
||||
EditorRouter = require("./Features/Editor/EditorRouter")
|
||||
Settings = require('settings-sharelatex')
|
||||
@@ -39,6 +37,7 @@ RealTimeProxyRouter = require('./Features/RealTimeProxy/RealTimeProxyRouter')
|
||||
InactiveProjectController = require("./Features/InactiveData/InactiveProjectController")
|
||||
ContactRouter = require("./Features/Contacts/ContactRouter")
|
||||
ReferencesController = require('./Features/References/ReferencesController')
|
||||
AuthorizationMiddlewear = require('./Features/Authorization/AuthorizationMiddlewear')
|
||||
|
||||
logger = require("logger-sharelatex")
|
||||
_ = require("underscore")
|
||||
@@ -54,7 +53,7 @@ module.exports = class Router
|
||||
|
||||
webRouter.post '/login', AuthenticationController.login
|
||||
webRouter.get '/logout', UserController.logout
|
||||
webRouter.get '/restricted', SecurityManager.restricted
|
||||
webRouter.get '/restricted', AuthorizationMiddlewear.restricted
|
||||
|
||||
# Left as a placeholder for implementing a public register page
|
||||
webRouter.get '/register', UserPagesController.registerPage
|
||||
@@ -99,13 +98,13 @@ module.exports = class Router
|
||||
params: ["Project_id"]
|
||||
maxRequests: 10
|
||||
timeInterval: 60
|
||||
}), SecurityManager.requestCanAccessProject, ProjectController.loadEditor
|
||||
webRouter.get '/Project/:Project_id/file/:File_id', SecurityManager.requestCanAccessProject, FileStoreController.getFile
|
||||
webRouter.post '/project/:Project_id/settings', SecurityManager.requestCanModifyProject, ProjectController.updateProjectSettings
|
||||
webRouter.post '/project/:Project_id/settings/admin', SecurityManager.requestIsOwner, ProjectController.updateProjectAdminSettings
|
||||
}), AuthorizationMiddlewear.ensureUserCanReadProject, ProjectController.loadEditor
|
||||
webRouter.get '/Project/:Project_id/file/:File_id', AuthorizationMiddlewear.ensureUserCanReadProject, FileStoreController.getFile
|
||||
webRouter.post '/project/:Project_id/settings', AuthorizationMiddlewear.ensureUserCanWriteProjectSettings, ProjectController.updateProjectSettings
|
||||
webRouter.post '/project/:Project_id/settings/admin', AuthorizationMiddlewear.ensureUserCanAdminProject, ProjectController.updateProjectAdminSettings
|
||||
|
||||
webRouter.post '/project/:Project_id/compile', SecurityManager.requestCanAccessProject, CompileController.compile
|
||||
webRouter.get '/Project/:Project_id/output/output.pdf', SecurityManager.requestCanAccessProject, CompileController.downloadPdf
|
||||
webRouter.post '/project/:Project_id/compile', AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.compile
|
||||
webRouter.get '/Project/:Project_id/output/output.pdf', AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.downloadPdf
|
||||
webRouter.get /^\/project\/([^\/]*)\/output\/(.*)$/,
|
||||
((req, res, next) ->
|
||||
params =
|
||||
@@ -113,24 +112,24 @@ module.exports = class Router
|
||||
"file": req.params[1]
|
||||
req.params = params
|
||||
next()
|
||||
), SecurityManager.requestCanAccessProject, CompileController.getFileFromClsi
|
||||
webRouter.delete "/project/:Project_id/output", SecurityManager.requestCanAccessProject, CompileController.deleteAuxFiles
|
||||
webRouter.get "/project/:Project_id/sync/code", SecurityManager.requestCanAccessProject, CompileController.proxySync
|
||||
webRouter.get "/project/:Project_id/sync/pdf", SecurityManager.requestCanAccessProject, CompileController.proxySync
|
||||
webRouter.get "/project/:Project_id/wordcount", SecurityManager.requestCanAccessProject, CompileController.wordCount
|
||||
), AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.getFileFromClsi
|
||||
webRouter.delete "/project/:Project_id/output", AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.deleteAuxFiles
|
||||
webRouter.get "/project/:Project_id/sync/code", AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.proxySync
|
||||
webRouter.get "/project/:Project_id/sync/pdf", AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.proxySync
|
||||
webRouter.get "/project/:Project_id/wordcount", AuthorizationMiddlewear.ensureUserCanReadProject, CompileController.wordCount
|
||||
|
||||
webRouter.delete '/Project/:Project_id', SecurityManager.requestIsOwner, ProjectController.deleteProject
|
||||
webRouter.post '/Project/:Project_id/restore', SecurityManager.requestIsOwner, ProjectController.restoreProject
|
||||
webRouter.post '/Project/:Project_id/clone', SecurityManager.requestCanAccessProject, ProjectController.cloneProject
|
||||
webRouter.delete '/Project/:Project_id', AuthorizationMiddlewear.ensureUserCanAdminProject, ProjectController.deleteProject
|
||||
webRouter.post '/Project/:Project_id/restore', AuthorizationMiddlewear.ensureUserCanAdminProject, ProjectController.restoreProject
|
||||
webRouter.post '/Project/:Project_id/clone', AuthorizationMiddlewear.ensureUserCanReadProject, ProjectController.cloneProject
|
||||
|
||||
webRouter.post '/project/:Project_id/rename', SecurityManager.requestIsOwner, ProjectController.renameProject
|
||||
webRouter.post '/project/:Project_id/rename', AuthorizationMiddlewear.ensureUserCanAdminProject, ProjectController.renameProject
|
||||
|
||||
webRouter.get "/project/:Project_id/updates", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
|
||||
webRouter.get "/project/:Project_id/doc/:doc_id/diff", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
|
||||
webRouter.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", SecurityManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
|
||||
webRouter.get "/project/:Project_id/updates", AuthorizationMiddlewear.ensureUserCanReadProject, TrackChangesController.proxyToTrackChangesApi
|
||||
webRouter.get "/project/:Project_id/doc/:doc_id/diff", AuthorizationMiddlewear.ensureUserCanReadProject, TrackChangesController.proxyToTrackChangesApi
|
||||
webRouter.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", AuthorizationMiddlewear.ensureUserCanReadProject, TrackChangesController.proxyToTrackChangesApi
|
||||
|
||||
webRouter.get '/Project/:Project_id/download/zip', SecurityManager.requestCanAccessProject, ProjectDownloadsController.downloadProject
|
||||
webRouter.get '/project/download/zip', SecurityManager.requestCanAccessMultipleProjects, ProjectDownloadsController.downloadMultipleProjects
|
||||
webRouter.get '/Project/:Project_id/download/zip', AuthorizationMiddlewear.ensureUserCanReadProject, ProjectDownloadsController.downloadProject
|
||||
webRouter.get '/project/download/zip', AuthorizationMiddlewear.ensureUserCanReadMultipleProjects, ProjectDownloadsController.downloadMultipleProjects
|
||||
|
||||
webRouter.get '/tag', AuthenticationController.requireLogin(), TagsController.getAllTags
|
||||
webRouter.post '/tag', AuthenticationController.requireLogin(), TagsController.createTag
|
||||
@@ -174,26 +173,26 @@ module.exports = class Router
|
||||
webRouter.post "/spelling/check", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi
|
||||
webRouter.post "/spelling/learn", AuthenticationController.requireLogin(), SpellingController.proxyRequestToSpellingApi
|
||||
|
||||
webRouter.get "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.getMessages
|
||||
webRouter.post "/project/:Project_id/messages", SecurityManager.requestCanAccessProject, ChatController.sendMessage
|
||||
webRouter.get "/project/:Project_id/messages", AuthorizationMiddlewear.ensureUserCanReadProject, ChatController.getMessages
|
||||
webRouter.post "/project/:Project_id/messages", AuthorizationMiddlewear.ensureUserCanReadProject, ChatController.sendMessage
|
||||
|
||||
webRouter.get /learn(\/.*)?/, WikiController.getPage
|
||||
|
||||
webRouter.post "/project/:Project_id/references/index", SecurityManager.requestCanAccessProject, ReferencesController.index
|
||||
webRouter.post "/project/:Project_id/references/indexAll", SecurityManager.requestCanAccessProject, ReferencesController.indexAll
|
||||
webRouter.post "/project/:Project_id/references/index", AuthorizationMiddlewear.ensureUserCanReadProject, ReferencesController.index
|
||||
webRouter.post "/project/:Project_id/references/indexAll", AuthorizationMiddlewear.ensureUserCanReadProject, ReferencesController.indexAll
|
||||
|
||||
#Admin Stuff
|
||||
webRouter.get '/admin', SecurityManager.requestIsAdmin, AdminController.index
|
||||
webRouter.get '/admin/user', SecurityManager.requestIsAdmin, (req, res)-> res.redirect("/admin/register") #this gets removed by admin-panel addon
|
||||
webRouter.get '/admin/register', SecurityManager.requestIsAdmin, AdminController.registerNewUser
|
||||
webRouter.post '/admin/register', SecurityManager.requestIsAdmin, UserController.register
|
||||
webRouter.post '/admin/closeEditor', SecurityManager.requestIsAdmin, AdminController.closeEditor
|
||||
webRouter.post '/admin/dissconectAllUsers', SecurityManager.requestIsAdmin, AdminController.dissconectAllUsers
|
||||
webRouter.post '/admin/syncUserToSubscription', SecurityManager.requestIsAdmin, AdminController.syncUserToSubscription
|
||||
webRouter.post '/admin/flushProjectToTpds', SecurityManager.requestIsAdmin, AdminController.flushProjectToTpds
|
||||
webRouter.post '/admin/pollDropboxForUser', SecurityManager.requestIsAdmin, AdminController.pollDropboxForUser
|
||||
webRouter.post '/admin/messages', SecurityManager.requestIsAdmin, AdminController.createMessage
|
||||
webRouter.post '/admin/messages/clear', SecurityManager.requestIsAdmin, AdminController.clearMessages
|
||||
webRouter.get '/admin', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.index
|
||||
webRouter.get '/admin/user', AuthorizationMiddlewear.ensureUserIsSiteAdmin, (req, res)-> res.redirect("/admin/register") #this gets removed by admin-panel addon
|
||||
webRouter.get '/admin/register', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.registerNewUser
|
||||
webRouter.post '/admin/register', AuthorizationMiddlewear.ensureUserIsSiteAdmin, UserController.register
|
||||
webRouter.post '/admin/closeEditor', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.closeEditor
|
||||
webRouter.post '/admin/dissconectAllUsers', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.dissconectAllUsers
|
||||
webRouter.post '/admin/syncUserToSubscription', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.syncUserToSubscription
|
||||
webRouter.post '/admin/flushProjectToTpds', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.flushProjectToTpds
|
||||
webRouter.post '/admin/pollDropboxForUser', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.pollDropboxForUser
|
||||
webRouter.post '/admin/messages', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.createMessage
|
||||
webRouter.post '/admin/messages/clear', AuthorizationMiddlewear.ensureUserIsSiteAdmin, AdminController.clearMessages
|
||||
|
||||
apiRouter.get '/perfTest', (req,res)->
|
||||
res.send("hello")
|
||||
@@ -205,7 +204,7 @@ module.exports = class Router
|
||||
webRouter.get '/health_check', HealthCheckController.check
|
||||
webRouter.get '/health_check/redis', HealthCheckController.checkRedis
|
||||
|
||||
apiRouter.get "/status/compiler/:Project_id", SecurityManager.requestCanAccessProject, (req, res) ->
|
||||
apiRouter.get "/status/compiler/:Project_id", AuthorizationMiddlewear.ensureUserCanReadProject, (req, res) ->
|
||||
sendRes = _.once (statusCode, message)->
|
||||
res.writeHead statusCode
|
||||
res.end message
|
||||
|
||||
@@ -10,7 +10,7 @@ describe "EditorHttpController", ->
|
||||
'../Project/ProjectDeleter' : @ProjectDeleter = {}
|
||||
'../Project/ProjectGetter' : @ProjectGetter = {}
|
||||
'../User/UserGetter' : @UserGetter = {}
|
||||
"../Security/AuthorizationManager": @AuthorizationManager = {}
|
||||
"../Authorization/AuthorizationManager": @AuthorizationManager = {}
|
||||
'../Project/ProjectEditorHandler': @ProjectEditorHandler = {}
|
||||
"./EditorRealTimeController": @EditorRealTimeController = {}
|
||||
"logger-sharelatex": @logger = { log: sinon.stub(), error: sinon.stub() }
|
||||
@@ -119,7 +119,7 @@ describe "EditorHttpController", ->
|
||||
|
||||
it "should check the privilege level", ->
|
||||
@AuthorizationManager.getPrivilegeLevelForProject
|
||||
.calledWith(@project, @user)
|
||||
.calledWith(@user_id, @project_id)
|
||||
.should.equal true
|
||||
|
||||
it "should return the project model view, privilege level and protocol version", ->
|
||||
|
||||
@@ -39,8 +39,8 @@ describe "ProjectController", ->
|
||||
findOne: sinon.stub()
|
||||
@UserModel =
|
||||
findById: sinon.stub()
|
||||
@SecurityManager =
|
||||
userCanAccessProject:sinon.stub()
|
||||
@AuthorizationManager =
|
||||
getPrivilegeLevelForProject:sinon.stub()
|
||||
@EditorController =
|
||||
renameProject:sinon.stub()
|
||||
@InactiveProjectManager =
|
||||
@@ -66,7 +66,7 @@ describe "ProjectController", ->
|
||||
"../Notifications/NotificationsHandler":@NotificationsHandler
|
||||
'../../models/Project': Project:@ProjectModel
|
||||
"../../models/User":User:@UserModel
|
||||
"../../managers/SecurityManager":@SecurityManager
|
||||
"../Authorization/AuthorizationManager":@AuthorizationManager
|
||||
"../InactiveData/InactiveProjectManager":@InactiveProjectManager
|
||||
"./ProjectUpdateHandler":@ProjectUpdateHandler
|
||||
"../ReferencesSearch/ReferencesSearchHandler": @ReferencesSearchHandler
|
||||
@@ -299,7 +299,7 @@ describe "ProjectController", ->
|
||||
@ProjectModel.findOne.callsArgWith 1, null, @project
|
||||
@UserModel.findById.callsArgWith(1, null, @user)
|
||||
@SubscriptionLocator.getUsersSubscription.callsArgWith(1, null, {})
|
||||
@SecurityManager.userCanAccessProject.callsArgWith 2, true, "owner"
|
||||
@AuthorizationManager.getPrivilegeLevelForProject.callsArgWith 2, null, true, "owner"
|
||||
@ProjectDeleter.unmarkAsDeletedByExternalSource = sinon.stub()
|
||||
@InactiveProjectManager.reactivateProjectIfRequired.callsArgWith(1)
|
||||
@ProjectUpdateHandler.markAsOpened.callsArgWith(1)
|
||||
@@ -332,7 +332,7 @@ describe "ProjectController", ->
|
||||
@ProjectController.loadEditor @req, @res
|
||||
|
||||
it "should not render the page if the project can not be accessed", (done)->
|
||||
@SecurityManager.userCanAccessProject = sinon.stub().callsArgWith 2, false
|
||||
@AuthorizationManager.getPrivilegeLevelForProject = sinon.stub().callsArgWith 2, null, false
|
||||
@res.sendStatus = (resCode, opts)=>
|
||||
resCode.should.equal 401
|
||||
done()
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
SandboxedModule = require('sandboxed-module')
|
||||
sinon = require('sinon')
|
||||
require('chai').should()
|
||||
modulePath = require('path').join __dirname, '../../../../app/js/Features/Security/AuthorizationManager'
|
||||
MockClient = require "../helpers/MockClient"
|
||||
|
||||
describe "AuthorizationManager", ->
|
||||
beforeEach ->
|
||||
@client = new MockClient()
|
||||
@AuthorizationManager = SandboxedModule.require modulePath, requires:
|
||||
'../../managers/SecurityManager':{}
|
||||
|
||||
describe "ensureClientCanViewProject", ->
|
||||
beforeEach ->
|
||||
@client.set("project_id", "project-id")
|
||||
|
||||
it "should let the request through for a readOnly privilege", (done) ->
|
||||
@client.set("privilege_level", "readOnly")
|
||||
@AuthorizationManager.ensureClientCanViewProject @client, done
|
||||
|
||||
it "should let the request through for a readAndWrite privilege", (done) ->
|
||||
@client.set("privilege_level", "readAndWrite")
|
||||
@AuthorizationManager.ensureClientCanViewProject @client, done
|
||||
|
||||
it "should let the request through for a owner privilege", (done) ->
|
||||
@client.set("privilege_level", "owner")
|
||||
@AuthorizationManager.ensureClientCanViewProject @client, done
|
||||
|
||||
it "should ignore an empty privilege", ->
|
||||
@AuthorizationManager.ensureClientCanViewProject @client, () ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
describe "ensureClientCanEditProject", ->
|
||||
beforeEach ->
|
||||
@client.set("project_id", "project-id")
|
||||
|
||||
it "should ignore a readOnly privilege", ->
|
||||
@client.set("privilege_level", "readOnly")
|
||||
@AuthorizationManager.ensureClientCanEditProject @client, () ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
it "should let the request through for a readAndWrite privilege", (done) ->
|
||||
@client.set("privilege_level", "readAndWrite")
|
||||
@AuthorizationManager.ensureClientCanEditProject @client, done
|
||||
|
||||
it "should let the request through for a owner privilege", (done) ->
|
||||
@client.set("privilege_level", "owner")
|
||||
@AuthorizationManager.ensureClientCanEditProject @client, done
|
||||
|
||||
it "should ignore an empty privilege", ->
|
||||
@AuthorizationManager.ensureClientCanEditProject @client, () ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
describe "ensureClientCanAdminProject", ->
|
||||
beforeEach ->
|
||||
@client.set("project_id", "project-id")
|
||||
|
||||
it "should ignore a readOnly privilege", ->
|
||||
@client.set("privilege_level", "readOnly")
|
||||
@AuthorizationManager.ensureClientCanAdminProject @client, () ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
it "should ignore a readAndWrite privilege", ->
|
||||
@client.set("privilege_level", "readAndWrite")
|
||||
@AuthorizationManager.ensureClientCanAdminProject @client, () ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
it "should let the request through for a owner privilege", (done) ->
|
||||
@client.set("privilege_level", "owner")
|
||||
@AuthorizationManager.ensureClientCanAdminProject @client, done
|
||||
|
||||
it "should ignore an empty privilege", ->
|
||||
@AuthorizationManager.ensureClientCanAdminProject @client, () ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
describe "ensureClientHasPrivilegeLevelForProject", ->
|
||||
it "should ignore callback if privilege_level is not set", ->
|
||||
@client.set("project_id", "project-id")
|
||||
@AuthorizationManager.ensureClientHasPrivilegeLevelForProject @client,
|
||||
["owner"], (error, project_id) ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
it "should ignore callback if project_id is not set", ->
|
||||
@client.set("privilege_level", "owner")
|
||||
@AuthorizationManager.ensureClientHasPrivilegeLevelForProject @client,
|
||||
["owner"], (error, project_id) ->
|
||||
throw new Error("Should not be called")
|
||||
|
||||
it "should return the project_id", (done) ->
|
||||
@client.set("privilege_level", "owner")
|
||||
@client.set("project_id", "project-id-123")
|
||||
@AuthorizationManager.ensureClientHasPrivilegeLevelForProject @client,
|
||||
["owner"], (error, project_id) ->
|
||||
project_id.should.equal "project-id-123"
|
||||
done()
|
||||
|
||||
@@ -23,8 +23,8 @@ describe "SubscriptionController sanboxed", ->
|
||||
@user = {email:"tom@yahoo.com"}
|
||||
@activeRecurlySubscription = mockSubscriptions["subscription-123-active"]
|
||||
|
||||
@SecurityManager =
|
||||
getCurrentUser: sinon.stub().callsArgWith(1, null, @user)
|
||||
@AuthenticationController =
|
||||
getLoggedInUser: sinon.stub().callsArgWith(1, null, @user)
|
||||
@SubscriptionHandler =
|
||||
createSubscription: sinon.stub().callsArgWith(3)
|
||||
updateSubscription: sinon.stub().callsArgWith(3)
|
||||
@@ -61,7 +61,7 @@ describe "SubscriptionController sanboxed", ->
|
||||
@SubscriptionDomainHandler =
|
||||
getDomainLicencePage:sinon.stub()
|
||||
@SubscriptionController = SandboxedModule.require modulePath, requires:
|
||||
'../../managers/SecurityManager': @SecurityManager
|
||||
'../Authentication/AuthenticationController': @AuthenticationController
|
||||
'./SubscriptionHandler': @SubscriptionHandler
|
||||
"./PlansLocator": @PlansLocator
|
||||
'./SubscriptionViewModelBuilder': @SubscriptionViewModelBuilder
|
||||
|
||||
Reference in New Issue
Block a user