router.js 41 KB

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