Add is_admin column with first-account-is-admin migration
This commit is contained in:
parent
a5588ca21b
commit
05afff9538
2 changed files with 47 additions and 0 deletions
|
|
@ -344,6 +344,7 @@ async def shell(
|
||||||
"inventory": [],
|
"inventory": [],
|
||||||
"description": "",
|
"description": "",
|
||||||
"home_zone": None,
|
"home_zone": None,
|
||||||
|
"is_admin": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Resolve zone from zone_name using zone registry
|
# Resolve zone from zone_name using zone registry
|
||||||
|
|
@ -388,6 +389,7 @@ async def shell(
|
||||||
# Set description and home zone
|
# Set description and home zone
|
||||||
player.description = player_data.get("description", "")
|
player.description = player_data.get("description", "")
|
||||||
player.home_zone = player_data.get("home_zone")
|
player.home_zone = player_data.get("home_zone")
|
||||||
|
player.is_admin = player_data.get("is_admin", False)
|
||||||
|
|
||||||
# Load aliases from database
|
# Load aliases from database
|
||||||
player.aliases = load_aliases(player_name)
|
player.aliases = load_aliases(player_name)
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ class PlayerData(TypedDict):
|
||||||
inventory: list[str]
|
inventory: list[str]
|
||||||
description: str
|
description: str
|
||||||
home_zone: str | None
|
home_zone: str | None
|
||||||
|
is_admin: bool
|
||||||
|
|
||||||
|
|
||||||
class StatsData(TypedDict):
|
class StatsData(TypedDict):
|
||||||
|
|
@ -112,6 +113,15 @@ def init_db(db_path: str | Path) -> None:
|
||||||
)
|
)
|
||||||
if "home_zone" not in columns:
|
if "home_zone" not in columns:
|
||||||
cursor.execute("ALTER TABLE accounts ADD COLUMN home_zone TEXT")
|
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.commit()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
@ -171,6 +181,10 @@ def create_account(name: str, password: str) -> bool:
|
||||||
"INSERT INTO accounts (name, password_hash, salt) VALUES (?, ?, ?)",
|
"INSERT INTO accounts (name, password_hash, salt) VALUES (?, ?, ?)",
|
||||||
(name, password_hash, salt.hex()),
|
(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()
|
conn.commit()
|
||||||
return True
|
return True
|
||||||
except sqlite3.IntegrityError:
|
except sqlite3.IntegrityError:
|
||||||
|
|
@ -329,6 +343,7 @@ def load_player_data(name: str) -> PlayerData | None:
|
||||||
has_inventory = "inventory" in columns
|
has_inventory = "inventory" in columns
|
||||||
has_description = "description" in columns
|
has_description = "description" in columns
|
||||||
has_home_zone = "home_zone" in columns
|
has_home_zone = "home_zone" in columns
|
||||||
|
has_is_admin = "is_admin" in columns
|
||||||
|
|
||||||
# Build SELECT based on available columns
|
# Build SELECT based on available columns
|
||||||
select_cols = "x, y, pl, stamina, max_stamina, flying"
|
select_cols = "x, y, pl, stamina, max_stamina, flying"
|
||||||
|
|
@ -340,6 +355,8 @@ def load_player_data(name: str) -> PlayerData | None:
|
||||||
select_cols += ", description"
|
select_cols += ", description"
|
||||||
if has_home_zone:
|
if has_home_zone:
|
||||||
select_cols += ", home_zone"
|
select_cols += ", home_zone"
|
||||||
|
if has_is_admin:
|
||||||
|
select_cols += ", is_admin"
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
f"SELECT {select_cols} FROM accounts WHERE name = ?",
|
f"SELECT {select_cols} FROM accounts WHERE name = ?",
|
||||||
|
|
@ -376,6 +393,11 @@ def load_player_data(name: str) -> PlayerData | None:
|
||||||
home_zone = result[idx]
|
home_zone = result[idx]
|
||||||
idx += 1
|
idx += 1
|
||||||
|
|
||||||
|
is_admin = False
|
||||||
|
if has_is_admin:
|
||||||
|
is_admin = bool(result[idx])
|
||||||
|
idx += 1
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"x": x,
|
"x": x,
|
||||||
"y": y,
|
"y": y,
|
||||||
|
|
@ -387,6 +409,7 @@ def load_player_data(name: str) -> PlayerData | None:
|
||||||
"inventory": inventory,
|
"inventory": inventory,
|
||||||
"description": description,
|
"description": description,
|
||||||
"home_zone": home_zone,
|
"home_zone": home_zone,
|
||||||
|
"is_admin": is_admin,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -407,6 +430,28 @@ def update_last_login(name: str) -> None:
|
||||||
conn.close()
|
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(
|
def save_aliases(
|
||||||
name: str, aliases: dict[str, str], db_path: str | Path | None = None
|
name: str, aliases: dict[str, str], db_path: str | Path | None = None
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue