Persist runtime config in app db and seed from env

This commit is contained in:
2026-04-20 15:56:10 +02:00
parent 3f7c9e43d9
commit 179aae264e
21 changed files with 921 additions and 125 deletions
+15 -8
View File
@@ -18,6 +18,7 @@ from app.services.auth import (
revoke_session,
validate_csrf_token,
)
from app.services.config_page import build_config_sections
logger = logging.getLogger(__name__)
templates = Jinja2Templates(directory=str(Path(__file__).resolve().parents[2] / "templates"))
@@ -33,7 +34,7 @@ def login_page(
current_auth: AuthenticatedSession | None = Depends(get_current_auth_session),
) -> Response:
if current_auth is not None:
return RedirectResponse(url="/admin", status_code=status.HTTP_303_SEE_OTHER)
return RedirectResponse(url="/config", status_code=status.HTTP_303_SEE_OTHER)
csrf_token = issue_login_csrf_token()
response = templates.TemplateResponse(
@@ -79,7 +80,7 @@ def login_submit(
)
auth_session, raw_token = create_session(session, user=user, settings=settings)
response = RedirectResponse(url="/admin", status_code=status.HTTP_303_SEE_OTHER)
response = RedirectResponse(url="/config", status_code=status.HTTP_303_SEE_OTHER)
response.delete_cookie(LOGIN_CSRF_COOKIE_NAME, path="/login")
response.set_cookie(
key=settings.auth_session_cookie_name,
@@ -94,7 +95,7 @@ def login_submit(
return response
@router.post("/admin/change-password", response_class=HTMLResponse)
@router.post("/config/change-password", response_class=HTMLResponse)
def change_password_submit(
request: Request,
current_password: str = Form(),
@@ -110,9 +111,10 @@ def change_password_submit(
if not validate_csrf_token(expected=current_auth.session.csrf_token, actual=csrf_token):
logger.warning("Rejected password change attempt due to CSRF validation failure")
return _render_admin_page(
return _render_config_page(
request,
settings=settings,
auth_db_session=session,
current_auth=current_auth,
status_code=status.HTTP_400_BAD_REQUEST,
password_change_error="invalid password change request",
@@ -132,16 +134,17 @@ def change_password_submit(
current_auth.user.username,
exc,
)
return _render_admin_page(
return _render_config_page(
request,
settings=settings,
auth_db_session=session,
current_auth=current_auth,
status_code=status.HTTP_400_BAD_REQUEST,
password_change_error="password change failed",
)
logger.info("Password updated for user '%s'", current_auth.user.username)
return RedirectResponse(url="/admin", status_code=status.HTTP_303_SEE_OTHER)
return RedirectResponse(url="/config", status_code=status.HTTP_303_SEE_OTHER)
@router.post("/logout")
@@ -200,17 +203,18 @@ def _set_login_csrf_cookie(response: HTMLResponse, *, settings: Settings, token:
)
def _render_admin_page(
def _render_config_page(
request: Request,
*,
settings: Settings,
auth_db_session: Session,
current_auth: AuthenticatedSession,
status_code: int,
password_change_error: str | None,
) -> HTMLResponse:
return templates.TemplateResponse(
request,
"admin.html",
"config.html",
{
"app_name": settings.app_name,
"app_env": settings.app_env,
@@ -218,6 +222,9 @@ def _render_admin_page(
"csrf_token": current_auth.session.csrf_token,
"force_password_change": current_auth.user.force_password_change,
"password_change_error": password_change_error,
"config_error": None,
"config_saved": False,
"config_sections": build_config_sections(auth_db_session, settings),
},
status_code=status_code,
)