migrate_audit_logs.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. const { batchedUpdate } = require('./helpers/batchedUpdate')
  2. const { promiseMapWithLimit, promisify } = require('../app/src/util/promises')
  3. const { db, ObjectId, waitForDb } = require('../app/src/infrastructure/mongodb')
  4. const sleep = promisify(setTimeout)
  5. const _ = require('lodash')
  6. async function main(options) {
  7. if (!options) {
  8. options = {}
  9. }
  10. _.defaults(options, {
  11. dryRun: process.env.DRY_RUN !== 'false',
  12. projectId: process.env.PROJECT_ID,
  13. userId: process.env.USER_ID,
  14. writeConcurrency: parseInt(process.env.WRITE_CONCURRENCY, 10) || 10,
  15. letUserDoubleCheckInputsFor: parseInt(
  16. process.env.LET_USER_DOUBLE_CHECK_INPUTS_FOR || 10 * 1000,
  17. 10
  18. ),
  19. })
  20. await letUserDoubleCheckInputs(options)
  21. if (options.projectId) {
  22. console.log('migrating projectId=' + options.projectId)
  23. const project = await db.projects.findOne(
  24. { _id: ObjectId(options.projectId) },
  25. { _id: 1, auditLog: 1 }
  26. )
  27. await processProject(project, options)
  28. } else if (options.userId) {
  29. console.log('migrating userId=' + options.userId)
  30. const user = await db.users.findOne(
  31. { _id: ObjectId(options.userId) },
  32. { _id: 1, auditLog: 1 }
  33. )
  34. await processUser(user, options)
  35. } else {
  36. await batchedUpdate(
  37. 'users',
  38. { auditLog: { $exists: true } },
  39. async (_, users) => {
  40. await processUsersBatch(users, options)
  41. },
  42. { _id: 1, auditLog: 1 }
  43. )
  44. }
  45. }
  46. async function processUsersBatch(users, options) {
  47. await promiseMapWithLimit(options.writeConcurrency, users, async user => {
  48. await processUser(user, options)
  49. })
  50. }
  51. async function processUser(user, options) {
  52. const entries = user.auditLog.map(log => ({ ...log, userId: user._id }))
  53. if (!options.dryRun && entries?.length > 0) {
  54. await db.userAuditLogEntries.insertMany(entries)
  55. }
  56. if (!options.dryRun) {
  57. await db.users.updateOne({ _id: user._id }, { $unset: { auditLog: 1 } })
  58. }
  59. const projects = await db.projects.find(
  60. { owner_ref: user._id, auditLog: { $exists: true } },
  61. { _id: 1, auditLog: 1 }
  62. )
  63. projects.forEach(project => processProject(project, options))
  64. }
  65. async function processProject(project, options) {
  66. const entries = project.auditLog.map(log => ({
  67. ...log,
  68. projectId: project._id,
  69. }))
  70. if (!options.dryRun && entries?.length > 0) {
  71. await db.projectAuditLogEntries.insertMany(entries)
  72. }
  73. if (!options.dryRun) {
  74. await db.projects.updateOne(
  75. { _id: project._id },
  76. { $unset: { auditLog: 1 } }
  77. )
  78. }
  79. }
  80. async function letUserDoubleCheckInputs(options) {
  81. const allOptions = {
  82. ...options,
  83. // batchedUpdate() environment variables
  84. BATCH_DESCENDING: process.env.BATCH_DESCENDING,
  85. BATCH_SIZE: process.env.BATCH_SIZE,
  86. VERBOSE_LOGGING: process.env.VERBOSE_LOGGING,
  87. BATCH_LAST_ID: process.env.BATCH_LAST_ID,
  88. BATCH_RANGE_END: process.env.BATCH_RANGE_END,
  89. }
  90. console.error('Options:', JSON.stringify(allOptions, null, 2))
  91. console.error(
  92. 'Waiting for you to double check inputs for',
  93. options.letUserDoubleCheckInputsFor,
  94. 'ms'
  95. )
  96. await sleep(options.letUserDoubleCheckInputsFor)
  97. }
  98. module.exports = main
  99. if (require.main === module) {
  100. waitForDb()
  101. .then(main)
  102. .then(() => {
  103. console.log('Done.')
  104. process.exit(0)
  105. })
  106. .catch(error => {
  107. console.error({ error })
  108. process.exit(1)
  109. })
  110. }