Merge pull request #71 from R0m1k3/1.1

1.1
This commit is contained in:
LogiFlow authored and GitHub committed 2025-08-13 10:15:09 +02:00
commit 4892859d74
4 files changed
+3 -71

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 KiB

-11
View File
@@ -79,13 +79,6 @@ export default function UsersPage() {
// Protection React Error #310 - Vérification Array pour users et groups
console.log('👥 Users page data:', {
usersLoading,
usersCount: Array.isArray(users) ? users.length : 'NOT_ARRAY',
groupsCount: Array.isArray(groups) ? groups.length : 'NOT_ARRAY',
usersType: typeof users,
groupsType: typeof groups
});
// Protection: s'assurer que users et groups sont des arrays
const safeUsers = Array.isArray(users) ? users : [];
@@ -125,8 +118,6 @@ export default function UsersPage() {
const updateUserMutation = useMutation({
mutationFn: async (data: { id: string; updates: any }) => {
console.log('🔄 Frontend updateUser mutation:', data);
// Nettoyer les données côté frontend avant envoi
const cleanedUpdates: any = {};
for (const [key, value] of Object.entries(data.updates)) {
@@ -138,8 +129,6 @@ export default function UsersPage() {
}
}
console.log('📤 Sending cleaned data:', cleanedUpdates);
const response = await apiRequest(`/api/users/${data.id}`, "PUT", cleanedUpdates);
return response;
},
+3 -35
View File
@@ -974,11 +974,8 @@ export async function registerRoutes(app: Express): Promise<Server> {
return res.status(403).json({ message: "Access denied" });
}
console.log('🔍 GET /api/users - Fetching users with simplified approach');
// Get all basic users first
const baseUsers = await storage.getUsers();
console.log(`📊 Found ${baseUsers.length} base users`);
// Add userGroups and userRoles to each user individually with error handling
const usersWithData = await Promise.all(
@@ -1002,12 +999,6 @@ export async function registerRoutes(app: Express): Promise<Server> {
})
);
console.log('🔐 API /api/users - Returning:', {
isArray: Array.isArray(usersWithData),
length: usersWithData.length,
totalGroups: usersWithData.reduce((sum, u) => sum + (u.userGroups?.length || 0), 0)
});
res.json(usersWithData);
} catch (error) {
console.error("❌ Critical error fetching users:", error);
@@ -1019,13 +1010,9 @@ export async function registerRoutes(app: Express): Promise<Server> {
app.post('/api/users', isAuthenticated, async (req: any, res) => {
try {
console.log('🔍 POST /api/users - Creating new user');
console.log('📥 Request body:', JSON.stringify(req.body, null, 2));
const userId = req.user.claims ? req.user.claims.sub : req.user.id;
const currentUser = await storage.getUserWithGroups(userId);
if (!currentUser || currentUser.role !== 'admin') {
console.log('❌ Access denied - user not admin');
return res.status(403).json({ message: "Access denied" });
}
@@ -1040,17 +1027,13 @@ export async function registerRoutes(app: Express): Promise<Server> {
role: z.enum(['admin', 'directeur', 'manager', 'employee']).optional(),
});
console.log('🔍 Parsing user data...');
const userData = createUserSchema.parse(req.body);
console.log('✅ User data parsed successfully');
// Hash password with improved error handling
let hashedPassword = userData.password;
if (userData.password) {
try {
console.log('🔒 Hashing password...');
hashedPassword = await hashPasswordSimple(userData.password);
console.log('✅ Password hashed successfully');
} catch (hashError) {
console.error('❌ Password hashing failed:', hashError);
return res.status(500).json({ message: "Failed to secure password" });
@@ -1059,21 +1042,18 @@ export async function registerRoutes(app: Express): Promise<Server> {
// Generate unique ID
const newUserId = userData.id || `manual_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
console.log('🔍 Generated user ID:', newUserId);
const userToCreate = {
id: newUserId,
username: userData.username,
email: userData.email && userData.email.trim() !== '' ? userData.email : null, // Use NULL instead of empty string
email: userData.email && userData.email.trim() !== '' ? userData.email : undefined,
firstName: userData.firstName || '',
lastName: userData.lastName || '',
password: hashedPassword,
role: userData.role || 'employee',
};
console.log('🔍 Creating user in database...');
const newUser = await storage.createUser(userToCreate);
console.log('✅ User created successfully:', newUser.username);
res.json(newUser);
} catch (error) {
@@ -1113,12 +1093,8 @@ export async function registerRoutes(app: Express): Promise<Server> {
app.put('/api/users/:id', isAuthenticated, async (req: any, res) => {
try {
console.log('🔍 PUT /api/users/:id - Updating user:', req.params.id);
console.log('📥 Update data:', JSON.stringify(req.body, null, 2));
const user = await storage.getUserWithGroups(req.user.claims ? req.user.claims.sub : req.user.id);
if (!user || user.role !== 'admin') {
console.log('❌ Access denied - user not admin');
return res.status(403).json({ message: "Access denied" });
}
@@ -1132,36 +1108,28 @@ export async function registerRoutes(app: Express): Promise<Server> {
password: z.string().optional(),
});
console.log('🔍 Parsing update data...');
const userData = updateUserSchema.parse(req.body);
console.log('✅ Update data parsed successfully');
// Clean up the data - handle empty emails properly
const cleanUserData: any = { ...userData };
// Handle email field - convert empty string to null
// Handle email field - convert empty string to undefined
if (cleanUserData.email !== undefined) {
cleanUserData.email = cleanUserData.email && cleanUserData.email.trim() !== '' ? cleanUserData.email : null;
console.log('🔍 Email field processed:', cleanUserData.email === null ? 'NULL' : cleanUserData.email);
cleanUserData.email = cleanUserData.email && cleanUserData.email.trim() !== '' ? cleanUserData.email : undefined;
}
// Hash password if provided
if (cleanUserData.password) {
try {
console.log('🔒 Hashing password...');
cleanUserData.password = await hashPasswordSimple(cleanUserData.password);
cleanUserData.passwordChanged = true;
console.log('✅ Password hashed successfully');
} catch (hashError) {
console.error('❌ Password hashing failed:', hashError);
return res.status(500).json({ message: "Failed to secure password" });
}
}
console.log('🔍 Updating user in database...');
const updatedUser = await storage.updateUser(req.params.id, cleanUserData);
console.log('✅ User updated successfully:', updatedUser.username);
res.json(updatedUser);
} catch (error: any) {
console.error("❌ Error updating user:", error);
-25
View File
@@ -187,18 +187,14 @@ export class DatabaseStorage implements IStorage {
}
async getUserWithGroups(id: string): Promise<UserWithGroups | undefined> {
console.log(`🔍 getUserWithGroups called for user: ${id}`);
// Get the user first
const user = await this.getUser(id);
if (!user) {
console.log(`❌ User ${id} not found`);
return undefined;
}
// Fixed: Use manual SQL to avoid userGroups.createdAt column that doesn't exist
try {
console.log(`🔍 Querying user_groups for user: ${id}`);
const result = await db.execute(sql`
SELECT
ug.user_id,
@@ -217,9 +213,6 @@ export class DatabaseStorage implements IStorage {
WHERE ug.user_id = ${id}
`);
console.log(`🔍 Found ${result.rows.length} group assignments for user ${id}`);
console.log(`🔍 Raw query result:`, result.rows);
const userGroupsData = result.rows.map((row: any) => ({
userId: row.user_id,
groupId: row.group_id,
@@ -237,15 +230,12 @@ export class DatabaseStorage implements IStorage {
}
}));
console.log(`✅ Processed ${userGroupsData.length} groups for user ${id}`);
return {
...user,
userGroups: userGroupsData,
};
} catch (error) {
console.error('❌ getUserWithGroups error:', error);
console.error('❌ Error details:', error?.code, error?.message);
// Fallback: return user with empty groups
return {
...user,
@@ -270,18 +260,13 @@ export class DatabaseStorage implements IStorage {
}
async getUsersWithRolesAndGroups(): Promise<(UserWithRoles & { userGroups: any[] })[]> {
console.log('🔍 getUsersWithRolesAndGroups called');
const baseUsers = await this.getUsers();
console.log('📊 Base users found:', baseUsers.length);
const usersWithRolesAndGroups = await Promise.all(
baseUsers.map(async (user) => {
console.log(`🔍 Processing user: ${user.username}`);
const userWithRoles = await this.getUserWithRoles(user.id);
const userWithGroups = await this.getUserWithGroups(user.id);
console.log(`📊 User ${user.username} groups:`, userWithGroups?.userGroups?.length || 0);
return {
...user,
userRoles: userWithRoles?.userRoles || [],
@@ -291,12 +276,10 @@ export class DatabaseStorage implements IStorage {
})
);
console.log('🔍 Final users with roles and groups:', usersWithRolesAndGroups.length);
return usersWithRolesAndGroups;
}
async createUser(userData: UpsertUser): Promise<User> {
console.log('🔍 Storage createUser called with:', userData.username);
try {
const [user] = await db
.insert(users)
@@ -306,19 +289,14 @@ export class DatabaseStorage implements IStorage {
updatedAt: new Date(),
})
.returning();
console.log('✅ Storage createUser successful:', user.username);
return user;
} catch (error) {
console.error('❌ Storage createUser error:', error);
console.error('❌ Storage error code:', error.code);
console.error('❌ Storage error constraint:', error.constraint);
throw error;
}
}
async updateUser(id: string, userData: Partial<UpsertUser>): Promise<User> {
console.log('🔍 Storage updateUser called for:', id);
console.log('🔍 Update data:', userData);
try {
const [user] = await db
.update(users)
@@ -328,12 +306,9 @@ export class DatabaseStorage implements IStorage {
})
.where(eq(users.id, id))
.returning();
console.log('✅ Storage updateUser successful:', user.username);
return user;
} catch (error) {
console.error('❌ Storage updateUser error:', error);
console.error('❌ Storage error code:', error.code);
console.error('❌ Storage error constraint:', error.constraint);
throw error;
}
}