Checkpoint: Le champ de connexion accepte maintenant un identifiant (ex: adminItinova) ou une adresse e-mail. Le backend recherche dans les deux cas. Le label et le placeholder ont été mis à jour.

This commit is contained in:
Manus
2026-03-20 08:44:29 -04:00
parent e9a8ae9016
commit cab8629125
5 changed files with 39 additions and 5 deletions

View File

@@ -0,0 +1,9 @@
{
"query": "INSERT INTO local_users (email, passwordHash, name, role, isActive, createdAt, updatedAt)\nVALUES (\n 'adminItinova',\n '$2b$12$BFswq4nzwOXHx1CHW2QIq.qSlfYgJD1iPC07Wx6Bi8V8pKJyK6BBq',\n 'Admin Itinova',\n 'admin',\n 1,\n NOW(),\n NOW()\n);",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.63b125a8f9ca --database VepzDyqR8YkJNcqpZ729Bw --execute INSERT INTO local_users (email, passwordHash, name, role, isActive, createdAt, updatedAt)\nVALUES (\n 'adminItinova',\n '$2b$12$BFswq4nzwOXHx1CHW2QIq.qSlfYgJD1iPC07Wx6Bi8V8pKJyK6BBq',\n 'Admin Itinova',\n 'admin',\n 1,\n NOW(),\n NOW()\n);",
"rows": [],
"messages": [],
"stdout": "",
"stderr": "",
"execution_time_ms": 529
}

View File

@@ -0,0 +1,17 @@
{
"query": "SELECT id, email, name, role, isActive FROM local_users WHERE email = 'adminItinova';",
"command": "mysql --batch --raw --column-names --default-character-set=utf8mb4 --host gateway02.us-east-1.prod.aws.tidbcloud.com --port 4000 --user 4CrrYuB5tme73Qo.63b125a8f9ca --database VepzDyqR8YkJNcqpZ729Bw --execute SELECT id, email, name, role, isActive FROM local_users WHERE email = 'adminItinova';",
"rows": [
{
"id": "60001",
"email": "adminItinova",
"name": "Admin Itinova",
"role": "admin",
"isActive": "1"
}
],
"messages": [],
"stdout": "id\temail\tname\trole\tisActive\n60001\tadminItinova\tAdmin Itinova\tadmin\t1\n",
"stderr": "",
"execution_time_ms": 53
}

View File

@@ -62,11 +62,11 @@ export default function Login() {
<CardContent>
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Adresse e-mail</Label>
<Label htmlFor="email">Identifiant ou e-mail</Label>
<Input
id="email"
type="email"
placeholder="votre@email.fr"
type="text"
placeholder="Identifiant ou e-mail"
value={email}
onChange={(e) => setEmail(e.target.value)}
autoComplete="email"

View File

@@ -1,7 +1,7 @@
import bcrypt from "bcryptjs";
import { getDb } from "./db";
import { localUsers } from "../drizzle/schema";
import { eq } from "drizzle-orm";
import { eq, or } from "drizzle-orm";
import { SignJWT, jwtVerify } from "jose";
import { ENV } from "./_core/env";
@@ -41,10 +41,17 @@ export async function loginLocalUser(email: string, password: string) {
const db = await getDb();
if (!db) throw new Error("Base de données indisponible");
// Recherche par e-mail (insensible à la casse) OU par identifiant exact
const identifier = email.trim();
const users = await db
.select()
.from(localUsers)
.where(eq(localUsers.email, email.toLowerCase().trim()))
.where(
or(
eq(localUsers.email, identifier.toLowerCase()),
eq(localUsers.email, identifier)
)
)
.limit(1);
const user = users[0];

View File

@@ -44,3 +44,4 @@
- [x] Vignettes AAP : coloriser les étiquettes Région (violet) et Date (orange)
- [x] Vignettes Veille : coloriser les étiquettes Niveau (violet), Territoire (teal) et Date (orange)
- [x] Page Login : supprimer l'encart affichant les identifiants du compte par défaut
- [x] Login : accepter un identifiant (e-mail ou nom d'utilisateur) au lieu d'un e-mail obligatoire