refactor: centralize frontend detection with FrontendDetector
Major architecture change to unify frontend detection: ## Problem Solved - Eliminated code duplication across 3 middleware files - Fixed incomplete path detection (now detects /api/v1/admin/*) - Unified on FrontendType enum (deprecates RequestContext) - Added request.state.frontend_type for all requests ## New Components - app/core/frontend_detector.py: Centralized FrontendDetector class - middleware/frontend_type.py: FrontendTypeMiddleware (replaces ContextMiddleware) - docs/architecture/frontend-detection.md: Complete architecture documentation ## Changes - main.py: Use FrontendTypeMiddleware instead of ContextMiddleware - middleware/context.py: Deprecated (kept for backwards compatibility) - middleware/platform_context.py: Use FrontendDetector.is_admin() - middleware/vendor_context.py: Use FrontendDetector.is_admin() - middleware/language.py: Use FrontendType instead of context_value - app/exceptions/handler.py: Use FrontendType.STOREFRONT - app/exceptions/error_renderer.py: Use FrontendType - Customer routes: Cookie path changed from /shop to /storefront ## Documentation - docs/architecture/frontend-detection.md: New comprehensive docs - docs/architecture/middleware.md: Updated for new system - docs/architecture/request-flow.md: Updated for FrontendType - docs/backend/middleware-reference.md: Updated API reference ## Tests - tests/unit/core/test_frontend_detector.py: 37 new tests - tests/unit/middleware/test_frontend_type.py: 11 new tests - tests/unit/middleware/test_context.py: Updated for compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,7 +16,8 @@ from fastapi import HTTPException, Request
|
||||
from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
|
||||
from middleware.context import RequestContext, get_request_context
|
||||
from app.modules.enums import FrontendType
|
||||
from middleware.frontend_type import get_frontend_type
|
||||
|
||||
from .base import WizamartException
|
||||
from .error_renderer import ErrorPageRenderer
|
||||
@@ -382,17 +383,17 @@ def _is_html_page_request(request: Request) -> bool:
|
||||
|
||||
def _redirect_to_login(request: Request) -> RedirectResponse:
|
||||
"""
|
||||
Redirect to appropriate login page based on request context.
|
||||
Redirect to appropriate login page based on request frontend type.
|
||||
|
||||
Uses context detection to determine admin vs vendor vs shop login.
|
||||
Uses FrontendType detection to determine admin vs vendor vs storefront login.
|
||||
Properly handles multi-access routing (domain, subdomain, path-based).
|
||||
"""
|
||||
context_type = get_request_context(request)
|
||||
frontend_type = get_frontend_type(request)
|
||||
|
||||
if context_type == RequestContext.ADMIN:
|
||||
if frontend_type == FrontendType.ADMIN:
|
||||
logger.debug("Redirecting to /admin/login")
|
||||
return RedirectResponse(url="/admin/login", status_code=302)
|
||||
if context_type == RequestContext.VENDOR_DASHBOARD:
|
||||
if frontend_type == FrontendType.VENDOR:
|
||||
# Extract vendor code from the request path
|
||||
# Path format: /vendor/{vendor_code}/...
|
||||
path_parts = request.url.path.split("/")
|
||||
@@ -417,8 +418,8 @@ def _redirect_to_login(request: Request) -> RedirectResponse:
|
||||
|
||||
logger.debug(f"Redirecting to {login_url}")
|
||||
return RedirectResponse(url=login_url, status_code=302)
|
||||
if context_type == RequestContext.SHOP:
|
||||
# For shop context, redirect to shop login (customer login)
|
||||
if frontend_type == FrontendType.STOREFRONT:
|
||||
# For storefront context, redirect to storefront login (customer login)
|
||||
# Calculate base_url for proper routing (supports domain, subdomain, and path-based access)
|
||||
vendor = getattr(request.state, "vendor", None)
|
||||
vendor_context = getattr(request.state, "vendor_context", None)
|
||||
@@ -437,11 +438,11 @@ def _redirect_to_login(request: Request) -> RedirectResponse:
|
||||
)
|
||||
base_url = f"{full_prefix}{vendor.subdomain}/"
|
||||
|
||||
login_url = f"{base_url}shop/account/login"
|
||||
login_url = f"{base_url}storefront/account/login"
|
||||
logger.debug(f"Redirecting to {login_url}")
|
||||
return RedirectResponse(url=login_url, status_code=302)
|
||||
# Fallback to root for unknown contexts
|
||||
logger.debug("Unknown context, redirecting to /")
|
||||
# Fallback to root for unknown contexts (PLATFORM)
|
||||
logger.debug("Platform context, redirecting to /")
|
||||
return RedirectResponse(url="/", status_code=302)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user