UserMembershipHandler.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /* eslint-disable
  2. n/handle-callback-err,
  3. max-len,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS101: Remove unnecessary use of Array.from
  11. * DS207: Consider shorter variations of null checks
  12. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  13. */
  14. const { ObjectId } = require('mongodb')
  15. const async = require('async')
  16. const { promisifyAll } = require('@overleaf/promise-utils')
  17. const Errors = require('../Errors/Errors')
  18. const EntityModels = {
  19. Institution: require('../../models/Institution').Institution,
  20. Subscription: require('../../models/Subscription').Subscription,
  21. Publisher: require('../../models/Publisher').Publisher,
  22. }
  23. const UserMembershipViewModel = require('./UserMembershipViewModel')
  24. const UserGetter = require('../User/UserGetter')
  25. const logger = require('@overleaf/logger')
  26. const UserMembershipEntityConfigs = require('./UserMembershipEntityConfigs')
  27. const { UserIsManagerError } = require('./UserMembershipErrors')
  28. const UserMembershipHandler = {
  29. getEntityWithoutAuthorizationCheck(entityId, entityConfig, callback) {
  30. if (callback == null) {
  31. callback = function () {}
  32. }
  33. const query = buildEntityQuery(entityId, entityConfig)
  34. EntityModels[entityConfig.modelName].findOne(query, callback)
  35. },
  36. createEntity(entityId, entityConfig, callback) {
  37. if (callback == null) {
  38. callback = function () {}
  39. }
  40. const data = buildEntityQuery(entityId, entityConfig)
  41. EntityModels[entityConfig.modelName].create(data, callback)
  42. },
  43. getUsers(entity, entityConfig, callback) {
  44. if (callback == null) {
  45. callback = function () {}
  46. }
  47. const attributes = entityConfig.fields.read
  48. getPopulatedListOfMembers(entity, attributes, callback)
  49. },
  50. addUser(entity, entityConfig, email, callback) {
  51. if (callback == null) {
  52. callback = function () {}
  53. }
  54. const attribute = entityConfig.fields.write
  55. UserGetter.getUserByAnyEmail(email, function (error, user) {
  56. if (error != null) {
  57. return callback(error)
  58. }
  59. if (!user) {
  60. const err = { userNotFound: true }
  61. return callback(err)
  62. }
  63. if (entity[attribute].some(managerId => managerId.equals(user._id))) {
  64. error = { alreadyAdded: true }
  65. return callback(error)
  66. }
  67. addUserToEntity(entity, attribute, user, error =>
  68. callback(error, UserMembershipViewModel.build(user))
  69. )
  70. })
  71. },
  72. removeUser(entity, entityConfig, userId, callback) {
  73. if (callback == null) {
  74. callback = function () {}
  75. }
  76. const attribute = entityConfig.fields.write
  77. if (entity.admin_id != null ? entity.admin_id.equals(userId) : undefined) {
  78. return callback(new UserIsManagerError())
  79. }
  80. removeUserFromEntity(entity, attribute, userId, callback)
  81. },
  82. }
  83. UserMembershipHandler.promises = promisifyAll(UserMembershipHandler)
  84. module.exports = UserMembershipHandler
  85. function getPopulatedListOfMembers(entity, attributes, callback) {
  86. if (callback == null) {
  87. callback = function () {}
  88. }
  89. const userObjects = []
  90. for (const attribute of Array.from(attributes)) {
  91. for (const userObject of Array.from(entity[attribute] || [])) {
  92. // userObject can be an email as String, a user id as ObjectId or an
  93. // invite as Object with an email attribute as String. We want to pass to
  94. // UserMembershipViewModel either an email as (String) or a user id (ObjectId)
  95. const userIdOrEmail = userObject.email || userObject
  96. userObjects.push(userIdOrEmail)
  97. }
  98. }
  99. async.map(userObjects, UserMembershipViewModel.buildAsync, (err, users) => {
  100. if (err) {
  101. return callback(err)
  102. }
  103. for (const user of users) {
  104. if (
  105. user?._id &&
  106. entity?.admin_id &&
  107. user._id.toString() === entity.admin_id.toString()
  108. ) {
  109. user.isEntityAdmin = true
  110. }
  111. }
  112. callback(null, users)
  113. })
  114. }
  115. function addUserToEntity(entity, attribute, user, callback) {
  116. if (callback == null) {
  117. callback = function () {}
  118. }
  119. const fieldUpdate = {}
  120. fieldUpdate[attribute] = user._id
  121. entity.updateOne({ $addToSet: fieldUpdate }, callback)
  122. }
  123. function removeUserFromEntity(entity, attribute, userId, callback) {
  124. if (callback == null) {
  125. callback = function () {}
  126. }
  127. const fieldUpdate = {}
  128. fieldUpdate[attribute] = userId
  129. entity.updateOne({ $pull: fieldUpdate }, callback)
  130. }
  131. function buildEntityQuery(entityId, entityConfig, loggedInUser) {
  132. if (ObjectId.isValid(entityId.toString())) {
  133. entityId = ObjectId(entityId)
  134. }
  135. const query = Object.assign({}, entityConfig.baseQuery)
  136. query[entityConfig.fields.primaryKey] = entityId
  137. return query
  138. }