router.mjs 40 KB

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