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