ProjectGetter.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. const { db } = require('../../infrastructure/mongodb')
  2. const { normalizeQuery } = require('../Helpers/Mongo')
  3. const OError = require('@overleaf/o-error')
  4. const metrics = require('@overleaf/metrics')
  5. const { promisifyAll } = require('../../util/promises')
  6. const { Project } = require('../../models/Project')
  7. const logger = require('@overleaf/logger')
  8. const LockManager = require('../../infrastructure/LockManager')
  9. const { DeletedProject } = require('../../models/DeletedProject')
  10. const ProjectGetter = {
  11. EXCLUDE_DEPTH: 8,
  12. getProjectWithoutDocLines(projectId, callback) {
  13. const excludes = {}
  14. for (let i = 1; i <= ProjectGetter.EXCLUDE_DEPTH; i++) {
  15. excludes[`rootFolder${Array(i).join('.folders')}.docs.lines`] = 0
  16. }
  17. ProjectGetter.getProject(projectId, excludes, callback)
  18. },
  19. getProjectWithOnlyFolders(projectId, callback) {
  20. const excludes = {}
  21. for (let i = 1; i <= ProjectGetter.EXCLUDE_DEPTH; i++) {
  22. excludes[`rootFolder${Array(i).join('.folders')}.docs`] = 0
  23. excludes[`rootFolder${Array(i).join('.folders')}.fileRefs`] = 0
  24. }
  25. ProjectGetter.getProject(projectId, excludes, callback)
  26. },
  27. getProject(projectId, projection, callback) {
  28. if (typeof projection === 'function' && callback == null) {
  29. callback = projection
  30. projection = {}
  31. }
  32. if (projectId == null) {
  33. return callback(new Error('no project id provided'))
  34. }
  35. if (typeof projection !== 'object') {
  36. return callback(new Error('projection is not an object'))
  37. }
  38. if (projection.rootFolder || Object.keys(projection).length === 0) {
  39. const ProjectEntityMongoUpdateHandler = require('./ProjectEntityMongoUpdateHandler')
  40. LockManager.runWithLock(
  41. ProjectEntityMongoUpdateHandler.LOCK_NAMESPACE,
  42. projectId,
  43. cb => ProjectGetter.getProjectWithoutLock(projectId, projection, cb),
  44. callback
  45. )
  46. } else {
  47. ProjectGetter.getProjectWithoutLock(projectId, projection, callback)
  48. }
  49. },
  50. getProjectWithoutLock(projectId, projection, callback) {
  51. if (typeof projection === 'function' && callback == null) {
  52. callback = projection
  53. projection = {}
  54. }
  55. if (projectId == null) {
  56. return callback(new Error('no project id provided'))
  57. }
  58. if (typeof projection !== 'object') {
  59. return callback(new Error('projection is not an object'))
  60. }
  61. let query
  62. try {
  63. query = normalizeQuery(projectId)
  64. } catch (err) {
  65. return callback(err)
  66. }
  67. db.projects.findOne(query, { projection }, function (err, project) {
  68. if (err) {
  69. OError.tag(err, 'error getting project', {
  70. query,
  71. projection,
  72. })
  73. return callback(err)
  74. }
  75. callback(null, project)
  76. })
  77. },
  78. getProjectIdByReadAndWriteToken(token, callback) {
  79. Project.findOne(
  80. { 'tokens.readAndWrite': token },
  81. { _id: 1 },
  82. function (err, project) {
  83. if (err) {
  84. return callback(err)
  85. }
  86. if (project == null) {
  87. return callback()
  88. }
  89. callback(null, project._id)
  90. }
  91. )
  92. },
  93. findAllUsersProjects(userId, fields, callback) {
  94. const CollaboratorsGetter = require('../Collaborators/CollaboratorsGetter')
  95. Project.find(
  96. { owner_ref: userId },
  97. fields,
  98. function (error, ownedProjects) {
  99. if (error) {
  100. return callback(error)
  101. }
  102. CollaboratorsGetter.getProjectsUserIsMemberOf(
  103. userId,
  104. fields,
  105. function (error, projects) {
  106. if (error) {
  107. return callback(error)
  108. }
  109. const result = {
  110. owned: ownedProjects || [],
  111. readAndWrite: projects.readAndWrite || [],
  112. readOnly: projects.readOnly || [],
  113. tokenReadAndWrite: projects.tokenReadAndWrite || [],
  114. tokenReadOnly: projects.tokenReadOnly || [],
  115. }
  116. callback(null, result)
  117. }
  118. )
  119. }
  120. )
  121. },
  122. /**
  123. * Return all projects with the given name that belong to the given user.
  124. *
  125. * Projects include the user's own projects as well as collaborations with
  126. * read/write access.
  127. */
  128. findUsersProjectsByName(userId, projectName, callback) {
  129. ProjectGetter.findAllUsersProjects(
  130. userId,
  131. 'name archived trashed',
  132. (err, allProjects) => {
  133. if (err != null) {
  134. return callback(err)
  135. }
  136. const { owned, readAndWrite } = allProjects
  137. const projects = owned.concat(readAndWrite)
  138. const lowerCasedProjectName = projectName.toLowerCase()
  139. const matches = projects.filter(
  140. project => project.name.toLowerCase() === lowerCasedProjectName
  141. )
  142. callback(null, matches)
  143. }
  144. )
  145. },
  146. getUsersDeletedProjects(userId, callback) {
  147. DeletedProject.find(
  148. {
  149. 'deleterData.deletedProjectOwnerId': userId,
  150. },
  151. callback
  152. )
  153. },
  154. }
  155. ;['getProject', 'getProjectWithoutDocLines'].map(method =>
  156. metrics.timeAsyncMethod(ProjectGetter, method, 'mongo.ProjectGetter', logger)
  157. )
  158. ProjectGetter.promises = promisifyAll(ProjectGetter)
  159. module.exports = ProjectGetter