chore: build
ci-api / test (push) Successful in 25m3s
ci-web / test (push) Successful in 15m11s

This commit is contained in:
Xor290
2026-08-24 18:46:44 +02:00
parent 8df0841686
commit cb48bb2b70
8 changed files with 116 additions and 97 deletions
+14 -27
View File
@@ -1,19 +1,8 @@
// Client HTTP vers l'API Omnex.
const BASE = import.meta.env.VITE_API_URL ?? 'http://localhost:8080'
const TOKEN_KEY = 'omnex.token'
export function getToken(): string | null {
return localStorage.getItem(TOKEN_KEY)
}
export function setToken(t: string) {
localStorage.setItem(TOKEN_KEY, t)
}
export function clearToken() {
localStorage.removeItem(TOKEN_KEY)
}
// Client HTTP vers l'API Omnex. "" (chemin relatif) par défaut : same-origin
// en prod (nginx proxy /api/ vers l'API, voir docker/waf/nginx.conf) et en
// dev (proxy Vite, voir vite.config.ts) — nécessaire pour que le cookie de
// session SameSite=Lax soit envoyé (jamais cross-origin, voir lib/auth.tsx).
const BASE = import.meta.env.VITE_API_URL ?? ''
export class ApiError extends Error {
status: number
@@ -23,14 +12,19 @@ export class ApiError extends Error {
}
}
// Authentification exclusivement via le cookie de session HttpOnly (posé par
// le backend sur /auth/login et /auth/register) — jamais de JWT lu/stocké en
// JS. Le dupliquer en localStorage (comme avant) annulait la protection
// HttpOnly contre le vol de session par XSS (pentest F-003) : le SPA et
// l'API étant same-origin, le cookie authentifie déjà chaque fetch() sans
// qu'aucun en-tête Authorization manuel ne soit nécessaire.
async function request<T>(method: string, path: string, body?: unknown): Promise<T> {
const headers: Record<string, string> = { 'Content-Type': 'application/json' }
const token = getToken()
if (token) headers.Authorization = `Bearer ${token}`
const res = await fetch(`${BASE}/api/v1${path}`, {
method,
headers,
credentials: 'include',
body: body ? JSON.stringify(body) : undefined,
})
if (!res.ok) {
@@ -177,16 +171,9 @@ export interface AppDownloadsResponse {
export const api = {
login: (username: string, password: string, role: Role) =>
request<{ token: string; token_type: string; role: Role }>('POST', '/auth/login', {
username,
password,
role,
}),
request<{ role: Role }>('POST', '/auth/login', { username, password, role }),
register: (username: string, password: string) =>
request<{ token: string; token_type: string; role: Role }>('POST', '/auth/register', {
username,
password,
}),
request<{ role: Role }>('POST', '/auth/register', { username, password }),
me: () =>
request<{
user_id: string