82 lines
2.6 KiB
Python
82 lines
2.6 KiB
Python
import logging
|
|
|
|
from pydantic import EmailStr, TypeAdapter, ValidationError
|
|
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.config import settings
|
|
from app.core.security import hash_password
|
|
from app.models.user import User
|
|
from app.repositories.rbac_repository import RbacRepository
|
|
from app.services.audit_service import write_audit_log
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
email_adapter = TypeAdapter(EmailStr)
|
|
|
|
|
|
def bootstrap_initial_admin(db: Session) -> None:
|
|
active_user_exists = db.scalar(select(User.id).where(User.is_active.is_(True)).limit(1))
|
|
if active_user_exists is not None:
|
|
logger.info("initial_admin.skipped_active_user_exists")
|
|
return
|
|
|
|
username = (settings.initial_admin_username or "").strip()
|
|
email = (settings.initial_admin_email or "").strip()
|
|
password = settings.initial_admin_password or ""
|
|
|
|
if not username or not email or not password:
|
|
logger.warning(
|
|
"initial_admin.not_configured",
|
|
extra={"reason": "missing_required_initial_admin_environment"},
|
|
)
|
|
return
|
|
|
|
try:
|
|
normalized_email = str(email_adapter.validate_python(email))
|
|
except ValidationError:
|
|
logger.warning("initial_admin.invalid_email")
|
|
return
|
|
|
|
administrator_role = RbacRepository.get_role_by_name(db, "administrator")
|
|
if administrator_role is None:
|
|
logger.warning("initial_admin.missing_administrator_role")
|
|
return
|
|
|
|
existing_user = db.scalar(select(User).where((User.username == username) | (User.email == normalized_email)))
|
|
if existing_user is not None:
|
|
logger.info("initial_admin.skipped_user_already_exists")
|
|
return
|
|
|
|
admin = User(
|
|
first_name=settings.initial_admin_first_name.strip(),
|
|
last_name=settings.initial_admin_last_name.strip(),
|
|
username=username,
|
|
email=normalized_email,
|
|
password_hash=hash_password(password),
|
|
role="administrator",
|
|
role_id=administrator_role.id,
|
|
is_active=True,
|
|
)
|
|
db.add(admin)
|
|
db.commit()
|
|
db.refresh(admin)
|
|
|
|
write_audit_log(
|
|
db,
|
|
action="users.initial_admin_bootstrap",
|
|
entity_type="users",
|
|
entity_id=admin.id,
|
|
entity_label=admin.username,
|
|
actor_username="system",
|
|
after_data={
|
|
"id": admin.id,
|
|
"username": admin.username,
|
|
"email": admin.email,
|
|
"role": admin.role,
|
|
"role_id": admin.role_id,
|
|
"is_active": admin.is_active,
|
|
},
|
|
metadata={"source": "initial_admin_bootstrap"},
|
|
)
|
|
logger.info("initial_admin.created", extra={"user_id": admin.id})
|