Просмотр исходного кода

[web] `update_institution_user_saml_ids.mjs` script (#30691)

The update_institution_user_saml_ids.mjs script updates `samlIdentifiers.externalUserId`
for users with a specific `samlIdentifiers.providerId`, performing a string replacement.

GitOrigin-RevId: 9d9897b17a528ea2ef3abf60d3b5e6679bf11943
Miguel Serrano 7 месяцев назад
Родитель
Сommit
422b474a17
1 измененных файлов с 114 добавлено и 0 удалено
  1. 114 0
      services/web/scripts/update_institution_user_saml_ids.mjs

+ 114 - 0
services/web/scripts/update_institution_user_saml_ids.mjs

@@ -0,0 +1,114 @@
+import { db } from '../app/src/infrastructure/mongodb.mjs'
+import minimist from 'minimist'
+import UserGetter from '../app/src/Features/User/UserGetter.mjs'
+import { scriptRunner } from './lib/ScriptRunner.mjs'
+
+function usage() {
+  console.log(
+    'Usage: node update_institution_user_saml_ids.mjs -i <institution-id> -s <search> [-r <replace>]'
+  )
+  console.log(
+    'Performs string replacement on external user IDs for all users in an institution'
+  )
+  console.log('Options:')
+  console.log(
+    '  --institution-id, -i                     Institution ID to update'
+  )
+  console.log('  --search, -s                             String to search for')
+  console.log(
+    '  --replace, -r                            String to replace with (optional, defaults to empty string)'
+  )
+  console.log(
+    '  --dry-run, -d                            Shows changes but does not perform updates'
+  )
+  console.log(
+    '  --help, -h                               Show this help message'
+  )
+  process.exit(0)
+}
+
+const {
+  'dry-run': dryRun,
+  'institution-id': providerId,
+  search,
+  replace,
+  help,
+} = minimist(process.argv.slice(2), {
+  string: ['institution-id', 'search', 'replace'],
+  boolean: ['dry-run', 'help'],
+  alias: {
+    'institution-id': 'i',
+    search: 's',
+    replace: 'r',
+    'dry-run': 'd',
+    help: 'h',
+  },
+  default: {
+    'dry-run': true,
+    replace: '',
+  },
+})
+
+async function main() {
+  if (help || !providerId || !search) {
+    usage()
+  }
+
+  const users = await UserGetter.promises.getSsoUsersAtInstitution(providerId, {
+    _id: 1,
+    samlIdentifiers: 1,
+  })
+  console.log('SSO Users found for institution: ' + users.length)
+
+  let usersToUpdate = 0
+  let usersUpdated = 0
+
+  for (const user of users) {
+    const matchingIdentifier = user.samlIdentifiers.find(
+      u => u.providerId === providerId
+    )
+
+    if (
+      !matchingIdentifier ||
+      !matchingIdentifier.externalUserId.includes(search)
+    ) {
+      continue
+    }
+
+    const updatedId = matchingIdentifier.externalUserId.replaceAll(
+      search,
+      replace
+    )
+
+    usersToUpdate = usersToUpdate + 1
+    console.log(`${user._id},${matchingIdentifier.externalUserId},${updatedId}`)
+
+    if (dryRun) {
+      continue
+    }
+
+    try {
+      await db.users.updateOne(
+        { _id: user._id, 'samlIdentifiers.providerId': providerId },
+        { $set: { 'samlIdentifiers.$.externalUserId': updatedId } }
+      )
+      usersUpdated = usersUpdated + 1
+    } catch (error) {
+      console.error(error)
+    }
+  }
+
+  if (dryRun) {
+    console.log(`DRY RUN: ${usersToUpdate} users will be updated`)
+  } else {
+    console.log(`UPDATED: ${usersUpdated}/${usersToUpdate} users successfully`)
+  }
+}
+
+try {
+  await scriptRunner(main)
+  process.exit(0)
+} catch (error) {
+  console.error(error)
+  process.exit(1)
+}