router.js 33 KB

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