import logging from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.config import get_settings from app.models import Role, User from app.permissions import SYSTEM_ROLES from app.security import hash_password log = logging.getLogger(__name__) async def bootstrap(db: AsyncSession) -> None: """Create system roles and the initial admin on a fresh database.""" roles = {r.name: r for r in (await db.scalars(select(Role))).all()} for name, perms in SYSTEM_ROLES.items(): role = roles.get(name) if role is None: db.add(Role(name=name, permissions=perms, is_system=True)) elif name == "admin": # admin always has every permission, including newly added ones role.permissions = perms await db.flush() if await db.scalar(select(func.count()).select_from(User)): await db.commit() return settings = get_settings() admin_role = await db.scalar(select(Role).where(Role.name == "admin")) db.add( User( username=settings.admin_username, password_hash=hash_password(settings.admin_password), role_id=admin_role.id, must_change_password=True, must_change_username=True, ) ) await db.commit() log.warning("Created initial admin '%s'; credentials must be changed on first login", settings.admin_username)