Files
ForbiddenStarsApp/backend/app/bootstrap.py
T

66 lines
2.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Идемпотентный бутстрап: справочники + учётная запись администратора.
Запуск: `python -m app.bootstrap` (вызывается из entrypoint.sh после миграций).
"""
from __future__ import annotations
from sqlmodel import Session, select
from app.core.config import settings
from app.core.security import hash_password, verify_password
from app.db.session import engine
from app.models import User
from app.seed.reference_data import seed_reference_data
def _ensure_admin(session: Session) -> None:
if not settings.admin_bootstrap_enabled:
return
password = (settings.admin_password or "").strip()
username = (settings.admin_username or "admin").strip()
existing = session.exec(select(User).where(User.role == "admin")).first()
if existing is None:
if not password:
raise RuntimeError("Отказ создавать администратора без пароля (ADMIN_PASSWORD пуст).")
# Логин администратора = его никнейм (отдельной таблицы админов нет).
session.add(
User(
nickname=username,
role="admin",
auth_provider="local",
password_hash=hash_password(password),
)
)
session.commit()
print(f"[bootstrap] Создан администратор: {username}")
return
# Администратор уже существует.
if not settings.is_development:
# В test/prod пароль НЕ перезаписываем (мог быть изменён через панель).
return
# DEV: подтягиваем логин/пароль из .env (env — источник истины в деве).
changed: list[str] = []
if password and not verify_password(password, existing.password_hash or ""):
existing.password_hash = hash_password(password)
changed.append("пароль")
if username and existing.nickname != username:
existing.nickname = username
changed.append("логин")
if changed:
session.add(existing)
session.commit()
print(f"[bootstrap] DEV: администратор обновлён из .env ({', '.join(changed)})")
def bootstrap() -> None:
with Session(engine) as session:
seed_reference_data(session) # идемпотентно
_ensure_admin(session)
if __name__ == "__main__":
bootstrap()