UserDeleter.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. const { callbackify } = require('util')
  2. const logger = require('@overleaf/logger')
  3. const moment = require('moment')
  4. const { User } = require('../../models/User')
  5. const { DeletedUser } = require('../../models/DeletedUser')
  6. const NewsletterManager = require('../Newsletter/NewsletterManager')
  7. const ProjectDeleter = require('../Project/ProjectDeleter')
  8. const SubscriptionHandler = require('../Subscription/SubscriptionHandler')
  9. const SubscriptionUpdater = require('../Subscription/SubscriptionUpdater')
  10. const SubscriptionLocator = require('../Subscription/SubscriptionLocator')
  11. const UserMembershipsHandler = require('../UserMembership/UserMembershipsHandler')
  12. const UserSessionsManager = require('./UserSessionsManager')
  13. const InstitutionsAPI = require('../Institutions/InstitutionsAPI')
  14. const Errors = require('../Errors/Errors')
  15. module.exports = {
  16. deleteUser: callbackify(deleteUser),
  17. deleteMongoUser: callbackify(deleteMongoUser),
  18. expireDeletedUser: callbackify(expireDeletedUser),
  19. ensureCanDeleteUser: callbackify(ensureCanDeleteUser),
  20. expireDeletedUsersAfterDuration: callbackify(expireDeletedUsersAfterDuration),
  21. promises: {
  22. deleteUser,
  23. deleteMongoUser,
  24. expireDeletedUser,
  25. ensureCanDeleteUser,
  26. expireDeletedUsersAfterDuration,
  27. },
  28. }
  29. async function deleteUser(userId, options = {}) {
  30. if (!userId) {
  31. logger.warn('user_id is null when trying to delete user')
  32. throw new Error('no user_id')
  33. }
  34. try {
  35. const user = await User.findById(userId).exec()
  36. logger.debug({ user }, 'deleting user')
  37. await ensureCanDeleteUser(user)
  38. await _cleanupUser(user)
  39. await _createDeletedUser(user, options)
  40. await ProjectDeleter.promises.deleteUsersProjects(user._id)
  41. await deleteMongoUser(user._id)
  42. } catch (error) {
  43. logger.warn({ error, userId }, 'something went wrong deleting the user')
  44. throw error
  45. }
  46. }
  47. /**
  48. * delete a user document only
  49. */
  50. async function deleteMongoUser(userId) {
  51. if (!userId) {
  52. throw new Error('no user_id')
  53. }
  54. await User.deleteOne({ _id: userId }).exec()
  55. }
  56. async function expireDeletedUser(userId) {
  57. const deletedUser = await DeletedUser.findOne({
  58. 'deleterData.deletedUserId': userId,
  59. }).exec()
  60. deletedUser.user = undefined
  61. deletedUser.deleterData.deleterIpAddress = undefined
  62. await deletedUser.save()
  63. }
  64. async function expireDeletedUsersAfterDuration() {
  65. const DURATION = 90
  66. const deletedUsers = await DeletedUser.find({
  67. 'deleterData.deletedAt': {
  68. $lt: new Date(moment().subtract(DURATION, 'days')),
  69. },
  70. user: {
  71. $ne: null,
  72. },
  73. }).exec()
  74. if (deletedUsers.length === 0) {
  75. return
  76. }
  77. for (let i = 0; i < deletedUsers.length; i++) {
  78. await expireDeletedUser(deletedUsers[i].deleterData.deletedUserId)
  79. }
  80. }
  81. async function ensureCanDeleteUser(user) {
  82. const subscription = await SubscriptionLocator.promises.getUsersSubscription(
  83. user
  84. )
  85. if (subscription) {
  86. throw new Errors.SubscriptionAdminDeletionError({})
  87. }
  88. }
  89. async function _createDeletedUser(user, options) {
  90. await DeletedUser.updateOne(
  91. { 'deleterData.deletedUserId': user._id },
  92. {
  93. user,
  94. deleterData: {
  95. deletedAt: new Date(),
  96. deleterId: options.deleterUser ? options.deleterUser._id : undefined,
  97. deleterIpAddress: options.ipAddress,
  98. deletedUserId: user._id,
  99. deletedUserLastLoggedIn: user.lastLoggedIn,
  100. deletedUserSignUpDate: user.signUpDate,
  101. deletedUserLoginCount: user.loginCount,
  102. deletedUserReferralId: user.referal_id,
  103. deletedUserReferredUsers: user.refered_users,
  104. deletedUserReferredUserCount: user.refered_user_count,
  105. deletedUserOverleafId: user.overleaf ? user.overleaf.id : undefined,
  106. },
  107. },
  108. { upsert: true }
  109. )
  110. }
  111. async function _cleanupUser(user) {
  112. await UserSessionsManager.promises.revokeAllUserSessions(user._id, [])
  113. await NewsletterManager.promises.unsubscribe(user, { delete: true })
  114. await SubscriptionHandler.promises.cancelSubscription(user)
  115. await InstitutionsAPI.promises.deleteAffiliations(user._id)
  116. await SubscriptionUpdater.promises.removeUserFromAllGroups(user._id)
  117. await UserMembershipsHandler.promises.removeUserFromAllEntities(user._id)
  118. }