TpdsUpdateHandler.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. const UpdateMerger = require('./UpdateMerger')
  2. const logger = require('logger-sharelatex')
  3. const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
  4. const ProjectCreationHandler = require('../Project/ProjectCreationHandler')
  5. const ProjectDeleter = require('../Project/ProjectDeleter')
  6. const ProjectGetter = require('../Project/ProjectGetter')
  7. const ProjectHelper = require('../Project/ProjectHelper')
  8. const ProjectRootDocManager = require('../Project/ProjectRootDocManager')
  9. const FileTypeManager = require('../Uploads/FileTypeManager')
  10. const CooldownManager = require('../Cooldown/CooldownManager')
  11. const Errors = require('../Errors/Errors')
  12. const Modules = require('../../infrastructure/Modules')
  13. const ROOT_DOC_TIMEOUT_LENGTH = 30 * 1000
  14. function newUpdate(userId, projectName, path, updateRequest, source, callback) {
  15. getOrCreateProject(userId, projectName, (err, project) => {
  16. if (err) {
  17. return callback(err)
  18. }
  19. if (project == null) {
  20. return callback()
  21. }
  22. CooldownManager.isProjectOnCooldown(
  23. project._id,
  24. (err, projectIsOnCooldown) => {
  25. if (err) {
  26. return callback(err)
  27. }
  28. if (projectIsOnCooldown) {
  29. return callback(
  30. new Errors.TooManyRequestsError('project on cooldown')
  31. )
  32. }
  33. FileTypeManager.shouldIgnore(path, (err, shouldIgnore) => {
  34. if (shouldIgnore) {
  35. return callback()
  36. }
  37. UpdateMerger.mergeUpdate(
  38. userId,
  39. project._id,
  40. path,
  41. updateRequest,
  42. source,
  43. callback
  44. )
  45. })
  46. }
  47. )
  48. })
  49. }
  50. function deleteUpdate(userId, projectName, path, source, callback) {
  51. logger.debug({ userId, filePath: path }, 'handling delete update from tpds')
  52. ProjectGetter.findUsersProjectsByName(
  53. userId,
  54. projectName,
  55. (err, projects) => {
  56. if (err) {
  57. return callback(err)
  58. }
  59. const activeProjects = projects.filter(
  60. project => !ProjectHelper.isArchivedOrTrashed(project, userId)
  61. )
  62. if (activeProjects.length === 0) {
  63. logger.debug(
  64. { userId, filePath: path, projectName },
  65. 'project not found from tpds update, ignoring folder or project'
  66. )
  67. return callback()
  68. }
  69. if (projects.length > 1) {
  70. // There is more than one project with that name, and one of them is
  71. // active (previous condition)
  72. return handleDuplicateProjects(userId, projectName, callback)
  73. }
  74. const project = activeProjects[0]
  75. if (path === '/') {
  76. logger.debug(
  77. { userId, filePath: path, projectName, project_id: project._id },
  78. 'project found for delete update, path is root so marking project as deleted'
  79. )
  80. ProjectDeleter.markAsDeletedByExternalSource(project._id, callback)
  81. } else {
  82. UpdateMerger.deleteUpdate(userId, project._id, path, source, err => {
  83. callback(err)
  84. })
  85. }
  86. }
  87. )
  88. }
  89. function getOrCreateProject(userId, projectName, callback) {
  90. ProjectGetter.findUsersProjectsByName(
  91. userId,
  92. projectName,
  93. (err, projects) => {
  94. if (err) {
  95. return callback(err)
  96. }
  97. if (projects.length === 0) {
  98. // No project with that name -- active, archived or trashed -- has been
  99. // found. Create one.
  100. return ProjectCreationHandler.createBlankProject(
  101. userId,
  102. projectName,
  103. (err, project) => {
  104. // have a crack at setting the root doc after a while, on creation
  105. // we won't have it yet, but should have been sent it it within 30
  106. // seconds
  107. setTimeout(() => {
  108. ProjectRootDocManager.setRootDocAutomatically(project._id)
  109. }, ROOT_DOC_TIMEOUT_LENGTH)
  110. callback(err, project)
  111. }
  112. )
  113. }
  114. const activeProjects = projects.filter(
  115. project => !ProjectHelper.isArchivedOrTrashed(project, userId)
  116. )
  117. if (activeProjects.length === 0) {
  118. // All projects with that name are archived or trashed. Ignore.
  119. return callback(null, null)
  120. }
  121. if (projects.length > 1) {
  122. // There is more than one project with that name, and one of them is
  123. // active (previous condition)
  124. return handleDuplicateProjects(userId, projectName, err => {
  125. if (err) {
  126. return callback(err)
  127. }
  128. callback(null, null)
  129. })
  130. }
  131. callback(err, activeProjects[0])
  132. }
  133. )
  134. }
  135. function handleDuplicateProjects(userId, projectName, callback) {
  136. Modules.hooks.fire('removeDropbox', userId, 'duplicate-projects', err => {
  137. if (err) {
  138. return callback(err)
  139. }
  140. NotificationsBuilder.dropboxDuplicateProjectNames(userId).create(
  141. projectName,
  142. callback
  143. )
  144. })
  145. }
  146. module.exports = {
  147. newUpdate,
  148. deleteUpdate,
  149. }