router.js 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  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. ProjectController.projectListPage
  244. )
  245. webRouter.post(
  246. '/project/new',
  247. AuthenticationController.requireLogin(),
  248. RateLimiterMiddleware.rateLimit({
  249. endpointName: 'create-project',
  250. maxRequests: 20,
  251. timeInterval: 60
  252. }),
  253. ProjectController.newProject
  254. )
  255. webRouter.get(
  256. '/Project/:Project_id',
  257. RateLimiterMiddleware.rateLimit({
  258. endpointName: 'open-project',
  259. params: ['Project_id'],
  260. maxRequests: 15,
  261. timeInterval: 60
  262. }),
  263. AuthorizationMiddleware.ensureUserCanReadProject,
  264. ProjectController.loadEditor
  265. )
  266. webRouter.head(
  267. '/Project/:Project_id/file/:File_id',
  268. AuthorizationMiddleware.ensureUserCanReadProject,
  269. FileStoreController.getFileHead
  270. )
  271. webRouter.get(
  272. '/Project/:Project_id/file/:File_id',
  273. AuthorizationMiddleware.ensureUserCanReadProject,
  274. FileStoreController.getFile
  275. )
  276. webRouter.post(
  277. '/project/:Project_id/settings',
  278. AuthorizationMiddleware.ensureUserCanWriteProjectSettings,
  279. ProjectController.updateProjectSettings
  280. )
  281. webRouter.post(
  282. '/project/:Project_id/settings/admin',
  283. AuthorizationMiddleware.ensureUserCanAdminProject,
  284. ProjectController.updateProjectAdminSettings
  285. )
  286. webRouter.post(
  287. '/project/:Project_id/compile',
  288. RateLimiterMiddleware.rateLimit({
  289. endpointName: 'compile-project-http',
  290. params: ['Project_id'],
  291. maxRequests: 800,
  292. timeInterval: 60 * 60
  293. }),
  294. AuthorizationMiddleware.ensureUserCanReadProject,
  295. CompileController.compile
  296. )
  297. webRouter.post(
  298. '/project/:Project_id/compile/stop',
  299. AuthorizationMiddleware.ensureUserCanReadProject,
  300. CompileController.stopCompile
  301. )
  302. // LEGACY: Used by the web download buttons, adds filename header, TODO: remove at some future date
  303. webRouter.get(
  304. '/project/:Project_id/output/output.pdf',
  305. AuthorizationMiddleware.ensureUserCanReadProject,
  306. CompileController.downloadPdf
  307. )
  308. // PDF Download button
  309. webRouter.get(
  310. /^\/download\/project\/([^/]*)\/output\/output\.pdf$/,
  311. function(req, res, next) {
  312. const params = { Project_id: req.params[0] }
  313. req.params = params
  314. next()
  315. },
  316. AuthorizationMiddleware.ensureUserCanReadProject,
  317. CompileController.downloadPdf
  318. )
  319. // PDF Download button for specific build
  320. webRouter.get(
  321. /^\/download\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/output\.pdf$/,
  322. function(req, res, next) {
  323. const params = {
  324. Project_id: req.params[0],
  325. build_id: req.params[1]
  326. }
  327. req.params = params
  328. next()
  329. },
  330. AuthorizationMiddleware.ensureUserCanReadProject,
  331. CompileController.downloadPdf
  332. )
  333. // Used by the pdf viewers
  334. webRouter.get(
  335. /^\/project\/([^/]*)\/output\/(.*)$/,
  336. function(req, res, next) {
  337. const params = {
  338. Project_id: req.params[0],
  339. file: req.params[1]
  340. }
  341. req.params = params
  342. next()
  343. },
  344. AuthorizationMiddleware.ensureUserCanReadProject,
  345. CompileController.getFileFromClsi
  346. )
  347. // direct url access to output files for a specific build (query string not required)
  348. webRouter.get(
  349. /^\/project\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  350. function(req, res, next) {
  351. const params = {
  352. Project_id: req.params[0],
  353. build_id: req.params[1],
  354. file: req.params[2]
  355. }
  356. req.params = params
  357. next()
  358. },
  359. AuthorizationMiddleware.ensureUserCanReadProject,
  360. CompileController.getFileFromClsi
  361. )
  362. // direct url access to output files for user but no build, to retrieve files when build fails
  363. webRouter.get(
  364. /^\/project\/([^/]*)\/user\/([0-9a-f-]+)\/output\/(.*)$/,
  365. function(req, res, next) {
  366. const params = {
  367. Project_id: req.params[0],
  368. user_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 a specific user and build (query string not required)
  378. webRouter.get(
  379. /^\/project\/([^/]*)\/user\/([0-9a-f]+)\/build\/([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. build_id: req.params[2],
  385. file: req.params[3]
  386. }
  387. req.params = params
  388. next()
  389. },
  390. AuthorizationMiddleware.ensureUserCanReadProject,
  391. CompileController.getFileFromClsi
  392. )
  393. webRouter.delete(
  394. '/project/:Project_id/output',
  395. AuthorizationMiddleware.ensureUserCanReadProject,
  396. CompileController.deleteAuxFiles
  397. )
  398. webRouter.get(
  399. '/project/:Project_id/sync/code',
  400. AuthorizationMiddleware.ensureUserCanReadProject,
  401. CompileController.proxySyncCode
  402. )
  403. webRouter.get(
  404. '/project/:Project_id/sync/pdf',
  405. AuthorizationMiddleware.ensureUserCanReadProject,
  406. CompileController.proxySyncPdf
  407. )
  408. webRouter.get(
  409. '/project/:Project_id/wordcount',
  410. AuthorizationMiddleware.ensureUserCanReadProject,
  411. CompileController.wordCount
  412. )
  413. webRouter.delete(
  414. '/Project/:Project_id',
  415. AuthorizationMiddleware.ensureUserCanAdminProject,
  416. ProjectController.deleteProject
  417. )
  418. webRouter.post(
  419. '/Project/:Project_id/restore',
  420. AuthorizationMiddleware.ensureUserCanAdminProject,
  421. ProjectController.restoreProject
  422. )
  423. webRouter.post(
  424. '/Project/:Project_id/clone',
  425. AuthorizationMiddleware.ensureUserCanReadProject,
  426. ProjectController.cloneProject
  427. )
  428. webRouter.post(
  429. '/project/:Project_id/rename',
  430. AuthorizationMiddleware.ensureUserCanAdminProject,
  431. ProjectController.renameProject
  432. )
  433. webRouter.get(
  434. '/project/:Project_id/updates',
  435. AuthorizationMiddleware.ensureUserCanReadProject,
  436. HistoryController.selectHistoryApi,
  437. HistoryController.proxyToHistoryApiAndInjectUserDetails
  438. )
  439. webRouter.get(
  440. '/project/:Project_id/doc/:doc_id/diff',
  441. AuthorizationMiddleware.ensureUserCanReadProject,
  442. HistoryController.selectHistoryApi,
  443. HistoryController.proxyToHistoryApi
  444. )
  445. webRouter.get(
  446. '/project/:Project_id/diff',
  447. AuthorizationMiddleware.ensureUserCanReadProject,
  448. HistoryController.selectHistoryApi,
  449. HistoryController.proxyToHistoryApiAndInjectUserDetails
  450. )
  451. webRouter.get(
  452. '/project/:Project_id/filetree/diff',
  453. AuthorizationMiddleware.ensureUserCanReadProject,
  454. HistoryController.selectHistoryApi,
  455. HistoryController.proxyToHistoryApi
  456. )
  457. webRouter.post(
  458. '/project/:Project_id/doc/:doc_id/version/:version_id/restore',
  459. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  460. HistoryController.selectHistoryApi,
  461. HistoryController.proxyToHistoryApi
  462. )
  463. webRouter.post(
  464. '/project/:project_id/doc/:doc_id/restore',
  465. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  466. HistoryController.restoreDocFromDeletedDoc
  467. )
  468. webRouter.post(
  469. '/project/:project_id/restore_file',
  470. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  471. HistoryController.restoreFileFromV2
  472. )
  473. webRouter.get(
  474. '/project/:project_id/version/:version/zip',
  475. AuthorizationMiddleware.ensureUserCanReadProject,
  476. HistoryController.downloadZipOfVersion
  477. )
  478. privateApiRouter.post(
  479. '/project/:Project_id/history/resync',
  480. AuthenticationController.httpAuth,
  481. HistoryController.resyncProjectHistory
  482. )
  483. webRouter.get(
  484. '/project/:Project_id/labels',
  485. AuthorizationMiddleware.ensureUserCanReadProject,
  486. HistoryController.selectHistoryApi,
  487. HistoryController.ensureProjectHistoryEnabled,
  488. HistoryController.getLabels
  489. )
  490. webRouter.post(
  491. '/project/:Project_id/labels',
  492. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  493. HistoryController.selectHistoryApi,
  494. HistoryController.ensureProjectHistoryEnabled,
  495. HistoryController.createLabel
  496. )
  497. webRouter.delete(
  498. '/project/:Project_id/labels/:label_id',
  499. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  500. HistoryController.selectHistoryApi,
  501. HistoryController.ensureProjectHistoryEnabled,
  502. HistoryController.deleteLabel
  503. )
  504. webRouter.post(
  505. '/project/:project_id/export/:brand_variation_id',
  506. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  507. ExportsController.exportProject
  508. )
  509. webRouter.get(
  510. '/project/:project_id/export/:export_id',
  511. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  512. ExportsController.exportStatus
  513. )
  514. webRouter.get(
  515. '/project/:project_id/export/:export_id/:type',
  516. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  517. ExportsController.exportDownload
  518. )
  519. webRouter.get(
  520. '/Project/:Project_id/download/zip',
  521. AuthorizationMiddleware.ensureUserCanReadProject,
  522. ProjectDownloadsController.downloadProject
  523. )
  524. webRouter.get(
  525. '/project/download/zip',
  526. AuthorizationMiddleware.ensureUserCanReadMultipleProjects,
  527. ProjectDownloadsController.downloadMultipleProjects
  528. )
  529. webRouter.get(
  530. '/project/:project_id/metadata',
  531. AuthorizationMiddleware.ensureUserCanReadProject,
  532. AuthenticationController.requireLogin(),
  533. MetaController.getMetadata
  534. )
  535. webRouter.post(
  536. '/project/:project_id/doc/:doc_id/metadata',
  537. AuthorizationMiddleware.ensureUserCanReadProject,
  538. AuthenticationController.requireLogin(),
  539. MetaController.broadcastMetadataForDoc
  540. )
  541. privateApiRouter.post(
  542. '/internal/expire-deleted-projects-after-duration',
  543. AuthenticationController.httpAuth,
  544. ProjectController.expireDeletedProjectsAfterDuration
  545. )
  546. privateApiRouter.post(
  547. '/internal/expire-deleted-users-after-duration',
  548. AuthenticationController.httpAuth,
  549. UserController.expireDeletedUsersAfterDuration
  550. )
  551. privateApiRouter.post(
  552. '/internal/project/:projectId/expire-deleted-project',
  553. AuthenticationController.httpAuth,
  554. ProjectController.expireDeletedProject
  555. )
  556. privateApiRouter.post(
  557. '/internal/users/:userId/expire',
  558. AuthenticationController.httpAuth,
  559. UserController.expireDeletedUser
  560. )
  561. webRouter.get(
  562. '/tag',
  563. AuthenticationController.requireLogin(),
  564. TagsController.getAllTags
  565. )
  566. webRouter.post(
  567. '/tag',
  568. AuthenticationController.requireLogin(),
  569. RateLimiterMiddleware.rateLimit({
  570. endpointName: 'create-tag',
  571. maxRequests: 30,
  572. timeInterval: 60
  573. }),
  574. TagsController.createTag
  575. )
  576. webRouter.post(
  577. '/tag/:tag_id/rename',
  578. AuthenticationController.requireLogin(),
  579. RateLimiterMiddleware.rateLimit({
  580. endpointName: 'rename-tag',
  581. maxRequests: 30,
  582. timeInterval: 60
  583. }),
  584. TagsController.renameTag
  585. )
  586. webRouter.delete(
  587. '/tag/:tag_id',
  588. AuthenticationController.requireLogin(),
  589. RateLimiterMiddleware.rateLimit({
  590. endpointName: 'delete-tag',
  591. maxRequests: 30,
  592. timeInterval: 60
  593. }),
  594. TagsController.deleteTag
  595. )
  596. webRouter.post(
  597. '/tag/:tag_id/project/:project_id',
  598. AuthenticationController.requireLogin(),
  599. RateLimiterMiddleware.rateLimit({
  600. endpointName: 'add-project-to-tag',
  601. maxRequests: 30,
  602. timeInterval: 60
  603. }),
  604. TagsController.addProjectToTag
  605. )
  606. webRouter.delete(
  607. '/tag/:tag_id/project/:project_id',
  608. AuthenticationController.requireLogin(),
  609. RateLimiterMiddleware.rateLimit({
  610. endpointName: 'remove-project-from-tag',
  611. maxRequests: 30,
  612. timeInterval: 60
  613. }),
  614. TagsController.removeProjectFromTag
  615. )
  616. webRouter.get(
  617. '/notifications',
  618. AuthenticationController.requireLogin(),
  619. NotificationsController.getAllUnreadNotifications
  620. )
  621. webRouter.delete(
  622. '/notifications/:notification_id',
  623. AuthenticationController.requireLogin(),
  624. NotificationsController.markNotificationAsRead
  625. )
  626. webRouter.get(
  627. '/announcements',
  628. AuthenticationController.requireLogin(),
  629. AnnouncementsController.getUndreadAnnouncements
  630. )
  631. // Deprecated in favour of /internal/project/:project_id but still used by versioning
  632. privateApiRouter.get(
  633. '/project/:project_id/details',
  634. AuthenticationController.httpAuth,
  635. ProjectApiController.getProjectDetails
  636. )
  637. // New 'stable' /internal API end points
  638. privateApiRouter.get(
  639. '/internal/project/:project_id',
  640. AuthenticationController.httpAuth,
  641. ProjectApiController.getProjectDetails
  642. )
  643. privateApiRouter.get(
  644. '/internal/project/:Project_id/zip',
  645. AuthenticationController.httpAuth,
  646. ProjectDownloadsController.downloadProject
  647. )
  648. privateApiRouter.get(
  649. '/internal/project/:project_id/compile/pdf',
  650. AuthenticationController.httpAuth,
  651. CompileController.compileAndDownloadPdf
  652. )
  653. privateApiRouter.post(
  654. '/internal/deactivateOldProjects',
  655. AuthenticationController.httpAuth,
  656. InactiveProjectController.deactivateOldProjects
  657. )
  658. privateApiRouter.post(
  659. '/internal/project/:project_id/deactivate',
  660. AuthenticationController.httpAuth,
  661. InactiveProjectController.deactivateProject
  662. )
  663. webRouter.get(
  664. /^\/internal\/project\/([^/]*)\/output\/(.*)$/,
  665. function(req, res, next) {
  666. const params = {
  667. Project_id: req.params[0],
  668. file: req.params[1]
  669. }
  670. req.params = params
  671. next()
  672. },
  673. AuthenticationController.httpAuth,
  674. CompileController.getFileFromClsi
  675. )
  676. privateApiRouter.get(
  677. '/project/:Project_id/doc/:doc_id',
  678. AuthenticationController.httpAuth,
  679. DocumentController.getDocument
  680. )
  681. privateApiRouter.post(
  682. '/project/:Project_id/doc/:doc_id',
  683. AuthenticationController.httpAuth,
  684. DocumentController.setDocument
  685. )
  686. privateApiRouter.post(
  687. '/user/:user_id/update/*',
  688. AuthenticationController.httpAuth,
  689. TpdsController.mergeUpdate
  690. )
  691. privateApiRouter.delete(
  692. '/user/:user_id/update/*',
  693. AuthenticationController.httpAuth,
  694. TpdsController.deleteUpdate
  695. )
  696. privateApiRouter.post(
  697. '/project/:project_id/contents/*',
  698. AuthenticationController.httpAuth,
  699. TpdsController.updateProjectContents
  700. )
  701. privateApiRouter.delete(
  702. '/project/:project_id/contents/*',
  703. AuthenticationController.httpAuth,
  704. TpdsController.deleteProjectContents
  705. )
  706. webRouter.post(
  707. '/spelling/check',
  708. AuthenticationController.requireLogin(),
  709. SpellingController.proxyRequestToSpellingApi
  710. )
  711. webRouter.post(
  712. '/spelling/learn',
  713. AuthenticationController.requireLogin(),
  714. SpellingController.proxyRequestToSpellingApi
  715. )
  716. webRouter.get(
  717. '/project/:project_id/messages',
  718. AuthorizationMiddleware.ensureUserCanReadProject,
  719. ChatController.getMessages
  720. )
  721. webRouter.post(
  722. '/project/:project_id/messages',
  723. AuthorizationMiddleware.ensureUserCanReadProject,
  724. RateLimiterMiddleware.rateLimit({
  725. endpointName: 'send-chat-message',
  726. maxRequests: 100,
  727. timeInterval: 60
  728. }),
  729. ChatController.sendMessage
  730. )
  731. webRouter.post(
  732. '/project/:Project_id/references/index',
  733. AuthorizationMiddleware.ensureUserCanReadProject,
  734. RateLimiterMiddleware.rateLimit({
  735. endpointName: 'index-project-references',
  736. maxRequests: 30,
  737. timeInterval: 60
  738. }),
  739. ReferencesController.index
  740. )
  741. webRouter.post(
  742. '/project/:Project_id/references/indexAll',
  743. AuthorizationMiddleware.ensureUserCanReadProject,
  744. RateLimiterMiddleware.rateLimit({
  745. endpointName: 'index-all-project-references',
  746. maxRequests: 30,
  747. timeInterval: 60
  748. }),
  749. ReferencesController.indexAll
  750. )
  751. // disable beta program while v2 is in beta
  752. webRouter.get(
  753. '/beta/participate',
  754. AuthenticationController.requireLogin(),
  755. BetaProgramController.optInPage
  756. )
  757. webRouter.post(
  758. '/beta/opt-in',
  759. AuthenticationController.requireLogin(),
  760. BetaProgramController.optIn
  761. )
  762. webRouter.post(
  763. '/beta/opt-out',
  764. AuthenticationController.requireLogin(),
  765. BetaProgramController.optOut
  766. )
  767. webRouter.get(
  768. '/confirm-password',
  769. AuthenticationController.requireLogin(),
  770. SudoModeController.sudoModePrompt
  771. )
  772. webRouter.post(
  773. '/confirm-password',
  774. AuthenticationController.requireLogin(),
  775. RateLimiterMiddleware.rateLimit({
  776. endpointName: 'confirm-password',
  777. maxRequests: 10,
  778. timeInterval: 60
  779. }),
  780. SudoModeController.submitPassword
  781. )
  782. // New "api" endpoints. Started as a way for v1 to call over to v2 (for
  783. // long-term features, as opposed to the nominally temporary ones in the
  784. // overleaf-integration module), but may expand beyond that role.
  785. publicApiRouter.post(
  786. '/api/clsi/compile/:submission_id',
  787. AuthenticationController.httpAuth,
  788. CompileController.compileSubmission
  789. )
  790. publicApiRouter.get(
  791. /^\/api\/clsi\/compile\/([^/]*)\/build\/([0-9a-f-]+)\/output\/(.*)$/,
  792. function(req, res, next) {
  793. const params = {
  794. submission_id: req.params[0],
  795. build_id: req.params[1],
  796. file: req.params[2]
  797. }
  798. req.params = params
  799. next()
  800. },
  801. AuthenticationController.httpAuth,
  802. CompileController.getFileFromClsiWithoutUser
  803. )
  804. publicApiRouter.post(
  805. '/api/institutions/confirm_university_domain',
  806. RateLimiterMiddleware.rateLimit({
  807. endpointName: 'confirm-university-domain',
  808. maxRequests: 1,
  809. timeInterval: 60
  810. }),
  811. AuthenticationController.httpAuth,
  812. InstitutionsController.confirmDomain
  813. )
  814. webRouter.get('/chrome', function(req, res, next) {
  815. // Match v1 behaviour - this is used for a Chrome web app
  816. if (AuthenticationController.isUserLoggedIn(req)) {
  817. res.redirect('/project')
  818. } else {
  819. res.redirect('/register')
  820. }
  821. })
  822. // Admin Stuff
  823. webRouter.get(
  824. '/admin',
  825. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  826. AdminController.index
  827. )
  828. webRouter.get(
  829. '/admin/user',
  830. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  831. (req, res) => res.redirect('/admin/register')
  832. ) // this gets removed by admin-panel addon
  833. webRouter.get(
  834. '/admin/register',
  835. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  836. AdminController.registerNewUser
  837. )
  838. webRouter.post(
  839. '/admin/register',
  840. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  841. UserController.register
  842. )
  843. webRouter.post(
  844. '/admin/closeEditor',
  845. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  846. AdminController.closeEditor
  847. )
  848. webRouter.post(
  849. '/admin/dissconectAllUsers',
  850. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  851. AdminController.dissconectAllUsers
  852. )
  853. webRouter.post(
  854. '/admin/syncUserToSubscription',
  855. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  856. AdminController.syncUserToSubscription
  857. )
  858. webRouter.post(
  859. '/admin/flushProjectToTpds',
  860. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  861. AdminController.flushProjectToTpds
  862. )
  863. webRouter.post(
  864. '/admin/pollDropboxForUser',
  865. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  866. AdminController.pollDropboxForUser
  867. )
  868. webRouter.post(
  869. '/admin/messages',
  870. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  871. AdminController.createMessage
  872. )
  873. webRouter.post(
  874. '/admin/messages/clear',
  875. AuthorizationMiddleware.ensureUserIsSiteAdmin,
  876. AdminController.clearMessages
  877. )
  878. privateApiRouter.post(
  879. '/disconnectAllUsers',
  880. AdminController.dissconectAllUsers
  881. )
  882. privateApiRouter.get('/perfTest', (req, res) => res.send('hello'))
  883. publicApiRouter.get('/status', (req, res) =>
  884. res.send('web sharelatex is alive (web)')
  885. )
  886. privateApiRouter.get('/status', (req, res) =>
  887. res.send('web sharelatex is alive (api)')
  888. )
  889. webRouter.get('/dev/csrf', (req, res) => res.send(res.locals.csrfToken))
  890. publicApiRouter.get('/health_check', HealthCheckController.check)
  891. privateApiRouter.get('/health_check', HealthCheckController.check)
  892. publicApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  893. privateApiRouter.get('/health_check/redis', HealthCheckController.checkRedis)
  894. publicApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  895. privateApiRouter.get('/health_check/mongo', HealthCheckController.checkMongo)
  896. webRouter.get(
  897. '/status/compiler/:Project_id',
  898. AuthorizationMiddleware.ensureUserCanReadProject,
  899. function(req, res) {
  900. const projectId = req.params.Project_id
  901. const sendRes = _.once(function(statusCode, message) {
  902. res.status(statusCode)
  903. res.send(message)
  904. ClsiCookieManager.clearServerId(projectId)
  905. }) // force every compile to a new server
  906. // set a timeout
  907. var handler = setTimeout(function() {
  908. sendRes(500, 'Compiler timed out')
  909. handler = null
  910. }, 10000)
  911. // use a valid user id for testing
  912. const testUserId = '123456789012345678901234'
  913. // run the compile
  914. CompileManager.compile(projectId, testUserId, {}, function(
  915. error,
  916. status
  917. ) {
  918. if (handler) {
  919. clearTimeout(handler)
  920. }
  921. if (error) {
  922. sendRes(500, `Compiler returned error ${error.message}`)
  923. } else if (status === 'success') {
  924. sendRes(200, 'Compiler returned in less than 10 seconds')
  925. } else {
  926. sendRes(500, `Compiler returned failure ${status}`)
  927. }
  928. })
  929. }
  930. )
  931. webRouter.get('/no-cache', function(req, res, next) {
  932. res.header('Cache-Control', 'max-age=0')
  933. res.sendStatus(404)
  934. })
  935. webRouter.get('/oops-express', (req, res, next) =>
  936. next(new Error('Test error'))
  937. )
  938. webRouter.get('/oops-internal', function(req, res, next) {
  939. throw new Error('Test error')
  940. })
  941. webRouter.get('/oops-mongo', (req, res, next) =>
  942. require('./models/Project').Project.findOne({}, function() {
  943. throw new Error('Test error')
  944. })
  945. )
  946. privateApiRouter.get('/opps-small', function(req, res, next) {
  947. logger.err('test error occured')
  948. res.send()
  949. })
  950. webRouter.post('/error/client', function(req, res, next) {
  951. logger.warn(
  952. { err: req.body.error, meta: req.body.meta },
  953. 'client side error'
  954. )
  955. metrics.inc('client-side-error')
  956. res.sendStatus(204)
  957. })
  958. webRouter.get(
  959. '/read/:read_only_token([a-z]+)',
  960. RateLimiterMiddleware.rateLimit({
  961. endpointName: 'read-only-token',
  962. maxRequests: 15,
  963. timeInterval: 60
  964. }),
  965. TokenAccessController.readOnlyToken
  966. )
  967. webRouter.get(
  968. '/:read_and_write_token([0-9]+[a-z]+)',
  969. RateLimiterMiddleware.rateLimit({
  970. endpointName: 'read-and-write-token',
  971. maxRequests: 15,
  972. timeInterval: 60
  973. }),
  974. TokenAccessController.readAndWriteToken
  975. )
  976. webRouter.get('*', ErrorController.notFound)
  977. }