From 70839e4c221bf194df19186fdb403415690e460b Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Mon, 11 Aug 2025 16:34:08 +0000 Subject: [PATCH] Safely remove users and reassign their data to an administrator Implement a transactional delete for users, ensuring all associated records in customer_orders, orders, deliveries, publicities, dlcProducts, tasks, and nocodbConfig are transferred to an admin user before the user record is removed. Replit-Commit-Author: Agent Replit-Commit-Session-Id: a8a78c07-e900-425c-a577-5b4c5894379d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/a8a78c07-e900-425c-a577-5b4c5894379d/vetH0Gp --- server/storage.ts | 91 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/server/storage.ts b/server/storage.ts index bc7b72e..f08cf65 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -354,7 +354,62 @@ export class DatabaseStorage implements IStorage { } async deleteUser(id: string): Promise { - await db.delete(users).where(eq(users.id, id)); + // Use a transaction to ensure atomicity + await db.transaction(async (tx: typeof db) => { + // Transfer ownership of all records created by this user to admin_dev + const adminUserId = "admin_dev"; + + // Update customer orders + await tx + .update(customerOrders) + .set({ createdBy: adminUserId }) + .where(eq(customerOrders.createdBy, id)); + + // Update orders + await tx + .update(orders) + .set({ createdBy: adminUserId }) + .where(eq(orders.createdBy, id)); + + // Update deliveries + await tx + .update(deliveries) + .set({ createdBy: adminUserId }) + .where(eq(deliveries.createdBy, id)); + + // Update publicities + await tx + .update(publicities) + .set({ createdBy: adminUserId }) + .where(eq(publicities.createdBy, id)); + + // Update DLC products + await tx + .update(dlcProducts) + .set({ createdBy: adminUserId }) + .where(eq(dlcProducts.createdBy, id)); + + // Update tasks + await tx + .update(tasks) + .set({ createdBy: adminUserId }) + .where(eq(tasks.createdBy, id)); + + // Update NocoDB configs + await tx + .update(nocodbConfig) + .set({ createdBy: adminUserId }) + .where(eq(nocodbConfig.createdBy, id)); + + // Delete user-group assignments + await tx.delete(userGroups).where(eq(userGroups.userId, id)); + + // Delete user-role assignments + await tx.delete(userRoles).where(eq(userRoles.userId, id)); + + // Finally delete the user + await tx.delete(users).where(eq(users.id, id)); + }); } // Group operations @@ -2038,7 +2093,39 @@ class MemStorage implements IStorage { async userHasPermission(): Promise { return false; } async userHasRole(): Promise { return false; } async getDlcStats(): Promise { return {}; } - async validateDlcProduct(): Promise {} + async validateDlcProduct(id: number, validatedBy: string): Promise { + // MemStorage stub implementation - return a basic DlcProductFrontend object + return { + id, + productName: "Sample Product", + gencode: "1234567890123", + supplierId: 1, + groupId: 1, + dlcDate: new Date("2025-12-31"), + dateType: "dlc", + quantity: 1, + unit: "unité", + location: "Magasin", + alertThreshold: 15, + status: "valides", + notes: null, + createdBy: validatedBy, + validatedBy, + validatedAt: new Date(), + createdAt: new Date(), + updatedAt: new Date(), + } as DlcProductFrontend; + } + + // Missing interface methods - stub implementations for MemStorage + async addPermissionToRole(roleId: number, permissionId: number): Promise<{ createdAt: Date | null; roleId: number; permissionId: number; }> { + return { roleId, permissionId, createdAt: new Date() }; + } + async removePermissionFromRole(): Promise {} + async addRoleToUser(userId: string, roleId: number, assignedBy: string): Promise<{ userId: string; roleId: number; assignedBy: string; assignedAt: Date | null; }> { + return { userId, roleId, assignedBy, assignedAt: new Date() }; + } + async removeRoleFromUser(): Promise {} } // Use MemStorage in development, DatabaseStorage in production