update_institution_user_saml_ids.mjs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { db } from '../app/src/infrastructure/mongodb.mjs'
  2. import minimist from 'minimist'
  3. import UserGetter from '../app/src/Features/User/UserGetter.mjs'
  4. import { scriptRunner } from './lib/ScriptRunner.mjs'
  5. function usage() {
  6. console.log(
  7. 'Usage: node update_institution_user_saml_ids.mjs -i <institution-id> -s <search> [-r <replace>]'
  8. )
  9. console.log(
  10. 'Performs string replacement on external user IDs for all users in an institution'
  11. )
  12. console.log('Options:')
  13. console.log(
  14. ' --institution-id, -i Institution ID to update'
  15. )
  16. console.log(' --search, -s String to search for')
  17. console.log(
  18. ' --replace, -r String to replace with (optional, defaults to empty string)'
  19. )
  20. console.log(
  21. ' --dry-run, -d Shows changes but does not perform updates'
  22. )
  23. console.log(
  24. ' --help, -h Show this help message'
  25. )
  26. process.exit(0)
  27. }
  28. const {
  29. 'dry-run': dryRun,
  30. 'institution-id': providerId,
  31. search,
  32. replace,
  33. help,
  34. } = minimist(process.argv.slice(2), {
  35. string: ['institution-id', 'search', 'replace'],
  36. boolean: ['dry-run', 'help'],
  37. alias: {
  38. 'institution-id': 'i',
  39. search: 's',
  40. replace: 'r',
  41. 'dry-run': 'd',
  42. help: 'h',
  43. },
  44. default: {
  45. 'dry-run': true,
  46. replace: '',
  47. },
  48. })
  49. async function main() {
  50. if (help || !providerId || !search) {
  51. usage()
  52. }
  53. const users = await UserGetter.promises.getSsoUsersAtInstitution(providerId, {
  54. _id: 1,
  55. samlIdentifiers: 1,
  56. })
  57. console.log('SSO Users found for institution: ' + users.length)
  58. let usersToUpdate = 0
  59. let usersUpdated = 0
  60. for (const user of users) {
  61. const matchingIdentifier = user.samlIdentifiers.find(
  62. u => u.providerId === providerId
  63. )
  64. if (
  65. !matchingIdentifier ||
  66. !matchingIdentifier.externalUserId.includes(search)
  67. ) {
  68. continue
  69. }
  70. const updatedId = matchingIdentifier.externalUserId.replaceAll(
  71. search,
  72. replace
  73. )
  74. usersToUpdate = usersToUpdate + 1
  75. console.log(`${user._id},${matchingIdentifier.externalUserId},${updatedId}`)
  76. if (dryRun) {
  77. continue
  78. }
  79. try {
  80. await db.users.updateOne(
  81. { _id: user._id, 'samlIdentifiers.providerId': providerId },
  82. { $set: { 'samlIdentifiers.$.externalUserId': updatedId } }
  83. )
  84. usersUpdated = usersUpdated + 1
  85. } catch (error) {
  86. console.error(error)
  87. }
  88. }
  89. if (dryRun) {
  90. console.log(`DRY RUN: ${usersToUpdate} users will be updated`)
  91. } else {
  92. console.log(`UPDATED: ${usersUpdated}/${usersToUpdate} users successfully`)
  93. }
  94. }
  95. try {
  96. await scriptRunner(main)
  97. process.exit(0)
  98. } catch (error) {
  99. console.error(error)
  100. process.exit(1)
  101. }