AuthorizationMiddleware.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. let AuthorizationMiddleware
  2. const AuthorizationManager = require('./AuthorizationManager')
  3. const async = require('async')
  4. const logger = require('logger-sharelatex')
  5. const { ObjectId } = require('mongodb')
  6. const Errors = require('../Errors/Errors')
  7. const HttpErrorHandler = require('../Errors/HttpErrorHandler')
  8. const AuthenticationController = require('../Authentication/AuthenticationController')
  9. const TokenAccessHandler = require('../TokenAccess/TokenAccessHandler')
  10. module.exports = AuthorizationMiddleware = {
  11. ensureUserCanReadMultipleProjects(req, res, next) {
  12. const projectIds = (req.query.project_ids || '').split(',')
  13. AuthorizationMiddleware._getUserId(req, function (error, userId) {
  14. if (error) {
  15. return next(error)
  16. }
  17. // Remove the projects we have access to. Note rejectSeries doesn't use
  18. // errors in callbacks
  19. async.rejectSeries(
  20. projectIds,
  21. function (projectId, cb) {
  22. const token = TokenAccessHandler.getRequestToken(req, projectId)
  23. AuthorizationManager.canUserReadProject(
  24. userId,
  25. projectId,
  26. token,
  27. function (error, canRead) {
  28. if (error) {
  29. return next(error)
  30. }
  31. cb(canRead)
  32. }
  33. )
  34. },
  35. function (unauthorizedProjectIds) {
  36. if (unauthorizedProjectIds.length > 0) {
  37. return AuthorizationMiddleware.redirectToRestricted(req, res, next)
  38. }
  39. next()
  40. }
  41. )
  42. })
  43. },
  44. blockRestrictedUserFromProject(req, res, next) {
  45. AuthorizationMiddleware._getUserAndProjectId(
  46. req,
  47. function (error, userId, projectId) {
  48. if (error) {
  49. return next(error)
  50. }
  51. const token = TokenAccessHandler.getRequestToken(req, projectId)
  52. AuthorizationManager.isRestrictedUserForProject(
  53. userId,
  54. projectId,
  55. token,
  56. (err, isRestrictedUser) => {
  57. if (err) {
  58. return next(err)
  59. }
  60. if (isRestrictedUser) {
  61. return res.sendStatus(403)
  62. }
  63. next()
  64. }
  65. )
  66. }
  67. )
  68. },
  69. ensureUserCanReadProject(req, res, next) {
  70. AuthorizationMiddleware._getUserAndProjectId(
  71. req,
  72. function (error, userId, projectId) {
  73. if (error) {
  74. return next(error)
  75. }
  76. const token = TokenAccessHandler.getRequestToken(req, projectId)
  77. AuthorizationManager.canUserReadProject(
  78. userId,
  79. projectId,
  80. token,
  81. function (error, canRead) {
  82. if (error) {
  83. return next(error)
  84. }
  85. if (canRead) {
  86. logger.log(
  87. { userId, projectId },
  88. 'allowing user read access to project'
  89. )
  90. return next()
  91. }
  92. logger.log(
  93. { userId, projectId },
  94. 'denying user read access to project'
  95. )
  96. HttpErrorHandler.forbidden(req, res)
  97. }
  98. )
  99. }
  100. )
  101. },
  102. ensureUserCanWriteProjectSettings(req, res, next) {
  103. AuthorizationMiddleware._getUserAndProjectId(
  104. req,
  105. function (error, userId, projectId) {
  106. if (error) {
  107. return next(error)
  108. }
  109. const token = TokenAccessHandler.getRequestToken(req, projectId)
  110. AuthorizationManager.canUserWriteProjectSettings(
  111. userId,
  112. projectId,
  113. token,
  114. function (error, canWrite) {
  115. if (error) {
  116. return next(error)
  117. }
  118. if (canWrite) {
  119. logger.log(
  120. { userId, projectId },
  121. 'allowing user write access to project settings'
  122. )
  123. return next()
  124. }
  125. logger.log(
  126. { userId, projectId },
  127. 'denying user write access to project settings'
  128. )
  129. HttpErrorHandler.forbidden(req, res)
  130. }
  131. )
  132. }
  133. )
  134. },
  135. ensureUserCanWriteProjectContent(req, res, next) {
  136. AuthorizationMiddleware._getUserAndProjectId(
  137. req,
  138. function (error, userId, projectId) {
  139. if (error) {
  140. return next(error)
  141. }
  142. const token = TokenAccessHandler.getRequestToken(req, projectId)
  143. AuthorizationManager.canUserWriteProjectContent(
  144. userId,
  145. projectId,
  146. token,
  147. function (error, canWrite) {
  148. if (error) {
  149. return next(error)
  150. }
  151. if (canWrite) {
  152. logger.log(
  153. { userId, projectId },
  154. 'allowing user write access to project content'
  155. )
  156. return next()
  157. }
  158. logger.log(
  159. { userId, projectId },
  160. 'denying user write access to project settings'
  161. )
  162. HttpErrorHandler.forbidden(req, res)
  163. }
  164. )
  165. }
  166. )
  167. },
  168. ensureUserCanAdminProject(req, res, next) {
  169. AuthorizationMiddleware._getUserAndProjectId(
  170. req,
  171. function (error, userId, projectId) {
  172. if (error) {
  173. return next(error)
  174. }
  175. const token = TokenAccessHandler.getRequestToken(req, projectId)
  176. AuthorizationManager.canUserAdminProject(
  177. userId,
  178. projectId,
  179. token,
  180. function (error, canAdmin) {
  181. if (error) {
  182. return next(error)
  183. }
  184. if (canAdmin) {
  185. logger.log(
  186. { userId, projectId },
  187. 'allowing user admin access to project'
  188. )
  189. return next()
  190. }
  191. logger.log(
  192. { userId, projectId },
  193. 'denying user admin access to project'
  194. )
  195. HttpErrorHandler.forbidden(req, res)
  196. }
  197. )
  198. }
  199. )
  200. },
  201. ensureUserIsSiteAdmin(req, res, next) {
  202. AuthorizationMiddleware._getUserId(req, function (error, userId) {
  203. if (error) {
  204. return next(error)
  205. }
  206. AuthorizationManager.isUserSiteAdmin(userId, function (error, isAdmin) {
  207. if (error) {
  208. return next(error)
  209. }
  210. if (isAdmin) {
  211. logger.log({ userId }, 'allowing user admin access to site')
  212. return next()
  213. }
  214. logger.log({ userId }, 'denying user admin access to site')
  215. AuthorizationMiddleware.redirectToRestricted(req, res, next)
  216. })
  217. })
  218. },
  219. _getUserAndProjectId(req, callback) {
  220. const projectId = req.params.project_id || req.params.Project_id
  221. if (!projectId) {
  222. return callback(new Error('Expected project_id in request parameters'))
  223. }
  224. if (!ObjectId.isValid(projectId)) {
  225. return callback(
  226. new Errors.NotFoundError(`invalid projectId: ${projectId}`)
  227. )
  228. }
  229. AuthorizationMiddleware._getUserId(req, function (error, userId) {
  230. if (error) {
  231. return callback(error)
  232. }
  233. callback(null, userId, projectId)
  234. })
  235. },
  236. _getUserId(req, callback) {
  237. const userId =
  238. AuthenticationController.getLoggedInUserId(req) ||
  239. (req.oauth_user && req.oauth_user._id) ||
  240. null
  241. callback(null, userId)
  242. },
  243. redirectToRestricted(req, res, next) {
  244. // TODO: move this to throwing ForbiddenError
  245. res.redirect(
  246. `/restricted?from=${encodeURIComponent(res.locals.currentUrl)}`
  247. )
  248. },
  249. restricted(req, res, next) {
  250. if (AuthenticationController.isUserLoggedIn(req)) {
  251. return res.render('user/restricted', { title: 'restricted' })
  252. }
  253. const { from } = req.query
  254. logger.log({ from }, 'redirecting to login')
  255. if (from) {
  256. AuthenticationController.setRedirectInSession(req, from)
  257. }
  258. res.redirect('/login')
  259. },
  260. }