Full enterprise web operating system including: - Next.js 14 frontend with App Router, i18n (DE/EN), shadcn/ui - NestJS 10 backend with Prisma, JWT auth, Swagger docs - Keycloak 24 SSO with role-based access control - HR module (employees, time tracking, absences, org chart) - LEAN module (3S planning, morning meeting SQCDM, skill matrix) - Integrations module (PlentyONE, Zulip, Todoist, FreeScout, Nextcloud, ecoDMS, GembaDocs) - Dashboard with customizable drag & drop widget grid - Docker Compose infrastructure (PostgreSQL 16, Redis 7, Keycloak 24) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
184 lines
6.9 KiB
TypeScript
184 lines
6.9 KiB
TypeScript
'use client';
|
|
|
|
import { useTranslations } from 'next-intl';
|
|
import Link from 'next/link';
|
|
import { motion } from 'framer-motion';
|
|
import { ArrowLeft, Key, Shield, Smartphone, ExternalLink, AlertTriangle } from 'lucide-react';
|
|
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Badge } from '@/components/ui/badge';
|
|
|
|
interface SecuritySettingsContentProps {
|
|
locale: string;
|
|
}
|
|
|
|
/**
|
|
* Security settings content - Password and 2FA settings
|
|
*/
|
|
export function SecuritySettingsContent({ locale }: SecuritySettingsContentProps) {
|
|
const t = useTranslations('settings');
|
|
|
|
// Keycloak account management URL (would be configured via environment variable)
|
|
const keycloakAccountUrl = process.env.NEXT_PUBLIC_KEYCLOAK_ACCOUNT_URL || '#';
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Header with back button */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3 }}
|
|
className="flex items-center gap-4"
|
|
>
|
|
<Link href={`/${locale}/settings`}>
|
|
<Button variant="ghost" size="icon">
|
|
<ArrowLeft className="h-4 w-4" />
|
|
</Button>
|
|
</Link>
|
|
<div>
|
|
<h1 className="text-3xl font-bold tracking-tight">{t('securityTitle')}</h1>
|
|
<p className="text-muted-foreground">{t('securityDescription')}</p>
|
|
</div>
|
|
</motion.div>
|
|
|
|
{/* Info Banner */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.1 }}
|
|
>
|
|
<Card className="border-yellow-500/50 bg-yellow-500/5">
|
|
<CardContent className="flex items-start gap-4 pt-6">
|
|
<AlertTriangle className="h-5 w-5 text-yellow-500 shrink-0 mt-0.5" />
|
|
<div className="space-y-1">
|
|
<p className="font-medium">Sicherheitseinstellungen werden in Keycloak verwaltet</p>
|
|
<p className="text-sm text-muted-foreground">
|
|
Passwortaenderungen und Zwei-Faktor-Authentifizierung werden zentral ueber Keycloak
|
|
verwaltet. Klicken Sie auf die Buttons unten, um zur Keycloak-Kontoverwaltung
|
|
weitergeleitet zu werden.
|
|
</p>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</motion.div>
|
|
|
|
{/* Password Section */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.2 }}
|
|
>
|
|
<Card>
|
|
<CardHeader>
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
|
|
<Key className="h-5 w-5 text-primary" />
|
|
</div>
|
|
<div>
|
|
<CardTitle>{t('changePassword')}</CardTitle>
|
|
<CardDescription>Aendern Sie Ihr Kontopasswort</CardDescription>
|
|
</div>
|
|
</div>
|
|
<Badge variant="secondary">Via Keycloak</Badge>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<p className="text-sm text-muted-foreground">
|
|
Ihr Passwort wird zentral in Keycloak verwaltet. Ein starkes Passwort sollte
|
|
mindestens 12 Zeichen lang sein und Gross- und Kleinbuchstaben, Zahlen sowie
|
|
Sonderzeichen enthalten.
|
|
</p>
|
|
|
|
<Button asChild>
|
|
<a href={keycloakAccountUrl} target="_blank" rel="noopener noreferrer">
|
|
Passwort in Keycloak aendern
|
|
<ExternalLink className="ml-2 h-4 w-4" />
|
|
</a>
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
</motion.div>
|
|
|
|
{/* Two-Factor Authentication Section */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.3 }}
|
|
>
|
|
<Card>
|
|
<CardHeader>
|
|
<div className="flex items-center justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10">
|
|
<Smartphone className="h-5 w-5 text-primary" />
|
|
</div>
|
|
<div>
|
|
<CardTitle>{t('twoFactor')}</CardTitle>
|
|
<CardDescription>Zusaetzliche Sicherheit fuer Ihr Konto</CardDescription>
|
|
</div>
|
|
</div>
|
|
<Badge variant="outline">Empfohlen</Badge>
|
|
</div>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<p className="text-sm text-muted-foreground">
|
|
Die Zwei-Faktor-Authentifizierung bietet eine zusaetzliche Sicherheitsebene fuer Ihr
|
|
Konto. Selbst wenn jemand Ihr Passwort kennt, benoetigt er zusaetzlich Zugriff auf
|
|
Ihr Authentifizierungsgeraet.
|
|
</p>
|
|
|
|
<div className="rounded-lg border p-4 space-y-3">
|
|
<div className="flex items-center gap-3">
|
|
<Shield className="h-5 w-5 text-muted-foreground" />
|
|
<div>
|
|
<p className="font-medium">Unterstuetzte Methoden:</p>
|
|
<ul className="text-sm text-muted-foreground list-disc list-inside">
|
|
<li>Authenticator App (Google Authenticator, Authy, etc.)</li>
|
|
<li>WebAuthn / FIDO2 Security Keys</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<Button asChild variant="outline">
|
|
<a href={keycloakAccountUrl} target="_blank" rel="noopener noreferrer">
|
|
2FA in Keycloak konfigurieren
|
|
<ExternalLink className="ml-2 h-4 w-4" />
|
|
</a>
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
</motion.div>
|
|
|
|
{/* Active Sessions */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.3, delay: 0.4 }}
|
|
>
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Aktive Sitzungen</CardTitle>
|
|
<CardDescription>Verwalten Sie Ihre aktiven Anmeldesitzungen</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<p className="text-sm text-muted-foreground">
|
|
Sie koennen Ihre aktiven Sitzungen in der Keycloak-Kontoverwaltung einsehen und bei
|
|
Bedarf einzelne Sitzungen beenden.
|
|
</p>
|
|
|
|
<Button asChild variant="outline">
|
|
<a href={keycloakAccountUrl} target="_blank" rel="noopener noreferrer">
|
|
Sitzungen verwalten
|
|
<ExternalLink className="ml-2 h-4 w-4" />
|
|
</a>
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
</motion.div>
|
|
</div>
|
|
);
|
|
}
|