"use client"; import { Suspense, useState } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; /** * Validiert Redirect-URL: nur interne Routes erlauben * Verhindert Open Redirect zu externen Seiten */ function isInternalUrl(url: string): boolean { if (!url.startsWith("/")) return false; // Nur Admin- und Kunden-Routes erlauben return url.startsWith("/admin/") || url.startsWith("/kunden/"); } function AdminLoginForm() { const router = useRouter(); const searchParams = useSearchParams(); const rawFrom = searchParams.get("from"); // ✅ Validierung: nur interne URLs erlauben, Fallback auf /admin/anfragen const from = rawFrom && isInternalUrl(rawFrom) ? rawFrom : "/admin/anfragen"; const sessionExpired = searchParams.get("session_expired") === "true"; const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [error, setError] = useState( sessionExpired ? "Ihre Session ist abgelaufen. Bitte melden Sie sich erneut an." : "" ); const [loading, setLoading] = useState(false); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setError(""); setLoading(true); const res = await fetch("/api/admin/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email, password }), }); if (res.ok) { router.push(from); } else { setError("Ungültige Zugangsdaten"); } setLoading(false); } return (

Admin · Mietpark Hahn

Bitte anmelden

setEmail(e.target.value)} autoComplete="email" placeholder="admin@beispiel.de" className="mt-1 rounded-md" required />
setPassword(e.target.value)} autoComplete="current-password" className="mt-1 rounded-md" required />
{error && (

{error}

)}
); } export default function AdminLoginPage() { return ( ); }