router.mjs 39 KB

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