Files
Termix/src/backend/database/routes/delete-user-data.ts
T

100 lines
3.6 KiB
TypeScript
Raw Normal View History

2026-06-04 15:16:53 -04:00
import { authLogger } from "../../utils/logger.js";
import {
+8
2026-07-19 12:29:52 -05:00
createCurrentApiKeyRepository,
createCurrentAuditLogRepository,
createCurrentCredentialRepository,
createCurrentHostFolderRepository,
createCurrentHostRepository,
+5
2026-08-19 14:12:06 -05:00
createCurrentHostSidebarPreferenceRepository,
createCurrentCredentialSidebarPreferenceRepository,
createCurrentUiPreferenceRepository,
+8
2026-07-19 12:29:52 -05:00
createCurrentOpenTabRepository,
createCurrentRecentActivityRepository,
createCurrentRbacAccessRepository,
createCurrentRoleRepository,
createCurrentSessionRepository,
createCurrentSettingsRepository,
createCurrentSharedHostSecretsRepository,
createCurrentSshCredentialUsageRepository,
createCurrentTrustedDeviceRepository,
createCurrentUserPreferenceRepository,
createCurrentUserRepository,
+17
2026-09-20 14:56:39 -05:00
createCurrentSharedCredentialSecretsRepository,
createCurrentCredentialAccessRepository,
+8
2026-07-19 12:29:52 -05:00
} from "../repositories/factory.js";
2026-06-04 15:16:53 -04:00
+17
2026-09-20 14:56:39 -05:00
export async function deleteUserAndRelatedData(
userId: string,
options: { successorUserId?: string } = {},
): Promise<void> {
2026-06-04 15:16:53 -04:00
try {
+17
2026-09-20 14:56:39 -05:00
// With a successor, hosts and credentials (and the shares on them)
// change owner instead of disappearing with the account.
if (options.successorUserId) {
const { transferOwnership } =
await import("../../utils/transfer-ownership.js");
await transferOwnership(userId, options.successorUserId);
}
+8
2026-07-19 12:29:52 -05:00
await createCurrentSharedHostSecretsRepository().deleteByTargetUserId(
userId,
);
+17
2026-09-20 14:56:39 -05:00
await createCurrentSharedCredentialSecretsRepository().deleteByTargetUserId(
userId,
);
await createCurrentCredentialAccessRepository().deleteForUserReferences(
userId,
);
2026-06-04 15:16:53 -04:00
2026-10-01 16:20:16 -05:00
// Plugins drop or anonymize their own rows on user.deleted, or rely on
// their refUser() foreign keys cascading.
const { pluginEvents, TOPICS } = await import("../../plugins/events.js");
pluginEvents.emit(TOPICS.userDeleted, { userId });
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentRbacAccessRepository().deleteHostAccessForUserReferences(
userId,
);
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentSessionRepository().revokeAllForUser(userId);
await createCurrentApiKeyRepository().deleteByUserId(userId);
await createCurrentTrustedDeviceRepository().deleteByUserId(userId);
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentRoleRepository().removeAllRolesFromUser(userId);
+3
2026-08-06 14:41:39 -05:00
await createCurrentAuditLogRepository().anonymizeByUserId(userId);
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentSshCredentialUsageRepository().deleteByUserId(userId);
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentRecentActivityRepository().deleteByUserId(userId);
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentHostFolderRepository().deleteByUserId(userId);
2026-06-04 15:16:53 -04:00
+5
2026-08-19 14:12:06 -05:00
await createCurrentHostSidebarPreferenceRepository().deleteByUserId(userId);
await createCurrentCredentialSidebarPreferenceRepository().deleteByUserId(
userId,
);
await createCurrentUiPreferenceRepository().deleteByUserId(userId);
+8
2026-07-19 12:29:52 -05:00
await createCurrentHostRepository().deleteByUserId(userId);
await createCurrentCredentialRepository().deleteByUserId(userId);
2026-06-04 15:16:53 -04:00
2026-10-01 16:20:16 -05:00
// Plugin tables with a refUser() column cascade on the user row.
+8
2026-07-19 12:29:52 -05:00
await createCurrentOpenTabRepository().deleteByUserId(userId);
await createCurrentUserPreferenceRepository().deleteByUserId(userId);
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentSettingsRepository().deleteLike(`user_%_${userId}`);
2026-06-04 15:16:53 -04:00
+8
2026-07-19 12:29:52 -05:00
await createCurrentUserRepository().delete(userId);
2026-06-04 15:16:53 -04:00
authLogger.success("User and all related data deleted successfully", {
operation: "delete_user_and_related_data_complete",
userId,
});
} catch (error) {
authLogger.error("Failed to delete user and related data", error, {
operation: "delete_user_and_related_data_failed",
userId,
});
throw error;
}
}