8ad282aad8
- 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>
60 lines
2.1 KiB
TypeScript
60 lines
2.1 KiB
TypeScript
"use server";
|
|
|
|
import { redirect } from "next/navigation";
|
|
import { randomBytes, scryptSync } from "crypto";
|
|
import { getPlatformDb } from "../../lib/platform-db";
|
|
import { getSession } from "../../lib/auth";
|
|
|
|
function requireAuth() {
|
|
// Called inside server actions — session check is synchronous-safe via cache
|
|
}
|
|
|
|
function hashPassword(password: string): string {
|
|
const salt = randomBytes(16).toString("hex");
|
|
const hash = scryptSync(password, salt, 64).toString("hex");
|
|
return `${salt}:${hash}`;
|
|
}
|
|
|
|
export async function createTenant(formData: FormData) {
|
|
const session = await getSession();
|
|
if (!session) redirect("/login");
|
|
|
|
const name = (formData.get("name") as string).trim();
|
|
const slug = (formData.get("slug") as string).trim().toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
const adminEmail = (formData.get("admin_email") as string).trim();
|
|
const adminPassword = formData.get("admin_password") as string;
|
|
const adminName = (formData.get("admin_name") as string).trim();
|
|
|
|
if (!name || !slug || !adminEmail || !adminPassword || !adminName) {
|
|
redirect("/tenants?error=missing");
|
|
}
|
|
|
|
const db = getPlatformDb();
|
|
|
|
const existing = db.prepare("SELECT id FROM accounts WHERE slug = ?").get(slug);
|
|
if (existing) redirect("/tenants?error=slug");
|
|
|
|
db.prepare("INSERT INTO accounts (name, slug) VALUES (?, ?)").run(name, slug);
|
|
const account = db.prepare("SELECT id FROM accounts WHERE slug = ?").get(slug) as { id: number };
|
|
|
|
db.prepare(
|
|
"INSERT INTO users (account_id, email, password_hash, name, role) VALUES (?, ?, ?, ?, 'admin')"
|
|
).run(account.id, adminEmail, hashPassword(adminPassword), adminName);
|
|
|
|
redirect("/tenants");
|
|
}
|
|
|
|
export async function deleteTenant(formData: FormData) {
|
|
const session = await getSession();
|
|
if (!session) redirect("/login");
|
|
|
|
const accountId = Number(formData.get("account_id"));
|
|
if (!accountId) redirect("/tenants");
|
|
|
|
const db = getPlatformDb();
|
|
// Cascade via foreign keys: users, participants, measurements are deleted automatically
|
|
db.prepare("DELETE FROM accounts WHERE id = ?").run(accountId);
|
|
|
|
redirect("/tenants");
|
|
}
|