router.js 44 KB

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