feat(PROJ-23): Pro-Mandant LDAP Frontend

- domain_admin: neuer LDAP-Tab mit Tenant-Konfiguration (eigener Mandant)
  - Gruppen-Mapping auf user/auditor beschränkt (keine Eskalation)
  - Nutzt /api/tenant/ldap Endpunkte
- superadmin: globaler LDAP-Tab umbenannt zu "LDAP (Global)"
- superadmin: Mandantentabelle um LDAP-Statusspalte erweitert
  - Badge: Aktiv / Deaktiviert / ---
  - TenantLDAPDialog pro Mandant (alle Rollen bis domain_admin)
- api.ts: TenantLDAPConfig Interface + 8 neue API-Funktionen
  - getTenantLDAPConfig/save/delete/test (domain_admin)
  - getAdminTenantLDAPConfig/save/delete/test (superadmin)
- Tenant Interface: ldap_enabled + ldap_url Felder ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-03-18 00:27:51 +01:00
parent e333e34a03
commit 9e7add31cd
2 changed files with 814 additions and 1 deletions
+65
View File
@@ -678,6 +678,8 @@ export interface Tenant {
created_at: string;
domain_count?: number;
user_count?: number;
ldap_enabled?: boolean;
ldap_url?: string;
}
export interface TenantDomain {
@@ -734,3 +736,66 @@ export async function removeTenantDomain(
method: "DELETE",
});
}
// ── PROJ-23: Pro-Mandant LDAP (tenant_ldap) ──────────────────────────────
export interface TenantLDAPConfig extends LDAPConfig {
tenant_id?: number;
}
// domain_admin -- eigener Mandant
export async function getTenantLDAPConfig(): Promise<TenantLDAPConfig | null> {
try {
return await request<TenantLDAPConfig>("/api/tenant/ldap");
} catch (e: unknown) {
if (e instanceof Error && e.message.includes("404")) return null;
if (e instanceof Error && e.message.includes("no ldap config")) return null;
throw e;
}
}
export async function saveTenantLDAPConfig(cfg: Partial<TenantLDAPConfig>): Promise<void> {
await request<void>("/api/tenant/ldap", { method: "PUT", body: JSON.stringify(cfg) });
}
export async function deleteTenantLDAPConfig(): Promise<void> {
await request<void>("/api/tenant/ldap", { method: "DELETE" });
}
export async function testTenantLDAPConfig(
payload: { use_saved: boolean } & Partial<TenantLDAPConfig>
): Promise<LDAPTestResult> {
return request<LDAPTestResult>("/api/tenant/ldap/test", {
method: "POST",
body: JSON.stringify(payload),
});
}
// superadmin -- beliebiger Mandant per ID
export async function getAdminTenantLDAPConfig(tenantID: number): Promise<TenantLDAPConfig | null> {
try {
return await request<TenantLDAPConfig>(`/api/admin/tenants/${tenantID}/ldap`);
} catch (e: unknown) {
if (e instanceof Error && e.message.includes("404")) return null;
if (e instanceof Error && e.message.includes("no ldap config")) return null;
throw e;
}
}
export async function saveAdminTenantLDAPConfig(tenantID: number, cfg: Partial<TenantLDAPConfig>): Promise<void> {
await request<void>(`/api/admin/tenants/${tenantID}/ldap`, { method: "PUT", body: JSON.stringify(cfg) });
}
export async function deleteAdminTenantLDAPConfig(tenantID: number): Promise<void> {
await request<void>(`/api/admin/tenants/${tenantID}/ldap`, { method: "DELETE" });
}
export async function testAdminTenantLDAPConfig(
tenantID: number,
payload: { use_saved: boolean } & Partial<TenantLDAPConfig>
): Promise<LDAPTestResult> {
return request<LDAPTestResult>(`/api/admin/tenants/${tenantID}/ldap/test`, {
method: "POST",
body: JSON.stringify(payload),
});
}