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:
@@ -177,6 +177,52 @@ Injects: request.state.store = <Store object>
|
||||
|
||||
**Why it's needed**: Each store storefront can have custom branding
|
||||
|
||||
## Login Platform Resolution
|
||||
|
||||
The store login endpoint (`POST /api/v1/store/auth/login`) resolves the platform through a 3-source priority chain. This is necessary because on localhost the API path carries no platform information (unlike production where the domain does).
|
||||
|
||||
### Source Priority
|
||||
|
||||
```
|
||||
Source 1: Middleware (request.state.platform)
|
||||
↓ if null or "main"
|
||||
Source 2: Request body (platform_code field)
|
||||
↓ if null
|
||||
Source 3: Fallback (store's first active platform)
|
||||
```
|
||||
|
||||
### Resolution by URL Pattern
|
||||
|
||||
| Environment | Login Page URL | API Request Host | Source 1 | Source 2 | Source 3 |
|
||||
|-------------|---------------|-----------------|----------|----------|----------|
|
||||
| **Dev path-based** | `/platforms/loyalty/store/ACME/login` | `localhost:8000` | null (localhost → "main" → skipped) | `"loyalty"` from JS | — |
|
||||
| **Dev no prefix** | `/store/ACME/login` (after logout) | `localhost:8000` | null | `"loyalty"` from localStorage | — |
|
||||
| **Dev fresh browser** | `/store/ACME/login` (first visit) | `localhost:8000` | null | null | First active platform for store |
|
||||
| **Prod domain** | `omsflow.lu/store/ACME/login` | `omsflow.lu` | `"oms"` (domain lookup) | — | — |
|
||||
| **Prod subdomain** | `acme.omsflow.lu/store/login` | `acme.omsflow.lu` | `"oms"` (root domain lookup) | — | — |
|
||||
| **Prod custom domain** | `wizatech.shop/store/login` | `wizatech.shop` | `"oms"` (StoreDomain lookup) | — | — |
|
||||
|
||||
### Client-Side Platform Persistence
|
||||
|
||||
On successful login, `login.js` saves the platform to localStorage:
|
||||
```
|
||||
localStorage.setItem('store_platform', response.platform_code)
|
||||
```
|
||||
|
||||
On the login page, the platform_code sent in the body uses this priority:
|
||||
```
|
||||
window.STORE_PLATFORM_CODE || localStorage.getItem('store_platform') || null
|
||||
```
|
||||
|
||||
- `window.STORE_PLATFORM_CODE` is set by the server template when the URL contains `/platforms/{code}/`
|
||||
- `localStorage.store_platform` persists across logout (intentionally not cleared)
|
||||
- This ensures the logout → login cycle preserves platform context in dev mode
|
||||
|
||||
### Diagnostic Tools
|
||||
|
||||
- **Backend**: `/admin/platform-debug` — traces the full resolution pipeline for arbitrary host/path combos
|
||||
- **Frontend**: `Ctrl+Shift+P` on any store page (localhost only) — shows JWT platform, localStorage, window globals, and consistency checks
|
||||
|
||||
## Naming Conventions
|
||||
|
||||
### Middleware File Organization
|
||||
|
||||
Reference in New Issue
Block a user