router.mjs 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  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/features',
  452. AuthenticationController.requireLogin(),
  453. UserInfoController.getUserFeatures
  454. )
  455. webRouter.get(
  456. '/user/reconfirm',
  457. UserPagesController.renderReconfirmAccountPage
  458. )
  459. // for /user/reconfirm POST, see password router
  460. webRouter.get(
  461. '/user/tpds/queues',
  462. AuthenticationController.requireLogin(),
  463. TpdsController.getQueues
  464. )
  465. webRouter.post(
  466. '/tutorial/:tutorialKey/complete',
  467. AuthenticationController.requireLogin(),
  468. TutorialController.completeTutorial
  469. )
  470. webRouter.post(
  471. '/tutorial/:tutorialKey/postpone',
  472. AuthenticationController.requireLogin(),
  473. TutorialController.postponeTutorial
  474. )
  475. webRouter.get(
  476. '/user/projects',
  477. AuthenticationController.requireLogin(),
  478. ProjectController.userProjectsJson
  479. )
  480. webRouter.get(
  481. '/project/:Project_id/entities',
  482. AuthenticationController.requireLogin(),
  483. AuthorizationMiddleware.ensureUserCanReadProject,
  484. ProjectController.projectEntitiesJson
  485. )
  486. webRouter.get(
  487. '/project',
  488. AuthenticationController.requireLogin(),
  489. RateLimiterMiddleware.rateLimit(rateLimiters.openDashboard),
  490. PermissionsController.useCapabilities(),
  491. ProjectListController.projectListPage
  492. )
  493. webRouter.post(
  494. '/project/new',
  495. AuthenticationController.requireLogin(),
  496. RateLimiterMiddleware.rateLimit(rateLimiters.createProject),
  497. ProjectController.newProject
  498. )
  499. webRouter.post(
  500. '/api/project',
  501. AuthenticationController.requireLogin(),
  502. RateLimiterMiddleware.rateLimit(rateLimiters.getProjects),
  503. ProjectListController.getProjectsJson
  504. )
  505. for (const route of [
  506. // Keep the old route for continuous metrics
  507. '/Project/:Project_id',
  508. // New route for pdf-detach
  509. '/Project/:Project_id/:detachRole(detacher|detached)',
  510. ]) {
  511. webRouter.get(
  512. route,
  513. RateLimiterMiddleware.rateLimit(openProjectRateLimiter, {
  514. params: ['Project_id'],
  515. }),
  516. PermissionsController.useCapabilities(),
  517. AuthorizationMiddleware.ensureUserCanReadProject,
  518. ProjectController.loadEditor
  519. )
  520. }
  521. webRouter.head(
  522. '/Project/:Project_id/file/:File_id',
  523. AuthorizationMiddleware.ensureUserCanReadProject,
  524. FileStoreController.getFileHead
  525. )
  526. webRouter.get(
  527. '/Project/:Project_id/file/:File_id',
  528. AuthorizationMiddleware.ensureUserCanReadProject,
  529. FileStoreController.getFile
  530. )
  531. webRouter.get(
  532. '/Project/:Project_id/doc/:Doc_id/download', // "download" suffix to avoid conflict with private API route at doc/:doc_id
  533. AuthorizationMiddleware.ensureUserCanReadProject,
  534. DocumentUpdaterController.getDoc
  535. )
  536. webRouter.post(
  537. '/project/:Project_id/settings',
  538. validate({
  539. body: Joi.object({
  540. publicAccessLevel: Joi.string()
  541. .valid(PublicAccessLevels.PRIVATE, PublicAccessLevels.TOKEN_BASED)
  542. .optional(),
  543. }),
  544. }),
  545. AuthorizationMiddleware.ensureUserCanWriteProjectSettings,
  546. ProjectController.updateProjectSettings
  547. )
  548. webRouter.post(
  549. '/project/:Project_id/settings/admin',
  550. AuthenticationController.requireLogin(),
  551. AuthorizationMiddleware.ensureUserCanAdminProject,
  552. ProjectController.updateProjectAdminSettings
  553. )
  554. webRouter.post(
  555. '/project/:Project_id/compile',
  556. RateLimiterMiddleware.rateLimit(rateLimiters.compileProjectHttp, {
  557. params: ['Project_id'],
  558. }),
  559. AuthorizationMiddleware.ensureUserCanReadProject,
  560. CompileController.compile
  561. )
  562. webRouter.post(
  563. '/project/:Project_id/compile/stop',
  564. AuthorizationMiddleware.ensureUserCanReadProject,
  565. CompileController.stopCompile
  566. )
  567. webRouter.get(
  568. '/project/:Project_id/output/cached/output.overleaf.json',
  569. AuthorizationMiddleware.ensureUserCanReadProject,
  570. ClsiCacheController.getLatestBuildFromCache
  571. )
  572. webRouter.get(
  573. '/download/project/:Project_id/build/:buildId/output/cached/:filename',
  574. AuthorizationMiddleware.ensureUserCanReadProject,
  575. ClsiCacheController.downloadFromCache
  576. )
  577. // PDF Download button for specific build
  578. webRouter.get(
  579. '/download/project/:Project_id/build/:build_id/output/output.pdf',
  580. AuthorizationMiddleware.ensureUserCanReadProject,
  581. CompileController.downloadPdf
  582. )
  583. // Align with limits defined in CompileController.downloadPdf
  584. const rateLimiterMiddlewareOutputFiles = RateLimiterMiddleware.rateLimit(
  585. rateLimiters.miscOutputDownload,
  586. { params: ['Project_id'] }
  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. validate({ query: { clsiserverid: Joi.string() } }),
  624. AuthorizationMiddleware.ensureUserCanReadProject,
  625. CompileController.deleteAuxFiles
  626. )
  627. webRouter.get(
  628. '/project/:Project_id/sync/code',
  629. AuthorizationMiddleware.ensureUserCanReadProject,
  630. CompileController.proxySyncCode
  631. )
  632. webRouter.get(
  633. '/project/:Project_id/sync/pdf',
  634. AuthorizationMiddleware.ensureUserCanReadProject,
  635. CompileController.proxySyncPdf
  636. )
  637. webRouter.get(
  638. '/project/:Project_id/wordcount',
  639. validate({ query: { clsiserverid: Joi.string() } }),
  640. AuthorizationMiddleware.ensureUserCanReadProject,
  641. CompileController.wordCount
  642. )
  643. webRouter.post(
  644. '/Project/:Project_id/archive',
  645. AuthenticationController.requireLogin(),
  646. AuthorizationMiddleware.ensureUserCanReadProject,
  647. ProjectController.archiveProject
  648. )
  649. webRouter.delete(
  650. '/Project/:Project_id/archive',
  651. AuthenticationController.requireLogin(),
  652. AuthorizationMiddleware.ensureUserCanReadProject,
  653. ProjectController.unarchiveProject
  654. )
  655. webRouter.post(
  656. '/project/:project_id/trash',
  657. AuthenticationController.requireLogin(),
  658. AuthorizationMiddleware.ensureUserCanReadProject,
  659. ProjectController.trashProject
  660. )
  661. webRouter.delete(
  662. '/project/:project_id/trash',
  663. AuthenticationController.requireLogin(),
  664. AuthorizationMiddleware.ensureUserCanReadProject,
  665. ProjectController.untrashProject
  666. )
  667. webRouter.delete(
  668. '/Project/:Project_id',
  669. AuthenticationController.requireLogin(),
  670. AuthorizationMiddleware.ensureUserCanAdminProject,
  671. ProjectController.deleteProject
  672. )
  673. webRouter.post(
  674. '/Project/:Project_id/restore',
  675. AuthenticationController.requireLogin(),
  676. AuthorizationMiddleware.ensureUserCanAdminProject,
  677. ProjectController.restoreProject
  678. )
  679. webRouter.post(
  680. '/Project/:Project_id/clone',
  681. AuthorizationMiddleware.ensureUserCanReadProject,
  682. ProjectController.cloneProject
  683. )
  684. webRouter.post(
  685. '/project/:Project_id/rename',
  686. AuthenticationController.requireLogin(),
  687. AuthorizationMiddleware.ensureUserCanAdminProject,
  688. ProjectController.renameProject
  689. )
  690. webRouter.post(
  691. '/project/:project_id/export/:brand_variation_id',
  692. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  693. ExportsController.exportProject
  694. )
  695. webRouter.get(
  696. '/project/:project_id/export/:export_id',
  697. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  698. ExportsController.exportStatus
  699. )
  700. webRouter.get(
  701. '/project/:project_id/export/:export_id/:type',
  702. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  703. ExportsController.exportDownload
  704. )
  705. webRouter.get(
  706. '/Project/:Project_id/download/zip',
  707. RateLimiterMiddleware.rateLimit(rateLimiters.zipDownload, {
  708. params: ['Project_id'],
  709. }),
  710. AuthorizationMiddleware.ensureUserCanReadProject,
  711. ProjectDownloadsController.downloadProject
  712. )
  713. webRouter.get(
  714. '/project/download/zip',
  715. AuthenticationController.requireLogin(),
  716. RateLimiterMiddleware.rateLimit(rateLimiters.multipleProjectsZipDownload),
  717. AuthorizationMiddleware.ensureUserCanReadMultipleProjects,
  718. ProjectDownloadsController.downloadMultipleProjects
  719. )
  720. webRouter.get(
  721. '/project/:project_id/metadata',
  722. AuthorizationMiddleware.ensureUserCanReadProject,
  723. Settings.allowAnonymousReadAndWriteSharing
  724. ? (req, res, next) => {
  725. next()
  726. }
  727. : AuthenticationController.requireLogin(),
  728. MetaController.getMetadata
  729. )
  730. webRouter.post(
  731. '/project/:project_id/doc/:doc_id/metadata',
  732. AuthorizationMiddleware.ensureUserCanReadProject,
  733. Settings.allowAnonymousReadAndWriteSharing
  734. ? (req, res, next) => {
  735. next()
  736. }
  737. : AuthenticationController.requireLogin(),
  738. MetaController.broadcastMetadataForDoc
  739. )
  740. privateApiRouter.post(
  741. '/internal/expire-deleted-projects-after-duration',
  742. AuthenticationController.requirePrivateApiAuth(),
  743. ProjectController.expireDeletedProjectsAfterDuration
  744. )
  745. privateApiRouter.post(
  746. '/internal/expire-deleted-users-after-duration',
  747. AuthenticationController.requirePrivateApiAuth(),
  748. UserController.expireDeletedUsersAfterDuration
  749. )
  750. privateApiRouter.post(
  751. '/internal/project/:projectId/expire-deleted-project',
  752. AuthenticationController.requirePrivateApiAuth(),
  753. ProjectController.expireDeletedProject
  754. )
  755. privateApiRouter.post(
  756. '/internal/users/:userId/expire',
  757. AuthenticationController.requirePrivateApiAuth(),
  758. UserController.expireDeletedUser
  759. )
  760. privateApiRouter.get(
  761. '/user/:userId/tag',
  762. AuthenticationController.requirePrivateApiAuth(),
  763. TagsController.apiGetAllTags
  764. )
  765. webRouter.get(
  766. '/tag',
  767. AuthenticationController.requireLogin(),
  768. TagsController.getAllTags
  769. )
  770. webRouter.post(
  771. '/tag',
  772. AuthenticationController.requireLogin(),
  773. RateLimiterMiddleware.rateLimit(rateLimiters.createTag),
  774. validate({
  775. body: Joi.object({
  776. name: Joi.string().required(),
  777. color: Joi.string(),
  778. }),
  779. }),
  780. TagsController.createTag
  781. )
  782. webRouter.post(
  783. '/tag/:tagId/rename',
  784. AuthenticationController.requireLogin(),
  785. RateLimiterMiddleware.rateLimit(rateLimiters.renameTag),
  786. validate({
  787. body: Joi.object({
  788. name: Joi.string().required(),
  789. }),
  790. }),
  791. TagsController.renameTag
  792. )
  793. webRouter.post(
  794. '/tag/:tagId/edit',
  795. AuthenticationController.requireLogin(),
  796. RateLimiterMiddleware.rateLimit(rateLimiters.renameTag),
  797. validate({
  798. body: Joi.object({
  799. name: Joi.string().required(),
  800. color: Joi.string(),
  801. }),
  802. }),
  803. TagsController.editTag
  804. )
  805. webRouter.delete(
  806. '/tag/:tagId',
  807. AuthenticationController.requireLogin(),
  808. RateLimiterMiddleware.rateLimit(rateLimiters.deleteTag),
  809. TagsController.deleteTag
  810. )
  811. webRouter.post(
  812. '/tag/:tagId/project/:projectId',
  813. AuthenticationController.requireLogin(),
  814. RateLimiterMiddleware.rateLimit(rateLimiters.addProjectToTag),
  815. TagsController.addProjectToTag
  816. )
  817. webRouter.post(
  818. '/tag/:tagId/projects',
  819. AuthenticationController.requireLogin(),
  820. RateLimiterMiddleware.rateLimit(rateLimiters.addProjectsToTag),
  821. validate({
  822. body: Joi.object({
  823. projectIds: Joi.array().items(Joi.string()).required(),
  824. }),
  825. }),
  826. TagsController.addProjectsToTag
  827. )
  828. webRouter.delete(
  829. '/tag/:tagId/project/:projectId',
  830. AuthenticationController.requireLogin(),
  831. RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectFromTag),
  832. TagsController.removeProjectFromTag
  833. )
  834. webRouter.post(
  835. '/tag/:tagId/projects/remove',
  836. AuthenticationController.requireLogin(),
  837. RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectsFromTag),
  838. validate({
  839. body: Joi.object({
  840. projectIds: Joi.array().items(Joi.string()).required(),
  841. }),
  842. }),
  843. TagsController.removeProjectsFromTag
  844. )
  845. webRouter.get(
  846. '/notifications',
  847. AuthenticationController.requireLogin(),
  848. NotificationsController.getAllUnreadNotifications
  849. )
  850. webRouter.delete(
  851. '/notifications/:notificationId',
  852. AuthenticationController.requireLogin(),
  853. NotificationsController.markNotificationAsRead
  854. )
  855. // Deprecated in favour of /internal/project/:project_id but still used by versioning
  856. privateApiRouter.get(
  857. '/project/:project_id/details',
  858. AuthenticationController.requirePrivateApiAuth(),
  859. ProjectApiController.getProjectDetails
  860. )
  861. // New 'stable' /internal API end points
  862. privateApiRouter.get(
  863. '/internal/project/:project_id',
  864. AuthenticationController.requirePrivateApiAuth(),
  865. ProjectApiController.getProjectDetails
  866. )
  867. privateApiRouter.get(
  868. '/internal/project/:Project_id/zip',
  869. AuthenticationController.requirePrivateApiAuth(),
  870. ProjectDownloadsController.downloadProject
  871. )
  872. privateApiRouter.get(
  873. '/internal/project/:project_id/compile/pdf',
  874. AuthenticationController.requirePrivateApiAuth(),
  875. CompileController.compileAndDownloadPdf
  876. )
  877. privateApiRouter.post(
  878. '/internal/deactivateOldProjects',
  879. AuthenticationController.requirePrivateApiAuth(),
  880. InactiveProjectController.deactivateOldProjects
  881. )
  882. privateApiRouter.post(
  883. '/internal/project/:project_id/deactivate',
  884. AuthenticationController.requirePrivateApiAuth(),
  885. InactiveProjectController.deactivateProject
  886. )
  887. privateApiRouter.get(
  888. '/project/:Project_id/doc/:doc_id',
  889. AuthenticationController.requirePrivateApiAuth(),
  890. DocumentController.getDocument
  891. )
  892. privateApiRouter.post(
  893. '/project/:Project_id/doc/:doc_id',
  894. AuthenticationController.requirePrivateApiAuth(),
  895. DocumentController.setDocument
  896. )
  897. privateApiRouter.post(
  898. '/user/:user_id/project/new',
  899. AuthenticationController.requirePrivateApiAuth(),
  900. TpdsController.createProject
  901. )
  902. privateApiRouter.post(
  903. '/tpds/folder-update',
  904. AuthenticationController.requirePrivateApiAuth(),
  905. TpdsController.updateFolder
  906. )
  907. privateApiRouter.post(
  908. '/user/:user_id/update/*',
  909. AuthenticationController.requirePrivateApiAuth(),
  910. TpdsController.mergeUpdate
  911. )
  912. privateApiRouter.delete(
  913. '/user/:user_id/update/*',
  914. AuthenticationController.requirePrivateApiAuth(),
  915. TpdsController.deleteUpdate
  916. )
  917. privateApiRouter.post(
  918. '/project/:project_id/user/:user_id/update/*',
  919. AuthenticationController.requirePrivateApiAuth(),
  920. TpdsController.mergeUpdate
  921. )
  922. privateApiRouter.delete(
  923. '/project/:project_id/user/:user_id/update/*',
  924. AuthenticationController.requirePrivateApiAuth(),
  925. TpdsController.deleteUpdate
  926. )
  927. privateApiRouter.post(
  928. '/project/:project_id/contents/*',
  929. AuthenticationController.requirePrivateApiAuth(),
  930. TpdsController.updateProjectContents
  931. )
  932. privateApiRouter.delete(
  933. '/project/:project_id/contents/*',
  934. AuthenticationController.requirePrivateApiAuth(),
  935. TpdsController.deleteProjectContents
  936. )
  937. webRouter.post(
  938. '/spelling/learn',
  939. validate({
  940. body: Joi.object({
  941. word: Joi.string().required(),
  942. }),
  943. }),
  944. AuthenticationController.requireLogin(),
  945. SpellingController.learn
  946. )
  947. webRouter.post(
  948. '/spelling/unlearn',
  949. validate({
  950. body: Joi.object({
  951. word: Joi.string().required(),
  952. }),
  953. }),
  954. AuthenticationController.requireLogin(),
  955. SpellingController.unlearn
  956. )
  957. if (Features.hasFeature('chat')) {
  958. webRouter.get(
  959. '/project/:project_id/messages',
  960. AuthorizationMiddleware.blockRestrictedUserFromProject,
  961. AuthorizationMiddleware.ensureUserCanReadProject,
  962. PermissionsController.requirePermission('chat'),
  963. ChatController.getMessages
  964. )
  965. webRouter.post(
  966. '/project/:project_id/messages',
  967. AuthorizationMiddleware.blockRestrictedUserFromProject,
  968. AuthorizationMiddleware.ensureUserCanReadProject,
  969. PermissionsController.requirePermission('chat'),
  970. RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage),
  971. ChatController.sendMessage
  972. )
  973. }
  974. webRouter.post(
  975. '/project/:Project_id/references/indexAll',
  976. AuthorizationMiddleware.ensureUserCanReadProject,
  977. RateLimiterMiddleware.rateLimit(rateLimiters.indexAllProjectReferences),
  978. ReferencesController.indexAll
  979. )
  980. // disable beta program while v2 is in beta
  981. webRouter.get(
  982. '/beta/participate',
  983. AuthenticationController.requireLogin(),
  984. BetaProgramController.optInPage
  985. )
  986. webRouter.post(
  987. '/beta/opt-in',
  988. AuthenticationController.requireLogin(),
  989. BetaProgramController.optIn
  990. )
  991. webRouter.post(
  992. '/beta/opt-out',
  993. AuthenticationController.requireLogin(),
  994. BetaProgramController.optOut
  995. )
  996. webRouter.get('/chrome', function (req, res, next) {
  997. // Match v1 behaviour - this is used for a Chrome web app
  998. if (SessionManager.isUserLoggedIn(req.session)) {
  999. res.redirect('/project')
  1000. } else {
  1001. res.redirect('/register')
  1002. }
  1003. })
  1004. webRouter.get(
  1005. '/admin',
  1006. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1007. AdminController.index
  1008. )
  1009. if (!Features.hasFeature('saas')) {
  1010. webRouter.post(
  1011. '/admin/openEditor',
  1012. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1013. AdminController.openEditor
  1014. )
  1015. webRouter.post(
  1016. '/admin/closeEditor',
  1017. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1018. AdminController.closeEditor
  1019. )
  1020. webRouter.post(
  1021. '/admin/disconnectAllUsers',
  1022. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1023. AdminController.disconnectAllUsers
  1024. )
  1025. }
  1026. webRouter.post(
  1027. '/admin/flushProjectToTpds',
  1028. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1029. AdminController.flushProjectToTpds
  1030. )
  1031. webRouter.post(
  1032. '/admin/pollDropboxForUser',
  1033. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1034. AdminController.pollDropboxForUser
  1035. )
  1036. webRouter.post(
  1037. '/admin/messages',
  1038. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1039. AdminController.createMessage
  1040. )
  1041. webRouter.post(
  1042. '/admin/messages/clear',
  1043. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1044. AdminController.clearMessages
  1045. )
  1046. privateApiRouter.get('/perfTest', (req, res) => {
  1047. plainTextResponse(res, 'hello')
  1048. })
  1049. publicApiRouter.get('/status', (req, res) => {
  1050. if (Settings.shuttingDown) {
  1051. res.sendStatus(503) // Service unavailable
  1052. } else if (!Settings.siteIsOpen) {
  1053. plainTextResponse(res, 'web site is closed (web)')
  1054. } else if (!Settings.editorIsOpen) {
  1055. plainTextResponse(res, 'web editor is closed (web)')
  1056. } else {
  1057. plainTextResponse(res, 'web is alive (web)')
  1058. }
  1059. })
  1060. privateApiRouter.get('/status', (req, res) => {
  1061. plainTextResponse(res, 'web is alive (api)')
  1062. })
  1063. // used by kubernetes health-check and acceptance tests
  1064. webRouter.get('/dev/csrf', (req, res) => {
  1065. plainTextResponse(res, res.locals.csrfToken)
  1066. })
  1067. publicApiRouter.get(
  1068. '/health_check',
  1069. HealthCheckController.checkActiveHandles,
  1070. HealthCheckController.check
  1071. )
  1072. privateApiRouter.get(
  1073. '/health_check',
  1074. HealthCheckController.checkActiveHandles,
  1075. HealthCheckController.checkApi
  1076. )
  1077. publicApiRouter.get(
  1078. '/health_check/api',
  1079. HealthCheckController.checkActiveHandles,
  1080. HealthCheckController.checkApi
  1081. )
  1082. privateApiRouter.get(
  1083. '/health_check/api',
  1084. HealthCheckController.checkActiveHandles,
  1085. HealthCheckController.checkApi
  1086. )
  1087. publicApiRouter.get(
  1088. '/health_check/full',
  1089. HealthCheckController.checkActiveHandles,
  1090. HealthCheckController.check
  1091. )
  1092. privateApiRouter.get(
  1093. '/health_check/full',
  1094. HealthCheckController.checkActiveHandles,
  1095. HealthCheckController.check
  1096. )
  1097. publicApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1098. privateApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1099. publicApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1100. privateApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1101. webRouter.get(
  1102. '/status/compiler/:Project_id',
  1103. RateLimiterMiddleware.rateLimit(rateLimiters.statusCompiler),
  1104. AuthorizationMiddleware.ensureUserCanReadProject,
  1105. function (req, res) {
  1106. const projectId = req.params.Project_id
  1107. // use a valid user id for testing
  1108. const testUserId = '123456789012345678901234'
  1109. const sendRes = _.once(function (statusCode, message) {
  1110. res.status(statusCode)
  1111. plainTextResponse(res, message)
  1112. ClsiCookieManager.promises
  1113. .clearServerId(projectId, testUserId)
  1114. .catch(() => {})
  1115. }) // force every compile to a new server
  1116. // set a timeout
  1117. let handler = setTimeout(function () {
  1118. sendRes(500, 'Compiler timed out')
  1119. handler = null
  1120. }, 10000)
  1121. // run the compile
  1122. CompileManager.compile(
  1123. projectId,
  1124. testUserId,
  1125. {},
  1126. function (error, status) {
  1127. if (handler) {
  1128. clearTimeout(handler)
  1129. }
  1130. if (error) {
  1131. sendRes(500, `Compiler returned error ${error.message}`)
  1132. } else if (status === 'success') {
  1133. sendRes(200, 'Compiler returned in less than 10 seconds')
  1134. } else {
  1135. sendRes(500, `Compiler returned failure ${status}`)
  1136. }
  1137. }
  1138. )
  1139. }
  1140. )
  1141. webRouter.post('/error/client', function (req, res, next) {
  1142. logger.warn(
  1143. { err: req.body.error, meta: req.body.meta },
  1144. 'client side error'
  1145. )
  1146. metrics.inc('client-side-error')
  1147. res.sendStatus(204)
  1148. })
  1149. webRouter.get(
  1150. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})`,
  1151. RateLimiterMiddleware.rateLimit(rateLimiters.readOnlyToken),
  1152. AnalyticsRegistrationSourceMiddleware.setSource(
  1153. 'collaboration',
  1154. 'link-sharing'
  1155. ),
  1156. TokenAccessController.tokenAccessPage,
  1157. AnalyticsRegistrationSourceMiddleware.clearSource()
  1158. )
  1159. webRouter.get(
  1160. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})`,
  1161. RateLimiterMiddleware.rateLimit(rateLimiters.readAndWriteToken),
  1162. AnalyticsRegistrationSourceMiddleware.setSource(
  1163. 'collaboration',
  1164. 'link-sharing'
  1165. ),
  1166. TokenAccessController.tokenAccessPage,
  1167. AnalyticsRegistrationSourceMiddleware.clearSource()
  1168. )
  1169. webRouter.post(
  1170. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})/grant`,
  1171. RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadWrite),
  1172. TokenAccessController.grantTokenAccessReadAndWrite
  1173. )
  1174. webRouter.post(
  1175. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})/grant`,
  1176. RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadOnly),
  1177. TokenAccessController.grantTokenAccessReadOnly
  1178. )
  1179. webRouter.get('/unsupported-browser', renderUnsupportedBrowserPage)
  1180. webRouter.get('*', ErrorController.notFound)
  1181. }
  1182. export default { initialize, rateLimiters }