feat(housekeeping): deliver system vertical

This commit is contained in:
Simo committed 2026-08-28 23:31:47 +02:00
1 parent 0117b45d74
commit 3788ecd9f1
33 files changed
+4548 -423

No files matched your search

+45 -11
View File
@@ -1,8 +1,10 @@
"use server";
import { revalidatePath } from "next/cache";
import { systemMutationService } from "@/features/housekeeping/domains/system/services/mutations";
import { createHousekeepingCapabilityContext } from "@/features/housekeeping/foundation/capability-context";
import { createCorrelationId } from "@/features/housekeeping/foundation/correlation";
import { requirePermission } from "@/lib/admin/guard";
import { db, EmulatorSettings, EmulatorTexts } from "@/lib/db";
import { PERMS } from "@/lib/permissions";
// emulator_settings: PK is the string column `key`, payload is `value` (VarChar 512).
@@ -10,8 +12,40 @@ import { PERMS } from "@/lib/permissions";
// Both tables are emulator-owned; we only ever read/update existing rows or add new
// keys via upsert. We never migrate or drop them.
function mutationContext(staff: {
id: number;
rank: number;
username: string;
}) {
const matches = (slug: string) => slug === PERMS.SETTINGS_EDIT;
return {
capability: createHousekeepingCapabilityContext(staff, {
isSuperAdmin: false,
has: matches,
hasAny: (...slugs: string[]) => slugs.some(matches),
hasAll: (...slugs: string[]) => slugs.every(matches),
}),
correlationId: createCorrelationId(),
};
}
async function requireMutation(
staff: { id: number; rank: number; username: string },
operation:
| "configuration.emulator-setting.update"
| "configuration.emulator-text.update",
input: { key: string; value: string },
): Promise<void> {
const result = await systemMutationService.execute(
mutationContext(staff),
operation,
input,
);
if (!result.ok) throw new Error(result.error.messageKey);
}
export async function updateEmulatorSetting(formData: FormData): Promise<void> {
await requirePermission(PERMS.SETTINGS_EDIT);
const staff = await requirePermission(PERMS.SETTINGS_EDIT);
const key = String(formData.get("key") ?? "")
.normalize("NFC")
.trim()
@@ -20,15 +54,15 @@ export async function updateEmulatorSetting(formData: FormData): Promise<void> {
.normalize("NFC")
.slice(0, 512);
if (!key) return;
await db
.insert(EmulatorSettings)
.values({ key, value })
.onDuplicateKeyUpdate({ set: { value } });
await requireMutation(staff, "configuration.emulator-setting.update", {
key,
value,
});
revalidatePath("/admin/emulator");
}
export async function updateEmulatorText(formData: FormData): Promise<void> {
await requirePermission(PERMS.SETTINGS_EDIT);
const staff = await requirePermission(PERMS.SETTINGS_EDIT);
const key = String(formData.get("key") ?? "")
.normalize("NFC")
.trim()
@@ -37,9 +71,9 @@ export async function updateEmulatorText(formData: FormData): Promise<void> {
.normalize("NFC")
.slice(0, 4096);
if (!key) return;
await db
.insert(EmulatorTexts)
.values({ key, value })
.onDuplicateKeyUpdate({ set: { value } });
await requireMutation(staff, "configuration.emulator-text.update", {
key,
value,
});
revalidatePath("/admin/emulator");
}