router.js 42 KB

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