UserMembershipHandler.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* eslint-disable
  2. node/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. * DS102: Remove unnecessary code created because of implicit returns
  12. * DS207: Consider shorter variations of null checks
  13. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  14. */
  15. const { ObjectId } = require('mongodb')
  16. const async = require('async')
  17. const { promisifyAll } = require('../../util/promises')
  18. const Errors = require('../Errors/Errors')
  19. const EntityModels = {
  20. Institution: require('../../models/Institution').Institution,
  21. Subscription: require('../../models/Subscription').Subscription,
  22. Publisher: require('../../models/Publisher').Publisher,
  23. }
  24. const UserMembershipViewModel = require('./UserMembershipViewModel')
  25. const UserGetter = require('../User/UserGetter')
  26. const logger = require('logger-sharelatex')
  27. const UserMembershipEntityConfigs = require('./UserMembershipEntityConfigs')
  28. const UserMembershipHandler = {
  29. getEntityWithoutAuthorizationCheck(entityId, entityConfig, callback) {
  30. if (callback == null) {
  31. callback = function (error, entity) {}
  32. }
  33. const query = buildEntityQuery(entityId, entityConfig)
  34. return EntityModels[entityConfig.modelName].findOne(query, callback)
  35. },
  36. createEntity(entityId, entityConfig, callback) {
  37. if (callback == null) {
  38. callback = function (error, entity) {}
  39. }
  40. const data = buildEntityQuery(entityId, entityConfig)
  41. return EntityModels[entityConfig.modelName].create(data, callback)
  42. },
  43. getUsers(entity, entityConfig, callback) {
  44. if (callback == null) {
  45. callback = function (error, users) {}
  46. }
  47. const attributes = entityConfig.fields.read
  48. return getPopulatedListOfMembers(entity, attributes, callback)
  49. },
  50. addUser(entity, entityConfig, email, callback) {
  51. if (callback == null) {
  52. callback = function (error, user) {}
  53. }
  54. const attribute = entityConfig.fields.write
  55. return 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. return 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 (error) {}
  75. }
  76. const attribute = entityConfig.fields.write
  77. if (entity.admin_id != null ? entity.admin_id.equals(userId) : undefined) {
  78. const error = { isAdmin: true }
  79. return callback(error)
  80. }
  81. return removeUserFromEntity(entity, attribute, userId, callback)
  82. },
  83. }
  84. UserMembershipHandler.promises = promisifyAll(UserMembershipHandler)
  85. module.exports = UserMembershipHandler
  86. function getPopulatedListOfMembers(entity, attributes, callback) {
  87. if (callback == null) {
  88. callback = function (error, users) {}
  89. }
  90. const userObjects = []
  91. for (const attribute of Array.from(attributes)) {
  92. for (const userObject of Array.from(entity[attribute] || [])) {
  93. // userObject can be an email as String, a user id as ObjectId or an
  94. // invite as Object with an email attribute as String. We want to pass to
  95. // UserMembershipViewModel either an email as (String) or a user id (ObjectId)
  96. const userIdOrEmail = userObject.email || userObject
  97. userObjects.push(userIdOrEmail)
  98. }
  99. }
  100. return async.map(userObjects, UserMembershipViewModel.buildAsync, callback)
  101. }
  102. function addUserToEntity(entity, attribute, user, callback) {
  103. if (callback == null) {
  104. callback = function (error) {}
  105. }
  106. const fieldUpdate = {}
  107. fieldUpdate[attribute] = user._id
  108. return entity.updateOne({ $addToSet: fieldUpdate }, callback)
  109. }
  110. function removeUserFromEntity(entity, attribute, userId, callback) {
  111. if (callback == null) {
  112. callback = function (error) {}
  113. }
  114. const fieldUpdate = {}
  115. fieldUpdate[attribute] = userId
  116. return entity.updateOne({ $pull: fieldUpdate }, callback)
  117. }
  118. function buildEntityQuery(entityId, entityConfig, loggedInUser) {
  119. if (ObjectId.isValid(entityId.toString())) {
  120. entityId = ObjectId(entityId)
  121. }
  122. const query = Object.assign({}, entityConfig.baseQuery)
  123. query[entityConfig.fields.primaryKey] = entityId
  124. return query
  125. }