HistoryRouter.mjs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // @ts-check
  2. import Settings from '@overleaf/settings'
  3. import { Joi, validate } from '../../infrastructure/Validation.js'
  4. import { RateLimiter } from '../../infrastructure/RateLimiter.js'
  5. import AuthenticationController from '../Authentication/AuthenticationController.js'
  6. import AuthorizationMiddleware from '../Authorization/AuthorizationMiddleware.js'
  7. import RateLimiterMiddleware from '../Security/RateLimiterMiddleware.js'
  8. import HistoryController from './HistoryController.js'
  9. const rateLimiters = {
  10. downloadProjectRevision: new RateLimiter('download-project-revision', {
  11. points: 30,
  12. duration: 60 * 60,
  13. }),
  14. getProjectBlob: new RateLimiter('get-project-blob', {
  15. // Download project in full once per hour
  16. points: Settings.maxEntitiesPerProject,
  17. duration: 60 * 60,
  18. }),
  19. flushHistory: new RateLimiter('flush-project-history', {
  20. points: 30,
  21. duration: 60,
  22. }),
  23. }
  24. function apply(webRouter, privateApiRouter) {
  25. // Blobs
  26. webRouter.head(
  27. '/project/:project_id/blob/:hash',
  28. validate({
  29. params: Joi.object({
  30. project_id: Joi.objectId().required(),
  31. hash: Joi.string().required().hex().length(40),
  32. }),
  33. query: Joi.object({
  34. fallback: Joi.objectId().optional(),
  35. }),
  36. }),
  37. RateLimiterMiddleware.rateLimit(rateLimiters.getProjectBlob),
  38. AuthorizationMiddleware.ensureUserCanReadProject,
  39. HistoryController.headBlob
  40. )
  41. webRouter.get(
  42. '/project/:project_id/blob/:hash',
  43. validate({
  44. params: Joi.object({
  45. project_id: Joi.objectId().required(),
  46. hash: Joi.string().required().hex().length(40),
  47. }),
  48. query: Joi.object({
  49. fallback: Joi.objectId().optional(),
  50. }),
  51. }),
  52. RateLimiterMiddleware.rateLimit(rateLimiters.getProjectBlob),
  53. AuthorizationMiddleware.ensureUserCanReadProject,
  54. HistoryController.getBlob
  55. )
  56. // History diffs
  57. webRouter.get(
  58. '/project/:Project_id/updates',
  59. AuthorizationMiddleware.blockRestrictedUserFromProject,
  60. AuthorizationMiddleware.ensureUserCanReadProject,
  61. HistoryController.proxyToHistoryApiAndInjectUserDetails
  62. )
  63. webRouter.get(
  64. '/project/:Project_id/doc/:doc_id/diff',
  65. AuthorizationMiddleware.blockRestrictedUserFromProject,
  66. AuthorizationMiddleware.ensureUserCanReadProject,
  67. HistoryController.proxyToHistoryApi
  68. )
  69. webRouter.get(
  70. '/project/:Project_id/diff',
  71. AuthorizationMiddleware.blockRestrictedUserFromProject,
  72. AuthorizationMiddleware.ensureUserCanReadProject,
  73. HistoryController.proxyToHistoryApiAndInjectUserDetails
  74. )
  75. webRouter.get(
  76. '/project/:Project_id/filetree/diff',
  77. AuthorizationMiddleware.blockRestrictedUserFromProject,
  78. AuthorizationMiddleware.ensureUserCanReadProject,
  79. HistoryController.proxyToHistoryApi
  80. )
  81. // File and project restore
  82. webRouter.post(
  83. '/project/:project_id/restore_file',
  84. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  85. HistoryController.restoreFileFromV2
  86. )
  87. webRouter.post(
  88. '/project/:project_id/revert_file',
  89. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  90. HistoryController.revertFile
  91. )
  92. webRouter.post(
  93. '/project/:project_id/revert-project',
  94. AuthorizationMiddleware.ensureUserCanWriteProjectContent,
  95. HistoryController.revertProject
  96. )
  97. // History download
  98. webRouter.get(
  99. '/project/:project_id/version/:version/zip',
  100. RateLimiterMiddleware.rateLimit(rateLimiters.downloadProjectRevision),
  101. AuthorizationMiddleware.blockRestrictedUserFromProject,
  102. AuthorizationMiddleware.ensureUserCanReadProject,
  103. HistoryController.downloadZipOfVersion
  104. )
  105. // History flush and resync
  106. webRouter.post(
  107. '/project/:Project_id/flush',
  108. RateLimiterMiddleware.rateLimit(rateLimiters.flushHistory),
  109. AuthorizationMiddleware.blockRestrictedUserFromProject,
  110. AuthorizationMiddleware.ensureUserCanReadProject,
  111. HistoryController.proxyToHistoryApi
  112. )
  113. privateApiRouter.post(
  114. '/project/:Project_id/history/resync',
  115. AuthenticationController.requirePrivateApiAuth(),
  116. HistoryController.resyncProjectHistory
  117. )
  118. // History labels
  119. webRouter.get(
  120. '/project/:Project_id/labels',
  121. AuthorizationMiddleware.blockRestrictedUserFromProject,
  122. AuthorizationMiddleware.ensureUserCanReadProject,
  123. HistoryController.getLabels
  124. )
  125. webRouter.post(
  126. '/project/:Project_id/labels',
  127. AuthorizationMiddleware.ensureUserCanWriteOrReviewProjectContent,
  128. HistoryController.createLabel
  129. )
  130. webRouter.delete(
  131. '/project/:Project_id/labels/:label_id',
  132. AuthorizationMiddleware.ensureUserCanWriteOrReviewProjectContent,
  133. HistoryController.deleteLabel
  134. )
  135. // History snapshot
  136. webRouter.get(
  137. '/project/:project_id/latest/history',
  138. validate({
  139. params: Joi.object({
  140. project_id: Joi.objectId().required(),
  141. }),
  142. }),
  143. AuthorizationMiddleware.blockRestrictedUserFromProject,
  144. AuthorizationMiddleware.ensureUserCanReadProject,
  145. HistoryController.getLatestHistory
  146. )
  147. webRouter.get(
  148. '/project/:project_id/changes',
  149. validate({
  150. params: Joi.object({
  151. project_id: Joi.objectId().required(),
  152. }),
  153. query: Joi.object({
  154. since: Joi.number().integer().min(0).optional(),
  155. }),
  156. }),
  157. AuthorizationMiddleware.blockRestrictedUserFromProject,
  158. AuthorizationMiddleware.ensureUserCanReadProject,
  159. HistoryController.getChanges
  160. )
  161. }
  162. export default { apply }