router.js 44 KB

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