'use client' import React, { useCallback, useEffect, useState } from 'react' import { AlertTriangle, Info, Key, Plus, RefreshCw, Shield, Users, X, } from 'lucide-react' import type { SSOConfig, SSOFormData, SSOUser, TabId } from './_types' import { apiFetch } from './_components/helpers' import { EmptyState, LoadingSkeleton } from './_components/shared' import { SSOConfigFormModal } from './_components/SSOConfigFormModal' import { DeleteConfirmModal } from './_components/DeleteConfirmModal' import { SSOConfigCard } from './_components/SSOConfigCard' import { SSOUsersTable } from './_components/SSOUsersTable' import { SSOInfoSection } from './_components/SSOInfoSection' export default function SSOPage() { // State const [activeTab, setActiveTab] = useState('configs') const [configs, setConfigs] = useState([]) const [users, setUsers] = useState([]) const [loading, setLoading] = useState(true) const [usersLoading, setUsersLoading] = useState(true) const [error, setError] = useState(null) // Modal state const [showForm, setShowForm] = useState(false) const [editingConfig, setEditingConfig] = useState(null) const [deletingConfig, setDeletingConfig] = useState(null) // --------------------------------------------------------------------------- // Data Loading // --------------------------------------------------------------------------- const loadConfigs = useCallback(async () => { setLoading(true) setError(null) try { const data = await apiFetch<{ configs: SSOConfig[] }>('/configs') setConfigs(data.configs || []) } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Fehler beim Laden der SSO-Konfigurationen') } finally { setLoading(false) } }, []) const loadUsers = useCallback(async () => { setUsersLoading(true) try { const data = await apiFetch<{ users: SSOUser[] }>('/users') setUsers(data.users || []) } catch { // Users endpoint might not be available yet - fail silently setUsers([]) } finally { setUsersLoading(false) } }, []) useEffect(() => { loadConfigs() loadUsers() }, [loadConfigs, loadUsers]) // --------------------------------------------------------------------------- // Handlers // --------------------------------------------------------------------------- const handleSaveConfig = async (formData: SSOFormData) => { const roleMapping: Record = {} for (const m of formData.role_mappings) { if (m.sso_group.trim()) { roleMapping[m.sso_group.trim()] = m.internal_role } } const payload: Record = { provider_type: formData.provider_type, name: formData.name, oidc_issuer_url: formData.issuer_url, oidc_client_id: formData.client_id, oidc_redirect_uri: formData.redirect_uri, oidc_scopes: formData.scopes.split(',').map(s => s.trim()).filter(Boolean), role_mapping: roleMapping, auto_provision: formData.auto_provision, } if (formData.client_secret) { payload.oidc_client_secret = formData.client_secret } if (editingConfig) { await apiFetch(`/configs/${editingConfig.id}`, { method: 'PUT', body: JSON.stringify(payload), }) } else { payload.enabled = false payload.oidc_client_secret = formData.client_secret await apiFetch('/configs', { method: 'POST', body: JSON.stringify(payload), }) } await loadConfigs() } const handleDeleteConfig = async () => { if (!deletingConfig) return await apiFetch(`/configs/${deletingConfig.id}`, { method: 'DELETE' }) setDeletingConfig(null) await loadConfigs() await loadUsers() } const handleToggleConfig = async (config: SSOConfig) => { try { await apiFetch(`/configs/${config.id}`, { method: 'PUT', body: JSON.stringify({ enabled: !config.enabled }), }) await loadConfigs() } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Fehler beim Aendern des Status') } } const openCreateForm = () => { setEditingConfig(null) setShowForm(true) } const openEditForm = (config: SSOConfig) => { setEditingConfig(config) setShowForm(true) } // --------------------------------------------------------------------------- // Tab Configuration // --------------------------------------------------------------------------- const tabs: { id: TabId; label: string; icon: React.ReactNode; count?: number }[] = [ { id: 'configs', label: 'Konfigurationen', icon: , count: configs.length }, { id: 'users', label: 'SSO-Benutzer', icon: , count: users.length }, { id: 'info', label: 'Anleitung', icon: }, ] // --------------------------------------------------------------------------- // Render // --------------------------------------------------------------------------- return (
{/* Header */}

Single Sign-On (SSO)

Konfigurieren Sie OIDC-Authentifizierung fuer Ihr Unternehmen

{/* Stats Cards */}
Konfigurationen
{configs.length}
Aktive Provider
{configs.filter(c => c.enabled).length}
SSO-Benutzer
{users.length}
Aktive Benutzer
{users.filter(u => u.is_active).length}
{/* Tab Navigation */}
{/* Error Banner */} {error && (
{error}
)} {/* Tab Content */} {activeTab === 'configs' && (
{loading ? ( ) : configs.length === 0 ? (
} title="Keine SSO-Konfigurationen" description="Erstellen Sie Ihre erste SSO-Konfiguration, um Ihren Benutzern die Anmeldung ueber Ihren Identity Provider zu ermoeglichen." action={ } />
) : (
{configs.map(config => ( openEditForm(config)} onDelete={() => setDeletingConfig(config)} onToggle={() => handleToggleConfig(config)} /> ))}
)}
)} {activeTab === 'users' && (

SSO-Benutzer

Uebersicht aller ueber SSO provisionierten Benutzer

)} {activeTab === 'info' && ( )} {/* Modals */} { setShowForm(false) setEditingConfig(null) }} onSave={handleSaveConfig} /> setDeletingConfig(null)} onConfirm={handleDeleteConfig} />
) }