router.js 34 KB

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