router.js 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  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 SpellingController = require('./Features/Spelling/SpellingController')
  6. const EditorRouter = require('./Features/Editor/EditorRouter')
  7. const Settings = require('settings-sharelatex')
  8. const TpdsController = require('./Features/ThirdPartyDataStore/TpdsController')
  9. const SubscriptionRouter = require('./Features/Subscription/SubscriptionRouter')
  10. const UploadsRouter = require('./Features/Uploads/UploadsRouter')
  11. const metrics = require('metrics-sharelatex')
  12. const ReferalController = require('./Features/Referal/ReferalController')
  13. const AuthenticationController = require('./Features/Authentication/AuthenticationController')
  14. const TagsController = require('./Features/Tags/TagsController')
  15. const NotificationsController = require('./Features/Notifications/NotificationsController')
  16. const CollaboratorsRouter = require('./Features/Collaborators/CollaboratorsRouter')
  17. const UserInfoController = require('./Features/User/UserInfoController')
  18. const UserController = require('./Features/User/UserController')
  19. const UserEmailsController = require('./Features/User/UserEmailsController')
  20. const UserPagesController = require('./Features/User/UserPagesController')
  21. const DocumentController = require('./Features/Documents/DocumentController')
  22. const CompileManager = require('./Features/Compile/CompileManager')
  23. const CompileController = require('./Features/Compile/CompileController')
  24. const ClsiCookieManager = require('./Features/Compile/ClsiCookieManager')(
  25. Settings.apis.clsi != null ? Settings.apis.clsi.backendGroupName : undefined
  26. )
  27. const HealthCheckController = require('./Features/HealthCheck/HealthCheckController')
  28. const ProjectDownloadsController = require('./Features/Downloads/ProjectDownloadsController')
  29. const FileStoreController = require('./Features/FileStore/FileStoreController')
  30. const HistoryController = require('./Features/History/HistoryController')
  31. const ExportsController = require('./Features/Exports/ExportsController')
  32. const PasswordResetRouter = require('./Features/PasswordReset/PasswordResetRouter')
  33. const StaticPagesRouter = require('./Features/StaticPages/StaticPagesRouter')
  34. const ChatController = require('./Features/Chat/ChatController')
  35. const Modules = require('./infrastructure/Modules')
  36. const RateLimiterMiddleware = require('./Features/Security/RateLimiterMiddleware')
  37. const InactiveProjectController = require('./Features/InactiveData/InactiveProjectController')
  38. const ContactRouter = require('./Features/Contacts/ContactRouter')
  39. const ReferencesController = require('./Features/References/ReferencesController')
  40. const AuthorizationMiddleware = require('./Features/Authorization/AuthorizationMiddleware')
  41. const BetaProgramController = require('./Features/BetaProgram/BetaProgramController')
  42. const SudoModeController = require('./Features/SudoMode/SudoModeController')
  43. const SudoModeMiddleware = require('./Features/SudoMode/SudoModeMiddleware')
  44. const AnalyticsRouter = require('./Features/Analytics/AnalyticsRouter')
  45. const MetaController = require('./Features/Metadata/MetaController')
  46. const TokenAccessController = require('./Features/TokenAccess/TokenAccessController')
  47. const Features = require('./infrastructure/Features')
  48. const LinkedFilesRouter = require('./Features/LinkedFiles/LinkedFilesRouter')
  49. const TemplatesRouter = require('./Features/Templates/TemplatesRouter')
  50. const InstitutionsController = require('./Features/Institutions/InstitutionsController')
  51. const UserMembershipRouter = require('./Features/UserMembership/UserMembershipRouter')
  52. const logger = require('logger-sharelatex')
  53. const _ = require('underscore')
  54. module.exports = { initialize }
  55. function initialize(webRouter, privateApiRouter, publicApiRouter) {
  56. if (!Settings.allowPublicAccess) {
  57. webRouter.all('*', AuthenticationController.requireGlobalLogin)
  58. }
  59. webRouter.get('/login', UserPagesController.loginPage)
  60. AuthenticationController.addEndpointToLoginWhitelist('/login')
  61. webRouter.post('/login', AuthenticationController.passportLogin)
  62. webRouter.get(
  63. '/read-only/one-time-login',
  64. UserPagesController.oneTimeLoginPage
  65. )
  66. AuthenticationController.addEndpointToLoginWhitelist(
  67. '/read-only/one-time-login'
  68. )
  69. webRouter.get('/logout', UserPagesController.logoutPage)
  70. webRouter.post('/logout', UserController.logout)
  71. webRouter.get('/restricted', AuthorizationMiddleware.restricted)
  72. if (Features.hasFeature('registration')) {
  73. webRouter.get('/register', UserPagesController.registerPage)
  74. AuthenticationController.addEndpointToLoginWhitelist('/register')
  75. }
  76. EditorRouter.apply(webRouter, privateApiRouter)
  77. CollaboratorsRouter.apply(webRouter, privateApiRouter)
  78. SubscriptionRouter.apply(webRouter, privateApiRouter, publicApiRouter)
  79. UploadsRouter.apply(webRouter, privateApiRouter)
  80. PasswordResetRouter.apply(webRouter, privateApiRouter)
  81. StaticPagesRouter.apply(webRouter, privateApiRouter)
  82. ContactRouter.apply(webRouter, privateApiRouter)
  83. AnalyticsRouter.apply(webRouter, privateApiRouter, publicApiRouter)
  84. LinkedFilesRouter.apply(webRouter, privateApiRouter, publicApiRouter)
  85. TemplatesRouter.apply(webRouter)
  86. UserMembershipRouter.apply(webRouter)
  87. Modules.applyRouter(webRouter, privateApiRouter, publicApiRouter)
  88. if (Settings.enableSubscriptions) {
  89. webRouter.get(
  90. '/user/bonus',
  91. AuthenticationController.requireLogin(),
  92. ReferalController.bonus
  93. )
  94. }
  95. webRouter.get('/user/activate', UserPagesController.activateAccountPage)
  96. AuthenticationController.addEndpointToLoginWhitelist('/user/activate')
  97. webRouter.get(
  98. '/user/settings',
  99. AuthenticationController.requireLogin(),
  100. SudoModeMiddleware.protectPage,
  101. UserPagesController.settingsPage
  102. )
  103. webRouter.post(
  104. '/user/settings',
  105. AuthenticationController.requireLogin(),
  106. UserController.updateUserSettings
  107. )
  108. webRouter.post(
  109. '/user/password/update',
  110. AuthenticationController.requireLogin(),
  111. RateLimiterMiddleware.rateLimit({
  112. endpointName: 'change-password',
  113. maxRequests: 10,
  114. timeInterval: 60
  115. }),
  116. UserController.changePassword
  117. )
  118. webRouter.get(
  119. '/user/emails',
  120. AuthenticationController.requireLogin(),
  121. UserEmailsController.list
  122. )
  123. webRouter.get('/user/emails/confirm', UserEmailsController.showConfirm)
  124. webRouter.post(
  125. '/user/emails/confirm',
  126. RateLimiterMiddleware.rateLimit({
  127. endpointName: 'confirm-email',
  128. maxRequests: 10,
  129. timeInterval: 60
  130. }),
  131. UserEmailsController.confirm
  132. )
  133. webRouter.post(
  134. '/user/emails/resend_confirmation',
  135. AuthenticationController.requireLogin(),
  136. RateLimiterMiddleware.rateLimit({
  137. endpointName: 'resend-confirmation',
  138. maxRequests: 10,
  139. timeInterval: 60
  140. }),
  141. UserEmailsController.resendConfirmation
  142. )
  143. if (Features.hasFeature('affiliations')) {
  144. webRouter.post(
  145. '/user/emails',
  146. AuthenticationController.requireLogin(),
  147. RateLimiterMiddleware.rateLimit({
  148. endpointName: 'add-email',
  149. maxRequests: 10,
  150. timeInterval: 60
  151. }),
  152. UserEmailsController.add
  153. )
  154. webRouter.post(
  155. '/user/emails/delete',
  156. AuthenticationController.requireLogin(),
  157. RateLimiterMiddleware.rateLimit({
  158. endpointName: 'delete-email',
  159. maxRequests: 10,
  160. timeInterval: 60
  161. }),
  162. UserEmailsController.remove
  163. )
  164. webRouter.post(
  165. '/user/emails/default',
  166. AuthenticationController.requireLogin(),
  167. UserEmailsController.setDefault
  168. )
  169. webRouter.post(
  170. '/user/emails/endorse',
  171. AuthenticationController.requireLogin(),
  172. RateLimiterMiddleware.rateLimit({
  173. endpointName: 'endorse-email',
  174. maxRequests: 30,
  175. timeInterval: 60
  176. }),
  177. UserEmailsController.endorse
  178. )
  179. }
  180. webRouter.get(
  181. '/user/sessions',
  182. AuthenticationController.requireLogin(),
  183. SudoModeMiddleware.protectPage,
  184. UserPagesController.sessionsPage
  185. )
  186. webRouter.post(
  187. '/user/sessions/clear',
  188. AuthenticationController.requireLogin(),
  189. UserController.clearSessions
  190. )
  191. webRouter.delete(
  192. '/user/newsletter/unsubscribe',
  193. AuthenticationController.requireLogin(),
  194. UserController.unsubscribe
  195. )
  196. webRouter.post(
  197. '/user/delete',
  198. RateLimiterMiddleware.rateLimit({
  199. endpointName: 'delete-user',
  200. maxRequests: 10,
  201. timeInterval: 60
  202. }),
  203. AuthenticationController.requireLogin(),
  204. UserController.tryDeleteUser
  205. )
  206. webRouter.get(
  207. '/user/personal_info',
  208. AuthenticationController.requireLogin(),
  209. UserInfoController.getLoggedInUsersPersonalInfo
  210. )
  211. privateApiRouter.get(
  212. '/user/:user_id/personal_info',
  213. AuthenticationController.httpAuth,
  214. UserInfoController.getPersonalInfo
  215. )
  216. webRouter.get(
  217. '/user/reconfirm',
  218. UserPagesController.renderReconfirmAccountPage
  219. )
  220. // for /user/reconfirm POST, see password router
  221. webRouter.get(
  222. '/user/projects',
  223. AuthenticationController.requireLogin(),
  224. ProjectController.userProjectsJson
  225. )
  226. webRouter.get(
  227. '/project/:Project_id/entities',
  228. AuthenticationController.requireLogin(),
  229. AuthorizationMiddleware.ensureUserCanReadProject,
  230. ProjectController.projectEntitiesJson
  231. )
  232. webRouter.get(
  233. '/project',
  234. AuthenticationController.requireLogin(),
  235. RateLimiterMiddleware.rateLimit({
  236. endpointName: 'open-dashboard',
  237. maxRequests: 30,
  238. timeInterval: 60
  239. }),
  240. ProjectController.projectListPage
  241. )
  242. webRouter.post(
  243. '/project/new',
  244. AuthenticationController.requireLogin(),
  245. RateLimiterMiddleware.rateLimit({
  246. endpointName: 'create-project',
  247. maxRequests: 20,
  248. timeInterval: 60
  249. }),
  250. ProjectController.newProject
  251. )
  252. webRouter.get(
  253. '/Project/:Project_id',
  254. RateLimiterMiddleware.rateLimit({
  255. endpointName: 'open-project',
  256. params: ['Project_id'],
  257. maxRequests: 15,
  258. timeInterval: 60
  259. }),
  260. AuthenticationController.validateUserSession(),
  261. AuthorizationMiddleware.ensureUserCanReadProject,
  262. ProjectController.loadEditor
  263. )
  264. webRouter.head(
  265. '/Project/:Project_id/file/:File_id',
  266. AuthorizationMiddleware.ensureUserCanReadProject,
  267. FileStoreController.getFileHead
  268. )
  269. webRouter.get(
  270. '/Project/:Project_id/file/:File_id',
  271. AuthorizationMiddleware.ensureUserCanReadProject,
  272. FileStoreController.getFile
  273. )
  274. webRouter.post(
  275. '/project/:Project_id/settings',
  276. AuthorizationMiddleware.ensureUserCanWriteProjectSettings,
  277. ProjectController.updateProjectSettings
  278. )
  279. webRouter.post(
  280. '/project/:Project_id/settings/admin',
  281. AuthenticationController.requireLogin(),
  282. AuthorizationMiddleware.ensureUserCanAdminProject,
  283. ProjectController.updateProjectAdminSettings
  284. )
  285. webRouter.post(
  286. '/project/:Project_id/compile',
  287. RateLimiterMiddleware.rateLimit({
  288. endpointName: 'compile-project-http',
  289. params: ['Project_id'],
  290. maxRequests: 800,
  291. timeInterval: 60 * 60
  292. }),
  293. AuthorizationMiddleware.ensureUserCanReadProject,
  294. CompileController.compile
  295. )
  296. webRouter.post(
  297. '/project/:Project_id/compile/stop',
  298. AuthorizationMiddleware.ensureUserCanReadProject,
  299. CompileController.stopCompile
  300. )
  301. // LEGACY: Used by the web download buttons, adds filename header, TODO: remove at some future date
  302. webRouter.get(
  303. '/project/:Project_id/output/output.pdf',
  304. AuthorizationMiddleware.ensureUserCanReadProject,
  305. CompileController.downloadPdf
  306. )
  307. // PDF Download button
  308. webRouter.get(
  309. /^\/download\/project\/([^/]*)\/output\/output\.pdf$/,
  310. function(req, res, next) {
  311. const params = { Project_id: req.params[0] }
  312. req.params = params
  313. next()
  314. },
  315. AuthorizationMiddleware.ensureUserCanReadProject,
  316. CompileController.downloadPdf
  317. )
  318. // PDF Download button for specific build
  319. webRouter.get(
  320. /^\/download\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/output\.pdf$/,
  321. function(req, res, next) {
  322. const params = {
  323. Project_id: req.params[0],
  324. build_id: req.params[1]
  325. }
  326. req.params = params
  327. next()
  328. },
  329. AuthorizationMiddleware.ensureUserCanReadProject,
  330. CompileController.downloadPdf
  331. )
  332. // Used by the pdf viewers
  333. webRouter.get(
  334. /^\/project\/([^/]*)\/output\/(.*)$/,
  335. function(req, res, next) {
  336. const params = {
  337. Project_id: req.params[0],
  338. file: req.params[1]
  339. }
  340. req.params = params
  341. next()
  342. },
  343. AuthorizationMiddleware.ensureUserCanReadProject,
  344. CompileController.getFileFromClsi
  345. )
  346. // direct url access to output files for a specific build (query string not required)
  347. webRouter.get(
  348. /^\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  349. function(req, res, next) {
  350. const params = {
  351. Project_id: req.params[0],
  352. build_id: req.params[1],
  353. file: req.params[2]
  354. }
  355. req.params = params
  356. next()
  357. },
  358. AuthorizationMiddleware.ensureUserCanReadProject,
  359. CompileController.getFileFromClsi
  360. )
  361. // direct url access to output files for user but no build, to retrieve files when build fails
  362. webRouter.get(
  363. /^\/project\/([^/]*)\/user\/([0-9a-f-]+)\/output\/(.*)$/,
  364. function(req, res, next) {
  365. const params = {
  366. Project_id: req.params[0],
  367. user_id: req.params[1],
  368. file: req.params[2]
  369. }
  370. req.params = params
  371. next()
  372. },
  373. AuthorizationMiddleware.ensureUserCanReadProject,
  374. CompileController.getFileFromClsi
  375. )
  376. // direct url access to output files for a specific user and build (query string not required)
  377. webRouter.get(
  378. /^\/project\/([^/]*)\/user\/([0-9a-f]+)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  379. function(req, res, next) {
  380. const params = {
  381. Project_id: req.params[0],
  382. user_id: req.params[1],
  383. build_id: req.params[2],
  384. file: req.params[3]
  385. }
  386. req.params = params
  387. next()
  388. },
  389. AuthorizationMiddleware.ensureUserCanReadProject,
  390. CompileController.getFileFromClsi
  391. )
  392. webRouter.delete(
  393. '/project/:Project_id/output',
  394. AuthorizationMiddleware.ensureUserCanReadProject,
  395. CompileController.deleteAuxFiles
  396. )
  397. webRouter.get(
  398. '/project/:Project_id/sync/code',
  399. AuthorizationMiddleware.ensureUserCanReadProject,
  400. CompileController.proxySyncCode
  401. )
  402. webRouter.get(
  403. '/project/:Project_id/sync/pdf',
  404. AuthorizationMiddleware.ensureUserCanReadProject,
  405. CompileController.proxySyncPdf
  406. )
  407. webRouter.get(
  408. '/project/:Project_id/wordcount',
  409. AuthorizationMiddleware.ensureUserCanReadProject,
  410. CompileController.wordCount
  411. )
  412. webRouter.post(
  413. '/Project/:Project_id/archive',
  414. AuthorizationMiddleware.ensureUserCanReadProject,
  415. ProjectController.archiveProject
  416. )
  417. webRouter.delete(
  418. '/Project/:Project_id/archive',
  419. AuthorizationMiddleware.ensureUserCanReadProject,
  420. ProjectController.unarchiveProject
  421. )
  422. webRouter.post(
  423. '/project/:project_id/trash',
  424. AuthorizationMiddleware.ensureUserCanReadProject,
  425. ProjectController.trashProject
  426. )
  427. webRouter.delete(
  428. '/project/:project_id/trash',
  429. AuthorizationMiddleware.ensureUserCanReadProject,
  430. ProjectController.untrashProject
  431. )
  432. webRouter.delete(
  433. '/Project/:Project_id',
  434. AuthenticationController.requireLogin(),
  435. AuthorizationMiddleware.ensureUserCanAdminProject,
  436. ProjectController.deleteProject
  437. )
  438. webRouter.post(
  439. '/Project/:Project_id/restore',
  440. AuthenticationController.requireLogin(),
  441. AuthorizationMiddleware.ensureUserCanAdminProject,
  442. ProjectController.restoreProject
  443. )
  444. webRouter.post(
  445. '/Project/:Project_id/clone',
  446. AuthorizationMiddleware.ensureUserCanReadProject,
  447. ProjectController.cloneProject
  448. )
  449. webRouter.post(
  450. '/project/:Project_id/rename',
  451. AuthenticationController.requireLogin(),
  452. AuthorizationMiddleware.ensureUserCanAdminProject,
  453. ProjectController.renameProject
  454. )
  455. webRouter.get(
  456. '/project/:Project_id/updates',
  457. AuthorizationMiddleware.ensureUserCanReadProject,
  458. HistoryController.selectHistoryApi,
  459. HistoryController.proxyToHistoryApiAndInjectUserDetails
  460. )
  461. webRouter.get(
  462. '/project/:Project_id/doc/:doc_id/diff',
  463. AuthorizationMiddleware.ensureUserCanReadProject,
  464. HistoryController.selectHistoryApi,
  465. HistoryController.proxyToHistoryApi
  466. )
  467. webRouter.get(
  468. '/project/:Project_id/diff',
  469. AuthorizationMiddleware.ensureUserCanReadProject,
  470. HistoryController.selectHistoryApi,
  471. HistoryController.proxyToHistoryApiAndInjectUserDetails
  472. )
  473. webRouter.get(
  474. '/project/:Project_id/filetree/diff',
  475. AuthorizationMiddleware.ensureUserCanReadProject,
  476. HistoryController.selectHistoryApi,
  477. HistoryController.proxyToHistoryApi
  478. )
  479. webRouter.post(
  480. '/project/:Project_id/doc/:doc_id/version/:version_id/restore',
  481. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  482. HistoryController.selectHistoryApi,
  483. HistoryController.proxyToHistoryApi
  484. )
  485. webRouter.post(
  486. '/project/:project_id/doc/:doc_id/restore',
  487. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  488. HistoryController.restoreDocFromDeletedDoc
  489. )
  490. webRouter.post(
  491. '/project/:project_id/restore_file',
  492. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  493. HistoryController.restoreFileFromV2
  494. )
  495. webRouter.get(
  496. '/project/:project_id/version/:version/zip',
  497. AuthorizationMiddleware.ensureUserCanReadProject,
  498. HistoryController.downloadZipOfVersion
  499. )
  500. privateApiRouter.post(
  501. '/project/:Project_id/history/resync',
  502. AuthenticationController.httpAuth,
  503. HistoryController.resyncProjectHistory
  504. )
  505. webRouter.get(
  506. '/project/:Project_id/labels',
  507. AuthorizationMiddleware.ensureUserCanReadProject,
  508. HistoryController.selectHistoryApi,
  509. HistoryController.ensureProjectHistoryEnabled,
  510. HistoryController.getLabels
  511. )
  512. webRouter.post(
  513. '/project/:Project_id/labels',
  514. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  515. HistoryController.selectHistoryApi,
  516. HistoryController.ensureProjectHistoryEnabled,
  517. HistoryController.createLabel
  518. )
  519. webRouter.delete(
  520. '/project/:Project_id/labels/:label_id',
  521. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  522. HistoryController.selectHistoryApi,
  523. HistoryController.ensureProjectHistoryEnabled,
  524. HistoryController.deleteLabel
  525. )
  526. webRouter.post(
  527. '/project/:project_id/export/:brand_variation_id',
  528. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  529. ExportsController.exportProject
  530. )
  531. webRouter.get(
  532. '/project/:project_id/export/:export_id',
  533. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  534. ExportsController.exportStatus
  535. )
  536. webRouter.get(
  537. '/project/:project_id/export/:export_id/:type',
  538. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  539. ExportsController.exportDownload
  540. )
  541. webRouter.get(
  542. '/Project/:Project_id/download/zip',
  543. AuthorizationMiddleware.ensureUserCanReadProject,
  544. ProjectDownloadsController.downloadProject
  545. )
  546. webRouter.get(
  547. '/project/download/zip',
  548. AuthorizationMiddleware.ensureUserCanReadMultipleProjects,
  549. ProjectDownloadsController.downloadMultipleProjects
  550. )
  551. webRouter.get(
  552. '/project/:project_id/metadata',
  553. AuthorizationMiddleware.ensureUserCanReadProject,
  554. AuthenticationController.requireLogin(),
  555. MetaController.getMetadata
  556. )
  557. webRouter.post(
  558. '/project/:project_id/doc/:doc_id/metadata',
  559. AuthorizationMiddleware.ensureUserCanReadProject,
  560. AuthenticationController.requireLogin(),
  561. MetaController.broadcastMetadataForDoc
  562. )
  563. privateApiRouter.post(
  564. '/internal/expire-deleted-projects-after-duration',
  565. AuthenticationController.httpAuth,
  566. ProjectController.expireDeletedProjectsAfterDuration
  567. )
  568. privateApiRouter.post(
  569. '/internal/expire-deleted-users-after-duration',
  570. AuthenticationController.httpAuth,
  571. UserController.expireDeletedUsersAfterDuration
  572. )
  573. privateApiRouter.post(
  574. '/internal/project/:projectId/expire-deleted-project',
  575. AuthenticationController.httpAuth,
  576. ProjectController.expireDeletedProject
  577. )
  578. privateApiRouter.post(
  579. '/internal/users/:userId/expire',
  580. AuthenticationController.httpAuth,
  581. UserController.expireDeletedUser
  582. )
  583. webRouter.get(
  584. '/tag',
  585. AuthenticationController.requireLogin(),
  586. TagsController.getAllTags
  587. )
  588. webRouter.post(
  589. '/tag',
  590. AuthenticationController.requireLogin(),
  591. RateLimiterMiddleware.rateLimit({
  592. endpointName: 'create-tag',
  593. maxRequests: 30,
  594. timeInterval: 60
  595. }),
  596. TagsController.createTag
  597. )
  598. webRouter.post(
  599. '/tag/:tag_id/rename',
  600. AuthenticationController.requireLogin(),
  601. RateLimiterMiddleware.rateLimit({
  602. endpointName: 'rename-tag',
  603. maxRequests: 30,
  604. timeInterval: 60
  605. }),
  606. TagsController.renameTag
  607. )
  608. webRouter.delete(
  609. '/tag/:tag_id',
  610. AuthenticationController.requireLogin(),
  611. RateLimiterMiddleware.rateLimit({
  612. endpointName: 'delete-tag',
  613. maxRequests: 30,
  614. timeInterval: 60
  615. }),
  616. TagsController.deleteTag
  617. )
  618. webRouter.post(
  619. '/tag/:tag_id/project/:project_id',
  620. AuthenticationController.requireLogin(),
  621. RateLimiterMiddleware.rateLimit({
  622. endpointName: 'add-project-to-tag',
  623. maxRequests: 30,
  624. timeInterval: 60
  625. }),
  626. TagsController.addProjectToTag
  627. )
  628. webRouter.delete(
  629. '/tag/:tag_id/project/:project_id',
  630. AuthenticationController.requireLogin(),
  631. RateLimiterMiddleware.rateLimit({
  632. endpointName: 'remove-project-from-tag',
  633. maxRequests: 30,
  634. timeInterval: 60
  635. }),
  636. TagsController.removeProjectFromTag
  637. )
  638. webRouter.get(
  639. '/notifications',
  640. AuthenticationController.requireLogin(),
  641. NotificationsController.getAllUnreadNotifications
  642. )
  643. webRouter.delete(
  644. '/notifications/:notification_id',
  645. AuthenticationController.requireLogin(),
  646. NotificationsController.markNotificationAsRead
  647. )
  648. // Deprecated in favour of /internal/project/:project_id but still used by versioning
  649. privateApiRouter.get(
  650. '/project/:project_id/details',
  651. AuthenticationController.httpAuth,
  652. ProjectApiController.getProjectDetails
  653. )
  654. // New 'stable' /internal API end points
  655. privateApiRouter.get(
  656. '/internal/project/:project_id',
  657. AuthenticationController.httpAuth,
  658. ProjectApiController.getProjectDetails
  659. )
  660. privateApiRouter.get(
  661. '/internal/project/:Project_id/zip',
  662. AuthenticationController.httpAuth,
  663. ProjectDownloadsController.downloadProject
  664. )
  665. privateApiRouter.get(
  666. '/internal/project/:project_id/compile/pdf',
  667. AuthenticationController.httpAuth,
  668. CompileController.compileAndDownloadPdf
  669. )
  670. privateApiRouter.post(
  671. '/internal/deactivateOldProjects',
  672. AuthenticationController.httpAuth,
  673. InactiveProjectController.deactivateOldProjects
  674. )
  675. privateApiRouter.post(
  676. '/internal/project/:project_id/deactivate',
  677. AuthenticationController.httpAuth,
  678. InactiveProjectController.deactivateProject
  679. )
  680. privateApiRouter.get(
  681. /^\/internal\/project\/([^/]*)\/output\/(.*)$/,
  682. function(req, res, next) {
  683. const params = {
  684. Project_id: req.params[0],
  685. file: req.params[1]
  686. }
  687. req.params = params
  688. next()
  689. },
  690. AuthenticationController.httpAuth,
  691. CompileController.getFileFromClsi
  692. )
  693. privateApiRouter.get(
  694. '/project/:Project_id/doc/:doc_id',
  695. AuthenticationController.httpAuth,
  696. DocumentController.getDocument
  697. )
  698. privateApiRouter.post(
  699. '/project/:Project_id/doc/:doc_id',
  700. AuthenticationController.httpAuth,
  701. DocumentController.setDocument
  702. )
  703. privateApiRouter.post(
  704. '/user/:user_id/update/*',
  705. AuthenticationController.httpAuth,
  706. TpdsController.mergeUpdate
  707. )
  708. privateApiRouter.delete(
  709. '/user/:user_id/update/*',
  710. AuthenticationController.httpAuth,
  711. TpdsController.deleteUpdate
  712. )
  713. privateApiRouter.post(
  714. '/project/:project_id/contents/*',
  715. AuthenticationController.httpAuth,
  716. TpdsController.updateProjectContents
  717. )
  718. privateApiRouter.delete(
  719. '/project/:project_id/contents/*',
  720. AuthenticationController.httpAuth,
  721. TpdsController.deleteProjectContents
  722. )
  723. webRouter.post(
  724. '/spelling/check',
  725. AuthenticationController.requireLogin(),
  726. SpellingController.proxyRequestToSpellingApi
  727. )
  728. webRouter.post(
  729. '/spelling/learn',
  730. AuthenticationController.requireLogin(),
  731. SpellingController.proxyRequestToSpellingApi
  732. )
  733. webRouter.get(
  734. '/project/:project_id/messages',
  735. AuthorizationMiddleware.ensureUserCanReadProject,
  736. ChatController.getMessages
  737. )
  738. webRouter.post(
  739. '/project/:project_id/messages',
  740. AuthorizationMiddleware.ensureUserCanReadProject,
  741. RateLimiterMiddleware.rateLimit({
  742. endpointName: 'send-chat-message',
  743. maxRequests: 100,
  744. timeInterval: 60
  745. }),
  746. ChatController.sendMessage
  747. )
  748. webRouter.post(
  749. '/project/:Project_id/references/index',
  750. AuthorizationMiddleware.ensureUserCanReadProject,
  751. RateLimiterMiddleware.rateLimit({
  752. endpointName: 'index-project-references',
  753. maxRequests: 30,
  754. timeInterval: 60
  755. }),
  756. ReferencesController.index
  757. )
  758. webRouter.post(
  759. '/project/:Project_id/references/indexAll',
  760. AuthorizationMiddleware.ensureUserCanReadProject,
  761. RateLimiterMiddleware.rateLimit({
  762. endpointName: 'index-all-project-references',
  763. maxRequests: 30,
  764. timeInterval: 60
  765. }),
  766. ReferencesController.indexAll
  767. )
  768. // disable beta program while v2 is in beta
  769. webRouter.get(
  770. '/beta/participate',
  771. AuthenticationController.requireLogin(),
  772. BetaProgramController.optInPage
  773. )
  774. webRouter.post(
  775. '/beta/opt-in',
  776. AuthenticationController.requireLogin(),
  777. BetaProgramController.optIn
  778. )
  779. webRouter.post(
  780. '/beta/opt-out',
  781. AuthenticationController.requireLogin(),
  782. BetaProgramController.optOut
  783. )
  784. webRouter.get(
  785. '/confirm-password',
  786. AuthenticationController.requireLogin(),
  787. SudoModeController.sudoModePrompt
  788. )
  789. webRouter.post(
  790. '/confirm-password',
  791. AuthenticationController.requireLogin(),
  792. RateLimiterMiddleware.rateLimit({
  793. endpointName: 'confirm-password',
  794. maxRequests: 10,
  795. timeInterval: 60
  796. }),
  797. SudoModeController.submitPassword
  798. )
  799. // New "api" endpoints. Started as a way for v1 to call over to v2 (for
  800. // long-term features, as opposed to the nominally temporary ones in the
  801. // overleaf-integration module), but may expand beyond that role.
  802. publicApiRouter.post(
  803. '/api/clsi/compile/:submission_id',
  804. AuthenticationController.httpAuth,
  805. CompileController.compileSubmission
  806. )
  807. publicApiRouter.get(
  808. /^\/api\/clsi\/compile\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  809. function(req, res, next) {
  810. const params = {
  811. submission_id: req.params[0],
  812. build_id: req.params[1],
  813. file: req.params[2]
  814. }
  815. req.params = params
  816. next()
  817. },
  818. AuthenticationController.httpAuth,
  819. CompileController.getFileFromClsiWithoutUser
  820. )
  821. publicApiRouter.post(
  822. '/api/institutions/confirm_university_domain',
  823. RateLimiterMiddleware.rateLimit({
  824. endpointName: 'confirm-university-domain',
  825. maxRequests: 1,
  826. timeInterval: 60
  827. }),
  828. AuthenticationController.httpAuth,
  829. InstitutionsController.confirmDomain
  830. )
  831. webRouter.get('/chrome', function(req, res, next) {
  832. // Match v1 behaviour - this is used for a Chrome web app
  833. if (AuthenticationController.isUserLoggedIn(req)) {
  834. res.redirect('/project')
  835. } else {
  836. res.redirect('/register')
  837. }
  838. })
  839. // Admin Stuff
  840. webRouter.get(
  841. '/admin',
  842. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  843. AdminController.index
  844. )
  845. webRouter.get(
  846. '/admin/user',
  847. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  848. (req, res) => res.redirect('/admin/register')
  849. ) // this gets removed by admin-panel addon
  850. webRouter.get(
  851. '/admin/register',
  852. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  853. AdminController.registerNewUser
  854. )
  855. webRouter.post(
  856. '/admin/register',
  857. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  858. UserController.register
  859. )
  860. webRouter.post(
  861. '/admin/closeEditor',
  862. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  863. AdminController.closeEditor
  864. )
  865. webRouter.post(
  866. '/admin/dissconectAllUsers',
  867. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  868. AdminController.dissconectAllUsers
  869. )
  870. webRouter.post(
  871. '/admin/flushProjectToTpds',
  872. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  873. AdminController.flushProjectToTpds
  874. )
  875. webRouter.post(
  876. '/admin/pollDropboxForUser',
  877. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  878. AdminController.pollDropboxForUser
  879. )
  880. webRouter.post(
  881. '/admin/messages',
  882. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  883. AdminController.createMessage
  884. )
  885. webRouter.post(
  886. '/admin/messages/clear',
  887. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  888. AdminController.clearMessages
  889. )
  890. privateApiRouter.post(
  891. '/disconnectAllUsers',
  892. AdminController.dissconectAllUsers
  893. )
  894. privateApiRouter.get('/perfTest', (req, res) => res.send('hello'))
  895. publicApiRouter.get('/status', (req, res) =>
  896. res.send('web sharelatex is alive (web)')
  897. )
  898. privateApiRouter.get('/status', (req, res) =>
  899. res.send('web sharelatex is alive (api)')
  900. )
  901. // used by kubernetes health-check and acceptance tests
  902. webRouter.get('/dev/csrf', (req, res) => res.send(res.locals.csrfToken))
  903. publicApiRouter.get('/health_check', HealthCheckController.check)
  904. privateApiRouter.get('/health_check', HealthCheckController.check)
  905. publicApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  906. privateApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  907. publicApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  908. privateApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  909. webRouter.get(
  910. '/status/compiler/:Project_id',
  911. AuthorizationMiddleware.ensureUserCanReadProject,
  912. function(req, res) {
  913. const projectId = req.params.Project_id
  914. const sendRes = _.once(function(statusCode, message) {
  915. res.status(statusCode)
  916. res.send(message)
  917. ClsiCookieManager.clearServerId(projectId)
  918. }) // force every compile to a new server
  919. // set a timeout
  920. var handler = setTimeout(function() {
  921. sendRes(500, 'Compiler timed out')
  922. handler = null
  923. }, 10000)
  924. // use a valid user id for testing
  925. const testUserId = '123456789012345678901234'
  926. // run the compile
  927. CompileManager.compile(projectId, testUserId, {}, function(
  928. error,
  929. status
  930. ) {
  931. if (handler) {
  932. clearTimeout(handler)
  933. }
  934. if (error) {
  935. sendRes(500, `Compiler returned error ${error.message}`)
  936. } else if (status === 'success') {
  937. sendRes(200, 'Compiler returned in less than 10 seconds')
  938. } else {
  939. sendRes(500, `Compiler returned failure ${status}`)
  940. }
  941. })
  942. }
  943. )
  944. webRouter.get('/no-cache', function(req, res, next) {
  945. res.header('Cache-Control', 'max-age=0')
  946. res.sendStatus(404)
  947. })
  948. webRouter.get('/oops-express', (req, res, next) =>
  949. next(new Error('Test error'))
  950. )
  951. webRouter.get('/oops-internal', function(req, res, next) {
  952. throw new Error('Test error')
  953. })
  954. webRouter.get('/oops-mongo', (req, res, next) =>
  955. require('./models/Project').Project.findOne({}, function() {
  956. throw new Error('Test error')
  957. })
  958. )
  959. privateApiRouter.get('/opps-small', function(req, res, next) {
  960. logger.err('test error occured')
  961. res.send()
  962. })
  963. webRouter.post('/error/client', function(req, res, next) {
  964. logger.warn(
  965. { err: req.body.error, meta: req.body.meta },
  966. 'client side error'
  967. )
  968. metrics.inc('client-side-error')
  969. res.sendStatus(204)
  970. })
  971. webRouter.get(
  972. '/read/:read_only_token([a-z]+)',
  973. RateLimiterMiddleware.rateLimit({
  974. endpointName: 'read-only-token',
  975. maxRequests: 15,
  976. timeInterval: 60
  977. }),
  978. TokenAccessController.readOnlyToken
  979. )
  980. webRouter.get(
  981. '/:read_and_write_token([0-9]+[a-z]+)',
  982. RateLimiterMiddleware.rateLimit({
  983. endpointName: 'read-and-write-token',
  984. maxRequests: 15,
  985. timeInterval: 60
  986. }),
  987. TokenAccessController.readAndWriteToken
  988. )
  989. webRouter.get('*', ErrorController.notFound)
  990. }