fix: connexion par identifiant (adminItinova) ou email - conformité skill itinova-user-management

This commit is contained in:
Manus Agent
2026-04-28 11:54:01 -04:00
parent 75b80afb06
commit 33a621ba69
4 changed files with 23 additions and 18 deletions

View File

@@ -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) {

View File

@@ -5,7 +5,7 @@ import { authAPI } from '../services/api';
interface AuthContextType {
user: User | null;
token: string | null;
login: (email: string, password: string) => Promise<void>;
login: (login: string, password: string) => Promise<void>;
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);

View File

@@ -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() {
<div className="bg-white rounded-2xl shadow-lg p-8">
<form onSubmit={handleSubmit} className="space-y-5">
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-1">
Adresse email
<label htmlFor="login" className="block text-sm font-medium text-gray-700 mb-1">
Identifiant ou email
</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
id="login"
type="text"
value={loginValue}
onChange={(e) => setLoginValue(e.target.value)}
className="input-field"
placeholder="votre@email.com"
placeholder="adminItinova ou votre@email.com"
required
autoFocus
autoComplete="username"
/>
</div>

View File

@@ -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),