SecurityManager.coffee 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. logger = require('logger-sharelatex')
  2. crypto = require 'crypto'
  3. Assert = require 'assert'
  4. Settings = require 'settings-sharelatex'
  5. User = require('../models/User').User
  6. Project = require('../models/Project').Project
  7. ErrorController = require("../Features/Errors/ErrorController")
  8. AuthenticationController = require("../Features/Authentication/AuthenticationController")
  9. _ = require('underscore')
  10. metrics = require('../infrastructure/Metrics')
  11. querystring = require('querystring')
  12. async = require "async"
  13. module.exports = SecurityManager =
  14. restricted : (req, res, next)->
  15. if req.session.user?
  16. res.render 'user/restricted',
  17. title:'restricted'
  18. else
  19. logger.log "user not logged in and trying to access #{req.url}, being redirected to login"
  20. res.redirect '/register'
  21. getCurrentUser: (req, callback) ->
  22. if req.session.user?
  23. User.findById req.session.user._id, callback
  24. else
  25. callback null, null
  26. requestCanAccessMultipleProjects: (req, res, next) ->
  27. project_ids = req.query.project_ids?.split(",")
  28. jobs = []
  29. for project_id in project_ids or []
  30. do (project_id) ->
  31. jobs.push (callback) ->
  32. # This is a bit hacky - better to have an abstracted method
  33. # that we can pass project_id to, but this whole file needs
  34. # a serious refactor ATM.
  35. req.params.Project_id = project_id
  36. SecurityManager.requestCanAccessProject req, res, (error) ->
  37. delete req.params.Project_id
  38. callback(error)
  39. async.series jobs, next
  40. requestCanAccessProject : (req, res, next)->
  41. doRequest = (req, res, next) ->
  42. getRequestUserAndProject req, res, {allow_auth_token: options?.allow_auth_token}, (err, user, project)->
  43. if !project? or project.archived
  44. return ErrorController.notFound(req, res, next)
  45. userCanAccessProject user, project, (canAccess, permissionLevel)->
  46. if canAccess
  47. next()
  48. else if user?
  49. logger.log "user_id: #{user._id} email: #{user.email} trying to access restricted page #{req.path}"
  50. res.redirect('/restricted')
  51. else
  52. logger.log "user not logged in and trying to access #{req.url}, being redirected to login"
  53. req.query.redir = req._parsedUrl.pathname
  54. url = "/register?#{querystring.stringify(req.query)}"
  55. res.redirect url
  56. email = "not logged in user"
  57. if arguments.length > 1
  58. options =
  59. allow_auth_token: false
  60. doRequest.apply(this, arguments)
  61. else
  62. options = req
  63. return doRequest
  64. requestCanModifyProject : (req, res, next)->
  65. getRequestUserAndProject req, res, {}, (err, user, project)=>
  66. userCanModifyProject user, project, (canModify)->
  67. if canModify
  68. next()
  69. else
  70. logger.log "user_id: #{user._id} email: #{user.email} can not modify project redirecting to restricted page"
  71. res.redirect('/restricted')
  72. userCanModifyProject : userCanModifyProject = (user, project, callback)->
  73. if !user? or !project?
  74. callback false
  75. else if userIsOwner user, project
  76. callback true
  77. else if userIsCollaberator user, project
  78. callback true
  79. else if project.publicAccesLevel == "readAndWrite"
  80. callback true
  81. else if user.isAdmin
  82. callback true
  83. else
  84. callback false
  85. requestIsOwner : (req, res, next)->
  86. getRequestUserAndProject req, res, {}, (err, user, project)->
  87. if userIsOwner user, project || user.isAdmin
  88. next()
  89. else
  90. logger.log user_id: user?._id, email: user?.email, "user is not owner of project redirecting to restricted page"
  91. res.redirect('/restricted')
  92. requestIsAdmin : isAdmin = (req, res, next)->
  93. logger.log "checking if user is admin"
  94. user = req.session.user
  95. if(user? && user.isAdmin)
  96. logger.log user: user, "User is admin"
  97. next()
  98. else
  99. res.redirect('/restricted')
  100. logger.log user:user, "is not admin redirecting to restricted page"
  101. userCanAccessProject : userCanAccessProject = (user, project, callback)=>
  102. if !user?
  103. user = {_id:'anonymous-user'}
  104. if !project?
  105. callback false
  106. logger.log user:user, project:project, "Checking if can access"
  107. if userIsOwner user, project
  108. callback true, "owner"
  109. else if userIsCollaberator user, project
  110. callback true, "readAndWrite"
  111. else if userIsReadOnly user, project
  112. callback true, "readOnly"
  113. else if user.isAdmin
  114. logger.log user:user, project:project, "user is admin and can access project"
  115. callback true, "owner"
  116. else if project.publicAccesLevel == "readAndWrite"
  117. logger.log user:user, project:project, "project is a public read and write project"
  118. callback true, "readAndWrite"
  119. else if project.publicAccesLevel == "readOnly"
  120. logger.log user:user, project:project, "project is a public read only project"
  121. callback true, "readOnly"
  122. else
  123. metrics.inc "security.denied"
  124. logger.log user:user, project:project, "Security denied - user can not enter project"
  125. callback false
  126. userIsOwner : userIsOwner = (user, project)->
  127. if !user?
  128. return false
  129. else
  130. userId = user._id+''
  131. ownerRef = getProjectIdFromRef(project.owner_ref)
  132. if userId == ownerRef
  133. true
  134. else
  135. false
  136. userIsCollaberator : userIsCollaberator = (user, project)->
  137. if !user?
  138. return false
  139. else
  140. userId = user._id+''
  141. result = false
  142. _.each project.collaberator_refs, (colabRef)->
  143. colabRef = getProjectIdFromRef(colabRef)
  144. if colabRef == userId
  145. result = true
  146. return result
  147. userIsReadOnly : userIsReadOnly = (user, project)->
  148. if !user?
  149. return false
  150. else
  151. userId = user._id+''
  152. result = false
  153. _.each project.readOnly_refs, (readOnlyRef)->
  154. readOnlyRef = getProjectIdFromRef(readOnlyRef)
  155. if readOnlyRef == userId
  156. result = true
  157. return result
  158. getRequestUserAndProject = (req, res, options, callback)->
  159. project_id = req.params.Project_id
  160. Project.findById project_id, 'name owner_ref readOnly_refs collaberator_refs publicAccesLevel archived', (err, project)=>
  161. if err?
  162. logger.err err:err, "error getting project for security check"
  163. return callback err
  164. AuthenticationController.getLoggedInUser req, options, (err, user)=>
  165. if err?
  166. logger.err err:err, "error getting last logged in user for security check"
  167. callback err, user, project
  168. getProjectIdFromRef = (ref)->
  169. if !ref?
  170. return null
  171. else if ref._id?
  172. return ref._id+''
  173. else
  174. return ref+''