router.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380
  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.get(
  719. '/project/:project_id/version/:version/zip',
  720. RateLimiterMiddleware.rateLimit(rateLimiters.downloadProjectRevision),
  721. AuthorizationMiddleware.blockRestrictedUserFromProject,
  722. AuthorizationMiddleware.ensureUserCanReadProject,
  723. HistoryController.downloadZipOfVersion
  724. )
  725. privateApiRouter.post(
  726. '/project/:Project_id/history/resync',
  727. AuthenticationController.requirePrivateApiAuth(),
  728. HistoryController.resyncProjectHistory
  729. )
  730. webRouter.get(
  731. '/project/:Project_id/labels',
  732. AuthorizationMiddleware.blockRestrictedUserFromProject,
  733. AuthorizationMiddleware.ensureUserCanReadProject,
  734. HistoryController.getLabels
  735. )
  736. webRouter.post(
  737. '/project/:Project_id/labels',
  738. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  739. HistoryController.createLabel
  740. )
  741. webRouter.delete(
  742. '/project/:Project_id/labels/:label_id',
  743. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  744. HistoryController.deleteLabel
  745. )
  746. webRouter.post(
  747. '/project/:project_id/export/:brand_variation_id',
  748. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  749. ExportsController.exportProject
  750. )
  751. webRouter.get(
  752. '/project/:project_id/export/:export_id',
  753. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  754. ExportsController.exportStatus
  755. )
  756. webRouter.get(
  757. '/project/:project_id/export/:export_id/:type',
  758. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  759. ExportsController.exportDownload
  760. )
  761. webRouter.get(
  762. '/Project/:Project_id/download/zip',
  763. RateLimiterMiddleware.rateLimit(rateLimiters.zipDownload, {
  764. params: ['Project_id'],
  765. }),
  766. AuthorizationMiddleware.ensureUserCanReadProject,
  767. ProjectDownloadsController.downloadProject
  768. )
  769. webRouter.get(
  770. '/project/download/zip',
  771. AuthenticationController.requireLogin(),
  772. RateLimiterMiddleware.rateLimit(rateLimiters.multipleProjectsZipDownload),
  773. AuthorizationMiddleware.ensureUserCanReadMultipleProjects,
  774. ProjectDownloadsController.downloadMultipleProjects
  775. )
  776. webRouter.get(
  777. '/project/:project_id/metadata',
  778. AuthorizationMiddleware.ensureUserCanReadProject,
  779. Settings.allowAnonymousReadAndWriteSharing
  780. ? (req, res, next) => {
  781. next()
  782. }
  783. : AuthenticationController.requireLogin(),
  784. MetaController.getMetadata
  785. )
  786. webRouter.post(
  787. '/project/:project_id/doc/:doc_id/metadata',
  788. AuthorizationMiddleware.ensureUserCanReadProject,
  789. Settings.allowAnonymousReadAndWriteSharing
  790. ? (req, res, next) => {
  791. next()
  792. }
  793. : AuthenticationController.requireLogin(),
  794. MetaController.broadcastMetadataForDoc
  795. )
  796. privateApiRouter.post(
  797. '/internal/expire-deleted-projects-after-duration',
  798. AuthenticationController.requirePrivateApiAuth(),
  799. ProjectController.expireDeletedProjectsAfterDuration
  800. )
  801. privateApiRouter.post(
  802. '/internal/expire-deleted-users-after-duration',
  803. AuthenticationController.requirePrivateApiAuth(),
  804. UserController.expireDeletedUsersAfterDuration
  805. )
  806. privateApiRouter.post(
  807. '/internal/project/:projectId/expire-deleted-project',
  808. AuthenticationController.requirePrivateApiAuth(),
  809. ProjectController.expireDeletedProject
  810. )
  811. privateApiRouter.post(
  812. '/internal/users/:userId/expire',
  813. AuthenticationController.requirePrivateApiAuth(),
  814. UserController.expireDeletedUser
  815. )
  816. privateApiRouter.get(
  817. '/user/:userId/tag',
  818. AuthenticationController.requirePrivateApiAuth(),
  819. TagsController.apiGetAllTags
  820. )
  821. webRouter.get(
  822. '/tag',
  823. AuthenticationController.requireLogin(),
  824. TagsController.getAllTags
  825. )
  826. webRouter.post(
  827. '/tag',
  828. AuthenticationController.requireLogin(),
  829. RateLimiterMiddleware.rateLimit(rateLimiters.createTag),
  830. validate({
  831. body: Joi.object({
  832. name: Joi.string().required(),
  833. color: Joi.string(),
  834. }),
  835. }),
  836. TagsController.createTag
  837. )
  838. webRouter.post(
  839. '/tag/:tagId/rename',
  840. AuthenticationController.requireLogin(),
  841. RateLimiterMiddleware.rateLimit(rateLimiters.renameTag),
  842. validate({
  843. body: Joi.object({
  844. name: Joi.string().required(),
  845. }),
  846. }),
  847. TagsController.renameTag
  848. )
  849. webRouter.post(
  850. '/tag/:tagId/edit',
  851. AuthenticationController.requireLogin(),
  852. RateLimiterMiddleware.rateLimit(rateLimiters.renameTag),
  853. validate({
  854. body: Joi.object({
  855. name: Joi.string().required(),
  856. color: Joi.string(),
  857. }),
  858. }),
  859. TagsController.editTag
  860. )
  861. webRouter.delete(
  862. '/tag/:tagId',
  863. AuthenticationController.requireLogin(),
  864. RateLimiterMiddleware.rateLimit(rateLimiters.deleteTag),
  865. TagsController.deleteTag
  866. )
  867. webRouter.post(
  868. '/tag/:tagId/project/:projectId',
  869. AuthenticationController.requireLogin(),
  870. RateLimiterMiddleware.rateLimit(rateLimiters.addProjectToTag),
  871. TagsController.addProjectToTag
  872. )
  873. webRouter.post(
  874. '/tag/:tagId/projects',
  875. AuthenticationController.requireLogin(),
  876. RateLimiterMiddleware.rateLimit(rateLimiters.addProjectsToTag),
  877. validate({
  878. body: Joi.object({
  879. projectIds: Joi.array().items(Joi.string()).required(),
  880. }),
  881. }),
  882. TagsController.addProjectsToTag
  883. )
  884. webRouter.delete(
  885. '/tag/:tagId/project/:projectId',
  886. AuthenticationController.requireLogin(),
  887. RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectFromTag),
  888. TagsController.removeProjectFromTag
  889. )
  890. // Deprecated
  891. webRouter.delete(
  892. '/tag/:tagId/projects',
  893. AuthenticationController.requireLogin(),
  894. RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectsFromTag),
  895. validate({
  896. body: Joi.object({
  897. projectIds: Joi.array().items(Joi.string()).required(),
  898. }),
  899. }),
  900. TagsController.removeProjectsFromTag
  901. )
  902. webRouter.post(
  903. '/tag/:tagId/projects/remove',
  904. AuthenticationController.requireLogin(),
  905. RateLimiterMiddleware.rateLimit(rateLimiters.removeProjectsFromTag),
  906. validate({
  907. body: Joi.object({
  908. projectIds: Joi.array().items(Joi.string()).required(),
  909. }),
  910. }),
  911. TagsController.removeProjectsFromTag
  912. )
  913. webRouter.get(
  914. '/notifications',
  915. AuthenticationController.requireLogin(),
  916. NotificationsController.getAllUnreadNotifications
  917. )
  918. webRouter.delete(
  919. '/notifications/:notificationId',
  920. AuthenticationController.requireLogin(),
  921. NotificationsController.markNotificationAsRead
  922. )
  923. // Deprecated in favour of /internal/project/:project_id but still used by versioning
  924. privateApiRouter.get(
  925. '/project/:project_id/details',
  926. AuthenticationController.requirePrivateApiAuth(),
  927. ProjectApiController.getProjectDetails
  928. )
  929. // New 'stable' /internal API end points
  930. privateApiRouter.get(
  931. '/internal/project/:project_id',
  932. AuthenticationController.requirePrivateApiAuth(),
  933. ProjectApiController.getProjectDetails
  934. )
  935. privateApiRouter.get(
  936. '/internal/project/:Project_id/zip',
  937. AuthenticationController.requirePrivateApiAuth(),
  938. ProjectDownloadsController.downloadProject
  939. )
  940. privateApiRouter.get(
  941. '/internal/project/:project_id/compile/pdf',
  942. AuthenticationController.requirePrivateApiAuth(),
  943. CompileController.compileAndDownloadPdf
  944. )
  945. privateApiRouter.post(
  946. '/internal/deactivateOldProjects',
  947. AuthenticationController.requirePrivateApiAuth(),
  948. InactiveProjectController.deactivateOldProjects
  949. )
  950. privateApiRouter.post(
  951. '/internal/project/:project_id/deactivate',
  952. AuthenticationController.requirePrivateApiAuth(),
  953. InactiveProjectController.deactivateProject
  954. )
  955. privateApiRouter.get(
  956. /^\/internal\/project\/([^/]*)\/output\/(.*)$/,
  957. function (req, res, next) {
  958. const params = {
  959. Project_id: req.params[0],
  960. file: req.params[1],
  961. }
  962. req.params = params
  963. next()
  964. },
  965. AuthenticationController.requirePrivateApiAuth(),
  966. CompileController.getFileFromClsi
  967. )
  968. privateApiRouter.get(
  969. '/project/:Project_id/doc/:doc_id',
  970. AuthenticationController.requirePrivateApiAuth(),
  971. DocumentController.getDocument
  972. )
  973. privateApiRouter.post(
  974. '/project/:Project_id/doc/:doc_id',
  975. AuthenticationController.requirePrivateApiAuth(),
  976. DocumentController.setDocument
  977. )
  978. privateApiRouter.post(
  979. '/user/:user_id/project/new',
  980. AuthenticationController.requirePrivateApiAuth(),
  981. TpdsController.createProject
  982. )
  983. privateApiRouter.post(
  984. '/tpds/folder-update',
  985. AuthenticationController.requirePrivateApiAuth(),
  986. TpdsController.updateFolder
  987. )
  988. privateApiRouter.post(
  989. '/user/:user_id/update/*',
  990. AuthenticationController.requirePrivateApiAuth(),
  991. TpdsController.mergeUpdate
  992. )
  993. privateApiRouter.delete(
  994. '/user/:user_id/update/*',
  995. AuthenticationController.requirePrivateApiAuth(),
  996. TpdsController.deleteUpdate
  997. )
  998. privateApiRouter.post(
  999. '/project/:project_id/user/:user_id/update/*',
  1000. AuthenticationController.requirePrivateApiAuth(),
  1001. TpdsController.mergeUpdate
  1002. )
  1003. privateApiRouter.delete(
  1004. '/project/:project_id/user/:user_id/update/*',
  1005. AuthenticationController.requirePrivateApiAuth(),
  1006. TpdsController.deleteUpdate
  1007. )
  1008. privateApiRouter.post(
  1009. '/project/:project_id/contents/*',
  1010. AuthenticationController.requirePrivateApiAuth(),
  1011. TpdsController.updateProjectContents
  1012. )
  1013. privateApiRouter.delete(
  1014. '/project/:project_id/contents/*',
  1015. AuthenticationController.requirePrivateApiAuth(),
  1016. TpdsController.deleteProjectContents
  1017. )
  1018. webRouter.post(
  1019. '/spelling/check',
  1020. AuthenticationController.requireLogin(),
  1021. SpellingController.proxyRequestToSpellingApi
  1022. )
  1023. webRouter.post(
  1024. '/spelling/learn',
  1025. validate({
  1026. body: Joi.object({
  1027. word: Joi.string().required(),
  1028. }),
  1029. }),
  1030. AuthenticationController.requireLogin(),
  1031. SpellingController.learn
  1032. )
  1033. webRouter.post(
  1034. '/spelling/unlearn',
  1035. validate({
  1036. body: Joi.object({
  1037. word: Joi.string().required(),
  1038. }),
  1039. }),
  1040. AuthenticationController.requireLogin(),
  1041. SpellingController.unlearn
  1042. )
  1043. webRouter.get(
  1044. '/project/:project_id/messages',
  1045. AuthorizationMiddleware.blockRestrictedUserFromProject,
  1046. AuthorizationMiddleware.ensureUserCanReadProject,
  1047. ChatController.getMessages
  1048. )
  1049. webRouter.post(
  1050. '/project/:project_id/messages',
  1051. AuthorizationMiddleware.blockRestrictedUserFromProject,
  1052. AuthorizationMiddleware.ensureUserCanReadProject,
  1053. RateLimiterMiddleware.rateLimit(rateLimiters.sendChatMessage),
  1054. ChatController.sendMessage
  1055. )
  1056. webRouter.post(
  1057. '/project/:Project_id/references/indexAll',
  1058. AuthorizationMiddleware.ensureUserCanReadProject,
  1059. RateLimiterMiddleware.rateLimit(rateLimiters.indexAllProjectReferences),
  1060. ReferencesController.indexAll
  1061. )
  1062. // disable beta program while v2 is in beta
  1063. webRouter.get(
  1064. '/beta/participate',
  1065. AuthenticationController.requireLogin(),
  1066. BetaProgramController.optInPage
  1067. )
  1068. webRouter.post(
  1069. '/beta/opt-in',
  1070. AuthenticationController.requireLogin(),
  1071. BetaProgramController.optIn
  1072. )
  1073. webRouter.post(
  1074. '/beta/opt-out',
  1075. AuthenticationController.requireLogin(),
  1076. BetaProgramController.optOut
  1077. )
  1078. // New "api" endpoints. Started as a way for v1 to call over to v2 (for
  1079. // long-term features, as opposed to the nominally temporary ones in the
  1080. // overleaf-integration module), but may expand beyond that role.
  1081. publicApiRouter.post(
  1082. '/api/clsi/compile/:submission_id',
  1083. AuthenticationController.requirePrivateApiAuth(),
  1084. CompileController.compileSubmission
  1085. )
  1086. publicApiRouter.get(
  1087. /^\/api\/clsi\/compile\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  1088. function (req, res, next) {
  1089. const params = {
  1090. submission_id: req.params[0],
  1091. build_id: req.params[1],
  1092. file: req.params[2],
  1093. }
  1094. req.params = params
  1095. next()
  1096. },
  1097. AuthenticationController.requirePrivateApiAuth(),
  1098. CompileController.getFileFromClsiWithoutUser
  1099. )
  1100. publicApiRouter.post(
  1101. '/api/institutions/confirm_university_domain',
  1102. AuthenticationController.requirePrivateApiAuth(),
  1103. InstitutionsController.confirmDomain
  1104. )
  1105. webRouter.get('/chrome', function (req, res, next) {
  1106. // Match v1 behaviour - this is used for a Chrome web app
  1107. if (SessionManager.isUserLoggedIn(req.session)) {
  1108. res.redirect('/project')
  1109. } else {
  1110. res.redirect('/register')
  1111. }
  1112. })
  1113. webRouter.get(
  1114. '/admin',
  1115. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1116. AdminController.index
  1117. )
  1118. if (!Features.hasFeature('saas')) {
  1119. webRouter.post(
  1120. '/admin/openEditor',
  1121. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1122. AdminController.openEditor
  1123. )
  1124. webRouter.post(
  1125. '/admin/closeEditor',
  1126. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1127. AdminController.closeEditor
  1128. )
  1129. webRouter.post(
  1130. '/admin/disconnectAllUsers',
  1131. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1132. AdminController.disconnectAllUsers
  1133. )
  1134. }
  1135. webRouter.post(
  1136. '/admin/flushProjectToTpds',
  1137. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1138. AdminController.flushProjectToTpds
  1139. )
  1140. webRouter.post(
  1141. '/admin/pollDropboxForUser',
  1142. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1143. AdminController.pollDropboxForUser
  1144. )
  1145. webRouter.post(
  1146. '/admin/messages',
  1147. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1148. AdminController.createMessage
  1149. )
  1150. webRouter.post(
  1151. '/admin/messages/clear',
  1152. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  1153. AdminController.clearMessages
  1154. )
  1155. privateApiRouter.get('/perfTest', (req, res) => {
  1156. plainTextResponse(res, 'hello')
  1157. })
  1158. publicApiRouter.get('/status', (req, res) => {
  1159. if (Settings.shuttingDown) {
  1160. res.sendStatus(503) // Service unavailable
  1161. } else if (!Settings.siteIsOpen) {
  1162. plainTextResponse(res, 'web site is closed (web)')
  1163. } else if (!Settings.editorIsOpen) {
  1164. plainTextResponse(res, 'web editor is closed (web)')
  1165. } else {
  1166. plainTextResponse(res, 'web is alive (web)')
  1167. }
  1168. })
  1169. privateApiRouter.get('/status', (req, res) => {
  1170. plainTextResponse(res, 'web is alive (api)')
  1171. })
  1172. // used by kubernetes health-check and acceptance tests
  1173. webRouter.get('/dev/csrf', (req, res) => {
  1174. plainTextResponse(res, res.locals.csrfToken)
  1175. })
  1176. publicApiRouter.get(
  1177. '/health_check',
  1178. HealthCheckController.checkActiveHandles,
  1179. HealthCheckController.check
  1180. )
  1181. privateApiRouter.get(
  1182. '/health_check',
  1183. HealthCheckController.checkActiveHandles,
  1184. HealthCheckController.checkApi
  1185. )
  1186. publicApiRouter.get(
  1187. '/health_check/api',
  1188. HealthCheckController.checkActiveHandles,
  1189. HealthCheckController.checkApi
  1190. )
  1191. privateApiRouter.get(
  1192. '/health_check/api',
  1193. HealthCheckController.checkActiveHandles,
  1194. HealthCheckController.checkApi
  1195. )
  1196. publicApiRouter.get(
  1197. '/health_check/full',
  1198. HealthCheckController.checkActiveHandles,
  1199. HealthCheckController.check
  1200. )
  1201. privateApiRouter.get(
  1202. '/health_check/full',
  1203. HealthCheckController.checkActiveHandles,
  1204. HealthCheckController.check
  1205. )
  1206. publicApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1207. privateApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  1208. publicApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1209. privateApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  1210. webRouter.get(
  1211. '/status/compiler/:Project_id',
  1212. RateLimiterMiddleware.rateLimit(rateLimiters.statusCompiler),
  1213. AuthorizationMiddleware.ensureUserCanReadProject,
  1214. function (req, res) {
  1215. const projectId = req.params.Project_id
  1216. // use a valid user id for testing
  1217. const testUserId = '123456789012345678901234'
  1218. const sendRes = _.once(function (statusCode, message) {
  1219. res.status(statusCode)
  1220. plainTextResponse(res, message)
  1221. ClsiCookieManager.clearServerId(projectId, testUserId, () => {})
  1222. }) // force every compile to a new server
  1223. // set a timeout
  1224. let handler = setTimeout(function () {
  1225. sendRes(500, 'Compiler timed out')
  1226. handler = null
  1227. }, 10000)
  1228. // run the compile
  1229. CompileManager.compile(
  1230. projectId,
  1231. testUserId,
  1232. {},
  1233. function (error, status) {
  1234. if (handler) {
  1235. clearTimeout(handler)
  1236. }
  1237. if (error) {
  1238. sendRes(500, `Compiler returned error ${error.message}`)
  1239. } else if (status === 'success') {
  1240. sendRes(200, 'Compiler returned in less than 10 seconds')
  1241. } else {
  1242. sendRes(500, `Compiler returned failure ${status}`)
  1243. }
  1244. }
  1245. )
  1246. }
  1247. )
  1248. webRouter.post('/error/client', function (req, res, next) {
  1249. logger.warn(
  1250. { err: req.body.error, meta: req.body.meta },
  1251. 'client side error'
  1252. )
  1253. metrics.inc('client-side-error')
  1254. res.sendStatus(204)
  1255. })
  1256. webRouter.get(
  1257. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})`,
  1258. RateLimiterMiddleware.rateLimit(rateLimiters.readOnlyToken),
  1259. AnalyticsRegistrationSourceMiddleware.setSource(
  1260. 'collaboration',
  1261. 'link-sharing'
  1262. ),
  1263. TokenAccessController.tokenAccessPage,
  1264. AnalyticsRegistrationSourceMiddleware.clearSource()
  1265. )
  1266. webRouter.get(
  1267. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})`,
  1268. RateLimiterMiddleware.rateLimit(rateLimiters.readAndWriteToken),
  1269. AnalyticsRegistrationSourceMiddleware.setSource(
  1270. 'collaboration',
  1271. 'link-sharing'
  1272. ),
  1273. TokenAccessController.tokenAccessPage,
  1274. AnalyticsRegistrationSourceMiddleware.clearSource()
  1275. )
  1276. webRouter.post(
  1277. `/:token(${TokenAccessController.READ_AND_WRITE_TOKEN_PATTERN})/grant`,
  1278. RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadWrite),
  1279. TokenAccessController.grantTokenAccessReadAndWrite
  1280. )
  1281. webRouter.post(
  1282. `/read/:token(${TokenAccessController.READ_ONLY_TOKEN_PATTERN})/grant`,
  1283. RateLimiterMiddleware.rateLimit(rateLimiters.grantTokenAccessReadOnly),
  1284. TokenAccessController.grantTokenAccessReadOnly
  1285. )
  1286. webRouter.get('/unsupported-browser', renderUnsupportedBrowserPage)
  1287. webRouter.get('*', ErrorController.notFound)
  1288. }
  1289. module.exports = { initialize, rateLimiters }