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.
This commit is contained in:
81
frontend/src/lib/features/super-admin/api/super-admin.ts
Normal file
81
frontend/src/lib/features/super-admin/api/super-admin.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
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');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user