fix: customer authentication and shop error page styling

## Customer Authentication Fixes
- Fix get_current_customer_api to properly decode customer tokens (was using User model)
- Add _validate_customer_token() helper for shared customer token validation
- Add vendor validation: token.vendor_id must match request URL vendor
- Block admin/vendor tokens from shop endpoints (type != "customer")
- Update get_current_customer_optional to use proper customer token validation
- Customer auth functions now return Customer object (not User)

## Shop Orders API
- Update orders.py to receive Customer directly from auth dependency
- Remove broken get_customer_from_user() helper
- Use VendorNotFoundException instead of HTTPException

## Shop Error Pages
- Fix all error templates (400, 401, 403, 404, 422, 429, 500, 502, generic)
- Templates were using undefined CSS classes (.btn, .status-code, etc.)
- Now properly extend base.html and override specific blocks
- Use Tailwind utility classes for consistent styling

## Documentation
- Update docs/api/authentication.md with new Customer return types
- Document vendor validation security features
- Update docs/api/authentication-quick-reference.md examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-04 22:48:02 +01:00
parent 8a367077e1
commit cbfbbb4654
13 changed files with 302 additions and 394 deletions

View File

@@ -14,6 +14,7 @@ from app.api.deps import (
get_current_vendor_from_cookie_or_header,
get_current_customer_from_cookie_or_header
)
from models.database.customer import Customer
# Admin page
@router.get("/admin/dashboard")
@@ -25,10 +26,10 @@ def admin_page(user: User = Depends(get_current_admin_from_cookie_or_header)):
def vendor_page(user: User = Depends(get_current_vendor_from_cookie_or_header)):
pass
# Customer page
# Customer page - NOTE: Returns Customer, not User!
@router.get("/shop/account/dashboard")
def customer_page(user: User = Depends(get_current_customer_from_cookie_or_header)):
pass
def customer_page(customer: Customer = Depends(get_current_customer_from_cookie_or_header)):
pass # customer.id, customer.email, customer.vendor_id
```
### For API Endpoints (header only - better security)
@@ -39,6 +40,7 @@ from app.api.deps import (
get_current_vendor_api,
get_current_customer_api
)
from models.database.customer import Customer
# Admin API
@router.post("/api/v1/admin/vendors")
@@ -46,14 +48,14 @@ def admin_api(user: User = Depends(get_current_admin_api)):
pass
# Vendor API
@router.post("/api/v1/vendor/{code}/products")
@router.post("/api/v1/vendor/products")
def vendor_api(user: User = Depends(get_current_vendor_api)):
pass
pass # user.token_vendor_id for vendor context
# Customer API
# Customer API - NOTE: Returns Customer, not User!
@router.post("/api/v1/shop/orders")
def customer_api(user: User = Depends(get_current_customer_api)):
pass
def customer_api(request: Request, customer: Customer = Depends(get_current_customer_api)):
pass # customer.id, request.state.vendor validated to match
```
---