feat: add SQL query tool, platform debug, loyalty settings, and multi-module improvements
Some checks failed
Some checks failed
- Add admin SQL query tool with saved queries, schema explorer presets, and collapsible category sections (dev_tools module) - Add platform debug tool for admin diagnostics - Add loyalty settings page with owner-only access control - Fix loyalty settings owner check (use currentUser instead of window.__userData) - Replace HTTPException with AuthorizationException in loyalty routes - Expand loyalty module with PIN service, Apple Wallet, program management - Improve store login with platform detection and multi-platform support - Update billing feature gates and subscription services - Add store platform sync improvements and remove is_primary column - Add unit tests for loyalty (PIN, points, stamps, program services) - Update i18n translations across dev_tools locales Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,7 @@ class StoreLoginResponse(BaseModel):
|
||||
user: dict
|
||||
store: dict
|
||||
store_role: str
|
||||
platform_code: str | None = None
|
||||
|
||||
|
||||
@store_auth_router.post("/login", response_model=StoreLoginResponse)
|
||||
@@ -116,27 +117,48 @@ def store_login(
|
||||
f"for store {store.store_code} as {store_role}"
|
||||
)
|
||||
|
||||
# Resolve platform from the store's primary platform link.
|
||||
# Middleware-detected platform is unreliable for API paths on localhost
|
||||
# (e.g., /api/v1/store/auth/login defaults to "main" instead of the store's platform).
|
||||
platform_id = None
|
||||
platform_code = None
|
||||
if store:
|
||||
from app.modules.core.services.menu_service import menu_service
|
||||
from app.modules.tenancy.services.platform_service import platform_service
|
||||
# Resolve platform — prefer explicit sources, fall back to store's primary platform
|
||||
from app.modules.tenancy.services.platform_service import platform_service
|
||||
|
||||
primary_pid = menu_service.get_store_primary_platform_id(db, store.id)
|
||||
platform = None
|
||||
|
||||
# Source 1: middleware-detected platform (production domain-based)
|
||||
mw_platform = get_current_platform(request)
|
||||
if mw_platform and mw_platform.code != "main":
|
||||
platform = mw_platform
|
||||
|
||||
# Source 2: platform_code from login body (dev mode — JS sends platform from page context)
|
||||
if platform is None and user_credentials.platform_code:
|
||||
platform = platform_service.get_platform_by_code_optional(
|
||||
db, user_credentials.platform_code
|
||||
)
|
||||
if not platform:
|
||||
raise InvalidCredentialsException(
|
||||
f"Unknown platform: {user_credentials.platform_code}"
|
||||
)
|
||||
|
||||
# Source 3: fall back to store's primary platform
|
||||
if platform is None:
|
||||
primary_pid = platform_service.get_first_active_platform_id_for_store(
|
||||
db, store.id
|
||||
)
|
||||
if primary_pid:
|
||||
plat = platform_service.get_platform_by_id(db, primary_pid)
|
||||
if plat:
|
||||
platform_id = plat.id
|
||||
platform_code = plat.code
|
||||
platform = platform_service.get_platform_by_id(db, primary_pid)
|
||||
|
||||
if platform_id is None:
|
||||
# Fallback to middleware-detected platform
|
||||
platform = get_current_platform(request)
|
||||
platform_id = platform.id if platform else None
|
||||
platform_code = platform.code if platform else None
|
||||
# Verify store-platform link if platform was resolved explicitly (source 1 or 2)
|
||||
if platform is not None and (
|
||||
mw_platform or user_credentials.platform_code
|
||||
):
|
||||
link = platform_service.get_store_platform_entry(
|
||||
db, store.id, platform.id
|
||||
)
|
||||
if not link or not link.is_active:
|
||||
raise InvalidCredentialsException(
|
||||
f"Store {store.store_code} is not available on platform {platform.code}"
|
||||
)
|
||||
|
||||
platform_id = platform.id if platform else None
|
||||
platform_code = platform.code if platform else None
|
||||
|
||||
# Create store-scoped access token with store information
|
||||
token_data = auth_service.auth_manager.create_access_token(
|
||||
@@ -186,6 +208,7 @@ def store_login(
|
||||
"is_verified": store.is_verified,
|
||||
},
|
||||
store_role=store_role,
|
||||
platform_code=platform_code,
|
||||
)
|
||||
|
||||
|
||||
@@ -226,6 +249,7 @@ def get_current_store_user(
|
||||
email=user.email,
|
||||
role=user.role,
|
||||
is_active=user.is_active,
|
||||
platform_code=user.token_platform_code,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user