router.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. const AdminController = require('./Features/ServerAdmin/AdminController')
  2. const ErrorController = require('./Features/Errors/ErrorController')
  3. const ProjectController = require('./Features/Project/ProjectController')
  4. const ProjectApiController = require('./Features/Project/ProjectApiController')
  5. const SpellingController = require('./Features/Spelling/SpellingController')
  6. const EditorRouter = require('./Features/Editor/EditorRouter')
  7. const Settings = require('@overleaf/settings')
  8. const TpdsController = require('./Features/ThirdPartyDataStore/TpdsController')
  9. const SubscriptionRouter = require('./Features/Subscription/SubscriptionRouter')
  10. const UploadsRouter = require('./Features/Uploads/UploadsRouter')
  11. const metrics = require('@overleaf/metrics')
  12. const ReferalController = require('./Features/Referal/ReferalController')
  13. const AuthenticationController = require('./Features/Authentication/AuthenticationController')
  14. const SessionManager = require('./Features/Authentication/SessionManager')
  15. const TagsController = require('./Features/Tags/TagsController')
  16. const NotificationsController = require('./Features/Notifications/NotificationsController')
  17. const CollaboratorsRouter = require('./Features/Collaborators/CollaboratorsRouter')
  18. const UserInfoController = require('./Features/User/UserInfoController')
  19. const UserController = require('./Features/User/UserController')
  20. const UserEmailsController = require('./Features/User/UserEmailsController')
  21. const UserPagesController = require('./Features/User/UserPagesController')
  22. const DocumentController = require('./Features/Documents/DocumentController')
  23. const CompileManager = require('./Features/Compile/CompileManager')
  24. const CompileController = require('./Features/Compile/CompileController')
  25. const ClsiCookieManager = require('./Features/Compile/ClsiCookieManager')(
  26. Settings.apis.clsi != null ? Settings.apis.clsi.backendGroupName : undefined
  27. )
  28. const HealthCheckController = require('./Features/HealthCheck/HealthCheckController')
  29. const ProjectDownloadsController = require('./Features/Downloads/ProjectDownloadsController')
  30. const FileStoreController = require('./Features/FileStore/FileStoreController')
  31. const HistoryController = require('./Features/History/HistoryController')
  32. const ExportsController = require('./Features/Exports/ExportsController')
  33. const PasswordResetRouter = require('./Features/PasswordReset/PasswordResetRouter')
  34. const StaticPagesRouter = require('./Features/StaticPages/StaticPagesRouter')
  35. const ChatController = require('./Features/Chat/ChatController')
  36. const Modules = require('./infrastructure/Modules')
  37. const RateLimiterMiddleware = require('./Features/Security/RateLimiterMiddleware')
  38. const InactiveProjectController = require('./Features/InactiveData/InactiveProjectController')
  39. const ContactRouter = require('./Features/Contacts/ContactRouter')
  40. const ReferencesController = require('./Features/References/ReferencesController')
  41. const AuthorizationMiddleware = require('./Features/Authorization/AuthorizationMiddleware')
  42. const BetaProgramController = require('./Features/BetaProgram/BetaProgramController')
  43. const AnalyticsRouter = require('./Features/Analytics/AnalyticsRouter')
  44. const MetaController = require('./Features/Metadata/MetaController')
  45. const TokenAccessController = require('./Features/TokenAccess/TokenAccessController')
  46. const Features = require('./infrastructure/Features')
  47. const LinkedFilesRouter = require('./Features/LinkedFiles/LinkedFilesRouter')
  48. const TemplatesRouter = require('./Features/Templates/TemplatesRouter')
  49. const InstitutionsController = require('./Features/Institutions/InstitutionsController')
  50. const UserMembershipRouter = require('./Features/UserMembership/UserMembershipRouter')
  51. const SystemMessageController = require('./Features/SystemMessages/SystemMessageController')
  52. const AnalyticsRegistrationSourceMiddleware = require('./Features/Analytics/AnalyticsRegistrationSourceMiddleware')
  53. const AnalyticsUTMTrackingMiddleware = require('./Features/Analytics/AnalyticsUTMTrackingMiddleware')
  54. const SplitTestMiddleware = require('./Features/SplitTests/SplitTestMiddleware')
  55. const CaptchaMiddleware = require('./Features/Captcha/CaptchaMiddleware')
  56. const { Joi, validate } = require('./infrastructure/Validation')
  57. const {
  58. renderUnsupportedBrowserPage,
  59. unsupportedBrowserMiddleware,
  60. } = require('./infrastructure/UnsupportedBrowserMiddleware')
  61. const logger = require('@overleaf/logger')
  62. const _ = require('underscore')
  63. const { expressify } = require('./util/promises')
  64. const { plainTextResponse } = require('./infrastructure/Response')
  65. module.exports = { initialize }
  66. function initialize(webRouter, privateApiRouter, publicApiRouter) {
  67. webRouter.use(unsupportedBrowserMiddleware)
  68. if (!Settings.allowPublicAccess) {
  69. webRouter.all('*', AuthenticationController.requireGlobalLogin)
  70. }
  71. webRouter.get('*', AnalyticsRegistrationSourceMiddleware.setInbound())
  72. webRouter.get('*', AnalyticsUTMTrackingMiddleware.recordUTMTags())
  73. webRouter.get(
  74. '*',
  75. expressify(
  76. SplitTestMiddleware.loadAssignmentsInLocals(['unified-navigation'])
  77. )
  78. )
  79. // Mount onto /login in order to get the deviceHistory cookie.
  80. webRouter.post(
  81. '/login/can-skip-captcha',
  82. // Keep in sync with the overleaf-login options.
  83. RateLimiterMiddleware.rateLimit({
  84. endpointName: 'can-skip-captcha',
  85. maxRequests: 20,
  86. timeInterval: 60,
  87. }),
  88. CaptchaMiddleware.canSkipCaptcha
  89. )
  90. webRouter.get('/login', UserPagesController.loginPage)
  91. AuthenticationController.addEndpointToLoginWhitelist('/login')
  92. webRouter.post(
  93. '/login',
  94. CaptchaMiddleware.validateCaptcha('login'),
  95. AuthenticationController.passportLogin
  96. )
  97. if (Settings.enableLegacyLogin) {
  98. AuthenticationController.addEndpointToLoginWhitelist('/login/legacy')
  99. webRouter.get('/login/legacy', UserPagesController.loginPage)
  100. webRouter.post(
  101. '/login/legacy',
  102. CaptchaMiddleware.validateCaptcha('login'),
  103. AuthenticationController.passportLogin
  104. )
  105. }
  106. webRouter.get(
  107. '/read-only/one-time-login',
  108. UserPagesController.oneTimeLoginPage
  109. )
  110. AuthenticationController.addEndpointToLoginWhitelist(
  111. '/read-only/one-time-login'
  112. )
  113. webRouter.get('/logout', UserPagesController.logoutPage)
  114. webRouter.post('/logout', UserController.logout)
  115. webRouter.get('/restricted', AuthorizationMiddleware.restricted)
  116. if (Features.hasFeature('registration-page')) {
  117. webRouter.get('/register', UserPagesController.registerPage)
  118. AuthenticationController.addEndpointToLoginWhitelist('/register')
  119. }
  120. EditorRouter.apply(webRouter, privateApiRouter)
  121. CollaboratorsRouter.apply(webRouter, privateApiRouter)
  122. SubscriptionRouter.apply(webRouter, privateApiRouter, publicApiRouter)
  123. UploadsRouter.apply(webRouter, privateApiRouter)
  124. PasswordResetRouter.apply(webRouter, privateApiRouter)
  125. StaticPagesRouter.apply(webRouter, privateApiRouter)
  126. ContactRouter.apply(webRouter, privateApiRouter)
  127. AnalyticsRouter.apply(webRouter, privateApiRouter, publicApiRouter)
  128. LinkedFilesRouter.apply(webRouter, privateApiRouter, publicApiRouter)
  129. TemplatesRouter.apply(webRouter)
  130. UserMembershipRouter.apply(webRouter)
  131. Modules.applyRouter(webRouter, privateApiRouter, publicApiRouter)
  132. if (Settings.enableSubscriptions) {
  133. webRouter.get(
  134. '/user/bonus',
  135. AuthenticationController.requireLogin(),
  136. ReferalController.bonus
  137. )
  138. }
  139. // .getMessages will generate an empty response for anonymous users.
  140. webRouter.get('/system/messages', SystemMessageController.getMessages)
  141. webRouter.get(
  142. '/user/settings',
  143. AuthenticationController.requireLogin(),
  144. UserPagesController.settingsPage
  145. )
  146. webRouter.post(
  147. '/user/settings',
  148. AuthenticationController.requireLogin(),
  149. UserController.updateUserSettings
  150. )
  151. webRouter.post(
  152. '/user/password/update',
  153. AuthenticationController.requireLogin(),
  154. RateLimiterMiddleware.rateLimit({
  155. endpointName: 'change-password',
  156. maxRequests: 10,
  157. timeInterval: 60,
  158. }),
  159. UserController.changePassword
  160. )
  161. webRouter.get(
  162. '/user/emails',
  163. AuthenticationController.requireLogin(),
  164. UserController.promises.ensureAffiliationMiddleware,
  165. UserEmailsController.list
  166. )
  167. webRouter.get('/user/emails/confirm', UserEmailsController.showConfirm)
  168. webRouter.post(
  169. '/user/emails/confirm',
  170. RateLimiterMiddleware.rateLimit({
  171. endpointName: 'confirm-email',
  172. maxRequests: 10,
  173. timeInterval: 60,
  174. }),
  175. UserEmailsController.confirm
  176. )
  177. webRouter.post(
  178. '/user/emails/resend_confirmation',
  179. AuthenticationController.requireLogin(),
  180. RateLimiterMiddleware.rateLimit({
  181. endpointName: 'resend-confirmation',
  182. maxRequests: 10,
  183. timeInterval: 60,
  184. }),
  185. UserEmailsController.resendConfirmation
  186. )
  187. webRouter.get(
  188. '/user/emails/primary-email-check',
  189. AuthenticationController.requireLogin(),
  190. UserEmailsController.primaryEmailCheckPage
  191. )
  192. webRouter.post(
  193. '/user/emails/primary-email-check',
  194. AuthenticationController.requireLogin(),
  195. UserEmailsController.primaryEmailCheck
  196. )
  197. if (Features.hasFeature('affiliations')) {
  198. webRouter.post(
  199. '/user/emails',
  200. AuthenticationController.requireLogin(),
  201. RateLimiterMiddleware.rateLimit({
  202. endpointName: 'add-email',
  203. maxRequests: 10,
  204. timeInterval: 60,
  205. }),
  206. UserEmailsController.add
  207. )
  208. webRouter.post(
  209. '/user/emails/delete',
  210. AuthenticationController.requireLogin(),
  211. RateLimiterMiddleware.rateLimit({
  212. endpointName: 'delete-email',
  213. maxRequests: 10,
  214. timeInterval: 60,
  215. }),
  216. UserEmailsController.remove
  217. )
  218. webRouter.post(
  219. '/user/emails/default',
  220. AuthenticationController.requireLogin(),
  221. UserEmailsController.setDefault
  222. )
  223. webRouter.post(
  224. '/user/emails/endorse',
  225. AuthenticationController.requireLogin(),
  226. RateLimiterMiddleware.rateLimit({
  227. endpointName: 'endorse-email',
  228. maxRequests: 30,
  229. timeInterval: 60,
  230. }),
  231. UserEmailsController.endorse
  232. )
  233. }
  234. webRouter.get(
  235. '/user/sessions',
  236. AuthenticationController.requireLogin(),
  237. UserPagesController.sessionsPage
  238. )
  239. webRouter.post(
  240. '/user/sessions/clear',
  241. AuthenticationController.requireLogin(),
  242. UserController.clearSessions
  243. )
  244. // deprecated
  245. webRouter.delete(
  246. '/user/newsletter/unsubscribe',
  247. AuthenticationController.requireLogin(),
  248. UserController.unsubscribe
  249. )
  250. webRouter.post(
  251. '/user/newsletter/unsubscribe',
  252. AuthenticationController.requireLogin(),
  253. UserController.unsubscribe
  254. )
  255. webRouter.post(
  256. '/user/newsletter/subscribe',
  257. AuthenticationController.requireLogin(),
  258. UserController.subscribe
  259. )
  260. webRouter.get(
  261. '/user/email-preferences',
  262. AuthenticationController.requireLogin(),
  263. UserPagesController.emailPreferencesPage
  264. )
  265. webRouter.post(
  266. '/user/delete',
  267. RateLimiterMiddleware.rateLimit({
  268. endpointName: 'delete-user',
  269. maxRequests: 10,
  270. timeInterval: 60,
  271. }),
  272. AuthenticationController.requireLogin(),
  273. UserController.tryDeleteUser
  274. )
  275. webRouter.get(
  276. '/user/personal_info',
  277. AuthenticationController.requireLogin(),
  278. UserInfoController.getLoggedInUsersPersonalInfo
  279. )
  280. privateApiRouter.get(
  281. '/user/:user_id/personal_info',
  282. AuthenticationController.requirePrivateApiAuth(),
  283. UserInfoController.getPersonalInfo
  284. )
  285. webRouter.get(
  286. '/user/reconfirm',
  287. UserPagesController.renderReconfirmAccountPage
  288. )
  289. // for /user/reconfirm POST, see password router
  290. webRouter.get(
  291. '/user/tpds/queues',
  292. AuthenticationController.requireLogin(),
  293. TpdsController.getQueues
  294. )
  295. webRouter.get(
  296. '/user/projects',
  297. AuthenticationController.requireLogin(),
  298. ProjectController.userProjectsJson
  299. )
  300. webRouter.get(
  301. '/project/:Project_id/entities',
  302. AuthenticationController.requireLogin(),
  303. AuthorizationMiddleware.ensureUserCanReadProject,
  304. ProjectController.projectEntitiesJson
  305. )
  306. webRouter.get(
  307. '/project',
  308. AuthenticationController.requireLogin(),
  309. RateLimiterMiddleware.rateLimit({
  310. endpointName: 'open-dashboard',
  311. maxRequests: 30,
  312. timeInterval: 60,
  313. }),
  314. ProjectController.projectListPage
  315. )
  316. webRouter.post(
  317. '/project/new',
  318. AuthenticationController.requireLogin(),
  319. RateLimiterMiddleware.rateLimit({
  320. endpointName: 'create-project',
  321. maxRequests: 20,
  322. timeInterval: 60,
  323. }),
  324. ProjectController.newProject
  325. )
  326. for (const route of [
  327. // Keep the old route for continuous metrics
  328. '/Project/:Project_id',
  329. // New route for pdf-detach
  330. '/Project/:Project_id/:detachRole(detacher|detached)',
  331. ]) {
  332. webRouter.get(
  333. route,
  334. RateLimiterMiddleware.rateLimit({
  335. endpointName: 'open-project',
  336. params: ['Project_id'],
  337. maxRequests: 15,
  338. timeInterval: 60,
  339. }),
  340. AuthenticationController.validateUserSession(),
  341. AuthorizationMiddleware.ensureUserCanReadProject,
  342. ProjectController.loadEditor
  343. )
  344. }
  345. webRouter.head(
  346. '/Project/:Project_id/file/:File_id',
  347. AuthorizationMiddleware.ensureUserCanReadProject,
  348. FileStoreController.getFileHead
  349. )
  350. webRouter.get(
  351. '/Project/:Project_id/file/:File_id',
  352. AuthorizationMiddleware.ensureUserCanReadProject,
  353. FileStoreController.getFile
  354. )
  355. webRouter.post(
  356. '/project/:Project_id/settings',
  357. validate({ body: Joi.object() }),
  358. AuthorizationMiddleware.ensureUserCanWriteProjectSettings,
  359. ProjectController.updateProjectSettings
  360. )
  361. webRouter.post(
  362. '/project/:Project_id/settings/admin',
  363. AuthenticationController.requireLogin(),
  364. AuthorizationMiddleware.ensureUserCanAdminProject,
  365. ProjectController.updateProjectAdminSettings
  366. )
  367. webRouter.post(
  368. '/project/:Project_id/compile',
  369. RateLimiterMiddleware.rateLimit({
  370. endpointName: 'compile-project-http',
  371. params: ['Project_id'],
  372. maxRequests: 800,
  373. timeInterval: 60 * 60,
  374. }),
  375. AuthorizationMiddleware.ensureUserCanReadProject,
  376. CompileController.compile
  377. )
  378. webRouter.post(
  379. '/project/:Project_id/compile/stop',
  380. AuthorizationMiddleware.ensureUserCanReadProject,
  381. CompileController.stopCompile
  382. )
  383. // LEGACY: Used by the web download buttons, adds filename header, TODO: remove at some future date
  384. webRouter.get(
  385. '/project/:Project_id/output/output.pdf',
  386. AuthorizationMiddleware.ensureUserCanReadProject,
  387. CompileController.downloadPdf
  388. )
  389. // PDF Download button
  390. webRouter.get(
  391. /^\/download\/project\/([^/]*)\/output\/output\.pdf$/,
  392. function (req, res, next) {
  393. const params = { Project_id: req.params[0] }
  394. req.params = params
  395. next()
  396. },
  397. AuthorizationMiddleware.ensureUserCanReadProject,
  398. CompileController.downloadPdf
  399. )
  400. // PDF Download button for specific build
  401. webRouter.get(
  402. /^\/download\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/output\.pdf$/,
  403. function (req, res, next) {
  404. const params = {
  405. Project_id: req.params[0],
  406. build_id: req.params[1],
  407. }
  408. req.params = params
  409. next()
  410. },
  411. AuthorizationMiddleware.ensureUserCanReadProject,
  412. CompileController.downloadPdf
  413. )
  414. // Align with limits defined in CompileController.downloadPdf
  415. const rateLimiterMiddlewareOutputFiles = RateLimiterMiddleware.rateLimit({
  416. endpointName: 'misc-output-download',
  417. params: ['Project_id'],
  418. maxRequests: 1000,
  419. timeInterval: 60 * 60,
  420. })
  421. // Used by the pdf viewers
  422. webRouter.get(
  423. /^\/project\/([^/]*)\/output\/(.*)$/,
  424. function (req, res, next) {
  425. const params = {
  426. Project_id: req.params[0],
  427. file: req.params[1],
  428. }
  429. req.params = params
  430. next()
  431. },
  432. rateLimiterMiddlewareOutputFiles,
  433. AuthorizationMiddleware.ensureUserCanReadProject,
  434. CompileController.getFileFromClsi
  435. )
  436. // direct url access to output files for a specific build (query string not required)
  437. webRouter.get(
  438. /^\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  439. function (req, res, next) {
  440. const params = {
  441. Project_id: req.params[0],
  442. build_id: req.params[1],
  443. file: req.params[2],
  444. }
  445. req.params = params
  446. next()
  447. },
  448. rateLimiterMiddlewareOutputFiles,
  449. AuthorizationMiddleware.ensureUserCanReadProject,
  450. CompileController.getFileFromClsi
  451. )
  452. // direct url access to output files for user but no build, to retrieve files when build fails
  453. webRouter.get(
  454. /^\/project\/([^/]*)\/user\/([0-9a-f-]+)\/output\/(.*)$/,
  455. function (req, res, next) {
  456. const params = {
  457. Project_id: req.params[0],
  458. user_id: req.params[1],
  459. file: req.params[2],
  460. }
  461. req.params = params
  462. next()
  463. },
  464. rateLimiterMiddlewareOutputFiles,
  465. AuthorizationMiddleware.ensureUserCanReadProject,
  466. CompileController.getFileFromClsi
  467. )
  468. // direct url access to output files for a specific user and build (query string not required)
  469. webRouter.get(
  470. /^\/project\/([^/]*)\/user\/([0-9a-f]+)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  471. function (req, res, next) {
  472. const params = {
  473. Project_id: req.params[0],
  474. user_id: req.params[1],
  475. build_id: req.params[2],
  476. file: req.params[3],
  477. }
  478. req.params = params
  479. next()
  480. },
  481. rateLimiterMiddlewareOutputFiles,
  482. AuthorizationMiddleware.ensureUserCanReadProject,
  483. CompileController.getFileFromClsi
  484. )
  485. webRouter.delete(
  486. '/project/:Project_id/output',
  487. validate({ query: { clsiserverid: Joi.string() } }),
  488. AuthorizationMiddleware.ensureUserCanReadProject,
  489. CompileController.deleteAuxFiles
  490. )
  491. webRouter.get(
  492. '/project/:Project_id/sync/code',
  493. AuthorizationMiddleware.ensureUserCanReadProject,
  494. CompileController.proxySyncCode
  495. )
  496. webRouter.get(
  497. '/project/:Project_id/sync/pdf',
  498. AuthorizationMiddleware.ensureUserCanReadProject,
  499. CompileController.proxySyncPdf
  500. )
  501. webRouter.get(
  502. '/project/:Project_id/wordcount',
  503. validate({ query: { clsiserverid: Joi.string() } }),
  504. AuthorizationMiddleware.ensureUserCanReadProject,
  505. CompileController.wordCount
  506. )
  507. webRouter.post(
  508. '/Project/:Project_id/archive',
  509. AuthenticationController.requireLogin(),
  510. AuthorizationMiddleware.ensureUserCanReadProject,
  511. ProjectController.archiveProject
  512. )
  513. webRouter.delete(
  514. '/Project/:Project_id/archive',
  515. AuthenticationController.requireLogin(),
  516. AuthorizationMiddleware.ensureUserCanReadProject,
  517. ProjectController.unarchiveProject
  518. )
  519. webRouter.post(
  520. '/project/:project_id/trash',
  521. AuthenticationController.requireLogin(),
  522. AuthorizationMiddleware.ensureUserCanReadProject,
  523. ProjectController.trashProject
  524. )
  525. webRouter.delete(
  526. '/project/:project_id/trash',
  527. AuthenticationController.requireLogin(),
  528. AuthorizationMiddleware.ensureUserCanReadProject,
  529. ProjectController.untrashProject
  530. )
  531. webRouter.delete(
  532. '/Project/:Project_id',
  533. AuthenticationController.requireLogin(),
  534. AuthorizationMiddleware.ensureUserCanAdminProject,
  535. ProjectController.deleteProject
  536. )
  537. webRouter.post(
  538. '/Project/:Project_id/restore',
  539. AuthenticationController.requireLogin(),
  540. AuthorizationMiddleware.ensureUserCanAdminProject,
  541. ProjectController.restoreProject
  542. )
  543. webRouter.post(
  544. '/Project/:Project_id/clone',
  545. AuthorizationMiddleware.ensureUserCanReadProject,
  546. ProjectController.cloneProject
  547. )
  548. webRouter.post(
  549. '/project/:Project_id/rename',
  550. AuthenticationController.requireLogin(),
  551. AuthorizationMiddleware.ensureUserCanAdminProject,
  552. ProjectController.renameProject
  553. )
  554. webRouter.get(
  555. '/project/:Project_id/updates',
  556. AuthorizationMiddleware.blockRestrictedUserFromProject,
  557. AuthorizationMiddleware.ensureUserCanReadProject,
  558. HistoryController.selectHistoryApi,
  559. HistoryController.proxyToHistoryApiAndInjectUserDetails
  560. )
  561. webRouter.get(
  562. '/project/:Project_id/doc/:doc_id/diff',
  563. AuthorizationMiddleware.blockRestrictedUserFromProject,
  564. AuthorizationMiddleware.ensureUserCanReadProject,
  565. HistoryController.selectHistoryApi,
  566. HistoryController.proxyToHistoryApi
  567. )
  568. webRouter.get(
  569. '/project/:Project_id/diff',
  570. AuthorizationMiddleware.blockRestrictedUserFromProject,
  571. AuthorizationMiddleware.ensureUserCanReadProject,
  572. HistoryController.selectHistoryApi,
  573. HistoryController.proxyToHistoryApiAndInjectUserDetails
  574. )
  575. webRouter.get(
  576. '/project/:Project_id/filetree/diff',
  577. AuthorizationMiddleware.blockRestrictedUserFromProject,
  578. AuthorizationMiddleware.ensureUserCanReadProject,
  579. HistoryController.selectHistoryApi,
  580. HistoryController.proxyToHistoryApi
  581. )
  582. webRouter.post(
  583. '/project/:Project_id/doc/:doc_id/version/:version_id/restore',
  584. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  585. HistoryController.selectHistoryApi,
  586. HistoryController.proxyToHistoryApi
  587. )
  588. webRouter.post(
  589. '/project/:project_id/doc/:doc_id/restore',
  590. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  591. HistoryController.restoreDocFromDeletedDoc
  592. )
  593. webRouter.post(
  594. '/project/:project_id/restore_file',
  595. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  596. HistoryController.restoreFileFromV2
  597. )
  598. webRouter.get(
  599. '/project/:project_id/version/:version/zip',
  600. RateLimiterMiddleware.rateLimit({
  601. endpointName: 'download-project-revision',
  602. maxRequests: 30,
  603. timeInterval: 60 * 60,
  604. }),
  605. AuthorizationMiddleware.blockRestrictedUserFromProject,
  606. AuthorizationMiddleware.ensureUserCanReadProject,
  607. HistoryController.downloadZipOfVersion
  608. )
  609. privateApiRouter.post(
  610. '/project/:Project_id/history/resync',
  611. AuthenticationController.requirePrivateApiAuth(),
  612. HistoryController.resyncProjectHistory
  613. )
  614. webRouter.get(
  615. '/project/:Project_id/labels',
  616. AuthorizationMiddleware.blockRestrictedUserFromProject,
  617. AuthorizationMiddleware.ensureUserCanReadProject,
  618. HistoryController.selectHistoryApi,
  619. HistoryController.ensureProjectHistoryEnabled,
  620. HistoryController.getLabels
  621. )
  622. webRouter.post(
  623. '/project/:Project_id/labels',
  624. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  625. HistoryController.selectHistoryApi,
  626. HistoryController.ensureProjectHistoryEnabled,
  627. HistoryController.createLabel
  628. )
  629. webRouter.delete(
  630. '/project/:Project_id/labels/:label_id',
  631. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  632. HistoryController.selectHistoryApi,
  633. HistoryController.ensureProjectHistoryEnabled,
  634. HistoryController.deleteLabel
  635. )
  636. webRouter.post(
  637. '/project/:project_id/export/:brand_variation_id',
  638. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  639. ExportsController.exportProject
  640. )
  641. webRouter.get(
  642. '/project/:project_id/export/:export_id',
  643. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  644. ExportsController.exportStatus
  645. )
  646. webRouter.get(
  647. '/project/:project_id/export/:export_id/:type',
  648. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  649. ExportsController.exportDownload
  650. )
  651. webRouter.get(
  652. '/Project/:Project_id/download/zip',
  653. RateLimiterMiddleware.rateLimit({
  654. endpointName: 'zip-download',
  655. params: ['Project_id'],
  656. maxRequests: 10,
  657. timeInterval: 60,
  658. }),
  659. AuthorizationMiddleware.ensureUserCanReadProject,
  660. ProjectDownloadsController.downloadProject
  661. )
  662. webRouter.get(
  663. '/project/download/zip',
  664. AuthenticationController.requireLogin(),
  665. RateLimiterMiddleware.rateLimit({
  666. endpointName: 'multiple-projects-zip-download',
  667. maxRequests: 10,
  668. timeInterval: 60,
  669. }),
  670. AuthorizationMiddleware.ensureUserCanReadMultipleProjects,
  671. ProjectDownloadsController.downloadMultipleProjects
  672. )
  673. webRouter.get(
  674. '/project/:project_id/metadata',
  675. AuthorizationMiddleware.ensureUserCanReadProject,
  676. Settings.allowAnonymousReadAndWriteSharing
  677. ? (req, res, next) => {
  678. next()
  679. }
  680. : AuthenticationController.requireLogin(),
  681. MetaController.getMetadata
  682. )
  683. webRouter.post(
  684. '/project/:project_id/doc/:doc_id/metadata',
  685. AuthorizationMiddleware.ensureUserCanReadProject,
  686. Settings.allowAnonymousReadAndWriteSharing
  687. ? (req, res, next) => {
  688. next()
  689. }
  690. : AuthenticationController.requireLogin(),
  691. MetaController.broadcastMetadataForDoc
  692. )
  693. privateApiRouter.post(
  694. '/internal/expire-deleted-projects-after-duration',
  695. AuthenticationController.requirePrivateApiAuth(),
  696. ProjectController.expireDeletedProjectsAfterDuration
  697. )
  698. privateApiRouter.post(
  699. '/internal/expire-deleted-users-after-duration',
  700. AuthenticationController.requirePrivateApiAuth(),
  701. UserController.expireDeletedUsersAfterDuration
  702. )
  703. privateApiRouter.post(
  704. '/internal/project/:projectId/expire-deleted-project',
  705. AuthenticationController.requirePrivateApiAuth(),
  706. ProjectController.expireDeletedProject
  707. )
  708. privateApiRouter.post(
  709. '/internal/users/:userId/expire',
  710. AuthenticationController.requirePrivateApiAuth(),
  711. UserController.expireDeletedUser
  712. )
  713. privateApiRouter.get(
  714. '/user/:userId/tag',
  715. AuthenticationController.requirePrivateApiAuth(),
  716. TagsController.apiGetAllTags
  717. )
  718. webRouter.get(
  719. '/tag',
  720. AuthenticationController.requireLogin(),
  721. TagsController.getAllTags
  722. )
  723. webRouter.post(
  724. '/tag',
  725. AuthenticationController.requireLogin(),
  726. RateLimiterMiddleware.rateLimit({
  727. endpointName: 'create-tag',
  728. maxRequests: 30,
  729. timeInterval: 60,
  730. }),
  731. TagsController.createTag
  732. )
  733. webRouter.post(
  734. '/tag/:tagId/rename',
  735. AuthenticationController.requireLogin(),
  736. RateLimiterMiddleware.rateLimit({
  737. endpointName: 'rename-tag',
  738. maxRequests: 30,
  739. timeInterval: 60,
  740. }),
  741. TagsController.renameTag
  742. )
  743. webRouter.delete(
  744. '/tag/:tagId',
  745. AuthenticationController.requireLogin(),
  746. RateLimiterMiddleware.rateLimit({
  747. endpointName: 'delete-tag',
  748. maxRequests: 30,
  749. timeInterval: 60,
  750. }),
  751. TagsController.deleteTag
  752. )
  753. webRouter.post(
  754. '/tag/:tagId/project/:projectId',
  755. AuthenticationController.requireLogin(),
  756. RateLimiterMiddleware.rateLimit({
  757. endpointName: 'add-project-to-tag',
  758. maxRequests: 30,
  759. timeInterval: 60,
  760. }),
  761. TagsController.addProjectToTag
  762. )
  763. webRouter.delete(
  764. '/tag/:tagId/project/:projectId',
  765. AuthenticationController.requireLogin(),
  766. RateLimiterMiddleware.rateLimit({
  767. endpointName: 'remove-project-from-tag',
  768. maxRequests: 30,
  769. timeInterval: 60,
  770. }),
  771. TagsController.removeProjectFromTag
  772. )
  773. webRouter.get(
  774. '/notifications',
  775. AuthenticationController.requireLogin(),
  776. NotificationsController.getAllUnreadNotifications
  777. )
  778. webRouter.delete(
  779. '/notifications/:notificationId',
  780. AuthenticationController.requireLogin(),
  781. NotificationsController.markNotificationAsRead
  782. )
  783. // Deprecated in favour of /internal/project/:project_id but still used by versioning
  784. privateApiRouter.get(
  785. '/project/:project_id/details',
  786. AuthenticationController.requirePrivateApiAuth(),
  787. ProjectApiController.getProjectDetails
  788. )
  789. // New 'stable' /internal API end points
  790. privateApiRouter.get(
  791. '/internal/project/:project_id',
  792. AuthenticationController.requirePrivateApiAuth(),
  793. ProjectApiController.getProjectDetails
  794. )
  795. privateApiRouter.get(
  796. '/internal/project/:Project_id/zip',
  797. AuthenticationController.requirePrivateApiAuth(),
  798. ProjectDownloadsController.downloadProject
  799. )
  800. privateApiRouter.get(
  801. '/internal/project/:project_id/compile/pdf',
  802. AuthenticationController.requirePrivateApiAuth(),
  803. CompileController.compileAndDownloadPdf
  804. )
  805. privateApiRouter.post(
  806. '/internal/deactivateOldProjects',
  807. AuthenticationController.requirePrivateApiAuth(),
  808. InactiveProjectController.deactivateOldProjects
  809. )
  810. privateApiRouter.post(
  811. '/internal/project/:project_id/deactivate',
  812. AuthenticationController.requirePrivateApiAuth(),
  813. InactiveProjectController.deactivateProject
  814. )
  815. privateApiRouter.get(
  816. /^\/internal\/project\/([^/]*)\/output\/(.*)$/,
  817. function (req, res, next) {
  818. const params = {
  819. Project_id: req.params[0],
  820. file: req.params[1],
  821. }
  822. req.params = params
  823. next()
  824. },
  825. AuthenticationController.requirePrivateApiAuth(),
  826. CompileController.getFileFromClsi
  827. )
  828. privateApiRouter.get(
  829. '/project/:Project_id/doc/:doc_id',
  830. AuthenticationController.requirePrivateApiAuth(),
  831. DocumentController.getDocument
  832. )
  833. privateApiRouter.post(
  834. '/project/:Project_id/doc/:doc_id',
  835. AuthenticationController.requirePrivateApiAuth(),
  836. DocumentController.setDocument
  837. )
  838. privateApiRouter.post(
  839. '/user/:user_id/update/*',
  840. AuthenticationController.requirePrivateApiAuth(),
  841. TpdsController.mergeUpdate
  842. )
  843. privateApiRouter.delete(
  844. '/user/:user_id/update/*',
  845. AuthenticationController.requirePrivateApiAuth(),
  846. TpdsController.deleteUpdate
  847. )
  848. privateApiRouter.post(
  849. '/project/:project_id/contents/*',
  850. AuthenticationController.requirePrivateApiAuth(),
  851. TpdsController.updateProjectContents
  852. )
  853. privateApiRouter.delete(
  854. '/project/:project_id/contents/*',
  855. AuthenticationController.requirePrivateApiAuth(),
  856. TpdsController.deleteProjectContents
  857. )
  858. webRouter.post(
  859. '/spelling/check',
  860. AuthenticationController.requireLogin(),
  861. SpellingController.proxyRequestToSpellingApi
  862. )
  863. webRouter.post(
  864. '/spelling/learn',
  865. validate({
  866. body: Joi.object({
  867. word: Joi.string().required(),
  868. }),
  869. }),
  870. AuthenticationController.requireLogin(),
  871. SpellingController.learn
  872. )
  873. webRouter.post(
  874. '/spelling/unlearn',
  875. validate({
  876. body: Joi.object({
  877. word: Joi.string().required(),
  878. }),
  879. }),
  880. AuthenticationController.requireLogin(),
  881. SpellingController.unlearn
  882. )
  883. webRouter.get(
  884. '/project/:project_id/messages',
  885. AuthorizationMiddleware.blockRestrictedUserFromProject,
  886. AuthorizationMiddleware.ensureUserCanReadProject,
  887. ChatController.getMessages
  888. )
  889. webRouter.post(
  890. '/project/:project_id/messages',
  891. AuthorizationMiddleware.blockRestrictedUserFromProject,
  892. AuthorizationMiddleware.ensureUserCanReadProject,
  893. RateLimiterMiddleware.rateLimit({
  894. endpointName: 'send-chat-message',
  895. maxRequests: 100,
  896. timeInterval: 60,
  897. }),
  898. ChatController.sendMessage
  899. )
  900. webRouter.post(
  901. '/project/:Project_id/references/index',
  902. AuthorizationMiddleware.ensureUserCanReadProject,
  903. RateLimiterMiddleware.rateLimit({
  904. endpointName: 'index-project-references',
  905. maxRequests: 30,
  906. timeInterval: 60,
  907. }),
  908. ReferencesController.index
  909. )
  910. webRouter.post(
  911. '/project/:Project_id/references/indexAll',
  912. AuthorizationMiddleware.ensureUserCanReadProject,
  913. RateLimiterMiddleware.rateLimit({
  914. endpointName: 'index-all-project-references',
  915. maxRequests: 30,
  916. timeInterval: 60,
  917. }),
  918. ReferencesController.indexAll
  919. )
  920. // disable beta program while v2 is in beta
  921. webRouter.get(
  922. '/beta/participate',
  923. AuthenticationController.requireLogin(),
  924. BetaProgramController.optInPage
  925. )
  926. webRouter.post(
  927. '/beta/opt-in',
  928. AuthenticationController.requireLogin(),
  929. BetaProgramController.optIn
  930. )
  931. webRouter.post(
  932. '/beta/opt-out',
  933. AuthenticationController.requireLogin(),
  934. BetaProgramController.optOut
  935. )
  936. // New "api" endpoints. Started as a way for v1 to call over to v2 (for
  937. // long-term features, as opposed to the nominally temporary ones in the
  938. // overleaf-integration module), but may expand beyond that role.
  939. publicApiRouter.post(
  940. '/api/clsi/compile/:submission_id',
  941. AuthenticationController.requirePrivateApiAuth(),
  942. CompileController.compileSubmission
  943. )
  944. publicApiRouter.get(
  945. /^\/api\/clsi\/compile\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  946. function (req, res, next) {
  947. const params = {
  948. submission_id: req.params[0],
  949. build_id: req.params[1],
  950. file: req.params[2],
  951. }
  952. req.params = params
  953. next()
  954. },
  955. AuthenticationController.requirePrivateApiAuth(),
  956. CompileController.getFileFromClsiWithoutUser
  957. )
  958. publicApiRouter.post(
  959. '/api/institutions/confirm_university_domain',
  960. RateLimiterMiddleware.rateLimit({
  961. endpointName: 'confirm-university-domain',
  962. maxRequests: 1,
  963. timeInterval: 60,
  964. }),
  965. AuthenticationController.requirePrivateApiAuth(),
  966. InstitutionsController.confirmDomain
  967. )
  968. webRouter.get('/chrome', function (req, res, next) {
  969. // Match v1 behaviour - this is used for a Chrome web app
  970. if (SessionManager.isUserLoggedIn(req.session)) {
  971. res.redirect('/project')
  972. } else {
  973. res.redirect('/register')
  974. }
  975. })
  976. webRouter.get(
  977. '/admin',
  978. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  979. AdminController.index
  980. )
  981. if (!Features.hasFeature('saas')) {
  982. webRouter.post(
  983. '/admin/openEditor',
  984. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  985. AdminController.openEditor
  986. )
  987. webRouter.post(
  988. '/admin/closeEditor',
  989. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  990. AdminController.closeEditor
  991. )
  992. webRouter.post(
  993. '/admin/disconnectAllUsers',
  994. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  995. AdminController.disconnectAllUsers
  996. )
  997. }
  998. webRouter.post(
  999. '/admin/flushProjectToTpds',
  1000. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1001. AdminController.flushProjectToTpds
  1002. )
  1003. webRouter.post(
  1004. '/admin/pollDropboxForUser',
  1005. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1006. AdminController.pollDropboxForUser
  1007. )
  1008. webRouter.post(
  1009. '/admin/messages',
  1010. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1011. AdminController.createMessage
  1012. )
  1013. webRouter.post(
  1014. '/admin/messages/clear',
  1015. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1016. AdminController.clearMessages
  1017. )
  1018. webRouter.post(
  1019. '/admin/unregisterServiceWorker',
  1020. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1021. AdminController.unregisterServiceWorker
  1022. )
  1023. privateApiRouter.get('/perfTest', (req, res) => {
  1024. plainTextResponse(res, 'hello')
  1025. })
  1026. publicApiRouter.get('/status', (req, res) => {
  1027. if (!Settings.siteIsOpen) {
  1028. plainTextResponse(res, 'web site is closed (web)')
  1029. } else if (!Settings.editorIsOpen) {
  1030. plainTextResponse(res, 'web editor is closed (web)')
  1031. } else {
  1032. plainTextResponse(res, 'web sharelatex is alive (web)')
  1033. }
  1034. })
  1035. privateApiRouter.get('/status', (req, res) => {
  1036. plainTextResponse(res, 'web sharelatex is alive (api)')
  1037. })
  1038. // used by kubernetes health-check and acceptance tests
  1039. webRouter.get('/dev/csrf', (req, res) => {
  1040. plainTextResponse(res, res.locals.csrfToken)
  1041. })
  1042. publicApiRouter.get(
  1043. '/health_check',
  1044. HealthCheckController.checkActiveHandles,
  1045. HealthCheckController.check
  1046. )
  1047. privateApiRouter.get(
  1048. '/health_check',
  1049. HealthCheckController.checkActiveHandles,
  1050. HealthCheckController.checkApi
  1051. )
  1052. publicApiRouter.get(
  1053. '/health_check/api',
  1054. HealthCheckController.checkActiveHandles,
  1055. HealthCheckController.checkApi
  1056. )
  1057. privateApiRouter.get(
  1058. '/health_check/api',
  1059. HealthCheckController.checkActiveHandles,
  1060. HealthCheckController.checkApi
  1061. )
  1062. publicApiRouter.get(
  1063. '/health_check/full',
  1064. HealthCheckController.checkActiveHandles,
  1065. HealthCheckController.check
  1066. )
  1067. privateApiRouter.get(
  1068. '/health_check/full',
  1069. HealthCheckController.checkActiveHandles,
  1070. HealthCheckController.check
  1071. )
  1072. publicApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1073. privateApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1074. publicApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1075. privateApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1076. webRouter.get(
  1077. '/status/compiler/:Project_id',
  1078. RateLimiterMiddleware.rateLimit({
  1079. endpointName: 'status-compiler',
  1080. maxRequests: 10,
  1081. timeInterval: 60,
  1082. }),
  1083. AuthorizationMiddleware.ensureUserCanReadProject,
  1084. function (req, res) {
  1085. const projectId = req.params.Project_id
  1086. const sendRes = _.once(function (statusCode, message) {
  1087. res.status(statusCode)
  1088. plainTextResponse(res, message)
  1089. ClsiCookieManager.clearServerId(projectId)
  1090. }) // force every compile to a new server
  1091. // set a timeout
  1092. let handler = setTimeout(function () {
  1093. sendRes(500, 'Compiler timed out')
  1094. handler = null
  1095. }, 10000)
  1096. // use a valid user id for testing
  1097. const testUserId = '123456789012345678901234'
  1098. // run the compile
  1099. CompileManager.compile(
  1100. projectId,
  1101. testUserId,
  1102. {},
  1103. function (error, status) {
  1104. if (handler) {
  1105. clearTimeout(handler)
  1106. }
  1107. if (error) {
  1108. sendRes(500, `Compiler returned error ${error.message}`)
  1109. } else if (status === 'success') {
  1110. sendRes(200, 'Compiler returned in less than 10 seconds')
  1111. } else {
  1112. sendRes(500, `Compiler returned failure ${status}`)
  1113. }
  1114. }
  1115. )
  1116. }
  1117. )
  1118. webRouter.get('/no-cache', function (req, res, next) {
  1119. res.header('Cache-Control', 'max-age=0')
  1120. res.sendStatus(404)
  1121. })
  1122. webRouter.get('/oops-express', (req, res, next) =>
  1123. next(new Error('Test error'))
  1124. )
  1125. webRouter.get('/oops-internal', function (req, res, next) {
  1126. throw new Error('Test error')
  1127. })
  1128. webRouter.get('/oops-mongo', (req, res, next) =>
  1129. require('./models/Project').Project.findOne({}, function () {
  1130. throw new Error('Test error')
  1131. })
  1132. )
  1133. privateApiRouter.get('/opps-small', function (req, res, next) {
  1134. logger.err('test error occured')
  1135. res.sendStatus(200)
  1136. })
  1137. webRouter.post('/error/client', function (req, res, next) {
  1138. logger.warn(
  1139. { err: req.body.error, meta: req.body.meta },
  1140. 'client side error'
  1141. )
  1142. metrics.inc('client-side-error')
  1143. res.sendStatus(204)
  1144. })
  1145. webRouter.get(
  1146. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})`,
  1147. RateLimiterMiddleware.rateLimit({
  1148. endpointName: 'read-only-token',
  1149. maxRequests: 15,
  1150. timeInterval: 60,
  1151. }),
  1152. AnalyticsRegistrationSourceMiddleware.setSource(
  1153. 'collaboration',
  1154. 'link-sharing'
  1155. ),
  1156. TokenAccessController.tokenAccessPage,
  1157. AnalyticsRegistrationSourceMiddleware.clearSource()
  1158. )
  1159. webRouter.get(
  1160. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})`,
  1161. RateLimiterMiddleware.rateLimit({
  1162. endpointName: 'read-and-write-token',
  1163. maxRequests: 15,
  1164. timeInterval: 60,
  1165. }),
  1166. AnalyticsRegistrationSourceMiddleware.setSource(
  1167. 'collaboration',
  1168. 'link-sharing'
  1169. ),
  1170. TokenAccessController.tokenAccessPage,
  1171. AnalyticsRegistrationSourceMiddleware.clearSource()
  1172. )
  1173. webRouter.post(
  1174. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})/grant`,
  1175. RateLimiterMiddleware.rateLimit({
  1176. endpointName: 'grant-token-access-read-write',
  1177. maxRequests: 10,
  1178. timeInterval: 60,
  1179. }),
  1180. TokenAccessController.grantTokenAccessReadAndWrite
  1181. )
  1182. webRouter.post(
  1183. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})/grant`,
  1184. RateLimiterMiddleware.rateLimit({
  1185. endpointName: 'grant-token-access-read-only',
  1186. maxRequests: 10,
  1187. timeInterval: 60,
  1188. }),
  1189. TokenAccessController.grantTokenAccessReadOnly
  1190. )
  1191. webRouter.get('/unsupported-browser', renderUnsupportedBrowserPage)
  1192. webRouter.get('*', ErrorController.notFound)
  1193. }