router.js 34 KB

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