router.js 39 KB

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