feat(customers): add initial admin bootstrap and csv import

This commit is contained in:
DS | Schubert 2026-07-03 09:14:56 +02:00
parent c816e9869d
commit ecab0fe6b6
27 changed files with 1197 additions and 34 deletions

View file

@ -0,0 +1,82 @@
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})