feat(users): switch account management to single-role model

- add users.role_id for one global role per account
- seed protected account-manager role with account.create permission
- default new accounts to guest role
- block admin role assignment through user management
- allow account-manager permission to create accounts
This commit is contained in:
zhi
2026-03-21 08:44:19 +00:00
parent 7d42d567d1
commit 271d5140e6
6 changed files with 105 additions and 16 deletions

View File

@@ -215,6 +215,11 @@ def _migrate_schema():
"DEFAULT 'open'"
))
# --- users.role_id for single global account role ---
if _has_table(db, "users") and not _has_column(db, "users", "role_id"):
db.execute(text("ALTER TABLE users ADD COLUMN role_id INTEGER NULL"))
_ensure_fk(db, "users", "role_id", "roles", "id", "fk_users_role_id")
# --- monitored_servers.api_key for heartbeat v2 ---
if _has_table(db, "monitored_servers") and not _has_column(db, "monitored_servers", "api_key"):
db.execute(text("ALTER TABLE monitored_servers ADD COLUMN api_key VARCHAR(64) NULL"))
@@ -237,6 +242,29 @@ def _migrate_schema():
finally:
db.close()
def _sync_default_user_roles(db):
from app.models import models
from app.models.role_permission import Role
admin_role = db.query(Role).filter(Role.name == "admin").first()
guest_role = db.query(Role).filter(Role.name == "guest").first()
if admin_role:
db.query(models.User).filter(models.User.is_admin == True).update(
{models.User.role_id: admin_role.id},
synchronize_session=False,
)
if guest_role:
db.query(models.User).filter(
models.User.role_id == None,
models.User.is_admin == False,
).update(
{models.User.role_id: guest_role.id},
synchronize_session=False,
)
db.commit()
# Run database migration on startup
@app.on_event("startup")
def startup():
@@ -250,6 +278,7 @@ def startup():
db = SessionLocal()
try:
run_init(db)
_sync_default_user_roles(db)
finally:
db.close()