router.js 43 KB

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