router.js 42 KB

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