SecurityManager.coffee 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. AuthenticationController._redirectToLoginOrRegisterPage(req, res)
  54. if arguments.length > 1
  55. options =
  56. allow_auth_token: false
  57. doRequest.apply(this, arguments)
  58. else
  59. options = req
  60. return doRequest
  61. requestCanModifyProject : (req, res, next)->
  62. getRequestUserAndProject req, res, {}, (err, user, project)=>
  63. userCanModifyProject user, project, (canModify)->
  64. if canModify
  65. next()
  66. else
  67. logger.log "user_id: #{user?._id} email: #{user?.email} can not modify project redirecting to restricted page"
  68. res.redirect('/restricted')
  69. userCanModifyProject : userCanModifyProject = (user, project, callback)->
  70. if !user? or !project?
  71. callback false
  72. else if userIsOwner user, project
  73. callback true
  74. else if userIsCollaberator user, project
  75. callback true
  76. else if project.publicAccesLevel == "readAndWrite"
  77. callback true
  78. else if user.isAdmin
  79. callback true
  80. else
  81. callback false
  82. requestIsOwner : (req, res, next)->
  83. getRequestUserAndProject req, res, {}, (err, user, project)->
  84. if !user?
  85. return res.redirect('/restricted')
  86. else if userIsOwner user, project || user.isAdmin
  87. next()
  88. else
  89. logger.log user_id: user?._id, email: user?.email, "user is not owner of project redirecting to restricted page"
  90. res.redirect('/restricted')
  91. requestIsAdmin : isAdmin = (req, res, next)->
  92. logger.log "checking if user is admin"
  93. user = req.session.user
  94. if(user? && user.isAdmin)
  95. logger.log user: user, "User is admin"
  96. next()
  97. else
  98. res.redirect('/restricted')
  99. logger.log user:user, "is not admin redirecting to restricted page"
  100. userCanAccessProject : userCanAccessProject = (user, project, callback)=>
  101. if !user?
  102. user = {_id:'anonymous-user'}
  103. if !project?
  104. callback false
  105. logger.log user:user, project:project, "Checking if can access"
  106. if userIsOwner user, project
  107. callback true, "owner"
  108. else if userIsCollaberator user, project
  109. callback true, "readAndWrite"
  110. else if userIsReadOnly user, project
  111. callback true, "readOnly"
  112. else if user.isAdmin
  113. logger.log user:user, project:project, "user is admin and can access project"
  114. callback true, "owner"
  115. else if project.publicAccesLevel == "readAndWrite"
  116. logger.log user:user, project:project, "project is a public read and write project"
  117. callback true, "readAndWrite"
  118. else if project.publicAccesLevel == "readOnly"
  119. logger.log user:user, project:project, "project is a public read only project"
  120. callback true, "readOnly"
  121. else
  122. metrics.inc "security.denied"
  123. logger.log user:user, project:project, "Security denied - user can not enter project"
  124. callback false
  125. userIsOwner : userIsOwner = (user, project)->
  126. if !user?
  127. return false
  128. else
  129. userId = user._id+''
  130. ownerRef = getProjectIdFromRef(project.owner_ref)
  131. if userId == ownerRef
  132. true
  133. else
  134. false
  135. userIsCollaberator : userIsCollaberator = (user, project)->
  136. if !user?
  137. return false
  138. else
  139. userId = user._id+''
  140. result = false
  141. _.each project.collaberator_refs, (colabRef)->
  142. colabRef = getProjectIdFromRef(colabRef)
  143. if colabRef == userId
  144. result = true
  145. return result
  146. userIsReadOnly : userIsReadOnly = (user, project)->
  147. if !user?
  148. return false
  149. else
  150. userId = user._id+''
  151. result = false
  152. _.each project.readOnly_refs, (readOnlyRef)->
  153. readOnlyRef = getProjectIdFromRef(readOnlyRef)
  154. if readOnlyRef == userId
  155. result = true
  156. return result
  157. getRequestUserAndProject = (req, res, options, callback)->
  158. project_id = req.params.Project_id
  159. if !project_id?
  160. logger.log project_id:project_id, options:options, url:req?.url, "no project_id trying to getRequestUserAndProject"
  161. return res.send 422
  162. Project.findById project_id, 'name owner_ref readOnly_refs collaberator_refs publicAccesLevel archived', (err, project)=>
  163. if err?
  164. logger.err err:err, "error getting project for security check"
  165. return callback err
  166. AuthenticationController.getLoggedInUser req, options, (err, user)=>
  167. if err?
  168. logger.err err:err, "error getting last logged in user for security check"
  169. callback err, user, project
  170. getProjectIdFromRef = (ref)->
  171. if !ref?
  172. return null
  173. else if ref._id?
  174. return ref._id+''
  175. else
  176. return ref+''