feat: implement admin bootstrap settings and ensure default roles and admin account

This commit is contained in:
2025-11-09 23:43:13 +01:00
parent 118657491c
commit 24cb3c2f57
5 changed files with 326 additions and 0 deletions

View File

@@ -10,6 +10,17 @@ from typing import Optional
from services.security import JWTSettings
@dataclass(frozen=True, slots=True)
class AdminBootstrapSettings:
"""Default administrator bootstrap configuration."""
email: str
username: str
password: str
roles: tuple[str, ...]
force_reset: bool
@dataclass(frozen=True, slots=True)
class SessionSettings:
"""Cookie and header configuration for session token transport."""
@@ -40,6 +51,11 @@ class Settings:
session_header_name: str = "Authorization"
session_header_prefix: str = "Bearer"
session_allow_header_fallback: bool = True
admin_email: str = "admin@calminer.local"
admin_username: str = "admin"
admin_password: str = "ChangeMe123!"
admin_roles: tuple[str, ...] = ("admin",)
admin_force_reset: bool = False
@classmethod
def from_environment(cls) -> "Settings":
@@ -74,6 +90,21 @@ class Settings:
session_allow_header_fallback=cls._bool_from_env(
"CALMINER_SESSION_ALLOW_HEADER_FALLBACK", True
),
admin_email=os.getenv(
"CALMINER_SEED_ADMIN_EMAIL", "admin@calminer.local"
),
admin_username=os.getenv(
"CALMINER_SEED_ADMIN_USERNAME", "admin"
),
admin_password=os.getenv(
"CALMINER_SEED_ADMIN_PASSWORD", "ChangeMe123!"
),
admin_roles=cls._parse_admin_roles(
os.getenv("CALMINER_SEED_ADMIN_ROLES")
),
admin_force_reset=cls._bool_from_env(
"CALMINER_SEED_FORCE", False
),
)
@staticmethod
@@ -98,6 +129,22 @@ class Settings:
return False
return default
@staticmethod
def _parse_admin_roles(raw_value: str | None) -> tuple[str, ...]:
if not raw_value:
return ("admin",)
parts = [segment.strip()
for segment in raw_value.split(",") if segment.strip()]
if "admin" not in parts:
parts.insert(0, "admin")
seen: set[str] = set()
ordered: list[str] = []
for role_name in parts:
if role_name not in seen:
ordered.append(role_name)
seen.add(role_name)
return tuple(ordered)
def jwt_settings(self) -> JWTSettings:
"""Build runtime JWT settings compatible with token helpers."""
@@ -122,6 +169,17 @@ class Settings:
allow_header_fallback=self.session_allow_header_fallback,
)
def admin_bootstrap_settings(self) -> AdminBootstrapSettings:
"""Return configured admin bootstrap settings."""
return AdminBootstrapSettings(
email=self.admin_email,
username=self.admin_username,
password=self.admin_password,
roles=self.admin_roles,
force_reset=self.admin_force_reset,
)
@lru_cache(maxsize=1)
def get_settings() -> Settings: