router.js 34 KB

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