TokenAccessController.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /* eslint-disable
  2. camelcase,
  3. max-len,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS102: Remove unnecessary code created because of implicit returns
  10. * DS207: Consider shorter variations of null checks
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. let TokenAccessController
  14. const ProjectController = require('../Project/ProjectController')
  15. const AuthenticationController = require('../Authentication/AuthenticationController')
  16. const TokenAccessHandler = require('./TokenAccessHandler')
  17. const Errors = require('../Errors/Errors')
  18. const logger = require('logger-sharelatex')
  19. const settings = require('settings-sharelatex')
  20. module.exports = TokenAccessController = {
  21. _loadEditor(projectId, req, res, next) {
  22. req.params.Project_id = projectId.toString()
  23. return ProjectController.loadEditor(req, res, next)
  24. },
  25. _tryHigherAccess(token, userId, req, res, next) {
  26. return TokenAccessHandler.findProjectWithHigherAccess(
  27. token,
  28. userId,
  29. function(err, project) {
  30. if (err != null) {
  31. logger.warn(
  32. { err, token, userId },
  33. '[TokenAccess] error finding project with higher access'
  34. )
  35. return next(err)
  36. }
  37. if (project == null) {
  38. logger.log(
  39. { token, userId },
  40. '[TokenAccess] no project with higher access found for this user and token'
  41. )
  42. return next(new Errors.NotFoundError())
  43. }
  44. logger.log(
  45. { token, userId, projectId: project._id },
  46. '[TokenAccess] user has higher access to project, redirecting'
  47. )
  48. return res.redirect(302, `/project/${project._id}`)
  49. }
  50. )
  51. },
  52. readAndWriteToken(req, res, next) {
  53. const userId = AuthenticationController.getLoggedInUserId(req)
  54. const token = req.params['read_and_write_token']
  55. logger.log(
  56. { userId, token },
  57. '[TokenAccess] requesting read-and-write token access'
  58. )
  59. return TokenAccessHandler.findProjectWithReadAndWriteToken(token, function(
  60. err,
  61. project,
  62. projectExists
  63. ) {
  64. if (err != null) {
  65. logger.warn(
  66. { err, token, userId },
  67. '[TokenAccess] error getting project by readAndWrite token'
  68. )
  69. return next(err)
  70. }
  71. if (!projectExists && settings.overleaf) {
  72. logger.log(
  73. { token, userId },
  74. '[TokenAccess] no project found for this token'
  75. )
  76. return TokenAccessController._handleV1Project(
  77. token,
  78. userId,
  79. `/${token}`,
  80. res,
  81. next
  82. )
  83. } else if (project == null) {
  84. logger.log(
  85. { token, userId },
  86. '[TokenAccess] no token-based project found for readAndWrite token'
  87. )
  88. if (userId == null) {
  89. logger.log(
  90. { token },
  91. '[TokenAccess] No project found with read-write token, anonymous user, deny'
  92. )
  93. return next(new Errors.NotFoundError())
  94. }
  95. return TokenAccessController._tryHigherAccess(
  96. token,
  97. userId,
  98. req,
  99. res,
  100. next
  101. )
  102. } else {
  103. if (userId == null) {
  104. if (TokenAccessHandler.ANONYMOUS_READ_AND_WRITE_ENABLED) {
  105. logger.log(
  106. { token, projectId: project._id },
  107. '[TokenAccess] allow anonymous read-and-write token access'
  108. )
  109. TokenAccessHandler.grantSessionTokenAccess(req, project._id, token)
  110. req._anonymousAccessToken = token
  111. return TokenAccessController._loadEditor(
  112. project._id,
  113. req,
  114. res,
  115. next
  116. )
  117. } else {
  118. logger.log(
  119. { token, projectId: project._id },
  120. '[TokenAccess] deny anonymous read-and-write token access'
  121. )
  122. AuthenticationController.setRedirectInSession(req)
  123. return res.redirect('/restricted')
  124. }
  125. }
  126. if (project.owner_ref.toString() === userId) {
  127. logger.log(
  128. { userId, projectId: project._id },
  129. '[TokenAccess] user is already project owner'
  130. )
  131. return TokenAccessController._loadEditor(project._id, req, res, next)
  132. }
  133. logger.log(
  134. { userId, projectId: project._id },
  135. '[TokenAccess] adding user to project with readAndWrite token'
  136. )
  137. return TokenAccessHandler.addReadAndWriteUserToProject(
  138. userId,
  139. project._id,
  140. function(err) {
  141. if (err != null) {
  142. logger.warn(
  143. { err, token, userId, projectId: project._id },
  144. '[TokenAccess] error adding user to project with readAndWrite token'
  145. )
  146. return next(err)
  147. }
  148. return TokenAccessController._loadEditor(
  149. project._id,
  150. req,
  151. res,
  152. next
  153. )
  154. }
  155. )
  156. }
  157. })
  158. },
  159. readOnlyToken(req, res, next) {
  160. const userId = AuthenticationController.getLoggedInUserId(req)
  161. const token = req.params['read_only_token']
  162. logger.log(
  163. { userId, token },
  164. '[TokenAccess] requesting read-only token access'
  165. )
  166. return TokenAccessHandler.getV1DocPublishedInfo(token, function(
  167. err,
  168. doc_published_info
  169. ) {
  170. if (err != null) {
  171. return next(err)
  172. }
  173. if (doc_published_info.allow === false) {
  174. return res.redirect(doc_published_info.published_path)
  175. }
  176. return TokenAccessHandler.findProjectWithReadOnlyToken(token, function(
  177. err,
  178. project,
  179. projectExists
  180. ) {
  181. if (err != null) {
  182. logger.warn(
  183. { err, token, userId },
  184. '[TokenAccess] error getting project by readOnly token'
  185. )
  186. return next(err)
  187. }
  188. if (!projectExists && settings.overleaf) {
  189. logger.log(
  190. { token, userId },
  191. '[TokenAccess] no project found for this token'
  192. )
  193. return TokenAccessController._handleV1Project(
  194. token,
  195. userId,
  196. `/read/${token}`,
  197. res,
  198. next
  199. )
  200. } else if (project == null) {
  201. logger.log(
  202. { token, userId },
  203. '[TokenAccess] no project found for readOnly token'
  204. )
  205. if (userId == null) {
  206. logger.log(
  207. { token },
  208. '[TokenAccess] No project found with readOnly token, anonymous user, deny'
  209. )
  210. return next(new Errors.NotFoundError())
  211. }
  212. return TokenAccessController._tryHigherAccess(
  213. token,
  214. userId,
  215. req,
  216. res,
  217. next
  218. )
  219. } else {
  220. if (userId == null) {
  221. logger.log(
  222. { userId, projectId: project._id },
  223. '[TokenAccess] adding anonymous user to project with readOnly token'
  224. )
  225. TokenAccessHandler.grantSessionTokenAccess(req, project._id, token)
  226. req._anonymousAccessToken = token
  227. return TokenAccessController._loadEditor(
  228. project._id,
  229. req,
  230. res,
  231. next
  232. )
  233. } else {
  234. if (project.owner_ref.toString() === userId) {
  235. logger.log(
  236. { userId, projectId: project._id },
  237. '[TokenAccess] user is already project owner'
  238. )
  239. return TokenAccessController._loadEditor(
  240. project._id,
  241. req,
  242. res,
  243. next
  244. )
  245. }
  246. logger.log(
  247. { userId, projectId: project._id },
  248. '[TokenAccess] adding user to project with readOnly token'
  249. )
  250. return TokenAccessHandler.addReadOnlyUserToProject(
  251. userId,
  252. project._id,
  253. function(err) {
  254. if (err != null) {
  255. logger.warn(
  256. { err, token, userId, projectId: project._id },
  257. '[TokenAccess] error adding user to project with readAndWrite token'
  258. )
  259. return next(err)
  260. }
  261. return TokenAccessController._loadEditor(
  262. project._id,
  263. req,
  264. res,
  265. next
  266. )
  267. }
  268. )
  269. }
  270. }
  271. })
  272. })
  273. },
  274. _handleV1Project(token, userId, redirectPath, res, next) {
  275. if (userId == null) {
  276. return res.render('project/v2-import', { loginRedirect: redirectPath })
  277. } else {
  278. return TokenAccessHandler.getV1DocInfo(token, userId, function(
  279. err,
  280. doc_info
  281. ) {
  282. if (err != null) {
  283. return next(err)
  284. }
  285. if (!doc_info.exists) {
  286. return next(new Errors.NotFoundError())
  287. }
  288. if (doc_info.exported) {
  289. return next(new Errors.NotFoundError())
  290. }
  291. return res.render('project/v2-import', {
  292. projectId: token,
  293. hasOwner: doc_info.has_owner,
  294. name: doc_info.name || 'Untitled',
  295. hasAssignment: doc_info.has_assignment,
  296. brandInfo: doc_info.brand_info
  297. })
  298. })
  299. }
  300. }
  301. }