LabelsManager.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import OError from '@overleaf/o-error'
  2. import { db, ObjectId } from './mongodb.js'
  3. import * as HistoryStoreManager from './HistoryStoreManager.js'
  4. import * as UpdatesProcessor from './UpdatesProcessor.js'
  5. import * as WebApiManager from './WebApiManager.js'
  6. export function cloneLabels(sourceProjectId, targetProjectId, callback) {
  7. db.projectHistoryLabels
  8. .find({ project_id: new ObjectId(sourceProjectId) })
  9. .project({ _id: 0, project_id: 0 })
  10. .toArray((err, labels) => {
  11. if (err) return callback(OError.tag(err))
  12. if (labels.length === 0) return callback()
  13. db.projectHistoryLabels.insertMany(
  14. labels.map(label => ({
  15. ...label,
  16. project_id: new ObjectId(targetProjectId),
  17. })),
  18. err => {
  19. if (err) return callback(OError.tag(err))
  20. callback()
  21. }
  22. )
  23. })
  24. }
  25. export function getLabels(projectId, callback) {
  26. _toObjectId(projectId, function (error, projectId) {
  27. if (error) {
  28. return callback(OError.tag(error))
  29. }
  30. db.projectHistoryLabels
  31. .find({ project_id: new ObjectId(projectId) })
  32. .toArray(function (error, labels) {
  33. if (error) {
  34. return callback(OError.tag(error))
  35. }
  36. const formattedLabels = labels.map(_formatLabel)
  37. callback(null, formattedLabels)
  38. })
  39. })
  40. }
  41. export function createLabel(
  42. projectId,
  43. userId,
  44. version,
  45. comment,
  46. createdAt,
  47. shouldValidateExists,
  48. callback
  49. ) {
  50. const validateVersionExists = function (callback) {
  51. if (shouldValidateExists === false) {
  52. callback()
  53. } else {
  54. _validateChunkExistsForVersion(projectId.toString(), version, callback)
  55. }
  56. }
  57. _toObjectId(projectId, userId, function (error, projectId, userId) {
  58. if (error) {
  59. return callback(OError.tag(error))
  60. }
  61. validateVersionExists(function (error) {
  62. if (error) {
  63. return callback(OError.tag(error))
  64. }
  65. createdAt = createdAt != null ? new Date(createdAt) : new Date()
  66. const label = {
  67. project_id: new ObjectId(projectId),
  68. comment,
  69. version,
  70. created_at: createdAt,
  71. }
  72. if (userId) {
  73. label.user_id = userId
  74. }
  75. db.projectHistoryLabels.insertOne(label, function (error, confirmation) {
  76. if (error) {
  77. return callback(OError.tag(error))
  78. }
  79. label._id = confirmation.insertedId
  80. callback(null, _formatLabel(label))
  81. })
  82. })
  83. })
  84. }
  85. export function deleteLabelForUser(projectId, userId, labelId, callback) {
  86. _toObjectId(
  87. projectId,
  88. userId,
  89. labelId,
  90. function (error, projectId, userId, labelId) {
  91. if (error) {
  92. return callback(OError.tag(error))
  93. }
  94. db.projectHistoryLabels.deleteOne(
  95. {
  96. _id: new ObjectId(labelId),
  97. project_id: new ObjectId(projectId),
  98. user_id: new ObjectId(userId),
  99. },
  100. callback
  101. )
  102. }
  103. )
  104. }
  105. export function deleteLabel(projectId, labelId, callback) {
  106. _toObjectId(projectId, labelId, function (error, projectId, labelId) {
  107. if (error) {
  108. return callback(OError.tag(error))
  109. }
  110. db.projectHistoryLabels.deleteOne(
  111. {
  112. _id: new ObjectId(labelId),
  113. project_id: new ObjectId(projectId),
  114. },
  115. callback
  116. )
  117. })
  118. }
  119. export function transferLabels(fromUserId, toUserId, callback) {
  120. _toObjectId(fromUserId, toUserId, function (error, fromUserId, toUserId) {
  121. if (error) {
  122. return callback(OError.tag(error))
  123. }
  124. db.projectHistoryLabels.updateMany(
  125. {
  126. user_id: fromUserId,
  127. },
  128. {
  129. $set: { user_id: toUserId },
  130. },
  131. callback
  132. )
  133. })
  134. }
  135. function _toObjectId(...args1) {
  136. const adjustedLength = Math.max(args1.length, 1)
  137. const args = args1.slice(0, adjustedLength - 1)
  138. const callback = args1[adjustedLength - 1]
  139. try {
  140. const ids = args.map(id => {
  141. if (id) {
  142. return new ObjectId(id)
  143. } else {
  144. return undefined
  145. }
  146. })
  147. callback(null, ...ids)
  148. } catch (error) {
  149. callback(error)
  150. }
  151. }
  152. function _formatLabel(label) {
  153. return {
  154. id: label._id,
  155. comment: label.comment,
  156. version: label.version,
  157. user_id: label.user_id,
  158. created_at: label.created_at,
  159. }
  160. }
  161. function _validateChunkExistsForVersion(projectId, version, callback) {
  162. UpdatesProcessor.processUpdatesForProject(projectId, function (error) {
  163. if (error) {
  164. return callback(error)
  165. }
  166. WebApiManager.getHistoryId(projectId, function (error, historyId) {
  167. if (error) {
  168. return callback(error)
  169. }
  170. HistoryStoreManager.getChunkAtVersion(
  171. projectId,
  172. historyId,
  173. version,
  174. function (error) {
  175. if (error) {
  176. return callback(error)
  177. }
  178. callback()
  179. }
  180. )
  181. })
  182. })
  183. }