From 33a621ba69b5ee89d36843cf424969723d86d549 Mon Sep 17 00:00:00 2001 From: Manus Agent Date: Tue, 28 Apr 2026 11:54:01 -0400 Subject: [PATCH] =?UTF-8?q?fix:=20connexion=20par=20identifiant=20(adminIt?= =?UTF-8?q?inova)=20ou=20email=20-=20conformit=C3=A9=20skill=20itinova-use?= =?UTF-8?q?r-management?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/routes/auth.ts | 14 +++++++++----- frontend/src/context/AuthContext.tsx | 6 +++--- frontend/src/pages/Login.tsx | 19 ++++++++++--------- frontend/src/services/api.ts | 2 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/backend/src/routes/auth.ts b/backend/src/routes/auth.ts index f0ca16e..590596a 100644 --- a/backend/src/routes/auth.ts +++ b/backend/src/routes/auth.ts @@ -30,16 +30,20 @@ const router = Router(); // POST /api/auth/login router.post('/login', async (req: Request, res: Response) => { try { - const { email, password } = req.body; + // Accepter 'login' ou 'email' (compatibilité skill itinova-user-management) + const login = (req.body.login || req.body.email || '').trim(); + const { password } = req.body; - if (!email || !password) { - return res.status(400).json({ error: 'Email et mot de passe requis' }); + if (!login || !password) { + return res.status(400).json({ error: 'Identifiant et mot de passe requis' }); } const pool = getPool(); + // Recherche par email exact OU par identifiant (login sans @) + // Ex: 'adminItinova' trouvera 'adminItinova@santinova-soft.org' const [rows]: any = await pool.execute( - 'SELECT * FROM users WHERE email = ? AND is_active = TRUE', - [email] + `SELECT * FROM users WHERE (email = ? OR email = CONCAT(?, '@santinova-soft.org')) AND is_active = TRUE`, + [login, login] ); if (!rows.length) { diff --git a/frontend/src/context/AuthContext.tsx b/frontend/src/context/AuthContext.tsx index b275d0c..1c5b75e 100644 --- a/frontend/src/context/AuthContext.tsx +++ b/frontend/src/context/AuthContext.tsx @@ -5,7 +5,7 @@ import { authAPI } from '../services/api'; interface AuthContextType { user: User | null; token: string | null; - login: (email: string, password: string) => Promise; + login: (login: string, password: string) => Promise; logout: () => void; isLoading: boolean; } @@ -45,8 +45,8 @@ export function AuthProvider({ children }: { children: ReactNode }) { } }, []); - const login = async (email: string, password: string) => { - const res = await authAPI.login(email, password); + const login = async (login: string, password: string) => { + const res = await authAPI.login(login, password); const { token: newToken, user: newUser } = res.data; setToken(newToken); setUser(newUser); diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx index ff16682..2287471 100644 --- a/frontend/src/pages/Login.tsx +++ b/frontend/src/pages/Login.tsx @@ -4,7 +4,7 @@ import { useAuth } from '../context/AuthContext'; import toast from 'react-hot-toast'; export default function Login() { - const [email, setEmail] = useState(''); + const [loginValue, setLoginValue] = useState(''); const [password, setPassword] = useState(''); const [loading, setLoading] = useState(false); const { login } = useAuth(); @@ -14,7 +14,7 @@ export default function Login() { e.preventDefault(); setLoading(true); try { - await login(email, password); + await login(loginValue, password); toast.success('Connexion réussie'); navigate('/'); } catch (error: any) { @@ -79,18 +79,19 @@ export default function Login() {
-
diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts index f76f6e1..7bd4133 100644 --- a/frontend/src/services/api.ts +++ b/frontend/src/services/api.ts @@ -37,7 +37,7 @@ export default api; // Auth export const authAPI = { - login: (email: string, password: string) => api.post('/auth/login', { email, password }), + login: (login: string, password: string) => api.post('/auth/login', { login, password }), me: () => api.get('/auth/me'), getUsers: () => api.get('/auth/users'), createUser: (data: any) => api.post('/auth/users', data),