SPB Git forge

spb/immbot-ai

Public
1commits 1branches 0releases
1.5 MBsize
maindefault branch
19 days agolast push
TypeScript 98.3% CSS 0.9% Shell 0.7%
2.2 KB · 60 lines typescript
Raw Blame History
1import { beforeAll, describe, expect, it } from "vitest";2import { hashPassword, passwordPolicyError, verifyPassword } from "../lib/auth/password.ts";3import { createSession, destroyAllSessions, userForToken } from "../lib/auth/session.ts";4import { db, run } from "../lib/db/index.ts";5import { rateLimit } from "../lib/auth/rate-limit.ts";67describe("Mots de passe", () => {8  it("hache et vérifie avec bcrypt", () => {9    const h = hashPassword("MonMotDePasseSolide!");10    expect(h).not.toContain("MonMotDePasse");11    expect(verifyPassword("MonMotDePasseSolide!", h)).toBe(true);12    expect(verifyPassword("mauvais", h)).toBe(false);13  });1415  it("refuse admin123 comme mot de passe permanent", () => {16    expect(passwordPolicyError("admin123")).toBeTruthy();17    expect(passwordPolicyError("Admin123")).toBeTruthy();18  });1920  it("exige 10 caractères", () => {21    expect(passwordPolicyError("court")).toBeTruthy();22    expect(passwordPolicyError("assez-long-2026")).toBeNull();23  });24});2526describe("Sessions", () => {27  let userId: number;28  beforeAll(() => {29    db();30    const r = run(31      "INSERT INTO users (username, display_name, password_hash) VALUES ('test-session', 'Test', 'x')"32    );33    userId = Number(r.lastInsertRowid);34  });3536  it("le jeton n'est jamais stocké en clair (haché en BD)", () => {37    const { token } = createSession(userId);38    const raw = db().prepare("SELECT token_hash FROM sessions WHERE user_id = ?").all(userId) as { token_hash: string }[];39    expect(raw.some((r) => r.token_hash === token)).toBe(false);40    expect(userForToken(token)?.username).toBe("test-session");41  });4243  it("un jeton inconnu ou révoqué ne donne aucun accès", () => {44    const { token } = createSession(userId);45    destroyAllSessions(userId);46    expect(userForToken(token)).toBeNull();47    expect(userForToken("0".repeat(64))).toBeNull();48  });49});5051describe("Limitation de débit", () => {52  it("bloque après le maximum de tentatives dans la fenêtre", () => {53    const key = "test:" + Math.random();54    for (let i = 0; i < 5; i++) expect(rateLimit(key, 5, 60_000).ok).toBe(true);55    const blocked = rateLimit(key, 5, 60_000);56    expect(blocked.ok).toBe(false);57    expect(blocked.retryAfterS).toBeGreaterThan(0);58  });59});60