router.js 41 KB

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