router.js 43 KB

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