UserMembershipHandler.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. const { ObjectId } = require('mongodb-legacy')
  2. const { promisifyAll, callbackify } = require('@overleaf/promise-utils')
  3. const EntityModels = {
  4. Institution: require('../../models/Institution').Institution,
  5. Subscription: require('../../models/Subscription').Subscription,
  6. Publisher: require('../../models/Publisher').Publisher,
  7. }
  8. const UserMembershipViewModel = require('./UserMembershipViewModel')
  9. const UserGetter = require('../User/UserGetter')
  10. const {
  11. UserIsManagerError,
  12. UserNotFoundError,
  13. UserAlreadyAddedError,
  14. } = require('./UserMembershipErrors')
  15. const UserMembershipHandler = {
  16. async getEntityWithoutAuthorizationCheck(entityId, entityConfig) {
  17. const query = buildEntityQuery(entityId, entityConfig)
  18. return await EntityModels[entityConfig.modelName].findOne(query).exec()
  19. },
  20. async createEntity(entityId, entityConfig) {
  21. const data = buildEntityQuery(entityId, entityConfig)
  22. return await EntityModels[entityConfig.modelName].create(data)
  23. },
  24. async getUsers(entity, entityConfig) {
  25. const attributes = entityConfig.fields.read
  26. return await getPopulatedListOfMembers(entity, attributes)
  27. },
  28. async addUser(entity, entityConfig, email) {
  29. const attribute = entityConfig.fields.write
  30. const user = await UserGetter.promises.getUserByAnyEmail(email)
  31. if (!user) {
  32. throw new UserNotFoundError()
  33. }
  34. if (entity[attribute].some(managerId => managerId.equals(user._id))) {
  35. throw new UserAlreadyAddedError()
  36. }
  37. await addUserToEntity(entity, attribute, user)
  38. return UserMembershipViewModel.build(user)
  39. },
  40. async removeUser(entity, entityConfig, userId) {
  41. const attribute = entityConfig.fields.write
  42. if (entity.admin_id ? entity.admin_id.equals(userId) : undefined) {
  43. throw new UserIsManagerError()
  44. }
  45. return await removeUserFromEntity(entity, attribute, userId)
  46. },
  47. }
  48. UserMembershipHandler.promises = promisifyAll(UserMembershipHandler)
  49. module.exports = {
  50. getEntityWithoutAuthorizationCheck: callbackify(
  51. UserMembershipHandler.getEntityWithoutAuthorizationCheck
  52. ),
  53. createEntity: callbackify(UserMembershipHandler.createEntity),
  54. getUsers: callbackify(UserMembershipHandler.getUsers),
  55. addUser: callbackify(UserMembershipHandler.addUser),
  56. removeUser: callbackify(UserMembershipHandler.removeUser),
  57. promises: UserMembershipHandler,
  58. }
  59. async function getPopulatedListOfMembers(entity, attributes) {
  60. const userObjects = []
  61. for (const attribute of attributes) {
  62. for (const userObject of entity[attribute] || []) {
  63. // userObject can be an email as String, a user id as ObjectId or an
  64. // invite as Object with an email attribute as String. We want to pass to
  65. // UserMembershipViewModel either an email as (String) or a user id (ObjectId)
  66. const userIdOrEmail = userObject.email || userObject
  67. userObjects.push(userIdOrEmail)
  68. }
  69. }
  70. const users = await UserMembershipViewModel.promises.buildAsync(userObjects)
  71. for (const user of users) {
  72. if (
  73. user?._id &&
  74. entity?.admin_id &&
  75. user._id.toString() === entity.admin_id.toString()
  76. ) {
  77. user.isEntityAdmin = true
  78. }
  79. }
  80. return users
  81. }
  82. async function addUserToEntity(entity, attribute, user) {
  83. const fieldUpdate = {}
  84. fieldUpdate[attribute] = user._id
  85. return await entity.updateOne({ $addToSet: fieldUpdate }).exec()
  86. }
  87. async function removeUserFromEntity(entity, attribute, userId) {
  88. const fieldUpdate = {}
  89. fieldUpdate[attribute] = userId
  90. return await entity.updateOne({ $pull: fieldUpdate }).exec()
  91. }
  92. function buildEntityQuery(entityId, entityConfig) {
  93. if (ObjectId.isValid(entityId.toString())) {
  94. entityId = new ObjectId(entityId)
  95. }
  96. const query = Object.assign({}, entityConfig.baseQuery)
  97. query[entityConfig.fields.primaryKey] = entityId
  98. return query
  99. }