router.mjs 41 KB

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