diff --git a/services/web/scripts/update_institution_user_saml_ids.mjs b/services/web/scripts/update_institution_user_saml_ids.mjs new file mode 100644 index 0000000000..a7284a2f2b --- /dev/null +++ b/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 -s [-r ]' + ) + 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) +}