mirror of
https://github.com/fosrl/pangolin.git
synced 2026-01-28 22:00:51 +00:00
124 lines
5.0 KiB
TypeScript
124 lines
5.0 KiB
TypeScript
import { CommandModule } from "yargs";
|
|
import { db, clients, olms, currentFingerprint, userClients, approvals } from "@server/db";
|
|
import { eq, and, inArray } from "drizzle-orm";
|
|
|
|
type DeleteClientArgs = {
|
|
orgId: string;
|
|
niceId: string;
|
|
};
|
|
|
|
export const deleteClient: CommandModule<{}, DeleteClientArgs> = {
|
|
command: "delete-client",
|
|
describe:
|
|
"Delete a client and all associated data (OLMs, current fingerprint, userClients, approvals). Snapshots are preserved.",
|
|
builder: (yargs) => {
|
|
return yargs
|
|
.option("orgId", {
|
|
type: "string",
|
|
demandOption: true,
|
|
describe: "The organization ID"
|
|
})
|
|
.option("niceId", {
|
|
type: "string",
|
|
demandOption: true,
|
|
describe: "The client niceId (identifier)"
|
|
});
|
|
},
|
|
handler: async (argv: { orgId: string; niceId: string }) => {
|
|
try {
|
|
const { orgId, niceId } = argv;
|
|
|
|
console.log(
|
|
`Deleting client with orgId: ${orgId}, niceId: ${niceId}...`
|
|
);
|
|
|
|
// Find the client
|
|
const [client] = await db
|
|
.select()
|
|
.from(clients)
|
|
.where(and(eq(clients.orgId, orgId), eq(clients.niceId, niceId)))
|
|
.limit(1);
|
|
|
|
if (!client) {
|
|
console.error(
|
|
`Error: Client with orgId "${orgId}" and niceId "${niceId}" not found.`
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const clientId = client.clientId;
|
|
console.log(`Found client with clientId: ${clientId}`);
|
|
|
|
// Find all OLMs associated with this client
|
|
const associatedOlms = await db
|
|
.select()
|
|
.from(olms)
|
|
.where(eq(olms.clientId, clientId));
|
|
|
|
console.log(`Found ${associatedOlms.length} OLM(s) associated with this client`);
|
|
|
|
// Delete in a transaction to ensure atomicity
|
|
await db.transaction(async (trx) => {
|
|
// Delete currentFingerprint entries for the associated OLMs
|
|
// Note: We delete these explicitly before deleting OLMs to ensure
|
|
// we have control, even though cascade would handle it
|
|
let fingerprintCount = 0;
|
|
if (associatedOlms.length > 0) {
|
|
const olmIds = associatedOlms.map((olm) => olm.olmId);
|
|
const deletedFingerprints = await trx
|
|
.delete(currentFingerprint)
|
|
.where(inArray(currentFingerprint.olmId, olmIds))
|
|
.returning();
|
|
fingerprintCount = deletedFingerprints.length;
|
|
}
|
|
console.log(`Deleted ${fingerprintCount} current fingerprint(s)`);
|
|
|
|
// Delete OLMs
|
|
// Note: OLMs have onDelete: "set null" for clientId, so we need to delete them explicitly
|
|
const deletedOlms = await trx
|
|
.delete(olms)
|
|
.where(eq(olms.clientId, clientId))
|
|
.returning();
|
|
console.log(`Deleted ${deletedOlms.length} OLM(s)`);
|
|
|
|
// Delete approvals
|
|
// Note: Approvals have onDelete: "cascade" but we delete explicitly for clarity
|
|
const deletedApprovals = await trx
|
|
.delete(approvals)
|
|
.where(eq(approvals.clientId, clientId))
|
|
.returning();
|
|
console.log(`Deleted ${deletedApprovals.length} approval(s)`);
|
|
|
|
// Delete userClients
|
|
// Note: userClients have onDelete: "cascade" but we delete explicitly for clarity
|
|
const deletedUserClients = await trx
|
|
.delete(userClients)
|
|
.where(eq(userClients.clientId, clientId))
|
|
.returning();
|
|
console.log(`Deleted ${deletedUserClients.length} userClient association(s)`);
|
|
|
|
// Finally, delete the client itself
|
|
const deletedClients = await trx
|
|
.delete(clients)
|
|
.where(eq(clients.clientId, clientId))
|
|
.returning();
|
|
console.log(`Deleted client: ${deletedClients[0]?.name || niceId}`);
|
|
});
|
|
|
|
console.log("\nClient deletion completed successfully!");
|
|
console.log("\nSummary:");
|
|
console.log(` - Client: ${niceId} (clientId: ${clientId})`);
|
|
console.log(` - Olm(s): ${associatedOlms.length}`);
|
|
console.log(` - Current fingerprints: deleted`);
|
|
console.log(` - Approvals: deleted`);
|
|
console.log(` - UserClients: deleted`);
|
|
console.log(` - Snapshots: preserved (not deleted)`);
|
|
|
|
process.exit(0);
|
|
} catch (error) {
|
|
console.error("Error deleting client:", error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
};
|