From 6fef715316f0fdccde7c565f7da9134ddc284404 Mon Sep 17 00:00:00 2001 From: David <33458145+davidmcpowell@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:05:07 +0000 Subject: [PATCH] Merge pull request #17611 from overleaf/dp-unlink-sso-script Add script to unlink a third party identifier GitOrigin-RevId: ded0672121fdf8c6cf30f94580f4491af9321dd7 --- .../User/ThirdPartyIdentityManager.js | 1 + .../src/Features/User/UserAuditLogHandler.js | 1 + services/web/scripts/unlink_third_party_id.js | 91 +++++++++++++++++++ 3 files changed, 93 insertions(+) create mode 100644 services/web/scripts/unlink_third_party_id.js diff --git a/services/web/app/src/Features/User/ThirdPartyIdentityManager.js b/services/web/app/src/Features/User/ThirdPartyIdentityManager.js index d9aebb172b..b94be54c6a 100644 --- a/services/web/app/src/Features/User/ThirdPartyIdentityManager.js +++ b/services/web/app/src/Features/User/ThirdPartyIdentityManager.js @@ -147,6 +147,7 @@ function unlink(userId, providerId, auditLog, callback) { auditLog.initiatorId, auditLog.ipAddress, { + ...(auditLog.extraInfo || {}), providerId, }, error => { diff --git a/services/web/app/src/Features/User/UserAuditLogHandler.js b/services/web/app/src/Features/User/UserAuditLogHandler.js index a02ebe70cf..6f418f0e84 100644 --- a/services/web/app/src/Features/User/UserAuditLogHandler.js +++ b/services/web/app/src/Features/User/UserAuditLogHandler.js @@ -12,6 +12,7 @@ function _canHaveNoInitiatorId(operation, info) { if (operation === 'reset-password') return true if (operation === 'unlink-sso' && info.providerId === 'collabratec') return true + if (operation === 'unlink-sso' && info.script === true) return true if (operation === 'unlink-institution-sso-not-migrated') return true if (operation === 'remove-email' && info.script) return true if (operation === 'join-group-subscription') return true diff --git a/services/web/scripts/unlink_third_party_id.js b/services/web/scripts/unlink_third_party_id.js new file mode 100644 index 0000000000..77490a4a56 --- /dev/null +++ b/services/web/scripts/unlink_third_party_id.js @@ -0,0 +1,91 @@ +const { waitForDb } = require('../app/src/infrastructure/mongodb') +const minimist = require('minimist') +const ThirdPartyIdentityManager = require('../app/src/Features/User/ThirdPartyIdentityManager') +const UserGetter = require('../app/src/Features/User/UserGetter') + +/** + * This script is used to remove a linked third party identity from a user account. + * + * Parameters: + * --providerId: the third party identity provider (e.g. google, collabratec) + * --userId: the id of the user + * --commit: if present, the script will commit the changes to the database. + * + * Usage: + * + * - dry run: + * node scripts/unlink_third_party_id.js --providerId=google --userId=${SOME_USER_ID} + * - commit: + * node scripts/unlink_third_party_id.js --providerId=google --userId=${SOME_USER_ID} --commit + */ + +let COMMIT = false +let PROVIDER_ID +let USER_ID + +const setup = () => { + const argv = minimist(process.argv.slice(2)) + COMMIT = argv.commit !== undefined + PROVIDER_ID = argv.providerId + USER_ID = argv.userId + if (!COMMIT) { + console.warn('Doing dry run. Add --commit to commit changes') + } +} + +async function main() { + if (!PROVIDER_ID) { + throw new Error('No --providerId argument provided') + } + + if (!USER_ID) { + throw new Error('No --userId argument provided') + } + + await waitForDb() + + const auditLog = { + initiatorId: undefined, + ipAddress: '0.0.0.0', + extraInfo: { + script: true, + }, + } + + const user = await UserGetter.promises.getUser(USER_ID, { + thirdPartyIdentifiers: 1, + }) + + console.log( + `Existing thirdPartyIdentifiers: ${JSON.stringify( + user.thirdPartyIdentifiers + )}` + ) + + console.log(`Removing third party identifier for provider: ${PROVIDER_ID}`) + + if (COMMIT) { + const updatedUser = await ThirdPartyIdentityManager.promises.unlink( + USER_ID, + PROVIDER_ID, + auditLog + ) + + console.log( + `Remaining thirdPartyIdentifiers: ${JSON.stringify( + updatedUser.thirdPartyIdentifiers + )}` + ) + } +} + +setup() + +main() + .then(() => { + process.exit(0) + }) + .catch(err => { + console.error(err) + process.exit(1) + })