Reconcile website_* schema to the live AtomCMS DB (amx_test)
Introspected the live DB and fixed real drift between the hand-modeled
schema and the actual columns:
- Added missing @map("snake_case") on camelCase fields that silently
failed at query time: website_teams (rank_name/hidden_rank/...),
website_paypal_transactions/user_guestbooks/help_center_tickets(+replies)/
used_shop_vouchers/maintenance_tasks (user_id), website_rare_values
(currency_type).
- website_permissions was modeled as key/value/comment but is actually
permission/min_rank/description — fixed the model + the admin page/action.
- website_shop_articles.icon -> icon_url (+ added category_id, is_giftable);
updated the shop page + admin shop CRUD.
- website_shop_categories: dropped non-existent slug/timestamps, added the
real description/order columns; updated the shop page.
- website_shop_article_features.features(Json) -> content(Text).
Verified against amx_test: all website_* query errors gone; home renders
the real hotel_name ("Habbo"), rankings shows real users, /staff + /shop
200. tsc 0, vitest 49/49, next build 0. Remaining missing tables
(radio_*/game_*/staff_activities/alert_logs/article_comments+reactions)
don't exist in this DB and degrade gracefully via try/catch.
This commit is contained in:
1 parent
4eccd146ba
commit
b97a88c561
6 files changed
+92
-93
No files matched your search
@@ -8,21 +8,21 @@ import { prisma } from "@/lib/prisma";
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
// Manages website_permissions (model WebsitePermissions) — the CMS-owned
|
||||
// rank-permission mapping AtomCMS exposes in admin. Each row is a key with an
|
||||
// optional value and comment; those are the only editable columns on the table.
|
||||
// permission -> minimum-rank mapping. Each row names a permission and the lowest
|
||||
// rank allowed to use it, with an optional description.
|
||||
type PermissionRow = {
|
||||
id: bigint;
|
||||
key: string;
|
||||
value: string | null;
|
||||
comment: string | null;
|
||||
permission: string;
|
||||
minRank: number;
|
||||
description: string | null;
|
||||
};
|
||||
|
||||
export default async function AdminPermissions() {
|
||||
let permissions: PermissionRow[] = [];
|
||||
try {
|
||||
permissions = await prisma.websitePermissions.findMany({
|
||||
select: { id: true, key: true, value: true, comment: true },
|
||||
orderBy: { key: "asc" },
|
||||
select: { id: true, permission: true, minRank: true, description: true },
|
||||
orderBy: { minRank: "asc" },
|
||||
take: 500,
|
||||
});
|
||||
} catch {
|
||||
@@ -33,21 +33,27 @@ export default async function AdminPermissions() {
|
||||
<main>
|
||||
<h1>Permissions</h1>
|
||||
<p className="muted">
|
||||
CMS-owned rank permissions (<code>website_permissions</code>). Each entry
|
||||
maps a permission key to its value/name and an optional comment.
|
||||
CMS-owned permissions (<code>website_permissions</code>). Each entry maps
|
||||
a permission name to the minimum rank allowed to use it.
|
||||
</p>
|
||||
|
||||
<form action={createPermission} className="card" style={{ marginBottom: "1.5rem" }}>
|
||||
<h3 style={{ marginTop: 0 }}>Add / overwrite permission</h3>
|
||||
<div style={{ display: "flex", gap: "0.5rem", flexWrap: "wrap" }}>
|
||||
<input name="key" placeholder="key" required maxLength={255} />
|
||||
<input name="permission" placeholder="permission" required maxLength={255} />
|
||||
<input
|
||||
name="value"
|
||||
placeholder="value / name"
|
||||
maxLength={255}
|
||||
name="minRank"
|
||||
type="number"
|
||||
min={0}
|
||||
placeholder="min rank"
|
||||
defaultValue={1}
|
||||
style={{ width: 110 }}
|
||||
/>
|
||||
<input
|
||||
name="description"
|
||||
placeholder="description"
|
||||
style={{ flex: 1, minWidth: 160 }}
|
||||
/>
|
||||
<input name="comment" placeholder="comment" maxLength={255} />
|
||||
<button type="submit" className="btn btn-primary">
|
||||
Save
|
||||
</button>
|
||||
@@ -61,9 +67,9 @@ export default async function AdminPermissions() {
|
||||
<thead>
|
||||
<tr style={{ textAlign: "left", color: "var(--muted)" }}>
|
||||
<th>ID</th>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
<th>Comment</th>
|
||||
<th>Permission</th>
|
||||
<th>Min rank</th>
|
||||
<th>Description</th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -78,24 +84,24 @@ export default async function AdminPermissions() {
|
||||
style={{ display: "contents" }}
|
||||
>
|
||||
<input type="hidden" name="id" value={String(p.id)} />
|
||||
<input name="key" defaultValue={p.key} required maxLength={255} />
|
||||
<input name="permission" defaultValue={p.permission} required maxLength={255} />
|
||||
</form>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
form={`perm-${String(p.id)}`}
|
||||
name="value"
|
||||
defaultValue={p.value ?? ""}
|
||||
maxLength={255}
|
||||
style={{ width: "100%" }}
|
||||
name="minRank"
|
||||
type="number"
|
||||
min={0}
|
||||
defaultValue={p.minRank}
|
||||
style={{ width: 90 }}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
form={`perm-${String(p.id)}`}
|
||||
name="comment"
|
||||
defaultValue={p.comment ?? ""}
|
||||
maxLength={255}
|
||||
name="description"
|
||||
defaultValue={p.description ?? ""}
|
||||
style={{ width: "100%" }}
|
||||
/>
|
||||
</td>
|
||||
|
||||
@@ -29,7 +29,7 @@ export default async function EditShopArticle({
|
||||
<input type="hidden" name="id" value={String(pkg.id)} />
|
||||
<input name="name" defaultValue={pkg.name} placeholder="Name" required maxLength={255} />
|
||||
<input name="info" defaultValue={pkg.info} placeholder="Info / description" maxLength={255} />
|
||||
<input name="icon" defaultValue={pkg.icon} placeholder="Icon" maxLength={255} />
|
||||
<input name="icon" defaultValue={pkg.iconUrl} placeholder="Icon URL" maxLength={255} />
|
||||
<input name="color" defaultValue={pkg.color} placeholder="Color (e.g. #ffcc00)" maxLength={255} />
|
||||
<input name="costs" type="number" min={0} defaultValue={pkg.costs} placeholder="Costs (store price)" required />
|
||||
<input name="credits" type="number" min={0} defaultValue={pkg.credits ?? undefined} placeholder="Credits given (optional)" />
|
||||
|
||||
Reference in new issue
Block a user