Checkpoint: Ajout d'une page de connexion locale permettant aux utilisateurs de se connecter avec leur identifiant et mot de passe (username/password) au lieu de l'OAuth Manus. Implémentation complète avec route d'authentification backend, hashage bcrypt, session JWT, et reconnaissance automatique des sessions locales vs OAuth. Tests unitaires et manuels réussis avec l'utilisateur adminServFormation.
This commit is contained in:
106
server/__tests__/localAuth.test.ts
Normal file
106
server/__tests__/localAuth.test.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { describe, it, expect, beforeAll } from "vitest";
|
||||
import { getDb } from "../db";
|
||||
import { users } from "../../drizzle/schema";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
describe("Local Authentication", () => {
|
||||
beforeAll(async () => {
|
||||
// Vérifier que la base de données est accessible
|
||||
const db = await getDb();
|
||||
expect(db).toBeDefined();
|
||||
});
|
||||
|
||||
it("should have an admin user with username adminServFormation", async () => {
|
||||
const db = await getDb();
|
||||
if (!db) {
|
||||
throw new Error("Database not available");
|
||||
}
|
||||
|
||||
const result = await db
|
||||
.select()
|
||||
.from(users)
|
||||
.where(eq(users.username, "adminServFormation"))
|
||||
.limit(1);
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0].username).toBe("adminServFormation");
|
||||
expect(result[0].role).toBe("admin");
|
||||
expect(result[0].password).toBeDefined();
|
||||
expect(result[0].password).not.toBeNull();
|
||||
});
|
||||
|
||||
it("should authenticate with correct credentials", async () => {
|
||||
const response = await fetch("http://localhost:3000/api/auth/local/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: "adminServFormation",
|
||||
password: "Itinova69!",
|
||||
}),
|
||||
});
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
const data = await response.json();
|
||||
expect(data.success).toBe(true);
|
||||
expect(data.user).toBeDefined();
|
||||
expect(data.user.username).toBe("adminServFormation");
|
||||
expect(data.user.role).toBe("admin");
|
||||
expect(data.user.password).toBeUndefined(); // Le mot de passe ne doit pas être retourné
|
||||
});
|
||||
|
||||
it("should reject authentication with incorrect password", async () => {
|
||||
const response = await fetch("http://localhost:3000/api/auth/local/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: "adminServFormation",
|
||||
password: "wrongpassword",
|
||||
}),
|
||||
});
|
||||
|
||||
expect(response.status).toBe(401);
|
||||
const data = await response.json();
|
||||
expect(data.success).toBe(false);
|
||||
expect(data.message).toContain("incorrect");
|
||||
});
|
||||
|
||||
it("should reject authentication with non-existent username", async () => {
|
||||
const response = await fetch("http://localhost:3000/api/auth/local/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: "nonexistentuser",
|
||||
password: "anypassword",
|
||||
}),
|
||||
});
|
||||
|
||||
expect(response.status).toBe(401);
|
||||
const data = await response.json();
|
||||
expect(data.success).toBe(false);
|
||||
expect(data.message).toContain("incorrect");
|
||||
});
|
||||
|
||||
it("should reject authentication with missing credentials", async () => {
|
||||
const response = await fetch("http://localhost:3000/api/auth/local/login", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
username: "adminServFormation",
|
||||
// password manquant
|
||||
}),
|
||||
});
|
||||
|
||||
expect(response.status).toBe(400);
|
||||
const data = await response.json();
|
||||
expect(data.success).toBe(false);
|
||||
expect(data.message).toContain("requis");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user