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

Merge pull request #21547 from overleaf/ls-script-to-lowercase-external-user-id

script to lowercase external user ids

GitOrigin-RevId: 8651f638feab4a92c15fe3748377492d5107b539
Liangjun Song 1 год назад
Родитель
Сommit
7af96a49f6
1 измененных файлов с 120 добавлено и 0 удалено
  1. 120 0
      services/web/scripts/lowercase_institution_user_ids.mjs

+ 120 - 0
services/web/scripts/lowercase_institution_user_ids.mjs

@@ -0,0 +1,120 @@
+import { db } from '../app/src/infrastructure/mongodb.js'
+import minimist from 'minimist'
+import UserGetter from '../app/src/Features/User/UserGetter.js'
+import fs from 'fs'
+
+function usage() {
+  console.log(
+    'Usage: node lowercase_institution_user_ids.mjs -i <institution-id>'
+  )
+  console.log(
+    'Converts external user IDs to lowercase for all users in an institute'
+  )
+  console.log('Options:')
+  console.log(
+    '  --institution-id, -i                     Institution ID to update'
+  )
+  console.log(
+    '  --dry-run, -d                            Finds users with non-lowercase id but does not do any updates'
+  )
+  console.log(
+    '  --file, -f                               A file that contains external user ids to be updated'
+  )
+
+  console.log(
+    '                                           If not provided, the script will update all the users within the institution that have upper case external user id'
+  )
+  console.log(
+    '  -h, --help                               Show this help message'
+  )
+  process.exit(0)
+}
+
+const {
+  'dry-run': dryRun,
+  'institution-id': providerId,
+  help,
+  file,
+} = minimist(process.argv.slice(2), {
+  string: ['institution-id', 'file'],
+  boolean: ['dry-run', 'help'],
+  alias: {
+    'institution-id': 'i',
+    'dry-run': 'd',
+    help: 'h',
+    file: 'f',
+  },
+  default: {
+    'dry-run': true,
+  },
+})
+
+async function main() {
+  if (help || !providerId) {
+    usage()
+  }
+
+  let externalUserIdsToUpdate = null
+  if (file) {
+    const lines = fs.readFileSync(file, 'utf8').split('\n')
+    externalUserIdsToUpdate = new Set(lines)
+  }
+
+  const users = await UserGetter.promises.getSsoUsersAtInstitution(providerId, {
+    _id: 1,
+    samlIdentifiers: 1,
+  })
+
+  let userToUpdate = 0
+  let userUpdated = 0
+
+  for (const user of users) {
+    const matchingIdentifier = user.samlIdentifiers.find(
+      u => u.providerId === providerId
+    )
+    const lowercaseId = matchingIdentifier.externalUserId.toLowerCase()
+
+    // skip if external user id is already in lower case
+    if (lowercaseId === matchingIdentifier.externalUserId) {
+      continue
+    }
+
+    // skip if an id file is provided but current external user id is not in the file
+    if (externalUserIdsToUpdate && !externalUserIdsToUpdate.has(lowercaseId)) {
+      continue
+    }
+
+    userToUpdate = userToUpdate + 1
+    console.log(
+      `${user._id},${matchingIdentifier.externalUserId},${lowercaseId}`
+    )
+
+    if (dryRun) {
+      continue
+    }
+
+    try {
+      await db.users.updateOne(
+        { _id: user._id, 'samlIdentifiers.providerId': providerId },
+        { $set: { 'samlIdentifiers.$.externalUserId': lowercaseId } }
+      )
+      userUpdated = userUpdated + 1
+    } catch (error) {
+      console.error(error)
+    }
+  }
+
+  if (dryRun) {
+    console.log(`DRY RUN: ${userToUpdate} users will be updated`)
+  } else {
+    console.log(`UPDATED: ${userUpdated}/${userToUpdate} users successfully`)
+  }
+}
+
+try {
+  await main()
+  process.exit(0)
+} catch (error) {
+  console.error(error)
+  process.exit(1)
+}