docs: add consolidated dev URL reference and migrate /shop to /storefront
Some checks failed
Some checks failed
- Add Development URL Quick Reference section to url-routing overview with all login URLs, entry points, and full examples - Replace /shop/ path segments with /storefront/ across 50 docs files - Update file references: shop_pages.py → storefront_pages.py, templates/shop/ → templates/storefront/, api/v1/shop/ → api/v1/storefront/ - Preserve domain references (orion.shop) and /store/ staff dashboard paths - Archive docs left unchanged (historical) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,11 +5,11 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the implementation of customer authentication for the shop frontend, including login, registration, and account management pages. This work creates a complete separation between customer authentication and admin/store authentication systems.
|
||||
This document describes the implementation of customer authentication for the storefront frontend, including login, registration, and account management pages. This work creates a complete separation between customer authentication and admin/store authentication systems.
|
||||
|
||||
## Problem Statement
|
||||
|
||||
The shop frontend needed proper authentication pages (login, registration, forgot password) and a working customer authentication system. The initial implementation had several issues:
|
||||
The storefront frontend needed proper authentication pages (login, registration, forgot password) and a working customer authentication system. The initial implementation had several issues:
|
||||
|
||||
1. No styled authentication pages for customers
|
||||
2. Customer authentication was incorrectly trying to use the User model (admins/stores)
|
||||
@@ -27,7 +27,7 @@ The shop frontend needed proper authentication pages (login, registration, forgo
|
||||
- Have `username` field
|
||||
- Managed via `app/services/auth_service.py`
|
||||
|
||||
- **Customers** (`models/database/customer.py`): Shop customers
|
||||
- **Customers** (`models/database/customer.py`): Storefront customers
|
||||
- Store-scoped (each store has independent customers)
|
||||
- No `role` or `username` fields
|
||||
- Have `customer_number`, `total_orders`, store relationship
|
||||
@@ -56,9 +56,9 @@ Cookies must be set with paths that match how the store is accessed:
|
||||
|
||||
| Access Method | Example URL | Cookie Path |
|
||||
|--------------|-------------|-------------|
|
||||
| Domain | `orion.lu/shop/account/login` | `/shop` |
|
||||
| Subdomain | `orion.localhost/shop/account/login` | `/shop` |
|
||||
| Path-based | `localhost/stores/orion/shop/account/login` | `/stores/orion/shop` |
|
||||
| Domain | `orion.lu/storefront/account/login` | `/storefront` |
|
||||
| Subdomain | `orion.localhost/storefront/account/login` | `/storefront` |
|
||||
| Path-based | `localhost/stores/orion/storefront/account/login` | `/storefront/orion` |
|
||||
|
||||
This ensures cookies are only sent to the correct store's routes.
|
||||
|
||||
@@ -66,32 +66,32 @@ This ensures cookies are only sent to the correct store's routes.
|
||||
|
||||
### Files Created
|
||||
|
||||
1. **`app/templates/shop/account/login.html`**
|
||||
1. **`app/templates/storefront/account/login.html`**
|
||||
- Customer login page
|
||||
- Extends `shop/base.html` (follows design pattern)
|
||||
- Extends `storefront/base.html` (follows design pattern)
|
||||
- Uses Tailwind CSS and Alpine.js
|
||||
- Theme-aware styling with CSS variables
|
||||
- Two-column layout (branding + form)
|
||||
- Form validation and error handling
|
||||
|
||||
2. **`app/templates/shop/account/register.html`**
|
||||
2. **`app/templates/storefront/account/register.html`**
|
||||
- Customer registration page
|
||||
- Fields: first_name, last_name, email, phone (optional), password
|
||||
- Client-side validation
|
||||
- Marketing consent checkbox
|
||||
- Theme integration
|
||||
|
||||
3. **`app/templates/shop/account/forgot-password.html`**
|
||||
3. **`app/templates/storefront/account/forgot-password.html`**
|
||||
- Password reset request page
|
||||
- Two-state UI (form → success)
|
||||
- Email validation
|
||||
|
||||
4. **`app/templates/shop/account/dashboard.html`**
|
||||
4. **`app/templates/storefront/account/dashboard.html`**
|
||||
- Customer account dashboard
|
||||
- Displays account summary, order statistics
|
||||
- Quick links to orders, profile, addresses
|
||||
- Logout functionality
|
||||
- Follows shop design pattern (extends base.html)
|
||||
- Follows storefront design pattern (extends base.html)
|
||||
|
||||
### Important Schema Change
|
||||
|
||||
@@ -117,7 +117,7 @@ class UserLogin(BaseModel):
|
||||
**Impact**: This change affects all login endpoints:
|
||||
- Admin login: `/api/v1/admin/auth/login`
|
||||
- Store login: `/api/v1/store/auth/login`
|
||||
- Customer login: `/api/v1/shop/auth/login`
|
||||
- Customer login: `/api/v1/storefront/auth/login`
|
||||
|
||||
**Updated Files**:
|
||||
- `app/services/auth_service.py` - Changed `user_credentials.username` to `user_credentials.email_or_username`
|
||||
@@ -127,7 +127,7 @@ class UserLogin(BaseModel):
|
||||
|
||||
### Files Modified
|
||||
|
||||
#### 1. `app/api/v1/shop/auth.py`
|
||||
#### 1. `app/api/v1/storefront/auth.py`
|
||||
|
||||
**Changes**:
|
||||
- Added `CustomerLoginResponse` model (uses `CustomerResponse` instead of `UserResponse`)
|
||||
@@ -143,11 +143,11 @@ class UserLogin(BaseModel):
|
||||
store_context = getattr(request.state, 'store_context', None)
|
||||
access_method = store_context.get('detection_method', 'unknown') if store_context else 'unknown'
|
||||
|
||||
cookie_path = "/shop" # Default for domain/subdomain access
|
||||
cookie_path = "/storefront" # Default for domain/subdomain access
|
||||
if access_method == "path":
|
||||
# For path-based access like /stores/orion/shop
|
||||
# For path-based access like /storefront/orion
|
||||
full_prefix = store_context.get('full_prefix', '/store/') if store_context else '/store/'
|
||||
cookie_path = f"{full_prefix}{store.subdomain}/shop"
|
||||
cookie_path = f"/storefront/{store.subdomain}"
|
||||
|
||||
response.set_cookie(
|
||||
key="customer_token",
|
||||
@@ -232,7 +232,7 @@ def get_current_customer_from_cookie_or_header(
|
||||
return customer # Returns Customer, not User
|
||||
```
|
||||
|
||||
#### 4. `app/routes/shop_pages.py`
|
||||
#### 4. `app/routes/storefront_pages.py`
|
||||
|
||||
**Changes**:
|
||||
- Changed import from `User` to `Customer`
|
||||
@@ -300,35 +300,35 @@ The implementation properly supports all three store access methods:
|
||||
|
||||
#### Domain-based Access
|
||||
```
|
||||
URL: https://orion.lu/shop/account/login
|
||||
Cookie Path: /shop
|
||||
Cookie Sent To: https://orion.lu/shop/*
|
||||
URL: https://orion.lu/storefront/account/login
|
||||
Cookie Path: /storefront
|
||||
Cookie Sent To: https://orion.lu/storefront/*
|
||||
```
|
||||
|
||||
#### Subdomain-based Access
|
||||
```
|
||||
URL: https://orion.myplatform.com/shop/account/login
|
||||
Cookie Path: /shop
|
||||
Cookie Sent To: https://orion.myplatform.com/shop/*
|
||||
URL: https://orion.myplatform.com/storefront/account/login
|
||||
Cookie Path: /storefront
|
||||
Cookie Sent To: https://orion.myplatform.com/storefront/*
|
||||
```
|
||||
|
||||
#### Path-based Access
|
||||
```
|
||||
URL: https://myplatform.com/stores/orion/shop/account/login
|
||||
Cookie Path: /stores/orion/shop
|
||||
Cookie Sent To: https://myplatform.com/stores/orion/shop/*
|
||||
URL: https://myplatform.com/storefront/orion/account/login
|
||||
Cookie Path: /storefront/orion
|
||||
Cookie Sent To: https://myplatform.com/storefront/orion/*
|
||||
```
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
### Login Flow
|
||||
|
||||
1. **User loads login page** → `GET /stores/orion/shop/account/login`
|
||||
1. **User loads login page** → `GET /storefront/orion/account/login`
|
||||
- Middleware detects store from path
|
||||
- Sets `detection_method = "path"` in store_context
|
||||
- Renders login template
|
||||
|
||||
2. **User submits credentials** → `POST /api/v1/shop/auth/login`
|
||||
2. **User submits credentials** → `POST /api/v1/storefront/auth/login`
|
||||
- Middleware detects store from Referer header
|
||||
- Sets `detection_method = "path"` (harmonized!)
|
||||
- Validates credentials via `customer_service.login_customer()`
|
||||
@@ -337,7 +337,7 @@ Cookie Sent To: https://myplatform.com/stores/orion/shop/*
|
||||
- Sets `customer_token` cookie with correct path
|
||||
- Returns token + customer data
|
||||
|
||||
3. **Browser redirects to dashboard** → `GET /stores/orion/shop/account/dashboard`
|
||||
3. **Browser redirects to dashboard** → `GET /storefront/orion/account/dashboard`
|
||||
- Browser sends `customer_token` cookie (path matches!)
|
||||
- Dependency `get_current_customer_from_cookie_or_header` extracts token
|
||||
- Decodes JWT, validates `type == "customer"`
|
||||
@@ -352,7 +352,7 @@ Cookie Sent To: https://myplatform.com/stores/orion/shop/*
|
||||
- Smooth animations with transitions
|
||||
- Dark mode support
|
||||
|
||||
2. **User confirms logout** → `POST /api/v1/shop/auth/logout`
|
||||
2. **User confirms logout** → `POST /api/v1/storefront/auth/logout`
|
||||
- Calculates cookie path (same logic as login)
|
||||
- Deletes cookie with matching path
|
||||
- Returns success message
|
||||
@@ -374,7 +374,7 @@ response.set_cookie(
|
||||
secure=True, # HTTPS only (production/staging)
|
||||
samesite="lax", # CSRF protection
|
||||
max_age=1800, # 30 minutes (matches JWT expiry)
|
||||
path=cookie_path, # Restricted to store's shop routes
|
||||
path=cookie_path, # Restricted to store's storefront routes
|
||||
)
|
||||
```
|
||||
|
||||
@@ -395,10 +395,10 @@ response.set_cookie(
|
||||
|
||||
### Frontend Templates
|
||||
|
||||
All authentication pages follow the shop template pattern:
|
||||
All authentication pages follow the storefront template pattern:
|
||||
|
||||
```jinja2
|
||||
{% extends "shop/base.html" %}
|
||||
{% extends "storefront/base.html" %}
|
||||
|
||||
{% block title %}Page Title{% endblock %}
|
||||
|
||||
@@ -540,9 +540,9 @@ function accountDashboard() {
|
||||
3. **Session Management**: No refresh tokens, single JWT with 30-minute expiry
|
||||
|
||||
4. **Account Pages Are Placeholders**:
|
||||
- `/account/orders` - needs order history implementation
|
||||
- `/account/profile` - needs profile editing implementation
|
||||
- `/account/addresses` - needs address management implementation
|
||||
- `/storefront/account/orders` - needs order history implementation
|
||||
- `/storefront/account/profile` - needs profile editing implementation
|
||||
- `/storefront/account/addresses` - needs address management implementation
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
@@ -580,11 +580,11 @@ function accountDashboard() {
|
||||
|
||||
- **Customer Model**: `models/database/customer.py`
|
||||
- **Customer Service**: `app/services/customer_service.py`
|
||||
- **Auth Endpoints**: `app/api/v1/shop/auth.py`
|
||||
- **Auth Endpoints**: `app/api/v1/storefront/auth.py`
|
||||
- **Auth Dependencies**: `app/api/deps.py`
|
||||
- **Shop Routes**: `app/routes/shop_pages.py`
|
||||
- **Storefront Routes**: `app/routes/storefront_pages.py`
|
||||
- **Store Context**: `middleware/store_context.py`
|
||||
- **Templates**: `app/templates/shop/account/`
|
||||
- **Templates**: `app/templates/storefront/account/`
|
||||
|
||||
## Deployment Notes
|
||||
|
||||
@@ -604,10 +604,10 @@ No migrations required. Uses existing `customer` table.
|
||||
Ensure these files exist:
|
||||
- `static/shared/js/log-config.js`
|
||||
- `static/shared/js/icons.js`
|
||||
- `static/shop/js/shop-layout.js`
|
||||
- `static/storefront/js/storefront-layout.js`
|
||||
- `static/shared/js/utils.js`
|
||||
- `static/shared/js/api-client.js`
|
||||
- `static/shop/css/shop.css`
|
||||
- `static/storefront/css/storefront.css`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
Reference in New Issue
Block a user