From bb84d01e1404eaaf758ab4da0cd9f050318931fc Mon Sep 17 00:00:00 2001 From: Adrian Astles <49412215+adrianeastles@users.noreply.github.com> Date: Sun, 3 Aug 2025 20:47:27 +0800 Subject: [PATCH] Reset a user's security keys (passkeys) by deleting all their webauthn credentials. pangctl reset-user-security-keys --email user@example.com This command will: 1. Find the user by email address 2. Check if they have any registered security keys 3. Delete all their security keys from the database 4. Provide feedback on the operation --- cli/commands/resetUserSecurityKeys.ts | 67 +++++++++++++++++++++++++++ cli/index.ts | 2 + 2 files changed, 69 insertions(+) create mode 100644 cli/commands/resetUserSecurityKeys.ts diff --git a/cli/commands/resetUserSecurityKeys.ts b/cli/commands/resetUserSecurityKeys.ts new file mode 100644 index 00000000..84af7cec --- /dev/null +++ b/cli/commands/resetUserSecurityKeys.ts @@ -0,0 +1,67 @@ +import { CommandModule } from "yargs"; +import { db, users, securityKeys } from "@server/db"; +import { eq } from "drizzle-orm"; + +type ResetUserSecurityKeysArgs = { + email: string; +}; + +export const resetUserSecurityKeys: CommandModule<{}, ResetUserSecurityKeysArgs> = { + command: "reset-user-security-keys", + describe: "Reset a user's security keys (passkeys) by deleting all their webauthn credentials", + builder: (yargs) => { + return yargs + .option("email", { + type: "string", + demandOption: true, + describe: "User email address" + }); + }, + handler: async (argv: { email: string }) => { + try { + const { email } = argv; + + console.log(`Looking for user with email: ${email}`); + + // Find the user by email + const [user] = await db + .select() + .from(users) + .where(eq(users.email, email)) + .limit(1); + + if (!user) { + console.error(`User with email '${email}' not found`); + process.exit(1); + } + + console.log(`Found user: ${user.email} (ID: ${user.userId})`); + + // Check if user has any security keys + const userSecurityKeys = await db + .select() + .from(securityKeys) + .where(eq(securityKeys.userId, user.userId)); + + if (userSecurityKeys.length === 0) { + console.log(`User '${email}' has no security keys to reset`); + process.exit(0); + } + + console.log(`Found ${userSecurityKeys.length} security key(s) for user '${email}'`); + + // Delete all security keys for the user + await db + .delete(securityKeys) + .where(eq(securityKeys.userId, user.userId)); + + console.log(`Successfully reset security keys for user '${email}'`); + console.log(`Deleted ${userSecurityKeys.length} security key(s)`); + + process.exit(0); + } catch (error) { + console.error("Error:", error); + process.exit(1); + } + } +}; \ No newline at end of file diff --git a/cli/index.ts b/cli/index.ts index db76dbf9..f9e884cc 100644 --- a/cli/index.ts +++ b/cli/index.ts @@ -3,9 +3,11 @@ import yargs from "yargs"; import { hideBin } from "yargs/helpers"; import { setAdminCredentials } from "@cli/commands/setAdminCredentials"; +import { resetUserSecurityKeys } from "@cli/commands/resetUserSecurityKeys"; yargs(hideBin(process.argv)) .scriptName("pangctl") .command(setAdminCredentials) + .command(resetUserSecurityKeys) .demandCommand() .help().argv;