fix(middleware): prevent premature redirect to /login during loading

Users were incorrectly redirected to /login during the initial loading phase
before the loading was actually complete. Added loading_started and
loading_complete flags to properly track the initialization state so
the setup redirect middleware knows when it's safe to redirect.
This commit is contained in:
2026-06-07 20:23:11 +02:00
parent b800158648
commit de250bdd37
5 changed files with 43 additions and 7 deletions

View File

@@ -108,6 +108,7 @@ The middleware checks the current state and redirects accordingly:
| Flag | Purpose |
|------|---------|
| `setup_complete` | Initial configuration was saved |
| `loading_started` | Loading phase has been initiated (redirected to /loading) |
| `unresolved_completed` | User clicked "Done" on unresolved page |
| `loading_complete` | Series scan + initial loading finished |
| `nfo_scan_complete` | Final NFO scan finished |

View File

@@ -1,3 +1,7 @@
API key : 299ae8f630a31bda814263c551361448
9bc3e547caff878615cbdba2cc421d37
/setup
SeriesApp initialized for directory:

View File

@@ -117,6 +117,10 @@ async def setup_auth(req: SetupRequest):
# Store master password hash in config's other field
config.other['master_password_hash'] = password_hash
# Mark that loading has been initiated (used by middleware to prevent
# premature redirect to /login after setup)
config.other['loading_started'] = True
# Store anime directory in config's other field if provided
anime_directory = None
if req.anime_directory:

View File

@@ -118,6 +118,20 @@ class SetupRedirectMiddleware(BaseHTTPMiddleware):
return bool(other.get('unresolved_completed', False))
except Exception:
return False
def _is_loading_complete(self) -> bool:
"""Check if initial loading has completed.
Returns:
True if loading is complete, False otherwise
"""
try:
config_service = get_config_service()
config = config_service.load_config()
other = config.other or {}
return bool(other.get('loading_complete', False))
except Exception:
return False
async def dispatch(
self, request: Request, call_next: Callable
@@ -149,14 +163,17 @@ class SetupRedirectMiddleware(BaseHTTPMiddleware):
# 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)
# Only redirect if loading has actually completed
# If loading_started=True but loading_complete=False, user should stay
# on loading page to see progress
if self._is_loading_complete():
return RedirectResponse(url="/login", status_code=302)
# Otherwise, allow access to loading page (loading in progress)
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
# No phase specified and loading is complete
if self._is_loading_complete():
return RedirectResponse(url="/login", status_code=302)
# phase=nfo is always allowed - it triggers the NFO scan phase
# Skip setup check for exempt paths
if self._is_path_exempt(path):

View File

@@ -383,6 +383,16 @@ async def perform_initial_setup(progress_service=None):
# Mark the initial scan as completed
await _mark_initial_scan_completed()
# Mark loading as complete in config (used by middleware to allow redirect to /login)
try:
from src.server.services.config_service import get_config_service
config_svc = get_config_service()
init_config = config_svc.load_config()
init_config.other['loading_complete'] = True
config_svc.save_config(init_config, create_backup=False)
except Exception as e:
logger.warning("Failed to save loading_complete flag: %s", e)
# Load series into memory from database
await _load_series_into_memory(progress_service)