router.js 43 KB

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