Init
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
"use server";
|
||||
|
||||
import { hashSync } from "bcryptjs";
|
||||
import { redirect, unstable_rethrow } from "next/navigation";
|
||||
import { requireAdminUser } from "@/lib/auth";
|
||||
import { db, initDatabase, transaction } from "@/lib/db";
|
||||
import { emailValue, idValue, passwordValue, roleValue, text } from "@/lib/validation";
|
||||
import type { UserRole } from "@/lib/types";
|
||||
|
||||
function go(kind: "error" | "success", message: string): never {
|
||||
redirect(`/admin/users?${kind}=${encodeURIComponent(message)}`);
|
||||
}
|
||||
|
||||
function errorMessage(error: unknown) {
|
||||
if (error instanceof Error && error.message.includes("UNIQUE constraint failed")) {
|
||||
return "Diese E-Mail-Adresse ist bereits vergeben.";
|
||||
}
|
||||
return error instanceof Error ? error.message : "Die Aktion konnte nicht ausgeführt werden.";
|
||||
}
|
||||
|
||||
export async function createUserAction(formData: FormData) {
|
||||
await requireAdminUser();
|
||||
initDatabase();
|
||||
try {
|
||||
const name = text(formData, "name", { required: true, max: 100 });
|
||||
const email = emailValue(formData);
|
||||
const password = passwordValue(formData);
|
||||
const role = roleValue(formData);
|
||||
db.prepare(
|
||||
"INSERT INTO users (name, email, password_hash, role) VALUES (?, ?, ?, ?)",
|
||||
).run(name, email, hashSync(password, 12), role);
|
||||
go("success", "Benutzer wurde angelegt.");
|
||||
} catch (error) {
|
||||
unstable_rethrow(error);
|
||||
go("error", errorMessage(error));
|
||||
}
|
||||
}
|
||||
|
||||
export async function changeUserRoleAction(formData: FormData) {
|
||||
const currentUser = await requireAdminUser();
|
||||
initDatabase();
|
||||
try {
|
||||
const id = idValue(formData);
|
||||
const role = roleValue(formData);
|
||||
transaction(() => {
|
||||
const target = db.prepare("SELECT role FROM users WHERE id = ?").get(id) as
|
||||
| { role: UserRole }
|
||||
| undefined;
|
||||
if (!target) throw new Error("Benutzer wurde nicht gefunden.");
|
||||
if (target.role === "admin" && role === "member") {
|
||||
const count = db.prepare("SELECT COUNT(*) AS count FROM users WHERE role = 'admin'").get() as {
|
||||
count: number;
|
||||
};
|
||||
if (count.count <= 1) throw new Error("Der letzte Administrator kann nicht herabgestuft werden.");
|
||||
if (id === currentUser.id) {
|
||||
throw new Error("Die eigene Administratorrolle kann nicht herabgestuft werden.");
|
||||
}
|
||||
}
|
||||
db.prepare("UPDATE users SET role = ? WHERE id = ?").run(role, id);
|
||||
});
|
||||
go("success", "Rolle wurde geändert.");
|
||||
} catch (error) {
|
||||
unstable_rethrow(error);
|
||||
go("error", errorMessage(error));
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteUserAction(formData: FormData) {
|
||||
const currentUser = await requireAdminUser();
|
||||
initDatabase();
|
||||
try {
|
||||
const id = idValue(formData);
|
||||
if (id === currentUser.id) throw new Error("Das aktuell angemeldete Konto kann nicht gelöscht werden.");
|
||||
transaction(() => {
|
||||
const target = db.prepare("SELECT role FROM users WHERE id = ?").get(id) as
|
||||
| { role: UserRole }
|
||||
| undefined;
|
||||
if (!target) throw new Error("Benutzer wurde nicht gefunden.");
|
||||
if (target.role === "admin") {
|
||||
const count = db.prepare("SELECT COUNT(*) AS count FROM users WHERE role = 'admin'").get() as {
|
||||
count: number;
|
||||
};
|
||||
if (count.count <= 1) throw new Error("Der letzte Administrator kann nicht gelöscht werden.");
|
||||
}
|
||||
try {
|
||||
db.prepare("DELETE FROM users WHERE id = ?").run(id);
|
||||
} catch (error) {
|
||||
if (error instanceof Error && error.message.includes("FOREIGN KEY")) {
|
||||
throw new Error("Benutzer mit vorhandenen Einträgen kann nicht gelöscht werden.");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
go("success", "Benutzer wurde gelöscht.");
|
||||
} catch (error) {
|
||||
unstable_rethrow(error);
|
||||
go("error", errorMessage(error));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user