feat(setup): separate NFO scan into dedicated phase

- Add /nfo-scan-phase endpoint to trigger NFO scan independently
- Move NFO scan out of initial setup into separate post-unresolved phase
- Add phase query param handling for /loading page (?phase=initial, ?phase=nfo)
- Update setup redirect middleware to handle phase-based redirects
- Update auth setup to pass phase=initial to loading page
This commit is contained in:
2026-06-07 17:37:32 +02:00
parent cf00c9f7c5
commit 07c311c1cd
7 changed files with 350 additions and 71 deletions

View File

@@ -132,24 +132,31 @@ class SetupRedirectMiddleware(BaseHTTPMiddleware):
Either a redirect to /setup or the normal response
"""
path = request.url.path
query_params = request.query_params
# Check if trying to access setup or loading page after completion
if path in ("/setup", "/loading", "/setup/unresolved"):
if not self._needs_setup():
if path == "/setup":
# Redirect to loading if initialization is in progress
# Otherwise redirect to login
# Redirect to login if setup is already complete
return RedirectResponse(url="/login", status_code=302)
elif path == "/setup/unresolved":
# Check if unresolved phase is already completed
if self._is_unresolved_completed():
# Redirect to loading - unresolved phase already done
return RedirectResponse(url="/loading", status_code=302)
return RedirectResponse(url="/loading?phase=nfo", status_code=302)
elif path == "/loading":
# Always allow access to loading page - it handles its own
# redirect flow via WebSocket events (initialization_complete
# event triggers redirect to /setup/unresolved)
pass
# Handle phase query parameter
phase = query_params.get("phase")
if phase == "initial":
# phase=initial should not be accessed after setup is complete
# Redirect to login
return RedirectResponse(url="/login", status_code=302)
elif not phase:
# No phase specified and setup is complete
# Redirect to login since user should be further in the flow
return RedirectResponse(url="/login", status_code=302)
# phase=nfo is allowed - it triggers the NFO scan phase
# Skip setup check for exempt paths
if self._is_path_exempt(path):