diff --git a/src/lib/services/permission-ranks.test.ts b/src/lib/services/permission-ranks.test.ts index fed9925904..a7b31eaa4e 100644 --- a/src/lib/services/permission-ranks.test.ts +++ b/src/lib/services/permission-ranks.test.ts @@ -1,12 +1,21 @@ +import type { SQL } from "drizzle-orm"; +import { MySqlDialect } from "drizzle-orm/mysql-core"; import { describe, expect, it } from "vitest"; import { + fetchEmulatorRankForEdit, getRankPermissionColumn, RANK_GENERAL_FIELDS, splitRankUpdateFields, toPermissionValue, } from "./permission-ranks"; +const dialect = new MySqlDialect(); + +function queryText(query: SQL | string) { + return typeof query === "string" ? query : dialect.sqlToQuery(query).sql; +} + describe("getRankPermissionColumn", () => { it("returns rank_N for valid rank", () => { expect(getRankPermissionColumn(1)).toBe("rank_1"); @@ -76,3 +85,50 @@ describe("RANK_GENERAL_FIELDS", () => { expect(RANK_GENERAL_FIELDS.has("nonexistent")).toBe(false); }); }); + +describe("fetchEmulatorRankForEdit", () => { + it("repairs a missing permission_definitions column before loading an existing rank", async () => { + let hasRankColumn = false; + const db = { + execute: async (query: SQL | string) => { + const text = queryText(query); + if (text.includes("FROM permission_ranks")) { + return [ + [ + { + id: 11, + rank_name: "Developer", + level: 11, + }, + ], + [], + ]; + } + if (text.includes("FROM information_schema.columns")) { + return [[{ c: hasRankColumn ? 1 : 0 }], []]; + } + if (text.includes("ALTER TABLE permission_definitions")) { + hasRankColumn = true; + return [{ affectedRows: 0 }, []]; + } + if (text.includes("FROM permission_definitions")) { + if (!hasRankColumn) throw new Error("Unknown column 'rank_11'"); + return [ + [{ permission_key: "cmd_ban", max_value: 1, value: 0 }], + [], + ]; + } + throw new Error(`Unexpected query: ${text}`); + }, + transaction: async () => { + throw new Error("Unexpected transaction"); + }, + }; + + await expect(fetchEmulatorRankForEdit(db as never, 11)).resolves.toMatchObject({ + id: 11, + permissions: { cmd_ban: "0" }, + }); + expect(hasRankColumn).toBe(true); + }); +}); diff --git a/src/lib/services/permission-ranks.ts b/src/lib/services/permission-ranks.ts index bb1e60e614..d8db442917 100644 --- a/src/lib/services/permission-ranks.ts +++ b/src/lib/services/permission-ranks.ts @@ -124,6 +124,7 @@ export async function fetchEmulatorRankForEdit( ); if (rankRows.length === 0) return null; + await ensurePermissionRankColumn(db, rankId); const rankColumn = getRankPermissionColumn(rankId); const permissionRows = await rawRows< {