Voeg tenant beheer toe aan rikx-offerte

- Login pagina met HMAC-sessie authenticatie
- /tenants overzicht: lijst alle rikx-platform accounts
- Nieuw tenant aanmaken (naam, slug, admin gebruiker)
- Tenant verwijderen (cascade via foreign keys)
- Leest rikx-platform SQLite DB via /rikx-platform-data mount
- Homepage redirect naar /tenants of /login

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Maarten Elsenaar
2026-09-15 13:14:54 +02:00
parent 463f6d2c90
commit 8ad282aad8
6 changed files with 374 additions and 69 deletions
+74
View File
@@ -0,0 +1,74 @@
"use server";
import { redirect } from "next/navigation";
import { getUserByEmail, verifyPassword, createSession } from "../../lib/auth";
import { getSession } from "../../lib/auth";
export default async function LoginPage({
searchParams,
}: {
searchParams: Promise<{ error?: string }>;
}) {
const session = await getSession();
if (session) redirect("/tenants");
const { error } = await searchParams;
return (
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-zinc-950">
<div className="w-full max-w-sm">
<h1 className="text-2xl font-semibold text-center mb-8 text-zinc-900 dark:text-zinc-100">
Rikx Beheer
</h1>
<form
action={async (formData: FormData) => {
"use server";
const email = formData.get("email") as string;
const password = formData.get("password") as string;
const user = getUserByEmail(email);
if (!user || !verifyPassword(password, user.password_hash)) {
redirect("/login?error=1");
}
await createSession({ userId: user.id, email: user.email, name: user.name });
redirect("/tenants");
}}
className="flex flex-col gap-4 bg-white dark:bg-zinc-900 p-8 rounded-xl border border-zinc-200 dark:border-zinc-800"
>
{error && (
<p className="text-sm text-red-600 dark:text-red-400">
Ongeldig e-mailadres of wachtwoord.
</p>
)}
<div className="flex flex-col gap-1">
<label className="text-sm font-medium text-zinc-700 dark:text-zinc-300">
E-mailadres
</label>
<input
type="email"
name="email"
required
className="rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-zinc-500"
/>
</div>
<div className="flex flex-col gap-1">
<label className="text-sm font-medium text-zinc-700 dark:text-zinc-300">
Wachtwoord
</label>
<input
type="password"
name="password"
required
className="rounded-lg border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-800 px-3 py-2 text-sm text-zinc-900 dark:text-zinc-100 focus:outline-none focus:ring-2 focus:ring-zinc-500"
/>
</div>
<button
type="submit"
className="mt-2 rounded-lg bg-zinc-900 dark:bg-zinc-100 px-4 py-2 text-sm font-medium text-white dark:text-zinc-900 hover:bg-zinc-700 dark:hover:bg-zinc-300 transition-colors"
>
Inloggen
</button>
</form>
</div>
</div>
);
}