Add is_admin column with first-account-is-admin migration

This commit is contained in:
Jared Miller 2026-02-14 18:38:41 -05:00
parent a5588ca21b
commit 05afff9538
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
2 changed files with 47 additions and 0 deletions

View file

@ -344,6 +344,7 @@ async def shell(
"inventory": [],
"description": "",
"home_zone": None,
"is_admin": False,
}
# Resolve zone from zone_name using zone registry
@ -388,6 +389,7 @@ async def shell(
# Set description and home zone
player.description = player_data.get("description", "")
player.home_zone = player_data.get("home_zone")
player.is_admin = player_data.get("is_admin", False)
# Load aliases from database
player.aliases = load_aliases(player_name)

View file

@ -25,6 +25,7 @@ class PlayerData(TypedDict):
inventory: list[str]
description: str
home_zone: str | None
is_admin: bool
class StatsData(TypedDict):
@ -112,6 +113,15 @@ def init_db(db_path: str | Path) -> None:
)
if "home_zone" not in columns:
cursor.execute("ALTER TABLE accounts ADD COLUMN home_zone TEXT")
if "is_admin" not in columns:
cursor.execute(
"ALTER TABLE accounts ADD COLUMN is_admin INTEGER NOT NULL DEFAULT 0"
)
# First account ever created becomes admin
cursor.execute(
"UPDATE accounts SET is_admin = 1 "
"WHERE rowid = (SELECT rowid FROM accounts ORDER BY created_at ASC LIMIT 1)"
)
conn.commit()
conn.close()
@ -171,6 +181,10 @@ def create_account(name: str, password: str) -> bool:
"INSERT INTO accounts (name, password_hash, salt) VALUES (?, ?, ?)",
(name, password_hash, salt.hex()),
)
# First account ever created becomes admin
cursor.execute("SELECT COUNT(*) FROM accounts")
if cursor.fetchone()[0] == 1:
cursor.execute("UPDATE accounts SET is_admin = 1 WHERE name = ?", (name,))
conn.commit()
return True
except sqlite3.IntegrityError:
@ -329,6 +343,7 @@ def load_player_data(name: str) -> PlayerData | None:
has_inventory = "inventory" in columns
has_description = "description" in columns
has_home_zone = "home_zone" in columns
has_is_admin = "is_admin" in columns
# Build SELECT based on available columns
select_cols = "x, y, pl, stamina, max_stamina, flying"
@ -340,6 +355,8 @@ def load_player_data(name: str) -> PlayerData | None:
select_cols += ", description"
if has_home_zone:
select_cols += ", home_zone"
if has_is_admin:
select_cols += ", is_admin"
cursor.execute(
f"SELECT {select_cols} FROM accounts WHERE name = ?",
@ -376,6 +393,11 @@ def load_player_data(name: str) -> PlayerData | None:
home_zone = result[idx]
idx += 1
is_admin = False
if has_is_admin:
is_admin = bool(result[idx])
idx += 1
return {
"x": x,
"y": y,
@ -387,6 +409,7 @@ def load_player_data(name: str) -> PlayerData | None:
"inventory": inventory,
"description": description,
"home_zone": home_zone,
"is_admin": is_admin,
}
@ -407,6 +430,28 @@ def update_last_login(name: str) -> None:
conn.close()
def set_admin(name: str, is_admin: bool) -> bool:
"""Set admin status for an account.
Args:
name: Account name (case-insensitive)
is_admin: Whether the account should be admin
Returns:
True if account was found and updated, False if not found
"""
conn = _get_connection()
cursor = conn.cursor()
cursor.execute(
"UPDATE accounts SET is_admin = ? WHERE name = ?",
(1 if is_admin else 0, name),
)
updated = cursor.rowcount > 0
conn.commit()
conn.close()
return updated
def save_aliases(
name: str, aliases: dict[str, str], db_path: str | Path | None = None
) -> None: