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:
@@ -108,6 +108,7 @@ The middleware checks the current state and redirects accordingly:
|
|||||||
| Flag | Purpose |
|
| Flag | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `setup_complete` | Initial configuration was saved |
|
| `setup_complete` | Initial configuration was saved |
|
||||||
|
| `loading_started` | Loading phase has been initiated (redirected to /loading) |
|
||||||
| `unresolved_completed` | User clicked "Done" on unresolved page |
|
| `unresolved_completed` | User clicked "Done" on unresolved page |
|
||||||
| `loading_complete` | Series scan + initial loading finished |
|
| `loading_complete` | Series scan + initial loading finished |
|
||||||
| `nfo_scan_complete` | Final NFO scan finished |
|
| `nfo_scan_complete` | Final NFO scan finished |
|
||||||
|
|||||||
4
Docs/key
4
Docs/key
@@ -1,3 +1,7 @@
|
|||||||
API key : 299ae8f630a31bda814263c551361448
|
API key : 299ae8f630a31bda814263c551361448
|
||||||
9bc3e547caff878615cbdba2cc421d37
|
9bc3e547caff878615cbdba2cc421d37
|
||||||
|
|
||||||
|
/setup
|
||||||
|
|
||||||
|
|
||||||
|
SeriesApp initialized for directory:
|
||||||
@@ -117,6 +117,10 @@ async def setup_auth(req: SetupRequest):
|
|||||||
# Store master password hash in config's other field
|
# Store master password hash in config's other field
|
||||||
config.other['master_password_hash'] = password_hash
|
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
|
# Store anime directory in config's other field if provided
|
||||||
anime_directory = None
|
anime_directory = None
|
||||||
if req.anime_directory:
|
if req.anime_directory:
|
||||||
|
|||||||
@@ -118,6 +118,20 @@ class SetupRedirectMiddleware(BaseHTTPMiddleware):
|
|||||||
return bool(other.get('unresolved_completed', False))
|
return bool(other.get('unresolved_completed', False))
|
||||||
except Exception:
|
except Exception:
|
||||||
return False
|
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(
|
async def dispatch(
|
||||||
self, request: Request, call_next: Callable
|
self, request: Request, call_next: Callable
|
||||||
@@ -149,14 +163,17 @@ class SetupRedirectMiddleware(BaseHTTPMiddleware):
|
|||||||
# Handle phase query parameter
|
# Handle phase query parameter
|
||||||
phase = query_params.get("phase")
|
phase = query_params.get("phase")
|
||||||
if phase == "initial":
|
if phase == "initial":
|
||||||
# phase=initial should not be accessed after setup is complete
|
# Only redirect if loading has actually completed
|
||||||
# Redirect to login
|
# If loading_started=True but loading_complete=False, user should stay
|
||||||
return RedirectResponse(url="/login", status_code=302)
|
# 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:
|
elif not phase:
|
||||||
# No phase specified and setup is complete
|
# No phase specified and loading is complete
|
||||||
# Redirect to login since user should be further in the flow
|
if self._is_loading_complete():
|
||||||
return RedirectResponse(url="/login", status_code=302)
|
return RedirectResponse(url="/login", status_code=302)
|
||||||
# phase=nfo is allowed - it triggers the NFO scan phase
|
# phase=nfo is always allowed - it triggers the NFO scan phase
|
||||||
|
|
||||||
# Skip setup check for exempt paths
|
# Skip setup check for exempt paths
|
||||||
if self._is_path_exempt(path):
|
if self._is_path_exempt(path):
|
||||||
|
|||||||
@@ -383,6 +383,16 @@ async def perform_initial_setup(progress_service=None):
|
|||||||
# Mark the initial scan as completed
|
# Mark the initial scan as completed
|
||||||
await _mark_initial_scan_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
|
# Load series into memory from database
|
||||||
await _load_series_into_memory(progress_service)
|
await _load_series_into_memory(progress_service)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user