router.js 42 KB

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