feat(dev_tools): add tenant isolation audit to diagnostics page
Add a new "Tenant Isolation" diagnostic tool that scans all stores and reports where configuration values come from — flagging silent inheritance, missing data, and potential data commingling. Also fix merchant dashboard and onboarding integration tests that were missing require_platform dependency override. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,11 @@ from datetime import UTC, datetime, timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from app.api.deps import get_current_merchant_api, get_merchant_for_current_user
|
||||
from app.api.deps import (
|
||||
get_current_merchant_api,
|
||||
get_merchant_for_current_user,
|
||||
require_platform,
|
||||
)
|
||||
from app.modules.billing.models import (
|
||||
MerchantSubscription,
|
||||
SubscriptionStatus,
|
||||
@@ -177,7 +181,7 @@ def dash_subscription(db, dash_merchant, dash_platform):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def dash_auth(dash_owner, dash_merchant):
|
||||
def dash_auth(dash_owner, dash_merchant, dash_platform):
|
||||
"""Override auth dependencies for dashboard merchant."""
|
||||
user_context = UserContext(
|
||||
id=dash_owner.id,
|
||||
@@ -193,11 +197,16 @@ def dash_auth(dash_owner, dash_merchant):
|
||||
def _override_user():
|
||||
return user_context
|
||||
|
||||
def _override_platform():
|
||||
return dash_platform
|
||||
|
||||
app.dependency_overrides[get_merchant_for_current_user] = _override_merchant
|
||||
app.dependency_overrides[get_current_merchant_api] = _override_user
|
||||
app.dependency_overrides[require_platform] = _override_platform
|
||||
yield {"Authorization": "Bearer fake-token"}
|
||||
app.dependency_overrides.pop(get_merchant_for_current_user, None)
|
||||
app.dependency_overrides.pop(get_current_merchant_api, None)
|
||||
app.dependency_overrides.pop(require_platform, None)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -232,10 +241,14 @@ class TestMerchantDashboardStats:
|
||||
assert data["total_customers"] == 0
|
||||
assert data["team_members"] == 0
|
||||
|
||||
def test_requires_auth(self, client):
|
||||
def test_requires_auth(self, client, dash_platform):
|
||||
"""Returns 401 without auth."""
|
||||
# Remove any overrides
|
||||
# Remove auth overrides but keep platform to isolate auth check
|
||||
app.dependency_overrides.pop(get_merchant_for_current_user, None)
|
||||
app.dependency_overrides.pop(get_current_merchant_api, None)
|
||||
response = client.get(f"{BASE}/dashboard/stats")
|
||||
assert response.status_code == 401
|
||||
app.dependency_overrides[require_platform] = lambda: dash_platform
|
||||
try:
|
||||
response = client.get(f"{BASE}/dashboard/stats")
|
||||
assert response.status_code == 401
|
||||
finally:
|
||||
app.dependency_overrides.pop(require_platform, None)
|
||||
|
||||
@@ -15,7 +15,7 @@ import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from app.api.deps import get_current_store_api
|
||||
from app.api.deps import get_current_store_api, require_platform
|
||||
from app.modules.tenancy.models import Merchant, Platform, Store, User
|
||||
from app.modules.tenancy.models.store_platform import StorePlatform
|
||||
from app.modules.tenancy.schemas.auth import UserContext
|
||||
@@ -108,7 +108,7 @@ def onb_store_platform(db, onb_store, onb_platform):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def onb_auth(onb_owner, onb_store):
|
||||
def onb_auth(onb_owner, onb_store, onb_platform):
|
||||
"""Override auth dependency for store API auth."""
|
||||
user_context = UserContext(
|
||||
id=onb_owner.id,
|
||||
@@ -123,9 +123,14 @@ def onb_auth(onb_owner, onb_store):
|
||||
def _override():
|
||||
return user_context
|
||||
|
||||
def _override_platform():
|
||||
return onb_platform
|
||||
|
||||
app.dependency_overrides[get_current_store_api] = _override
|
||||
app.dependency_overrides[require_platform] = _override_platform
|
||||
yield {"Authorization": "Bearer fake-token"}
|
||||
app.dependency_overrides.pop(get_current_store_api, None)
|
||||
app.dependency_overrides.pop(require_platform, None)
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -206,10 +211,14 @@ class TestOnboardingEndpoint:
|
||||
if "/store/" in step["route"]:
|
||||
assert onb_store.store_code in step["route"]
|
||||
|
||||
def test_requires_auth(self, client):
|
||||
def test_requires_auth(self, client, onb_platform):
|
||||
"""Returns 401 without authentication."""
|
||||
app.dependency_overrides.pop(get_current_store_api, None)
|
||||
response = client.get(
|
||||
"/api/v1/store/dashboard/onboarding",
|
||||
)
|
||||
assert response.status_code == 401
|
||||
app.dependency_overrides[require_platform] = lambda: onb_platform
|
||||
try:
|
||||
response = client.get(
|
||||
"/api/v1/store/dashboard/onboarding",
|
||||
)
|
||||
assert response.status_code == 401
|
||||
finally:
|
||||
app.dependency_overrides.pop(require_platform, None)
|
||||
|
||||
Reference in New Issue
Block a user