ManagedUsersHandler.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. const { callbackify } = require('util')
  2. const { Subscription } = require('../../models/Subscription')
  3. const { GroupPolicy } = require('../../models/GroupPolicy')
  4. const { User } = require('../../models/User')
  5. const ManagedUsersPolicy = require('./ManagedUsersPolicy')
  6. const OError = require('@overleaf/o-error')
  7. const {
  8. UserNotFoundError,
  9. SubscriptionNotFoundError,
  10. } = require('../Errors/Errors')
  11. /**
  12. * This module contains functions for handling managed users in a
  13. * group subscription.
  14. */
  15. /**
  16. * Enables managed users for a given subscription by creating a new
  17. * group policy with default settings for managed users and updating
  18. * the subscription to use the new policy.
  19. * @async
  20. * @function
  21. * @param {string} subscriptionId - The ID of the subscription to enable
  22. * managed users for.
  23. * @returns {Promise<void>} - A Promise that resolves when the subscription
  24. * has been updated with the new group policy.
  25. */
  26. async function enableManagedUsers(subscriptionId) {
  27. const subscription = await Subscription.findById(subscriptionId).exec()
  28. // create a new Group policy with the default settings for managed users
  29. const policy = ManagedUsersPolicy.getDefaultPolicy()
  30. const groupPolicy = new GroupPolicy(policy)
  31. await groupPolicy.save()
  32. // update the subscription to use the new policy
  33. subscription.groupPolicy = groupPolicy._id
  34. await subscription.save()
  35. }
  36. /**
  37. * Retrieves the group policy for a user enrolled in a managed group.
  38. * @async
  39. * @function
  40. * @param {Object} user - The user object to retrieve the group policy for.
  41. * @returns {Promise<Object>} - A Promise that resolves with the group policy
  42. * object for the user's enrollment, or undefined if it does not exist.
  43. */
  44. async function getGroupPolicyForUser(requestedUser) {
  45. // Don't rely on the user being populated, it may be a session user without
  46. // the enrollment property. Force the user to be loaded from mongo.
  47. const user = await User.findById(requestedUser._id, 'enrollment')
  48. if (!user) {
  49. throw new UserNotFoundError({ info: { userId: requestedUser._id } })
  50. }
  51. // Now we are sure the user exists and we have the full contents
  52. if (user.enrollment?.managedBy == null) {
  53. return
  54. }
  55. // retrieve the subscription and the group policy (without the _id field)
  56. const subscription = await Subscription.findById(user.enrollment.managedBy)
  57. .populate('groupPolicy', '-_id')
  58. .exec()
  59. if (!subscription) {
  60. throw new SubscriptionNotFoundError({
  61. info: { subscriptionId: user.enrollment.managedBy, userId: user._id },
  62. })
  63. }
  64. // return the group policy as a plain object (without the __v field)
  65. const groupPolicy = subscription.groupPolicy.toObject({
  66. versionKey: false,
  67. })
  68. return groupPolicy
  69. }
  70. async function enrollInSubscription(userId, subscription) {
  71. // check whether the user is already enrolled in a subscription
  72. const user = await User.findOne({
  73. _id: userId,
  74. 'enrollment.managedBy': { $exists: true },
  75. }).exec()
  76. if (user != null) {
  77. throw new OError('User is already enrolled in a subscription', {
  78. userId,
  79. subscriptionId: subscription._id,
  80. })
  81. }
  82. // update the user to be enrolled in the subscription
  83. const updatedUser = await User.findOneAndUpdate(
  84. { _id: userId, 'enrollment.managedBy': { $exists: false } },
  85. {
  86. enrollment: {
  87. managedBy: subscription._id,
  88. enrolledAt: new Date(),
  89. },
  90. },
  91. { new: true }
  92. ).exec()
  93. // check whether the enrollment succeeded
  94. if (
  95. !updatedUser ||
  96. !subscription.equals(updatedUser?.enrollment?.managedBy)
  97. ) {
  98. throw new OError('Failed to enroll user in subscription', {
  99. userId,
  100. subscriptionId: subscription._id,
  101. })
  102. }
  103. }
  104. module.exports = {
  105. promises: {
  106. enableManagedUsers,
  107. getGroupPolicyForUser,
  108. enrollInSubscription,
  109. },
  110. enableManagedUsers: callbackify(enableManagedUsers),
  111. getGroupPolicyForUser: callbackify(getGroupPolicyForUser),
  112. enrollInSubscription: callbackify(enrollInSubscription),
  113. }