Эх сурвалжийг харах

[web] Add `update_group_policy` script (#31715)

* [web]  Add `update_group_policy` script

The script allows to update a policy for a subscription, or update
multiple policies via a file containing a list of subscription ids

GitOrigin-RevId: f3b3a6666eb62bb93d13c4c75d60b99f21f23db4
Miguel Serrano 3 сар өмнө
parent
commit
08701ca5aa

+ 145 - 0
services/web/scripts/update_group_policy.mjs

@@ -0,0 +1,145 @@
+import fs from 'node:fs'
+import minimist from 'minimist'
+import { ObjectId } from '../app/src/infrastructure/mongodb.mjs'
+import GroupPoliciesHandler from '../modules/group-settings/app/src/GroupPoliciesHandler.mjs'
+import { scriptRunner } from './lib/ScriptRunner.mjs'
+
+// Imported to ensure policies are registered before we attempt to update them
+import '../modules/group-settings/app/src/managed-users/ManagedUsersPolicy.mjs'
+import '../modules/institutions/app/src/InstitutionsPolicy.mjs'
+
+const USAGE = `Usage:
+  node scripts/update_group_policy.mjs --subscription-id=<id> --policy-name=<name> --policy-value=<true|false>
+  node scripts/update_group_policy.mjs --file=<path> --policy-name=<name> --policy-value=<true|false>
+
+Options:
+  --subscription-id  The id of a single subscription to update
+  --file             Path to a file with one subscription _id per line (ignored when --subscription-id is present)
+  --policy-name      The policy name to update (e.g. userCannotUseAIFeatures)
+  --policy-value     The policy value (true or false)
+  --dry-run          Perform the search but only log the count of subscriptions to update. Defaults to true
+  --initiator-id     The user id of the person running the script (for audit logs)
+  --verbose          Log each subscription id being updated
+  --help             Show this help message`
+
+function printUsageAndExit(code) {
+  console.log(USAGE)
+  process.exit(code)
+}
+
+const argv = minimist(process.argv.slice(2), {
+  string: [
+    'subscription-id',
+    'policy-name',
+    'policy-value',
+    'initiator-id',
+    'file',
+  ],
+  boolean: ['dry-run', 'help', 'verbose'],
+  default: { 'dry-run': true, verbose: false },
+})
+
+if (argv.help) {
+  printUsageAndExit(0)
+}
+
+async function main() {
+  const subscriptionId = argv['subscription-id']
+  const policyName = argv['policy-name']
+  const policyValue = argv['policy-value']
+  const filePath = argv.file
+  const dryRun = argv['dry-run']
+  const initiatorId = argv['initiator-id']
+  const verbose = argv.verbose
+
+  if (!policyName) {
+    console.error('Missing --policy-name argument')
+    printUsageAndExit(1)
+  }
+  if (!subscriptionId && !filePath) {
+    console.error(
+      'Missing --subscription-id or --file argument, one must be provided'
+    )
+    printUsageAndExit(1)
+  }
+  if (!policyValue) {
+    console.error('Missing --policy-value argument')
+    printUsageAndExit(1)
+  }
+  if (policyValue !== 'true' && policyValue !== 'false') {
+    console.error('--policy-value must be "true" or "false"')
+    printUsageAndExit(1)
+  }
+  if (initiatorId && !ObjectId.isValid(initiatorId)) {
+    console.error(`Invalid ObjectId for --initiator-id: ${initiatorId}`)
+    printUsageAndExit(1)
+  }
+
+  const policies = { [policyName]: policyValue === 'true' }
+  const auditLogInfo = {
+    initiatorId: initiatorId ? new ObjectId(initiatorId) : undefined,
+    ipAddress: '0.0.0.0',
+  }
+
+  let subscriptionIds
+  if (subscriptionId) {
+    subscriptionIds = [subscriptionId]
+  } else {
+    const fileContent = fs.readFileSync(filePath, 'utf8')
+    subscriptionIds = fileContent
+      .split('\n')
+      .map(line => line.trim())
+      .filter(line => line.length > 0)
+  }
+
+  const invalidIds = subscriptionIds.filter(id => !ObjectId.isValid(id))
+  if (invalidIds.length > 0) {
+    console.error(`Invalid ObjectId: ${invalidIds.join(', ')}`)
+    printUsageAndExit(1)
+  }
+
+  console.log(
+    `${dryRun ? 'Dry run: would update' : 'Updating'} policy ${policyName}=${policyValue}. Total subscriptions to update: ${subscriptionIds.length}`
+  )
+
+  const failedSubscriptions = []
+  for (const id of subscriptionIds) {
+    if (dryRun) {
+      if (verbose) {
+        console.log(`  Dry run: would update subscription ${id}`)
+      }
+    } else {
+      if (verbose) {
+        console.log(`  Updating subscription ${id}`)
+      }
+      try {
+        await GroupPoliciesHandler.promises.updateGroupPolicies(
+          new ObjectId(id),
+          policies,
+          auditLogInfo
+        )
+      } catch (error) {
+        console.error(`  Subscription ${id} update failed`)
+        console.error(error)
+        failedSubscriptions.push(id)
+      }
+    }
+  }
+
+  console.log(
+    `Total subscriptions ${dryRun ? 'found' : 'updated'}: ${subscriptionIds.length - failedSubscriptions.length}`
+  )
+  if (failedSubscriptions.length) {
+    console.log(`Total subscriptions failed: ${failedSubscriptions.length}:`)
+    failedSubscriptions.forEach(id => console.log(`  ${id}`))
+  }
+}
+
+try {
+  await scriptRunner(main)
+  console.log('Done.')
+  process.exit(0)
+} catch (error) {
+  console.error(error)
+  process.exit(1)
+}