router.mjs 39 KB

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