Files
Classeo/frontend/src/lib/features/super-admin/api/super-admin.ts
Mathias STRASSER 0951322d71 feat: Permettre au super admin de se connecter et accéder à son dashboard
Le super admin (table super_admins, master DB) ne pouvait pas se connecter
via /api/login car ce firewall n'utilisait que le provider tenant. De même,
le JWT n'était pas enrichi pour les super admins, l'endpoint /api/me/roles
les rejetait, et le frontend redirigeait systématiquement vers /dashboard.

Un chain provider (super_admin + tenant) résout l'authentification,
le JwtPayloadEnricher et MyRolesProvider gèrent désormais les deux types
d'utilisateurs, et le frontend redirige selon le rôle après login.
2026-02-18 10:15:47 +01:00

82 lines
2.4 KiB
TypeScript

import { getApiBaseUrl } from '$lib/api/config';
import { authenticatedFetch } from '$lib/auth/auth.svelte';
const apiUrl = getApiBaseUrl();
export interface EstablishmentData {
id: string;
tenantId: string;
name: string;
subdomain: string;
databaseName?: string;
status: string;
createdAt?: string;
lastActivityAt?: string;
}
export interface EstablishmentMetrics {
establishmentId: string;
name: string;
status: string;
userCount: number;
studentCount: number;
teacherCount: number;
lastLoginAt: string | null;
}
export interface CreateEstablishmentInput {
name: string;
subdomain: string;
adminEmail: string;
}
export async function getEstablishments(): Promise<EstablishmentData[]> {
const response = await authenticatedFetch(`${apiUrl}/super-admin/establishments`);
if (!response.ok) {
throw new Error('Erreur lors du chargement des établissements');
}
const data = await response.json();
return data['hydra:member'] ?? data['member'] ?? data;
}
export async function getEstablishment(id: string): Promise<EstablishmentData> {
const response = await authenticatedFetch(`${apiUrl}/super-admin/establishments/${id}`);
if (!response.ok) {
throw new Error('Établissement introuvable');
}
return response.json();
}
export async function createEstablishment(input: CreateEstablishmentInput): Promise<EstablishmentData> {
const response = await authenticatedFetch(`${apiUrl}/super-admin/establishments`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(input)
});
if (!response.ok) {
const error = await response.json().catch(() => null);
throw new Error(error?.message ?? 'Erreur lors de la création');
}
return response.json();
}
export async function getMetrics(): Promise<EstablishmentMetrics[]> {
const response = await authenticatedFetch(`${apiUrl}/super-admin/metrics`);
if (!response.ok) {
throw new Error('Erreur lors du chargement des métriques');
}
const data = await response.json();
return data['hydra:member'] ?? data['member'] ?? data;
}
export async function switchTenant(tenantId: string): Promise<void> {
const response = await authenticatedFetch(`${apiUrl}/super-admin/switch-tenant`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tenantId })
});
if (!response.ok) {
throw new Error('Erreur lors du basculement de contexte');
}
}