Fix error page links not respecting vendor context in path-based routing
by aligning with the pattern used throughout the codebase.
Problem:
- Error pages showed links like /shop/ instead of /vendors/wizamart/shop/
- error_renderer.py was checking request.state.access_method (never set)
- This meant access_method was always None, so base_url defaulted to "/"
- Links ignored vendor context and broke multi-access routing
Root Cause:
- Inconsistent pattern: error_renderer.py used wrong attribute
- Rest of codebase (6 locations) correctly uses vendor_context.get('detection_method')
- No code ever sets request.state.access_method anywhere
Solution:
- Change from: access_method = getattr(request.state, "access_method", None)
- Change to: access_method = vendor_context.get('detection_method', 'unknown')
- Aligns with pattern used in:
* app/exceptions/handler.py:384 (login redirect)
* main.py:336 (root redirect)
* app/routes/shop_pages.py:85, 391 (shop pages)
* app/api/v1/shop/auth.py:159, 223 (auth endpoints)
Changes:
- Line 263-264: Get vendor_context first, then extract detection_method from it
- Line 266: Now correctly detects path-based access method
- base_url now properly set to /vendors/wizamart/ for path-based routing
Impact:
- ✅ Path-based routing: /vendors/wizamart/shop123 → links to /vendors/wizamart/shop/
- ✅ Direct shop access: /shop/test → links to /shop/ (unchanged)
- ✅ No breaking changes (access_method was never used before)
- ✅ Consistent with entire codebase pattern
Testing:
- curl http://localhost:8000/vendors/wizamart/shop123
Before: href="/shop/" (wrong)
After: href="/vendors/wizamart/shop/" (correct)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement secure customer authentication system with dedicated JWT tokens,
separate from admin/vendor authentication.
Backend Changes:
- Add customer JWT token support in deps.py
- New get_current_customer_from_cookie_or_header dependency
- Validates customer-specific tokens with type checking
- Returns Customer object instead of User for shop routes
- Extend AuthService with customer token support
- Add verify_password() method
- Add create_access_token_with_data() for custom token payloads
- Update CustomerService authentication
- Generate customer-specific JWT tokens with type="customer"
- Use vendor-scoped customer lookup
- Enhance exception handler
- Sanitize validation errors to prevent password leaks in logs
- Fix shop login redirect to support multi-access routing
- Improve vendor context detection from Referer header
- Consistent "path" detection method for cookie path logic
Schema Changes:
- Rename UserLogin.username to email_or_username for flexibility
- Update field validators accordingly
API Changes:
- Update admin/vendor auth endpoints to use email_or_username
- Customer auth already uses email field correctly
Route Changes:
- Update shop account routes to use Customer dependency
- Add /account redirect (without trailing slash)
- Change parameter names from current_user to current_customer
Frontend Changes:
- Update login forms to use email_or_username in API calls
- Change button text from "Log in" to "Sign in" for consistency
- Improve loading spinner layout with flexbox
Security Improvements:
- Customer tokens scoped to vendor_id
- Token type validation prevents cross-context token usage
- Password inputs redacted from validation error logs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented a complete shopping cart system with database persistence,
replacing the previous stub implementation. The cart now properly stores
items across sessions and follows the project's architecture patterns.
Database Changes:
- Add cart_items table with vendor_id, session_id, product_id, quantity, price_at_add
- Create unique constraint to prevent duplicate items per session
- Add indexes for session lookups and old cart cleanup
- Run migration a2064e1dfcd4 to create cart_items table
New Models & Schemas:
- models/database/cart.py: CartItem SQLAlchemy model with relationships
- models/schema/cart.py: Pydantic schemas for requests/responses
* AddToCartRequest, UpdateCartItemRequest
* CartResponse, CartItemResponse, CartOperationResponse, ClearCartResponse
Exception Handling:
- app/exceptions/cart.py: Cart-specific exceptions following project patterns
* CartItemNotFoundException - item not found in cart
* InsufficientInventoryForCartException - not enough inventory for cart operation
* InvalidCartQuantityException - invalid quantity validation
* CartValidationException - general cart validation
* EmptyCartException - operations on empty cart
* ProductNotAvailableForCartException - product unavailable
- Updated app/exceptions/__init__.py to export cart exceptions
Service Layer:
- Implement cart_service.get_cart() - fetch cart from database with totals
- Implement cart_service.add_to_cart() - create or update cart items with inventory checks
- Implement cart_service.update_cart_item() - update quantity with validation
- Implement cart_service.remove_from_cart() - delete cart item
- Implement cart_service.clear_cart() - remove all items for session
- Replace generic exceptions with cart-specific ones
- Fix InsufficientInventoryException usage (was using wrong parameters)
API Layer:
- Update app/api/v1/shop/cart.py to use Pydantic schemas
- Add response_model declarations to all endpoints
- Add return type hints for type safety
- Convert service dict responses to Pydantic models
Features:
- Cart items persist in database across server restarts
- Inventory validation before adding/updating items
- Price captured at time of adding to cart
- Duplicate items update quantity instead of creating new entries
- Full CRUD operations with proper error handling
- Type-safe API with auto-generated OpenAPI documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>