router.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  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.post(
  398. '/tutorial/:tutorialKey/postpone',
  399. AuthenticationController.requireLogin(),
  400. TutorialController.postponeTutorial
  401. )
  402. webRouter.get(
  403. '/user/projects',
  404. AuthenticationController.requireLogin(),
  405. ProjectController.userProjectsJson
  406. )
  407. webRouter.get(
  408. '/project/:Project_id/entities',
  409. AuthenticationController.requireLogin(),
  410. AuthorizationMiddleware.ensureUserCanReadProject,
  411. ProjectController.projectEntitiesJson
  412. )
  413. webRouter.get(
  414. '/project',
  415. AuthenticationController.requireLogin(),
  416. RateLimiterMiddleware.rateLimit(rateLimiters.openDashboard),
  417. ProjectListController.projectListPage
  418. )
  419. webRouter.post(
  420. '/project/new',
  421. AuthenticationController.requireLogin(),
  422. RateLimiterMiddleware.rateLimit(rateLimiters.createProject),
  423. ProjectController.newProject
  424. )
  425. webRouter.post(
  426. '/api/project',
  427. AuthenticationController.requireLogin(),
  428. RateLimiterMiddleware.rateLimit(rateLimiters.getProjects),
  429. ProjectListController.getProjectsJson
  430. )
  431. for (const route of [
  432. // Keep the old route for continuous metrics
  433. '/Project/:Project_id',
  434. // New route for pdf-detach
  435. '/Project/:Project_id/:detachRole(detacher|detached)',
  436. ]) {
  437. webRouter.get(
  438. route,
  439. RateLimiterMiddleware.rateLimit(openProjectRateLimiter, {
  440. params: ['Project_id'],
  441. }),
  442. AuthenticationController.validateUserSession(),
  443. AuthorizationMiddleware.ensureUserCanReadProject,
  444. ProjectController.loadEditor
  445. )
  446. }
  447. webRouter.head(
  448. '/Project/:Project_id/file/:File_id',
  449. AuthorizationMiddleware.ensureUserCanReadProject,
  450. FileStoreController.getFileHead
  451. )
  452. webRouter.get(
  453. '/Project/:Project_id/file/:File_id',
  454. AuthorizationMiddleware.ensureUserCanReadProject,
  455. FileStoreController.getFile
  456. )
  457. webRouter.post(
  458. '/project/:Project_id/settings',
  459. validate({
  460. body: Joi.object({
  461. publicAccessLevel: Joi.string()
  462. .valid(PublicAccessLevels.PRIVATE, PublicAccessLevels.TOKEN_BASED)
  463. .optional(),
  464. }),
  465. }),
  466. AuthorizationMiddleware.ensureUserCanWriteProjectSettings,
  467. ProjectController.updateProjectSettings
  468. )
  469. webRouter.post(
  470. '/project/:Project_id/settings/admin',
  471. AuthenticationController.requireLogin(),
  472. AuthorizationMiddleware.ensureUserCanAdminProject,
  473. ProjectController.updateProjectAdminSettings
  474. )
  475. webRouter.post(
  476. '/project/:Project_id/compile',
  477. RateLimiterMiddleware.rateLimit(rateLimiters.compileProjectHttp, {
  478. params: ['Project_id'],
  479. }),
  480. AuthorizationMiddleware.ensureUserCanReadProject,
  481. CompileController.compile
  482. )
  483. webRouter.post(
  484. '/project/:Project_id/compile/stop',
  485. AuthorizationMiddleware.ensureUserCanReadProject,
  486. CompileController.stopCompile
  487. )
  488. // LEGACY: Used by the web download buttons, adds filename header, TODO: remove at some future date
  489. webRouter.get(
  490. '/project/:Project_id/output/output.pdf',
  491. AuthorizationMiddleware.ensureUserCanReadProject,
  492. CompileController.downloadPdf
  493. )
  494. // PDF Download button
  495. webRouter.get(
  496. /^\/download\/project\/([^/]*)\/output\/output\.pdf$/,
  497. function (req, res, next) {
  498. const params = { Project_id: req.params[0] }
  499. req.params = params
  500. next()
  501. },
  502. AuthorizationMiddleware.ensureUserCanReadProject,
  503. CompileController.downloadPdf
  504. )
  505. // PDF Download button for specific build
  506. webRouter.get(
  507. /^\/download\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/output\.pdf$/,
  508. function (req, res, next) {
  509. const params = {
  510. Project_id: req.params[0],
  511. build_id: req.params[1],
  512. }
  513. req.params = params
  514. next()
  515. },
  516. AuthorizationMiddleware.ensureUserCanReadProject,
  517. CompileController.downloadPdf
  518. )
  519. // Align with limits defined in CompileController.downloadPdf
  520. const rateLimiterMiddlewareOutputFiles = RateLimiterMiddleware.rateLimit(
  521. rateLimiters.miscOutputDownload,
  522. { params: ['Project_id'] }
  523. )
  524. // Used by the pdf viewers
  525. webRouter.get(
  526. /^\/project\/([^/]*)\/output\/(.*)$/,
  527. function (req, res, next) {
  528. const params = {
  529. Project_id: req.params[0],
  530. file: req.params[1],
  531. }
  532. req.params = params
  533. next()
  534. },
  535. rateLimiterMiddlewareOutputFiles,
  536. AuthorizationMiddleware.ensureUserCanReadProject,
  537. CompileController.getFileFromClsi
  538. )
  539. // direct url access to output files for a specific build (query string not required)
  540. webRouter.get(
  541. /^\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  542. function (req, res, next) {
  543. const params = {
  544. Project_id: req.params[0],
  545. build_id: req.params[1],
  546. file: req.params[2],
  547. }
  548. req.params = params
  549. next()
  550. },
  551. rateLimiterMiddlewareOutputFiles,
  552. AuthorizationMiddleware.ensureUserCanReadProject,
  553. CompileController.getFileFromClsi
  554. )
  555. // direct url access to output files for user but no build, to retrieve files when build fails
  556. webRouter.get(
  557. /^\/project\/([^/]*)\/user\/([0-9a-f-]+)\/output\/(.*)$/,
  558. function (req, res, next) {
  559. const params = {
  560. Project_id: req.params[0],
  561. user_id: req.params[1],
  562. file: req.params[2],
  563. }
  564. req.params = params
  565. next()
  566. },
  567. rateLimiterMiddlewareOutputFiles,
  568. AuthorizationMiddleware.ensureUserCanReadProject,
  569. CompileController.getFileFromClsi
  570. )
  571. // direct url access to output files for a specific user and build (query string not required)
  572. webRouter.get(
  573. /^\/project\/([^/]*)\/user\/([0-9a-f]+)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  574. function (req, res, next) {
  575. const params = {
  576. Project_id: req.params[0],
  577. user_id: req.params[1],
  578. build_id: req.params[2],
  579. file: req.params[3],
  580. }
  581. req.params = params
  582. next()
  583. },
  584. rateLimiterMiddlewareOutputFiles,
  585. AuthorizationMiddleware.ensureUserCanReadProject,
  586. CompileController.getFileFromClsi
  587. )
  588. webRouter.delete(
  589. '/project/:Project_id/output',
  590. validate({ query: { clsiserverid: Joi.string() } }),
  591. AuthorizationMiddleware.ensureUserCanReadProject,
  592. CompileController.deleteAuxFiles
  593. )
  594. webRouter.get(
  595. '/project/:Project_id/sync/code',
  596. AuthorizationMiddleware.ensureUserCanReadProject,
  597. CompileController.proxySyncCode
  598. )
  599. webRouter.get(
  600. '/project/:Project_id/sync/pdf',
  601. AuthorizationMiddleware.ensureUserCanReadProject,
  602. CompileController.proxySyncPdf
  603. )
  604. webRouter.get(
  605. '/project/:Project_id/wordcount',
  606. validate({ query: { clsiserverid: Joi.string() } }),
  607. AuthorizationMiddleware.ensureUserCanReadProject,
  608. CompileController.wordCount
  609. )
  610. webRouter.post(
  611. '/Project/:Project_id/archive',
  612. AuthenticationController.requireLogin(),
  613. AuthorizationMiddleware.ensureUserCanReadProject,
  614. ProjectController.archiveProject
  615. )
  616. webRouter.delete(
  617. '/Project/:Project_id/archive',
  618. AuthenticationController.requireLogin(),
  619. AuthorizationMiddleware.ensureUserCanReadProject,
  620. ProjectController.unarchiveProject
  621. )
  622. webRouter.post(
  623. '/project/:project_id/trash',
  624. AuthenticationController.requireLogin(),
  625. AuthorizationMiddleware.ensureUserCanReadProject,
  626. ProjectController.trashProject
  627. )
  628. webRouter.delete(
  629. '/project/:project_id/trash',
  630. AuthenticationController.requireLogin(),
  631. AuthorizationMiddleware.ensureUserCanReadProject,
  632. ProjectController.untrashProject
  633. )
  634. webRouter.delete(
  635. '/Project/:Project_id',
  636. AuthenticationController.requireLogin(),
  637. AuthorizationMiddleware.ensureUserCanAdminProject,
  638. ProjectController.deleteProject
  639. )
  640. webRouter.post(
  641. '/Project/:Project_id/restore',
  642. AuthenticationController.requireLogin(),
  643. AuthorizationMiddleware.ensureUserCanAdminProject,
  644. ProjectController.restoreProject
  645. )
  646. webRouter.post(
  647. '/Project/:Project_id/clone',
  648. AuthorizationMiddleware.ensureUserCanReadProject,
  649. ProjectController.cloneProject
  650. )
  651. webRouter.post(
  652. '/project/:Project_id/rename',
  653. AuthenticationController.requireLogin(),
  654. AuthorizationMiddleware.ensureUserCanAdminProject,
  655. ProjectController.renameProject
  656. )
  657. webRouter.get(
  658. '/project/:Project_id/updates',
  659. AuthorizationMiddleware.blockRestrictedUserFromProject,
  660. AuthorizationMiddleware.ensureUserCanReadProject,
  661. HistoryController.proxyToHistoryApiAndInjectUserDetails
  662. )
  663. webRouter.get(
  664. '/project/:Project_id/doc/:doc_id/diff',
  665. AuthorizationMiddleware.blockRestrictedUserFromProject,
  666. AuthorizationMiddleware.ensureUserCanReadProject,
  667. HistoryController.proxyToHistoryApi
  668. )
  669. webRouter.get(
  670. '/project/:Project_id/diff',
  671. AuthorizationMiddleware.blockRestrictedUserFromProject,
  672. AuthorizationMiddleware.ensureUserCanReadProject,
  673. HistoryController.proxyToHistoryApiAndInjectUserDetails
  674. )
  675. webRouter.get(
  676. '/project/:Project_id/filetree/diff',
  677. AuthorizationMiddleware.blockRestrictedUserFromProject,
  678. AuthorizationMiddleware.ensureUserCanReadProject,
  679. HistoryController.proxyToHistoryApi
  680. )
  681. webRouter.post(
  682. '/project/:project_id/restore_file',
  683. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  684. HistoryController.restoreFileFromV2
  685. )
  686. webRouter.get(
  687. '/project/:project_id/version/:version/zip',
  688. RateLimiterMiddleware.rateLimit(rateLimiters.downloadProjectRevision),
  689. AuthorizationMiddleware.blockRestrictedUserFromProject,
  690. AuthorizationMiddleware.ensureUserCanReadProject,
  691. HistoryController.downloadZipOfVersion
  692. )
  693. privateApiRouter.post(
  694. '/project/:Project_id/history/resync',
  695. AuthenticationController.requirePrivateApiAuth(),
  696. HistoryController.resyncProjectHistory
  697. )
  698. webRouter.get(
  699. '/project/:Project_id/labels',
  700. AuthorizationMiddleware.blockRestrictedUserFromProject,
  701. AuthorizationMiddleware.ensureUserCanReadProject,
  702. HistoryController.getLabels
  703. )
  704. webRouter.post(
  705. '/project/:Project_id/labels',
  706. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  707. HistoryController.createLabel
  708. )
  709. webRouter.delete(
  710. '/project/:Project_id/labels/:label_id',
  711. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  712. HistoryController.deleteLabel
  713. )
  714. webRouter.post(
  715. '/project/:project_id/export/:brand_variation_id',
  716. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  717. ExportsController.exportProject
  718. )
  719. webRouter.get(
  720. '/project/:project_id/export/:export_id',
  721. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  722. ExportsController.exportStatus
  723. )
  724. webRouter.get(
  725. '/project/:project_id/export/:export_id/:type',
  726. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  727. ExportsController.exportDownload
  728. )
  729. webRouter.get(
  730. '/Project/:Project_id/download/zip',
  731. RateLimiterMiddleware.rateLimit(rateLimiters.zipDownload, {
  732. params: ['Project_id'],
  733. }),
  734. AuthorizationMiddleware.ensureUserCanReadProject,
  735. ProjectDownloadsController.downloadProject
  736. )
  737. webRouter.get(
  738. '/project/download/zip',
  739. AuthenticationController.requireLogin(),
  740. RateLimiterMiddleware.rateLimit(rateLimiters.multipleProjectsZipDownload),
  741. AuthorizationMiddleware.ensureUserCanReadMultipleProjects,
  742. ProjectDownloadsController.downloadMultipleProjects
  743. )
  744. webRouter.get(
  745. '/project/:project_id/metadata',
  746. AuthorizationMiddleware.ensureUserCanReadProject,
  747. Settings.allowAnonymousReadAndWriteSharing
  748. ? (req, res, next) => {
  749. next()
  750. }
  751. : AuthenticationController.requireLogin(),
  752. MetaController.getMetadata
  753. )
  754. webRouter.post(
  755. '/project/:project_id/doc/:doc_id/metadata',
  756. AuthorizationMiddleware.ensureUserCanReadProject,
  757. Settings.allowAnonymousReadAndWriteSharing
  758. ? (req, res, next) => {
  759. next()
  760. }
  761. : AuthenticationController.requireLogin(),
  762. MetaController.broadcastMetadataForDoc
  763. )
  764. privateApiRouter.post(
  765. '/internal/expire-deleted-projects-after-duration',
  766. AuthenticationController.requirePrivateApiAuth(),
  767. ProjectController.expireDeletedProjectsAfterDuration
  768. )
  769. privateApiRouter.post(
  770. '/internal/expire-deleted-users-after-duration',
  771. AuthenticationController.requirePrivateApiAuth(),
  772. UserController.expireDeletedUsersAfterDuration
  773. )
  774. privateApiRouter.post(
  775. '/internal/project/:projectId/expire-deleted-project',
  776. AuthenticationController.requirePrivateApiAuth(),
  777. ProjectController.expireDeletedProject
  778. )
  779. privateApiRouter.post(
  780. '/internal/users/:userId/expire',
  781. AuthenticationController.requirePrivateApiAuth(),
  782. UserController.expireDeletedUser
  783. )
  784. privateApiRouter.get(
  785. '/user/:userId/tag',
  786. AuthenticationController.requirePrivateApiAuth(),
  787. TagsController.apiGetAllTags
  788. )
  789. webRouter.get(
  790. '/tag',
  791. AuthenticationController.requireLogin(),
  792. TagsController.getAllTags
  793. )
  794. webRouter.post(
  795. '/tag',
  796. AuthenticationController.requireLogin(),
  797. RateLimiterMiddleware.rateLimit(rateLimiters.createTag),
  798. validate({
  799. body: Joi.object({
  800. name: Joi.string().required(),
  801. color: Joi.string(),
  802. }),
  803. }),
  804. TagsController.createTag
  805. )
  806. webRouter.post(
  807. '/tag/:tagId/rename',
  808. AuthenticationController.requireLogin(),
  809. RateLimiterMiddleware.rateLimit(rateLimiters.renameTag),
  810. validate({
  811. body: Joi.object({
  812. name: Joi.string().required(),
  813. }),
  814. }),
  815. TagsController.renameTag
  816. )
  817. webRouter.post(
  818. '/tag/:tagId/edit',
  819. AuthenticationController.requireLogin(),
  820. RateLimiterMiddleware.rateLimit(rateLimiters.renameTag),
  821. validate({
  822. body: Joi.object({
  823. name: Joi.string().required(),
  824. color: Joi.string(),
  825. }),
  826. }),
  827. TagsController.editTag
  828. )
  829. webRouter.delete(
  830. '/tag/:tagId',
  831. AuthenticationController.requireLogin(),
  832. RateLimiterMiddleware.rateLimit(rateLimiters.deleteTag),
  833. TagsController.deleteTag
  834. )
  835. webRouter.post(
  836. '/tag/:tagId/project/:projectId',
  837. AuthenticationController.requireLogin(),
  838. RateLimiterMiddleware.rateLimit(rateLimiters.addProjectToTag),
  839. TagsController.addProjectToTag
  840. )
  841. webRouter.post(
  842. '/tag/:tagId/projects',
  843. AuthenticationController.requireLogin(),
  844. RateLimiterMiddleware.rateLimit(rateLimiters.addProjectsToTag),
  845. validate({
  846. body: Joi.object({
  847. projectIds: Joi.array().items(Joi.string()).required(),
  848. }),
  849. }),
  850. TagsController.addProjectsToTag
  851. )
  852. webRouter.delete(
  853. '/tag/:tagId/project/:projectId',
  854. AuthenticationController.requireLogin(),
  855. RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectFromTag),
  856. TagsController.removeProjectFromTag
  857. )
  858. webRouter.delete(
  859. '/tag/:tagId/projects',
  860. AuthenticationController.requireLogin(),
  861. RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectsFromTag),
  862. validate({
  863. body: Joi.object({
  864. projectIds: Joi.array().items(Joi.string()).required(),
  865. }),
  866. }),
  867. TagsController.removeProjectsFromTag
  868. )
  869. webRouter.get(
  870. '/notifications',
  871. AuthenticationController.requireLogin(),
  872. NotificationsController.getAllUnreadNotifications
  873. )
  874. webRouter.delete(
  875. '/notifications/:notificationId',
  876. AuthenticationController.requireLogin(),
  877. NotificationsController.markNotificationAsRead
  878. )
  879. // Deprecated in favour of /internal/project/:project_id but still used by versioning
  880. privateApiRouter.get(
  881. '/project/:project_id/details',
  882. AuthenticationController.requirePrivateApiAuth(),
  883. ProjectApiController.getProjectDetails
  884. )
  885. // New 'stable' /internal API end points
  886. privateApiRouter.get(
  887. '/internal/project/:project_id',
  888. AuthenticationController.requirePrivateApiAuth(),
  889. ProjectApiController.getProjectDetails
  890. )
  891. privateApiRouter.get(
  892. '/internal/project/:Project_id/zip',
  893. AuthenticationController.requirePrivateApiAuth(),
  894. ProjectDownloadsController.downloadProject
  895. )
  896. privateApiRouter.get(
  897. '/internal/project/:project_id/compile/pdf',
  898. AuthenticationController.requirePrivateApiAuth(),
  899. CompileController.compileAndDownloadPdf
  900. )
  901. privateApiRouter.post(
  902. '/internal/deactivateOldProjects',
  903. AuthenticationController.requirePrivateApiAuth(),
  904. InactiveProjectController.deactivateOldProjects
  905. )
  906. privateApiRouter.post(
  907. '/internal/project/:project_id/deactivate',
  908. AuthenticationController.requirePrivateApiAuth(),
  909. InactiveProjectController.deactivateProject
  910. )
  911. privateApiRouter.get(
  912. /^\/internal\/project\/([^/]*)\/output\/(.*)$/,
  913. function (req, res, next) {
  914. const params = {
  915. Project_id: req.params[0],
  916. file: req.params[1],
  917. }
  918. req.params = params
  919. next()
  920. },
  921. AuthenticationController.requirePrivateApiAuth(),
  922. CompileController.getFileFromClsi
  923. )
  924. privateApiRouter.get(
  925. '/project/:Project_id/doc/:doc_id',
  926. AuthenticationController.requirePrivateApiAuth(),
  927. DocumentController.getDocument
  928. )
  929. privateApiRouter.post(
  930. '/project/:Project_id/doc/:doc_id',
  931. AuthenticationController.requirePrivateApiAuth(),
  932. DocumentController.setDocument
  933. )
  934. privateApiRouter.post(
  935. '/user/:user_id/project/new',
  936. AuthenticationController.requirePrivateApiAuth(),
  937. TpdsController.createProject
  938. )
  939. privateApiRouter.post(
  940. '/tpds/folder-update',
  941. AuthenticationController.requirePrivateApiAuth(),
  942. TpdsController.updateFolder
  943. )
  944. privateApiRouter.post(
  945. '/user/:user_id/update/*',
  946. AuthenticationController.requirePrivateApiAuth(),
  947. TpdsController.mergeUpdate
  948. )
  949. privateApiRouter.delete(
  950. '/user/:user_id/update/*',
  951. AuthenticationController.requirePrivateApiAuth(),
  952. TpdsController.deleteUpdate
  953. )
  954. privateApiRouter.post(
  955. '/project/:project_id/user/:user_id/update/*',
  956. AuthenticationController.requirePrivateApiAuth(),
  957. TpdsController.mergeUpdate
  958. )
  959. privateApiRouter.delete(
  960. '/project/:project_id/user/:user_id/update/*',
  961. AuthenticationController.requirePrivateApiAuth(),
  962. TpdsController.deleteUpdate
  963. )
  964. privateApiRouter.post(
  965. '/project/:project_id/contents/*',
  966. AuthenticationController.requirePrivateApiAuth(),
  967. TpdsController.updateProjectContents
  968. )
  969. privateApiRouter.delete(
  970. '/project/:project_id/contents/*',
  971. AuthenticationController.requirePrivateApiAuth(),
  972. TpdsController.deleteProjectContents
  973. )
  974. webRouter.post(
  975. '/spelling/check',
  976. AuthenticationController.requireLogin(),
  977. SpellingController.proxyRequestToSpellingApi
  978. )
  979. webRouter.post(
  980. '/spelling/learn',
  981. validate({
  982. body: Joi.object({
  983. word: Joi.string().required(),
  984. }),
  985. }),
  986. AuthenticationController.requireLogin(),
  987. SpellingController.learn
  988. )
  989. webRouter.post(
  990. '/spelling/unlearn',
  991. validate({
  992. body: Joi.object({
  993. word: Joi.string().required(),
  994. }),
  995. }),
  996. AuthenticationController.requireLogin(),
  997. SpellingController.unlearn
  998. )
  999. webRouter.get(
  1000. '/project/:project_id/messages',
  1001. AuthorizationMiddleware.blockRestrictedUserFromProject,
  1002. AuthorizationMiddleware.ensureUserCanReadProject,
  1003. ChatController.getMessages
  1004. )
  1005. webRouter.post(
  1006. '/project/:project_id/messages',
  1007. AuthorizationMiddleware.blockRestrictedUserFromProject,
  1008. AuthorizationMiddleware.ensureUserCanReadProject,
  1009. RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage),
  1010. ChatController.sendMessage
  1011. )
  1012. webRouter.post(
  1013. '/project/:Project_id/references/indexAll',
  1014. AuthorizationMiddleware.ensureUserCanReadProject,
  1015. RateLimiterMiddleware.rateLimit(rateLimiters.indexAllProjectReferences),
  1016. ReferencesController.indexAll
  1017. )
  1018. // disable beta program while v2 is in beta
  1019. webRouter.get(
  1020. '/beta/participate',
  1021. AuthenticationController.requireLogin(),
  1022. BetaProgramController.optInPage
  1023. )
  1024. webRouter.post(
  1025. '/beta/opt-in',
  1026. AuthenticationController.requireLogin(),
  1027. BetaProgramController.optIn
  1028. )
  1029. webRouter.post(
  1030. '/beta/opt-out',
  1031. AuthenticationController.requireLogin(),
  1032. BetaProgramController.optOut
  1033. )
  1034. // New "api" endpoints. Started as a way for v1 to call over to v2 (for
  1035. // long-term features, as opposed to the nominally temporary ones in the
  1036. // overleaf-integration module), but may expand beyond that role.
  1037. publicApiRouter.post(
  1038. '/api/clsi/compile/:submission_id',
  1039. AuthenticationController.requirePrivateApiAuth(),
  1040. CompileController.compileSubmission
  1041. )
  1042. publicApiRouter.get(
  1043. /^\/api\/clsi\/compile\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  1044. function (req, res, next) {
  1045. const params = {
  1046. submission_id: req.params[0],
  1047. build_id: req.params[1],
  1048. file: req.params[2],
  1049. }
  1050. req.params = params
  1051. next()
  1052. },
  1053. AuthenticationController.requirePrivateApiAuth(),
  1054. CompileController.getFileFromClsiWithoutUser
  1055. )
  1056. publicApiRouter.post(
  1057. '/api/institutions/confirm_university_domain',
  1058. AuthenticationController.requirePrivateApiAuth(),
  1059. InstitutionsController.confirmDomain
  1060. )
  1061. webRouter.get('/chrome', function (req, res, next) {
  1062. // Match v1 behaviour - this is used for a Chrome web app
  1063. if (SessionManager.isUserLoggedIn(req.session)) {
  1064. res.redirect('/project')
  1065. } else {
  1066. res.redirect('/register')
  1067. }
  1068. })
  1069. webRouter.get(
  1070. '/admin',
  1071. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1072. AdminController.index
  1073. )
  1074. if (!Features.hasFeature('saas')) {
  1075. webRouter.post(
  1076. '/admin/openEditor',
  1077. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1078. AdminController.openEditor
  1079. )
  1080. webRouter.post(
  1081. '/admin/closeEditor',
  1082. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1083. AdminController.closeEditor
  1084. )
  1085. webRouter.post(
  1086. '/admin/disconnectAllUsers',
  1087. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1088. AdminController.disconnectAllUsers
  1089. )
  1090. }
  1091. webRouter.post(
  1092. '/admin/flushProjectToTpds',
  1093. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1094. AdminController.flushProjectToTpds
  1095. )
  1096. webRouter.post(
  1097. '/admin/pollDropboxForUser',
  1098. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1099. AdminController.pollDropboxForUser
  1100. )
  1101. webRouter.post(
  1102. '/admin/messages',
  1103. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1104. AdminController.createMessage
  1105. )
  1106. webRouter.post(
  1107. '/admin/messages/clear',
  1108. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1109. AdminController.clearMessages
  1110. )
  1111. privateApiRouter.get('/perfTest', (req, res) => {
  1112. plainTextResponse(res, 'hello')
  1113. })
  1114. publicApiRouter.get('/status', (req, res) => {
  1115. if (Settings.shuttingDown) {
  1116. res.sendStatus(503) // Service unavailable
  1117. } else if (!Settings.siteIsOpen) {
  1118. plainTextResponse(res, 'web site is closed (web)')
  1119. } else if (!Settings.editorIsOpen) {
  1120. plainTextResponse(res, 'web editor is closed (web)')
  1121. } else {
  1122. plainTextResponse(res, 'web sharelatex is alive (web)')
  1123. }
  1124. })
  1125. privateApiRouter.get('/status', (req, res) => {
  1126. plainTextResponse(res, 'web sharelatex is alive (api)')
  1127. })
  1128. // used by kubernetes health-check and acceptance tests
  1129. webRouter.get('/dev/csrf', (req, res) => {
  1130. plainTextResponse(res, res.locals.csrfToken)
  1131. })
  1132. publicApiRouter.get(
  1133. '/health_check',
  1134. HealthCheckController.checkActiveHandles,
  1135. HealthCheckController.check
  1136. )
  1137. privateApiRouter.get(
  1138. '/health_check',
  1139. HealthCheckController.checkActiveHandles,
  1140. HealthCheckController.checkApi
  1141. )
  1142. publicApiRouter.get(
  1143. '/health_check/api',
  1144. HealthCheckController.checkActiveHandles,
  1145. HealthCheckController.checkApi
  1146. )
  1147. privateApiRouter.get(
  1148. '/health_check/api',
  1149. HealthCheckController.checkActiveHandles,
  1150. HealthCheckController.checkApi
  1151. )
  1152. publicApiRouter.get(
  1153. '/health_check/full',
  1154. HealthCheckController.checkActiveHandles,
  1155. HealthCheckController.check
  1156. )
  1157. privateApiRouter.get(
  1158. '/health_check/full',
  1159. HealthCheckController.checkActiveHandles,
  1160. HealthCheckController.check
  1161. )
  1162. publicApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1163. privateApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1164. publicApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1165. privateApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1166. webRouter.get(
  1167. '/status/compiler/:Project_id',
  1168. RateLimiterMiddleware.rateLimit(rateLimiters.statusCompiler),
  1169. AuthorizationMiddleware.ensureUserCanReadProject,
  1170. function (req, res) {
  1171. const projectId = req.params.Project_id
  1172. // use a valid user id for testing
  1173. const testUserId = '123456789012345678901234'
  1174. const sendRes = _.once(function (statusCode, message) {
  1175. res.status(statusCode)
  1176. plainTextResponse(res, message)
  1177. ClsiCookieManager.clearServerId(projectId, testUserId, () => {})
  1178. }) // force every compile to a new server
  1179. // set a timeout
  1180. let handler = setTimeout(function () {
  1181. sendRes(500, 'Compiler timed out')
  1182. handler = null
  1183. }, 10000)
  1184. // run the compile
  1185. CompileManager.compile(
  1186. projectId,
  1187. testUserId,
  1188. {},
  1189. function (error, status) {
  1190. if (handler) {
  1191. clearTimeout(handler)
  1192. }
  1193. if (error) {
  1194. sendRes(500, `Compiler returned error ${error.message}`)
  1195. } else if (status === 'success') {
  1196. sendRes(200, 'Compiler returned in less than 10 seconds')
  1197. } else {
  1198. sendRes(500, `Compiler returned failure ${status}`)
  1199. }
  1200. }
  1201. )
  1202. }
  1203. )
  1204. webRouter.get('/no-cache', function (req, res, next) {
  1205. res.header('Cache-Control', 'max-age=0')
  1206. res.sendStatus(404)
  1207. })
  1208. webRouter.get('/oops-express', (req, res, next) =>
  1209. next(new Error('Test error'))
  1210. )
  1211. webRouter.get('/oops-internal', function (req, res, next) {
  1212. throw new Error('Test error')
  1213. })
  1214. webRouter.get('/oops-mongo', (req, res, next) =>
  1215. require('./models/Project').Project.findOne({}, function () {
  1216. throw new Error('Test error')
  1217. })
  1218. )
  1219. privateApiRouter.get('/opps-small', function (req, res, next) {
  1220. logger.err('test error occured')
  1221. res.sendStatus(200)
  1222. })
  1223. webRouter.post('/error/client', function (req, res, next) {
  1224. logger.warn(
  1225. { err: req.body.error, meta: req.body.meta },
  1226. 'client side error'
  1227. )
  1228. metrics.inc('client-side-error')
  1229. res.sendStatus(204)
  1230. })
  1231. webRouter.get(
  1232. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})`,
  1233. RateLimiterMiddleware.rateLimit(rateLimiters.readOnlyToken),
  1234. AnalyticsRegistrationSourceMiddleware.setSource(
  1235. 'collaboration',
  1236. 'link-sharing'
  1237. ),
  1238. TokenAccessController.tokenAccessPage,
  1239. AnalyticsRegistrationSourceMiddleware.clearSource()
  1240. )
  1241. webRouter.get(
  1242. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})`,
  1243. RateLimiterMiddleware.rateLimit(rateLimiters.readAndWriteToken),
  1244. AnalyticsRegistrationSourceMiddleware.setSource(
  1245. 'collaboration',
  1246. 'link-sharing'
  1247. ),
  1248. TokenAccessController.tokenAccessPage,
  1249. AnalyticsRegistrationSourceMiddleware.clearSource()
  1250. )
  1251. webRouter.post(
  1252. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})/grant`,
  1253. RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadWrite),
  1254. TokenAccessController.grantTokenAccessReadAndWrite
  1255. )
  1256. webRouter.post(
  1257. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})/grant`,
  1258. RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadOnly),
  1259. TokenAccessController.grantTokenAccessReadOnly
  1260. )
  1261. webRouter.get('/unsupported-browser', renderUnsupportedBrowserPage)
  1262. webRouter.get('*', ErrorController.notFound)
  1263. }
  1264. module.exports = { initialize, rateLimiters }