fix: support legacy rank permission schema
CI / check (push) Successful in 27s
CI / release (push) Skipped
CI / deploy (push) Successful in 43s

This commit is contained in:
Simo committed 2026-08-31 21:01:13 +02:00
1 parent 384ede19c4
commit 37ad27c5f3
2 files changed
+47 -18

No files matched your search

+17 -12
View File
@@ -87,8 +87,7 @@ describe("RANK_GENERAL_FIELDS", () => {
}); });
describe("fetchEmulatorRankForEdit", () => { describe("fetchEmulatorRankForEdit", () => {
it("repairs a missing permission_definitions column before loading an existing rank", async () => { it("loads permissions from the legacy table when permission_definitions is absent", async () => {
let hasRankColumn = false;
const db = { const db = {
execute: async (query: SQL | string) => { execute: async (query: SQL | string) => {
const text = queryText(query); const text = queryText(query);
@@ -105,15 +104,21 @@ describe("fetchEmulatorRankForEdit", () => {
]; ];
} }
if (text.includes("FROM information_schema.columns")) { if (text.includes("FROM information_schema.columns")) {
return [[{ c: hasRankColumn ? 1 : 0 }], []]; return [[], []];
} }
if (text.includes("ALTER TABLE permission_definitions")) { if (text.includes("FROM permissions")) {
hasRankColumn = true; return [
return [{ affectedRows: 0 }, []]; [
} {
if (text.includes("FROM permission_definitions")) { id: 11,
if (!hasRankColumn) throw new Error("Unknown column 'rank_11'"); rank_name: "Developer",
return [[{ permission_key: "cmd_ban", max_value: 1, value: 0 }], []]; level: 11,
cmd_ban: 1,
cmd_owner: 2,
},
],
[],
];
} }
throw new Error(`Unexpected query: ${text}`); throw new Error(`Unexpected query: ${text}`);
}, },
@@ -126,8 +131,8 @@ describe("fetchEmulatorRankForEdit", () => {
fetchEmulatorRankForEdit(db as never, 11), fetchEmulatorRankForEdit(db as never, 11),
).resolves.toMatchObject({ ).resolves.toMatchObject({
id: 11, id: 11,
permissions: { cmd_ban: "0" }, permissions: { cmd_ban: "1", cmd_owner: "2" },
permissionMaxValues: { cmd_ban: 1, cmd_owner: 2 },
}); });
expect(hasRankColumn).toBe(true);
}); });
}); });
+30 -6
View File
@@ -124,8 +124,11 @@ export async function fetchEmulatorRankForEdit(
); );
if (rankRows.length === 0) return null; if (rankRows.length === 0) return null;
await ensurePermissionRankColumn(db, rankId);
const rankColumn = getRankPermissionColumn(rankId); const rankColumn = getRankPermissionColumn(rankId);
const permissions: Record<string, string> = {};
const permissionMaxValues: Record<string, number> = {};
const definitionColumns = await getTableColumns(db, "permission_definitions");
if (definitionColumns.has(rankColumn)) {
const permissionRows = await rawRows< const permissionRows = await rawRows<
{ {
permission_key: string; permission_key: string;
@@ -141,11 +144,32 @@ export async function fetchEmulatorRankForEdit(
`, `,
); );
const permissions: Record<string, string> = {}; for (const permission of permissionRows) {
const permissionMaxValues: Record<string, number> = {}; permissions[permission.permission_key] = String(permission.value ?? 0);
for (const row of permissionRows) { permissionMaxValues[permission.permission_key] = Number(
permissions[row.permission_key] = String(row.value ?? 0); permission.max_value ?? 1,
permissionMaxValues[row.permission_key] = Number(row.max_value ?? 1); );
}
} else {
const legacyRows = await rawRows<Record<string, unknown>[]>(
db,
sql`SELECT * FROM permissions WHERE id = ${rankId} LIMIT 1`,
);
for (const [key, value] of Object.entries(legacyRows[0] ?? {})) {
if (
key === "id" ||
RANK_GENERAL_FIELDS.has(key) ||
!VALID_KEY.test(key)
) {
continue;
}
const permissionValue =
typeof value === "string" || typeof value === "number"
? toPermissionValue(value)
: 0;
permissions[key] = String(permissionValue);
permissionMaxValues[key] = Math.max(1, permissionValue);
}
} }
const row = rankRows[0]; const row = rankRows[0];