fix: storefront login 403, cookie path, double-storefront URLs, and auth redirects
- Extract store/platform context from Referer header for storefront API requests
(StoreContextMiddleware and PlatformContextMiddleware) so login POST works in
dev mode where API paths lack /platforms/{code}/ prefix
- Set customer token cookie path to "/" for cross-route compatibility
- Fix double storefront in URLs: replace {{ base_url }}storefront/ with {{ base_url }}
across all 24 storefront templates
- Fix auth error redirect to include platform prefix and use store_code
- Update seed script to output correct storefront login URLs
- Add 20 new unit tests covering all fixes; fix 9 pre-existing test failures
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -319,10 +319,12 @@ class PlatformContextMiddleware:
|
||||
|
||||
path = scope["path"]
|
||||
host = ""
|
||||
referer = ""
|
||||
for header_name, header_value in scope.get("headers", []):
|
||||
if header_name == b"host":
|
||||
host = header_value.decode("utf-8")
|
||||
break
|
||||
elif header_name == b"referer":
|
||||
referer = header_value.decode("utf-8")
|
||||
|
||||
# Skip for static files
|
||||
if self._is_static_file(path):
|
||||
@@ -354,6 +356,23 @@ class PlatformContextMiddleware:
|
||||
# Detect platform context
|
||||
platform_context = self._detect_platform_context(path, host)
|
||||
|
||||
# For storefront API requests on localhost, the path doesn't contain
|
||||
# /platforms/{code}/, so extract platform from the Referer header instead.
|
||||
# e.g., Referer: http://localhost:8000/platforms/loyalty/storefront/FASHIONHUB/...
|
||||
host_without_port = host.split(":")[0] if ":" in host else host
|
||||
if (
|
||||
host_without_port in _LOCAL_HOSTS
|
||||
and path.startswith("/api/v1/storefront/")
|
||||
and referer
|
||||
and platform_context
|
||||
and platform_context.get("detection_method") == "default"
|
||||
):
|
||||
referer_platform = self._extract_platform_from_referer(referer)
|
||||
if referer_platform:
|
||||
# Keep the original API path — don't rewrite to the Referer's path
|
||||
referer_platform["clean_path"] = path
|
||||
platform_context = referer_platform
|
||||
|
||||
if platform_context:
|
||||
db_gen = get_db()
|
||||
db = next(db_gen)
|
||||
@@ -488,6 +507,43 @@ class PlatformContextMiddleware:
|
||||
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _extract_platform_from_referer(referer: str) -> dict | None:
|
||||
"""
|
||||
Extract platform context from Referer header.
|
||||
|
||||
Used for storefront API requests on localhost where the API path
|
||||
doesn't contain /platforms/{code}/ but the Referer does.
|
||||
|
||||
e.g., Referer: http://localhost:8000/platforms/loyalty/storefront/FASHIONHUB/...
|
||||
→ platform_code = "loyalty"
|
||||
"""
|
||||
try:
|
||||
from urllib.parse import urlparse
|
||||
|
||||
parsed = urlparse(referer)
|
||||
referer_path = parsed.path or ""
|
||||
|
||||
if referer_path.startswith("/platforms/"):
|
||||
path_after = referer_path[11:] # Remove "/platforms/"
|
||||
parts = path_after.split("/", 1)
|
||||
platform_code = parts[0].lower()
|
||||
if platform_code:
|
||||
logger.debug(
|
||||
f"[PLATFORM] Extracted platform from Referer: {platform_code}"
|
||||
)
|
||||
return {
|
||||
"path_prefix": platform_code,
|
||||
"detection_method": "path",
|
||||
"host": parsed.hostname or "",
|
||||
"original_path": referer_path,
|
||||
"clean_path": "/" + parts[1] if len(parts) > 1 and parts[1] else "/",
|
||||
}
|
||||
except Exception as e:
|
||||
logger.warning(f"[PLATFORM] Failed to extract platform from Referer: {e}")
|
||||
|
||||
return None
|
||||
|
||||
def _is_static_file(self, path: str) -> bool:
|
||||
"""Check if path is for static files."""
|
||||
path_lower = path.lower()
|
||||
|
||||
Reference in New Issue
Block a user