'use client' import React, { useState, useEffect, useCallback } from 'react' import { useSDK } from '@/lib/sdk' import type { Tenant, Namespace, Role, UserRole, LLMPolicy, TabId } from './_types' import { apiFetch } from './_api' import { CreateTenantModal } from './_components/CreateTenantModal' import { CreateNamespaceModal } from './_components/CreateNamespaceModal' import { CreateRoleModal } from './_components/CreateRoleModal' import { AssignRoleModal } from './_components/AssignRoleModal' import { PolicyModal } from './_components/PolicyModal' import { TenantsTab } from './_components/TenantsTab' import { NamespacesTab } from './_components/NamespacesTab' import { RolesTab } from './_components/RolesTab' import { UsersTab } from './_components/UsersTab' import { PoliciesTab } from './_components/PoliciesTab' // ============================================================================= // MAIN PAGE // ============================================================================= export default function RBACPage() { const { state } = useSDK() void state const [activeTab, setActiveTab] = useState('tenants') const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [success, setSuccess] = useState(null) // Data const [tenants, setTenants] = useState([]) const [selectedTenantId, setSelectedTenantId] = useState(null) const [namespaces, setNamespaces] = useState([]) const [roles, setRoles] = useState([]) const [userRoles, setUserRoles] = useState([]) const [policies, setPolicies] = useState([]) // Modals const [showTenantModal, setShowTenantModal] = useState(false) const [showNamespaceModal, setShowNamespaceModal] = useState(false) const [showRoleModal, setShowRoleModal] = useState(false) const [showUserRoleModal, setShowUserRoleModal] = useState(false) const [showPolicyModal, setShowPolicyModal] = useState(false) const [editingPolicy, setEditingPolicy] = useState(null) // ─── Loaders ───────────────────────────────────────────────────────── const loadTenants = useCallback(async () => { setLoading(true); setError(null) try { const data = await apiFetch('tenants') setTenants(Array.isArray(data) ? data : data.tenants || []) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setLoading(false) } }, []) const loadNamespaces = useCallback(async (tenantId: string) => { setLoading(true); setError(null) try { const data = await apiFetch(`tenants/${tenantId}/namespaces`) setNamespaces(Array.isArray(data) ? data : data.namespaces || []) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setLoading(false) } }, []) const loadRoles = useCallback(async () => { setLoading(true); setError(null) try { const data = await apiFetch('roles') setRoles(Array.isArray(data) ? data : data.roles || []) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setLoading(false) } }, []) const loadUserRoles = useCallback(async () => { setLoading(true); setError(null) try { // Load for a specific user or all — the endpoint expects a userId // We'll load the current user's roles as default const data = await apiFetch('user-roles/00000000-0000-0000-0000-000000000001') setUserRoles(Array.isArray(data) ? data : data.roles || []) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setLoading(false) } }, []) const loadPolicies = useCallback(async () => { setLoading(true); setError(null) try { const data = await apiFetch('llm/policies') setPolicies(Array.isArray(data) ? data : data.policies || []) } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } finally { setLoading(false) } }, []) useEffect(() => { if (activeTab === 'tenants') loadTenants() else if (activeTab === 'namespaces') { loadTenants(); if (selectedTenantId) loadNamespaces(selectedTenantId) } else if (activeTab === 'roles') loadRoles() else if (activeTab === 'users') loadUserRoles() else if (activeTab === 'policies') loadPolicies() }, [activeTab, loadTenants, loadNamespaces, loadRoles, loadUserRoles, loadPolicies, selectedTenantId]) const showSuccessMsg = (msg: string) => { setSuccess(msg) setTimeout(() => setSuccess(null), 3000) } // ─── Actions ───────────────────────────────────────────────────────── const deleteLLMPolicy = async (id: string) => { if (!confirm('Policy wirklich loeschen?')) return try { await apiFetch(`llm/policies/${id}`, { method: 'DELETE' }) showSuccessMsg('Policy geloescht') loadPolicies() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } const togglePolicyActive = async (policy: LLMPolicy) => { try { await apiFetch(`llm/policies/${policy.id}`, { method: 'PUT', body: JSON.stringify({ ...policy, is_active: !policy.is_active }), }) loadPolicies() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } const revokeUserRole = async (userId: string, roleId: string) => { if (!confirm('Rolle wirklich entziehen?')) return try { await apiFetch(`user-roles/${userId}/${roleId}`, { method: 'DELETE' }) showSuccessMsg('Rolle entzogen') loadUserRoles() } catch (e) { setError(e instanceof Error ? e.message : 'Fehler') } } // ─── Tabs ──────────────────────────────────────────────────────────── const tabs: { id: TabId; label: string }[] = [ { id: 'tenants', label: 'Mandanten' }, { id: 'namespaces', label: 'Namespaces' }, { id: 'roles', label: 'Rollen' }, { id: 'users', label: 'Benutzer' }, { id: 'policies', label: 'LLM-Policies' }, ] return (
{/* Header */}

RBAC Administration

Mandanten, Rollen, Berechtigungen und LLM-Policies verwalten

{/* Tabs */}
{tabs.map(tab => ( ))}
{error &&
{error}
} {success &&
{success}
} {loading && (
)} {!loading && activeTab === 'tenants' && ( setShowTenantModal(true)} onSelectTenant={setSelectedTenantId} setActiveTab={setActiveTab} /> )} {!loading && activeTab === 'namespaces' && ( setShowNamespaceModal(true)} onLoadNamespaces={loadNamespaces} /> )} {!loading && activeTab === 'roles' && ( setShowRoleModal(true)} /> )} {!loading && activeTab === 'users' && ( setShowUserRoleModal(true)} onRevoke={revokeUserRole} setUserRoles={setUserRoles} setLoading={setLoading} setError={setError} /> )} {!loading && activeTab === 'policies' && ( { setEditingPolicy(null); setShowPolicyModal(true) }} onEdit={(policy) => { setEditingPolicy(policy); setShowPolicyModal(true) }} onDelete={deleteLLMPolicy} onToggleActive={togglePolicyActive} /> )} {/* ══════════════════════════════════════════════════════════════════ */} {/* MODALS */} {/* ══════════════════════════════════════════════════════════════════ */} {showTenantModal && ( setShowTenantModal(false)} onCreated={() => { setShowTenantModal(false); showSuccessMsg('Mandant erstellt'); loadTenants() }} /> )} {showNamespaceModal && selectedTenantId && ( setShowNamespaceModal(false)} onCreated={() => { setShowNamespaceModal(false); showSuccessMsg('Namespace erstellt'); loadNamespaces(selectedTenantId) }} /> )} {showRoleModal && ( setShowRoleModal(false)} onCreated={() => { setShowRoleModal(false); showSuccessMsg('Rolle erstellt'); loadRoles() }} /> )} {showUserRoleModal && ( setShowUserRoleModal(false)} onAssigned={() => { setShowUserRoleModal(false); showSuccessMsg('Rolle zugewiesen'); loadUserRoles() }} /> )} {showPolicyModal && ( { setShowPolicyModal(false); setEditingPolicy(null) }} onSaved={() => { setShowPolicyModal(false); setEditingPolicy(null); showSuccessMsg('Policy gespeichert'); loadPolicies() }} /> )}
) }