Make user creation and deletion more robust and prevent data loss

Update user schema to make username and password mandatory, adjust email validation, and handle foreign key constraints during user deletion, including updating the database_backups table.

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
This commit is contained in:
michaelschal committed 2025-08-11 18:12:20 +00:00
1 parent 7618fb1643
commit e7fb2c66f1
9 files changed
+152 -4

No files matched your search

@@ -0,0 +1,133 @@
📊 User system groups: 0
📊 User AnneLaure groups: 1
🔍 Final users with roles and groups: 7
🔐 API /api/users - Returning: { isArray: true, length: 7 }
GET /api/users 200 in 80ms
Error deleting user: error: update or delete on table "users" violates foreign key constraint "database_backups_created_by_fkey" on table "database_backups"
at /app/node_modules/pg/lib/client.js:545:17
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async file:///app/dist/index.js:1109:11
at async NodePgSession.transaction (file:///app/node_modules/drizzle-orm/node-postgres/session.js:142:22)
at async DatabaseStorage.deleteUser (file:///app/dist/index.js:1090:9)
at async file:///app/dist/index.js:4095:7 {
length: 327,
severity: 'ERROR',
code: '23503',
detail: 'Key (id)=(system) is still referenced from table "database_backups".',
hint: undefined,
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: 'public',
table: 'database_backups',
column: undefined,
dataType: undefined,
constraint: 'database_backups_created_by_fkey',
file: 'ri_triggers.c',
line: '2609',
routine: 'ri_ReportViolation'
}
DELETE /api/users/system 500 in 28ms
HEAD /api/health 200 in 1ms
Error creating user: ZodError: [
{
"validation": "email",
"code": "invalid_string",
"message": "Invalid email",
"path": [
"email"
]
}
]
at get error [as error] (file:///app/node_modules/zod/v3/types.js:39:31)
at ZodObject.parse (file:///app/node_modules/zod/v3/types.js:114:22)
at file:///app/dist/index.js:3988:41
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
issues: [
{
validation: 'email',
code: 'invalid_string',
message: 'Invalid email',
path: [Array]
}
],
addIssue: [Function (anonymous)],
addIssues: [Function (anonymous)],
errors: [
{
validation: 'email',
code: 'invalid_string',
message: 'Invalid email',
path: [Array]
}
]
}
POST /api/users 400 in 26ms
HEAD /api/health 200 in 1ms
Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

+1 -1
View File
@@ -446,7 +446,7 @@ export default function UsersPage() {
});
setShowCreateModal(false);
setNewUser({ email: "", firstName: "", lastName: "", password: "", role: "employee" });
setNewUser({ email: "", firstName: "", lastName: "", username: "", password: "", role: "employee" });
setUserGroups([]);
queryClient.invalidateQueries({ queryKey: ['/api/users'] });
} catch (error) {
+1 -1
View File
@@ -90,7 +90,7 @@ Preferred communication style: Simple, everyday language.
- Ownership transfer of all user-created records to existing admin before deletion
- Comprehensive handling of all foreign key relationships including role assignments
- Graceful error handling when no admin user exists
- **Tables Handled**: customer_orders, orders, deliveries, publicities, dlcProducts, tasks, nocodbConfig, userGroups, userRoles (both userId and assignedBy)
- **Tables Handled**: customer_orders, orders, deliveries, publicities, dlcProducts, tasks, nocodbConfig, userGroups, userRoles (both userId and assignedBy), database_backups
- **Result**: Safe user deletion while preserving business data integrity
#### User Name Fields Optional in Production
+3 -2
View File
@@ -877,10 +877,11 @@ export async function registerRoutes(app: Express): Promise<Server> {
// Schema création utilisateur SANS champs obligatoires pour résoudre le problème de production
const createUserSchema = z.object({
id: z.string().optional(),
email: z.string().email().optional(),
username: z.string().min(1, "L'identifiant est obligatoire"),
email: z.union([z.string().email(), z.literal("")]).optional(),
firstName: z.string().optional(),
lastName: z.string().optional(),
password: z.string().optional(),
password: z.string().min(1, "Le mot de passe est obligatoire"),
role: z.enum(['admin', 'manager', 'employee']).optional(),
});
+12
View File
@@ -419,6 +419,18 @@ export class DatabaseStorage implements IStorage {
.update(nocodbConfig)
.set({ createdBy: adminUserId })
.where(eq(nocodbConfig.createdBy, id));
// Update database backups if the table exists (production feature)
try {
await tx.execute(sql`
UPDATE database_backups
SET created_by = ${adminUserId}
WHERE created_by = ${id}
`);
} catch (error) {
// Table might not exist in development, ignore the error
console.log('Note: database_backups table not found or accessible');
}
// Update role assignments made BY this user (assignedBy field)
await tx
+2
View File
@@ -460,6 +460,8 @@ export const insertUserSchema = createInsertSchema(users).pick({
password: true,
role: true,
passwordChanged: true,
}).extend({
email: z.union([z.string().email(), z.literal("")]).optional(),
});
export const insertGroupSchema = createInsertSchema(groups).omit({