feat(middleware): harden routing with fail-closed policy, custom subdomain management, and perf fixes
- Fix IPv6 host parsing with _strip_port() utility - Remove dangerous StorePlatform→Store.subdomain silent fallback - Close storefront gate bypass when frontend_type is None - Add custom subdomain management UI and API for stores - Add domain health diagnostic tool - Convert db.add() in loops to db.add_all() (24 PERF-006 fixes) - Add tests for all new functionality (18 subdomain service tests) - Add .github templates for validator compliance Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
126
tests/unit/middleware/test_storefront_gate_bypass.py
Normal file
126
tests/unit/middleware/test_storefront_gate_bypass.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# tests/unit/middleware/test_storefront_gate_bypass.py
|
||||
"""
|
||||
Unit tests for the storefront gate bypass safety net.
|
||||
|
||||
Ensures that when frontend_type is None (upstream middleware failed),
|
||||
storefront paths are BLOCKED rather than passed through. Non-storefront
|
||||
paths with None frontend_type should pass through unchanged.
|
||||
"""
|
||||
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
from fastapi import Request
|
||||
from starlette.responses import JSONResponse
|
||||
|
||||
from middleware.storefront_access import (
|
||||
StorefrontAccessMiddleware,
|
||||
_looks_like_storefront,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.middleware
|
||||
class TestLooksLikeStorefront:
|
||||
"""Test the _looks_like_storefront helper."""
|
||||
|
||||
def test_storefront_page_path(self):
|
||||
assert _looks_like_storefront("/storefront/products") is True
|
||||
|
||||
def test_storefront_api_path(self):
|
||||
assert _looks_like_storefront("/api/v1/storefront/cart") is True
|
||||
|
||||
def test_admin_path(self):
|
||||
assert _looks_like_storefront("/admin/dashboard") is False
|
||||
|
||||
def test_static_path(self):
|
||||
assert _looks_like_storefront("/static/css/style.css") is False
|
||||
|
||||
def test_store_path(self):
|
||||
assert _looks_like_storefront("/store/ACME/login") is False
|
||||
|
||||
def test_root_path(self):
|
||||
assert _looks_like_storefront("/") is False
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
@pytest.mark.middleware
|
||||
class TestStorefrontGateBypass:
|
||||
"""Test that None frontend_type can't bypass the storefront gate."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_none_frontend_type_storefront_page_blocked(self):
|
||||
"""frontend_type=None + /storefront/ path → blocked with HTML 403."""
|
||||
middleware = StorefrontAccessMiddleware(app=None)
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/storefront/products")
|
||||
request.state = Mock()
|
||||
request.state.frontend_type = None
|
||||
request.state.store = None
|
||||
request.state.language = "en"
|
||||
request.state.theme = None
|
||||
call_next = AsyncMock()
|
||||
|
||||
with patch("app.templates_config.templates") as mock_templates:
|
||||
mock_templates.TemplateResponse.return_value = Mock(status_code=403)
|
||||
await middleware.dispatch(request, call_next)
|
||||
|
||||
call_next.assert_not_called()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_none_frontend_type_storefront_api_blocked(self):
|
||||
"""frontend_type=None + /api/v1/storefront/ path → JSON 403."""
|
||||
middleware = StorefrontAccessMiddleware(app=None)
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/api/v1/storefront/cart")
|
||||
request.state = Mock()
|
||||
request.state.frontend_type = None
|
||||
call_next = AsyncMock()
|
||||
|
||||
response = await middleware.dispatch(request, call_next)
|
||||
|
||||
call_next.assert_not_called()
|
||||
assert isinstance(response, JSONResponse)
|
||||
assert response.status_code == 403
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_none_frontend_type_admin_passes_through(self):
|
||||
"""frontend_type=None + /admin/ path → passes through (not storefront)."""
|
||||
middleware = StorefrontAccessMiddleware(app=None)
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/admin/dashboard")
|
||||
request.state = Mock()
|
||||
request.state.frontend_type = None
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
|
||||
await middleware.dispatch(request, call_next)
|
||||
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_none_frontend_type_static_passes_through(self):
|
||||
"""frontend_type=None + /static/ path → passes through."""
|
||||
middleware = StorefrontAccessMiddleware(app=None)
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/static/css/style.css")
|
||||
request.state = Mock()
|
||||
request.state.frontend_type = None
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
|
||||
await middleware.dispatch(request, call_next)
|
||||
|
||||
call_next.assert_called_once_with(request)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_none_frontend_type_root_passes_through(self):
|
||||
"""frontend_type=None + / path → passes through."""
|
||||
middleware = StorefrontAccessMiddleware(app=None)
|
||||
request = Mock(spec=Request)
|
||||
request.url = Mock(path="/")
|
||||
request.state = Mock()
|
||||
request.state.frontend_type = None
|
||||
call_next = AsyncMock(return_value=Mock())
|
||||
|
||||
await middleware.dispatch(request, call_next)
|
||||
|
||||
call_next.assert_called_once_with(request)
|
||||
Reference in New Issue
Block a user