refactor(admin): split sso page.tsx into colocated components
Extract types, constants, helpers, and UI pieces (shared LoadingSkeleton/ EmptyState/StatusBadge/CopyButton, SSOConfigFormModal, DeleteConfirmModal, ConnectionTestPanel, SSOConfigCard, SSOUsersTable, SSOInfoSection) into _components/ and _types.ts to bring page.tsx from 1482 LOC to 339 LOC (under the 500 hard cap). Behavior preserved. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
160
admin-compliance/app/sdk/sso/_components/SSOInfoSection.tsx
Normal file
160
admin-compliance/app/sdk/sso/_components/SSOInfoSection.tsx
Normal file
@@ -0,0 +1,160 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { ChevronDown, ChevronUp, Globe, Info, Shield } from 'lucide-react'
|
||||
|
||||
export function SSOInfoSection() {
|
||||
const [expandedProvider, setExpandedProvider] = useState<string | null>(null)
|
||||
|
||||
const providers = [
|
||||
{
|
||||
id: 'azure',
|
||||
name: 'Microsoft Entra ID (Azure AD)',
|
||||
steps: [
|
||||
'Melden Sie sich im Azure Portal (portal.azure.com) an',
|
||||
'Navigieren Sie zu "Microsoft Entra ID" > "App-Registrierungen" > "Neue Registrierung"',
|
||||
'Geben Sie einen Namen ein (z.B. "BreakPilot Comply SSO")',
|
||||
'Waehlen Sie den Kontotyp (Einzelmandant oder Mehrere Mandanten)',
|
||||
'Tragen Sie die Redirect URI ein (Typ: Web)',
|
||||
'Notieren Sie die Application (Client) ID und die Directory (Tenant) ID',
|
||||
'Erstellen Sie unter "Zertifikate & Geheimnisse" ein neues Client Secret',
|
||||
'Issuer URL: https://login.microsoftonline.com/{Tenant-ID}/v2.0',
|
||||
'Optional: Konfigurieren Sie Gruppen-Claims unter "Token-Konfiguration"',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'okta',
|
||||
name: 'Okta',
|
||||
steps: [
|
||||
'Melden Sie sich in der Okta Admin-Konsole an',
|
||||
'Navigieren Sie zu "Applications" > "Create App Integration"',
|
||||
'Waehlen Sie "OIDC - OpenID Connect" und "Web Application"',
|
||||
'Geben Sie einen Namen und die Redirect URI ein',
|
||||
'Notieren Sie die Client ID und das Client Secret',
|
||||
'Issuer URL: https://{your-domain}.okta.com',
|
||||
'Weisen Sie Benutzer/Gruppen der Applikation zu',
|
||||
'Optional: Konfigurieren Sie Gruppen-Claims im Authorization Server',
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'keycloak',
|
||||
name: 'Keycloak',
|
||||
steps: [
|
||||
'Melden Sie sich in der Keycloak Admin-Konsole an',
|
||||
'Waehlen Sie den gewuenschten Realm oder erstellen Sie einen neuen',
|
||||
'Navigieren Sie zu "Clients" > "Create client"',
|
||||
'Client Type: "OpenID Connect", geben Sie eine Client ID ein',
|
||||
'Aktivieren Sie "Client authentication" und "Standard flow"',
|
||||
'Tragen Sie die Redirect URI unter "Valid redirect URIs" ein',
|
||||
'Kopieren Sie das Client Secret aus dem Tab "Credentials"',
|
||||
'Issuer URL: https://{host}/realms/{realm-name}',
|
||||
'Optional: Konfigurieren Sie Gruppen-Mapper unter "Client scopes"',
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* How SSO Works */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
||||
<Info className="w-5 h-5 text-purple-600" />
|
||||
Wie funktioniert SSO?
|
||||
</h3>
|
||||
<div className="prose prose-sm prose-slate max-w-none">
|
||||
<p className="text-sm text-slate-600">
|
||||
Single Sign-On (SSO) ermoeglicht es Ihren Benutzern, sich mit den bestehenden Unternehmens-Zugangsdaten
|
||||
anzumelden, ohne ein separates Passwort erstellen zu muessen. BreakPilot Comply unterstuetzt den
|
||||
OpenID Connect (OIDC) Standard, der mit allen gaengigen Identity Providern kompatibel ist.
|
||||
</p>
|
||||
<div className="mt-4 grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div className="bg-slate-50 rounded-lg p-4">
|
||||
<div className="w-8 h-8 bg-purple-100 text-purple-700 rounded-lg flex items-center justify-center mb-2">
|
||||
<span className="font-bold text-sm">1</span>
|
||||
</div>
|
||||
<h4 className="font-medium text-slate-900 text-sm">Konfiguration</h4>
|
||||
<p className="text-xs text-slate-500 mt-1">
|
||||
Verbinden Sie Ihren Identity Provider (Azure AD, Okta, Keycloak, etc.) ueber OIDC.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-slate-50 rounded-lg p-4">
|
||||
<div className="w-8 h-8 bg-purple-100 text-purple-700 rounded-lg flex items-center justify-center mb-2">
|
||||
<span className="font-bold text-sm">2</span>
|
||||
</div>
|
||||
<h4 className="font-medium text-slate-900 text-sm">Authentifizierung</h4>
|
||||
<p className="text-xs text-slate-500 mt-1">
|
||||
Benutzer werden zum Identity Provider weitergeleitet und melden sich dort an.
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-slate-50 rounded-lg p-4">
|
||||
<div className="w-8 h-8 bg-purple-100 text-purple-700 rounded-lg flex items-center justify-center mb-2">
|
||||
<span className="font-bold text-sm">3</span>
|
||||
</div>
|
||||
<h4 className="font-medium text-slate-900 text-sm">Provisionierung</h4>
|
||||
<p className="text-xs text-slate-500 mt-1">
|
||||
Benutzerkonten werden automatisch angelegt und Rollen ueber Gruppen-Mappings zugewiesen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Provider Setup Guides */}
|
||||
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-slate-900 mb-4 flex items-center gap-2">
|
||||
<Globe className="w-5 h-5 text-purple-600" />
|
||||
Einrichtungsanleitungen
|
||||
</h3>
|
||||
<div className="space-y-3">
|
||||
{providers.map(provider => (
|
||||
<div key={provider.id} className="border border-slate-200 rounded-lg">
|
||||
<button
|
||||
onClick={() =>
|
||||
setExpandedProvider(expandedProvider === provider.id ? null : provider.id)
|
||||
}
|
||||
className="w-full px-4 py-3 flex items-center justify-between hover:bg-slate-50 transition-colors rounded-lg"
|
||||
>
|
||||
<span className="font-medium text-slate-900 text-sm">{provider.name}</span>
|
||||
{expandedProvider === provider.id ? (
|
||||
<ChevronUp className="w-4 h-4 text-slate-400" />
|
||||
) : (
|
||||
<ChevronDown className="w-4 h-4 text-slate-400" />
|
||||
)}
|
||||
</button>
|
||||
{expandedProvider === provider.id && (
|
||||
<div className="px-4 pb-4">
|
||||
<ol className="space-y-2">
|
||||
{provider.steps.map((step, idx) => (
|
||||
<li key={idx} className="flex gap-3 text-sm text-slate-600">
|
||||
<span className="w-5 h-5 bg-purple-100 text-purple-700 rounded-full flex items-center justify-center text-xs font-medium flex-shrink-0 mt-0.5">
|
||||
{idx + 1}
|
||||
</span>
|
||||
<span>{step}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Security Note */}
|
||||
<div className="bg-purple-50 border border-purple-200 rounded-lg p-4">
|
||||
<div className="flex items-start gap-3">
|
||||
<Shield className="w-5 h-5 text-purple-600 mt-0.5 flex-shrink-0" />
|
||||
<div>
|
||||
<h4 className="font-medium text-purple-900 text-sm">Sicherheitshinweis</h4>
|
||||
<p className="text-sm text-purple-700 mt-1">
|
||||
Client Secrets werden verschluesselt gespeichert und sind nach der Eingabe nicht mehr einsehbar.
|
||||
Aktivieren Sie Auto-Provisioning nur, wenn Sie sicherstellen koennen, dass nur autorisierte
|
||||
Benutzer Zugang zum Identity Provider haben. Verwenden Sie Rollen-Mappings, um die
|
||||
Berechtigungen Ihrer Benutzer granular zu steuern.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user