refactor: rename Wizamart to Orion across entire codebase
Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart with Orion/orion/ORION across 184 files. This includes database identifiers, email addresses, domain references, R2 bucket names, DNS prefixes, encryption salt, Celery app name, config defaults, Docker configs, CI configs, documentation, seed data, and templates. Renames homepage-wizamart.html template to homepage-orion.html. Fixes duplicate file_pattern key in api.yaml architecture rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Code Quality
|
||||
|
||||
This guide covers the code quality tools and standards used in the Wizamart platform.
|
||||
This guide covers the code quality tools and standards used in the Orion platform.
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
# Creating Modules
|
||||
|
||||
This guide explains how to create new **plug-and-play modules** for the Wizamart platform. Modules are fully self-contained and automatically discovered - no changes to framework files required.
|
||||
This guide explains how to create new **plug-and-play modules** for the Orion platform. Modules are fully self-contained and automatically discovered - no changes to framework files required.
|
||||
|
||||
## Quick Start (5 Minutes)
|
||||
|
||||
@@ -331,9 +331,9 @@ __all__ = ["mymodule_service", "MyModuleService"]
|
||||
|
||||
```python
|
||||
# app/modules/mymodule/exceptions.py
|
||||
from app.exceptions import WizamartException
|
||||
from app.exceptions import OrionException
|
||||
|
||||
class MyModuleException(WizamartException):
|
||||
class MyModuleException(OrionException):
|
||||
"""Base exception for mymodule."""
|
||||
pass
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ JWT tokens have `type: "customer"` to distinguish them.
|
||||
# Domain/Subdomain access
|
||||
cookie_path = "/shop"
|
||||
|
||||
# Path-based access (/stores/wizamart/shop)
|
||||
# Path-based access (/stores/orion/shop)
|
||||
cookie_path = f"/stores/{store_code}/shop"
|
||||
```
|
||||
|
||||
@@ -68,9 +68,9 @@ cookie_path = f"/stores/{store_code}/shop"
|
||||
|
||||
```
|
||||
# Path-based access
|
||||
http://localhost:8000/stores/wizamart/shop/account/login
|
||||
http://localhost:8000/stores/wizamart/shop/account/register
|
||||
http://localhost:8000/stores/wizamart/shop/account/dashboard
|
||||
http://localhost:8000/stores/orion/shop/account/login
|
||||
http://localhost:8000/stores/orion/shop/account/register
|
||||
http://localhost:8000/stores/orion/shop/account/dashboard
|
||||
```
|
||||
|
||||
## Next Steps (TODO)
|
||||
|
||||
@@ -56,9 +56,9 @@ Cookies must be set with paths that match how the store is accessed:
|
||||
|
||||
| Access Method | Example URL | Cookie Path |
|
||||
|--------------|-------------|-------------|
|
||||
| Domain | `wizamart.com/shop/account/login` | `/shop` |
|
||||
| Subdomain | `wizamart.localhost/shop/account/login` | `/shop` |
|
||||
| Path-based | `localhost/stores/wizamart/shop/account/login` | `/stores/wizamart/shop` |
|
||||
| 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` |
|
||||
|
||||
This ensures cookies are only sent to the correct store's routes.
|
||||
|
||||
@@ -145,7 +145,7 @@ access_method = store_context.get('detection_method', 'unknown') if store_contex
|
||||
|
||||
cookie_path = "/shop" # Default for domain/subdomain access
|
||||
if access_method == "path":
|
||||
# For path-based access like /stores/wizamart/shop
|
||||
# For path-based access like /stores/orion/shop
|
||||
full_prefix = store_context.get('full_prefix', '/store/') if store_context else '/store/'
|
||||
cookie_path = f"{full_prefix}{store.subdomain}/shop"
|
||||
|
||||
@@ -300,30 +300,30 @@ The implementation properly supports all three store access methods:
|
||||
|
||||
#### Domain-based Access
|
||||
```
|
||||
URL: https://wizamart.com/shop/account/login
|
||||
URL: https://orion.lu/shop/account/login
|
||||
Cookie Path: /shop
|
||||
Cookie Sent To: https://wizamart.com/shop/*
|
||||
Cookie Sent To: https://orion.lu/shop/*
|
||||
```
|
||||
|
||||
#### Subdomain-based Access
|
||||
```
|
||||
URL: https://wizamart.myplatform.com/shop/account/login
|
||||
URL: https://orion.myplatform.com/shop/account/login
|
||||
Cookie Path: /shop
|
||||
Cookie Sent To: https://wizamart.myplatform.com/shop/*
|
||||
Cookie Sent To: https://orion.myplatform.com/shop/*
|
||||
```
|
||||
|
||||
#### Path-based Access
|
||||
```
|
||||
URL: https://myplatform.com/stores/wizamart/shop/account/login
|
||||
Cookie Path: /stores/wizamart/shop
|
||||
Cookie Sent To: https://myplatform.com/stores/wizamart/shop/*
|
||||
URL: https://myplatform.com/stores/orion/shop/account/login
|
||||
Cookie Path: /stores/orion/shop
|
||||
Cookie Sent To: https://myplatform.com/stores/orion/shop/*
|
||||
```
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
### Login Flow
|
||||
|
||||
1. **User loads login page** → `GET /stores/wizamart/shop/account/login`
|
||||
1. **User loads login page** → `GET /stores/orion/shop/account/login`
|
||||
- Middleware detects store from path
|
||||
- Sets `detection_method = "path"` in store_context
|
||||
- Renders login template
|
||||
@@ -337,7 +337,7 @@ Cookie Sent To: https://myplatform.com/stores/wizamart/shop/*
|
||||
- Sets `customer_token` cookie with correct path
|
||||
- Returns token + customer data
|
||||
|
||||
3. **Browser redirects to dashboard** → `GET /stores/wizamart/shop/account/dashboard`
|
||||
3. **Browser redirects to dashboard** → `GET /stores/orion/shop/account/dashboard`
|
||||
- Browser sends `customer_token` cookie (path matches!)
|
||||
- Dependency `get_current_customer_from_cookie_or_header` extracts token
|
||||
- Decodes JWT, validates `type == "customer"`
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Database Initialization Guide
|
||||
|
||||
**Wizamart Platform - Database Management Documentation**
|
||||
**Orion Platform - Database Management Documentation**
|
||||
|
||||
This guide covers the database initialization, seeding, and management workflows for the Wizamart multi-tenant e-commerce platform.
|
||||
This guide covers the database initialization, seeding, and management workflows for the Orion multi-tenant e-commerce platform.
|
||||
|
||||
---
|
||||
|
||||
@@ -23,7 +23,7 @@ This guide covers the database initialization, seeding, and management workflows
|
||||
|
||||
### Database Initialization Philosophy
|
||||
|
||||
The Wizamart platform uses a **two-tier initialization system**:
|
||||
The Orion platform uses a **two-tier initialization system**:
|
||||
|
||||
1. **Production Initialization** (`init_production.py`)
|
||||
- Creates essential platform infrastructure
|
||||
@@ -112,7 +112,7 @@ ENVIRONMENT=development # development | staging | production
|
||||
# =============================================================================
|
||||
# ADMIN INITIALIZATION
|
||||
# =============================================================================
|
||||
ADMIN_EMAIL=admin@wizamart.com
|
||||
ADMIN_EMAIL=admin@orion.lu
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=admin123 # ⚠️ CHANGE IN PRODUCTION!
|
||||
ADMIN_FIRST_NAME=Platform
|
||||
@@ -185,7 +185,7 @@ if warnings:
|
||||
# 1. Configure environment
|
||||
cat > .env << EOF
|
||||
ENVIRONMENT=production
|
||||
DATABASE_URL=postgresql://user:pass@localhost/wizamart
|
||||
DATABASE_URL=postgresql://user:pass@localhost/orion
|
||||
ADMIN_EMAIL=admin@yourmerchant.com
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=SecurePassword123!
|
||||
@@ -373,10 +373,10 @@ Edit `scripts/seed/init_production.py` to add new platform settings:
|
||||
```python
|
||||
def create_admin_settings(db: Session) -> int:
|
||||
"""Create essential admin settings."""
|
||||
|
||||
|
||||
default_settings = [
|
||||
# ... existing settings ...
|
||||
|
||||
|
||||
# Add your new setting
|
||||
{
|
||||
"key": "your_new_setting",
|
||||
@@ -396,13 +396,13 @@ Edit `scripts/seed/seed_demo.py` to extend demo data creation:
|
||||
```python
|
||||
def seed_demo_data(db: Session, auth_manager: AuthManager):
|
||||
"""Seed demo data for development."""
|
||||
|
||||
|
||||
# ... existing steps ...
|
||||
|
||||
|
||||
# Add your new demo data
|
||||
print_step(7, "Creating your demo data...")
|
||||
create_your_demo_data(db, stores)
|
||||
|
||||
|
||||
# ... commit
|
||||
```
|
||||
|
||||
@@ -411,7 +411,7 @@ Create a new function for your data:
|
||||
```python
|
||||
def create_your_demo_data(db: Session, stores: List[Store]) -> List[YourModel]:
|
||||
"""Create demo data for your feature."""
|
||||
|
||||
|
||||
items = []
|
||||
for store in stores:
|
||||
# Create demo items for this store
|
||||
@@ -421,7 +421,7 @@ def create_your_demo_data(db: Session, stores: List[Store]) -> List[YourModel]:
|
||||
)
|
||||
db.add(item)
|
||||
items.append(item)
|
||||
|
||||
|
||||
db.flush()
|
||||
print_success(f"Created {len(items)} demo items")
|
||||
return items
|
||||
@@ -436,12 +436,12 @@ Edit `app/core/config.py`:
|
||||
```python
|
||||
class Settings(BaseSettings):
|
||||
# ... existing settings ...
|
||||
|
||||
|
||||
# Your new settings
|
||||
your_new_setting: str = "default_value"
|
||||
your_numeric_setting: int = 42
|
||||
your_boolean_setting: bool = True
|
||||
|
||||
|
||||
# Optional with validation
|
||||
your_list_setting: List[str] = ["item1", "item2"]
|
||||
```
|
||||
@@ -473,7 +473,7 @@ Edit the `DEMO_STORES` list in `scripts/seed/seed_demo.py`:
|
||||
```python
|
||||
DEMO_STORES = [
|
||||
# ... existing stores ...
|
||||
|
||||
|
||||
# Your new demo store
|
||||
{
|
||||
"store_code": "YOURSHOP",
|
||||
@@ -680,7 +680,7 @@ make migrate-status
|
||||
**Solution**: No action needed. This message confirms the admin user exists.
|
||||
|
||||
```
|
||||
⚠ Admin user already exists: admin@wizamart.com
|
||||
⚠ Admin user already exists: admin@orion.lu
|
||||
✓ All changes committed
|
||||
```
|
||||
|
||||
@@ -688,7 +688,7 @@ make migrate-status
|
||||
|
||||
**Cause**: Correct behavior - safety feature working
|
||||
|
||||
**Solution**:
|
||||
**Solution**:
|
||||
- If you're in development: Set `ENVIRONMENT=development` in `.env`
|
||||
- If you're in production: Don't seed demo data! Create stores via admin panel
|
||||
|
||||
@@ -712,7 +712,7 @@ pip list | grep pydantic
|
||||
|
||||
**Cause**: Running seed scripts multiple times without checking existence
|
||||
|
||||
**Solution**:
|
||||
**Solution**:
|
||||
- Use `make seed-demo-reset` for fresh data
|
||||
- Check scripts for proper idempotent checks
|
||||
- Verify database state before seeding
|
||||
@@ -778,7 +778,7 @@ python -c "from app.core.config import settings; print(f'Env: {settings.environm
|
||||
URL: http://localhost:8000/admin/login
|
||||
Username: admin
|
||||
Password: admin123 (⚠️ CHANGE IN PRODUCTION!)
|
||||
Email: admin@wizamart.com
|
||||
Email: admin@orion.lu
|
||||
```
|
||||
|
||||
#### Demo Stores (After `make seed-demo`)
|
||||
@@ -793,7 +793,7 @@ Store 3: store3@example.com / password123
|
||||
### File Locations
|
||||
|
||||
```
|
||||
wizamart/
|
||||
orion/
|
||||
├── .env # Environment configuration
|
||||
├── Makefile # Command definitions
|
||||
├── app/
|
||||
@@ -845,8 +845,8 @@ Complete list of database-related environment variables:
|
||||
| Variable | Type | Default | Description |
|
||||
|----------|------|---------|-------------|
|
||||
| `ENVIRONMENT` | string | `development` | Environment mode (development/staging/production) |
|
||||
| `DATABASE_URL` | string | `sqlite:///./wizamart.db` | Database connection string |
|
||||
| `ADMIN_EMAIL` | string | `admin@wizamart.com` | Platform admin email |
|
||||
| `DATABASE_URL` | string | `sqlite:///./orion.db` | Database connection string |
|
||||
| `ADMIN_EMAIL` | string | `admin@orion.lu` | Platform admin email |
|
||||
| `ADMIN_USERNAME` | string | `admin` | Platform admin username |
|
||||
| `ADMIN_PASSWORD` | string | `admin123` | Platform admin password |
|
||||
| `ADMIN_FIRST_NAME` | string | `Platform` | Admin first name |
|
||||
@@ -1000,6 +1000,6 @@ For questions or issues:
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2025
|
||||
**Maintained By**: Wizamart Platform Team
|
||||
**Version**: 2.0
|
||||
**Last Updated**: 2025
|
||||
**Maintained By**: Orion Platform Team
|
||||
**Version**: 2.0
|
||||
|
||||
@@ -68,10 +68,10 @@ make db-reset # rollback + migrate + reset
|
||||
### Required Settings
|
||||
```bash
|
||||
ENVIRONMENT=development # development/staging/production
|
||||
DATABASE_URL=sqlite:///./wizamart.db
|
||||
DATABASE_URL=sqlite:///./orion.db
|
||||
|
||||
# Admin credentials (CHANGE IN PRODUCTION!)
|
||||
ADMIN_EMAIL=admin@wizamart.com
|
||||
ADMIN_EMAIL=admin@orion.lu
|
||||
ADMIN_USERNAME=admin
|
||||
ADMIN_PASSWORD=admin123
|
||||
```
|
||||
@@ -121,35 +121,35 @@ Store 3: store3@example.com / password123
|
||||
## 📊 What Each Command Creates
|
||||
|
||||
### `make init-prod`
|
||||
✅ Platform admin user
|
||||
✅ Admin settings
|
||||
✅ Role templates
|
||||
✅ RBAC schema verification
|
||||
✅ Platform admin user
|
||||
✅ Admin settings
|
||||
✅ Role templates
|
||||
✅ RBAC schema verification
|
||||
|
||||
**Safe for production**: YES
|
||||
**Contains fake data**: NO
|
||||
**Safe for production**: YES
|
||||
**Contains fake data**: NO
|
||||
|
||||
### `make seed-demo`
|
||||
✅ 3 demo stores
|
||||
✅ Demo store users
|
||||
✅ ~45 customers (15 per store)
|
||||
✅ ~60 products (20 per store)
|
||||
✅ Store themes
|
||||
✅ Custom domains
|
||||
✅ 3 demo stores
|
||||
✅ Demo store users
|
||||
✅ ~45 customers (15 per store)
|
||||
✅ ~60 products (20 per store)
|
||||
✅ Store themes
|
||||
✅ Custom domains
|
||||
|
||||
**Safe for production**: NO
|
||||
**Contains fake data**: YES - ALL OF IT
|
||||
**Safe for production**: NO
|
||||
**Contains fake data**: YES - ALL OF IT
|
||||
|
||||
### `make seed-demo-minimal`
|
||||
✅ 1 demo store
|
||||
✅ 1 demo store user
|
||||
✅ ~15 customers
|
||||
✅ ~20 products
|
||||
✅ Store theme
|
||||
✅ Custom domain
|
||||
✅ 1 demo store
|
||||
✅ 1 demo store user
|
||||
✅ ~15 customers
|
||||
✅ ~20 products
|
||||
✅ Store theme
|
||||
✅ Custom domain
|
||||
|
||||
**Safe for production**: NO
|
||||
**Contains fake data**: YES
|
||||
**Safe for production**: NO
|
||||
**Contains fake data**: YES
|
||||
|
||||
---
|
||||
|
||||
@@ -244,4 +244,4 @@ make help-db # Database-specific help
|
||||
**Documentation**:
|
||||
- `database-init-guide.md` - Detailed guide
|
||||
- `MIGRATION_GUIDE.md` - Migration from old system
|
||||
- `README.md` - Project overview
|
||||
- `README.md` - Project overview
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
## Overview
|
||||
|
||||
I've created a comprehensive database seeder for your Wizamart platform that significantly expands coverage beyond your original implementation. The new seeder creates realistic test data across all your database models.
|
||||
I've created a comprehensive database seeder for your Orion platform that significantly expands coverage beyond your original implementation. The new seeder creates realistic test data across all your database models.
|
||||
|
||||
## What's New
|
||||
|
||||
### Original Seeder Coverage
|
||||
- ✓ Admin user
|
||||
- ✓ 2 Stores (TESTSTORE, WIZAMART)
|
||||
- ✓ 2 Stores (TESTSTORE, ORION)
|
||||
|
||||
### Enhanced Seeder Coverage
|
||||
- ✓ Admin user + multiple test users (stores, customers)
|
||||
@@ -88,7 +88,7 @@ python scripts/seed_database.py
|
||||
This creates:
|
||||
- 1 admin user
|
||||
- 3 test users (2 stores, 1 customer)
|
||||
- 3 stores (WIZAMART, FASHIONHUB, BOOKSTORE)
|
||||
- 3 stores (ORION, FASHIONHUB, BOOKSTORE)
|
||||
- 5 marketplace products
|
||||
- 10 store-product links
|
||||
- 4 customers
|
||||
@@ -107,7 +107,7 @@ python scripts/seed_database.py --minimal
|
||||
|
||||
This creates only:
|
||||
- 1 admin user
|
||||
- 1 store (WIZAMART)
|
||||
- 1 store (ORION)
|
||||
|
||||
#### Option C: Reset and Seed (Fresh Start)
|
||||
```bash
|
||||
@@ -133,7 +133,7 @@ This runs:
|
||||
|
||||
| Username | Email | Password | Role |
|
||||
|----------|-------|----------|------|
|
||||
| admin | admin@wizamart.com | admin123 | admin |
|
||||
| admin | admin@orion.lu | admin123 | admin |
|
||||
| store1 | store1@example.com | password123 | store |
|
||||
| store2 | store2@example.com | password123 | store |
|
||||
| customer1 | customer1@example.com | password123 | customer |
|
||||
@@ -142,7 +142,7 @@ This runs:
|
||||
|
||||
| Code | Name | Subdomain | Theme | Custom Domain |
|
||||
|------|------|-----------|-------|---------------|
|
||||
| WIZAMART | WizaMart | wizamart | modern | wizamart.shop |
|
||||
| ORION | Orion | orion | modern | orion.shop |
|
||||
| FASHIONHUB | Fashion Hub | fashionhub | vibrant | fashionhub.store |
|
||||
| BOOKSTORE | The Book Store | bookstore | classic | (none) |
|
||||
|
||||
@@ -218,12 +218,12 @@ python scripts/seed_database.py [--reset] [--minimal]
|
||||
- Password: `admin123`
|
||||
|
||||
### Store Shops
|
||||
- WIZAMART: `http://localhost:8000/shop/WIZAMART`
|
||||
- ORION: `http://localhost:8000/shop/ORION`
|
||||
- FASHIONHUB: `http://localhost:8000/shop/FASHIONHUB`
|
||||
- BOOKSTORE: `http://localhost:8000/shop/BOOKSTORE`
|
||||
|
||||
### Theme Editors
|
||||
- WIZAMART Theme: `http://localhost:8000/admin/stores/WIZAMART/theme`
|
||||
- ORION Theme: `http://localhost:8000/admin/stores/ORION/theme`
|
||||
- FASHIONHUB Theme: `http://localhost:8000/admin/stores/FASHIONHUB/theme`
|
||||
- BOOKSTORE Theme: `http://localhost:8000/admin/stores/BOOKSTORE/theme`
|
||||
|
||||
@@ -231,7 +231,7 @@ python scripts/seed_database.py [--reset] [--minimal]
|
||||
|
||||
```
|
||||
╔════════════════════════════════════════════════════════════════════╗
|
||||
║ WIZAMART DATABASE SEEDER ║
|
||||
║ ORION DATABASE SEEDER ║
|
||||
╚════════════════════════════════════════════════════════════════════╝
|
||||
|
||||
STEP 1: Verifying database...
|
||||
@@ -248,9 +248,9 @@ STEP 1: Creating users...
|
||||
✓ User 'customer1' created (ID: 4)
|
||||
|
||||
STEP 2: Creating stores...
|
||||
✓ WIZAMART created (ID: 1)
|
||||
✓ ORION created (ID: 1)
|
||||
✓ Theme 'modern' applied
|
||||
✓ Custom domain 'wizamart.shop' added
|
||||
✓ Custom domain 'orion.shop' added
|
||||
✓ FASHIONHUB created (ID: 2)
|
||||
✓ Theme 'vibrant' applied
|
||||
✓ Custom domain 'fashionhub.store' added
|
||||
@@ -285,7 +285,7 @@ You can customize the seeder by editing the configuration constants at the top o
|
||||
|
||||
```python
|
||||
# Admin credentials
|
||||
DEFAULT_ADMIN_EMAIL = "admin@wizamart.com"
|
||||
DEFAULT_ADMIN_EMAIL = "admin@orion.lu"
|
||||
DEFAULT_ADMIN_USERNAME = "admin"
|
||||
DEFAULT_ADMIN_PASSWORD = "admin123"
|
||||
|
||||
@@ -414,7 +414,7 @@ make db-setup
|
||||
|
||||
## Security Notes
|
||||
|
||||
⚠️ **IMPORTANT**:
|
||||
⚠️ **IMPORTANT**:
|
||||
- Default passwords are simple for development convenience
|
||||
- Change ALL default passwords in production environments
|
||||
- The admin password is intentionally weak for local development
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
The Wizamart platform uses **automatic environment detection** to determine the runtime environment (development, staging, or production) and adjust security settings accordingly.
|
||||
The Orion platform uses **automatic environment detection** to determine the runtime environment (development, staging, or production) and adjust security settings accordingly.
|
||||
|
||||
### Why Auto-Detection?
|
||||
|
||||
@@ -158,7 +158,7 @@ from app.core.environment import is_development, is_production
|
||||
def debug_info():
|
||||
if not is_development():
|
||||
raise HTTPException(status_code=404, detail="Not found")
|
||||
|
||||
|
||||
# Only accessible in development
|
||||
return {
|
||||
"database": get_db_info(),
|
||||
@@ -226,7 +226,7 @@ from app.core.environment import get_environment
|
||||
|
||||
def configure_logging():
|
||||
env = get_environment()
|
||||
|
||||
|
||||
if env == "development":
|
||||
# Verbose logging for development
|
||||
logging.basicConfig(
|
||||
@@ -255,10 +255,10 @@ from app.core.environment import get_cached_environment
|
||||
def process_request(request: Request):
|
||||
# Use cached version for frequent calls
|
||||
env = get_cached_environment() # Cached - faster
|
||||
|
||||
|
||||
# Instead of:
|
||||
# env = get_environment() # Re-detects every time
|
||||
|
||||
|
||||
if env == "production":
|
||||
# Production-specific optimization
|
||||
use_cache = True
|
||||
@@ -335,7 +335,7 @@ ExecStart=/usr/bin/uvicorn main:app --host 0.0.0.0 --port 8000
|
||||
```yaml
|
||||
services:
|
||||
web:
|
||||
image: wizamart:latest
|
||||
image: orion:latest
|
||||
environment:
|
||||
- ENV=production
|
||||
ports:
|
||||
@@ -421,14 +421,14 @@ from app.core.environment import get_environment, should_use_secure_cookies
|
||||
def test_environment_detection_with_env_var():
|
||||
"""Test environment detection with ENV variable."""
|
||||
os.environ["ENV"] = "production"
|
||||
|
||||
|
||||
# Clear cache first
|
||||
import app.core.environment as env_module
|
||||
env_module._cached_environment = None
|
||||
|
||||
|
||||
assert get_environment() == "production"
|
||||
assert should_use_secure_cookies() == True
|
||||
|
||||
|
||||
# Cleanup
|
||||
del os.environ["ENV"]
|
||||
|
||||
@@ -437,11 +437,11 @@ def test_environment_defaults_to_development():
|
||||
# Ensure no env vars set
|
||||
os.environ.pop("ENV", None)
|
||||
os.environ.pop("ENVIRONMENT", None)
|
||||
|
||||
|
||||
# Clear cache
|
||||
import app.core.environment as env_module
|
||||
env_module._cached_environment = None
|
||||
|
||||
|
||||
assert get_environment() == "development"
|
||||
assert should_use_secure_cookies() == False
|
||||
```
|
||||
@@ -453,17 +453,17 @@ def test_login_sets_secure_cookie_in_production(test_client, monkeypatch):
|
||||
"""Test that login sets secure cookie in production."""
|
||||
# Mock production environment
|
||||
monkeypatch.setenv("ENV", "production")
|
||||
|
||||
|
||||
# Clear cache
|
||||
import app.core.environment as env_module
|
||||
env_module._cached_environment = None
|
||||
|
||||
|
||||
# Test login
|
||||
response = test_client.post("/api/v1/admin/auth/login", json={
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
})
|
||||
|
||||
|
||||
# Check cookie has secure flag
|
||||
set_cookie_header = response.headers.get("set-cookie")
|
||||
assert "Secure" in set_cookie_header
|
||||
@@ -481,7 +481,7 @@ from app.core.environment import get_environment, should_use_secure_cookies
|
||||
async def startup_event():
|
||||
env = get_environment()
|
||||
secure = should_use_secure_cookies()
|
||||
|
||||
|
||||
print(f"🌍 Environment: {env}")
|
||||
print(f"🔒 Secure cookies: {secure}")
|
||||
print(f"📍 Running on: {os.getenv('HOSTNAME', 'localhost')}")
|
||||
@@ -498,7 +498,7 @@ def debug_environment():
|
||||
"""Debug endpoint to check environment detection."""
|
||||
if not is_development():
|
||||
raise HTTPException(status_code=404)
|
||||
|
||||
|
||||
return {
|
||||
"detected_environment": get_environment(),
|
||||
"should_use_secure_cookies": should_use_secure_cookies(),
|
||||
@@ -518,8 +518,8 @@ def debug_environment():
|
||||
**Setup:**
|
||||
```bash
|
||||
# Clone repo
|
||||
git clone <wizamart-repo>
|
||||
cd wizamart-repo
|
||||
git clone <orion-repo>
|
||||
cd orion-repo
|
||||
|
||||
# Create virtual environment
|
||||
python -m venv venv
|
||||
@@ -553,16 +553,16 @@ services:
|
||||
build: .
|
||||
environment:
|
||||
- ENV=staging
|
||||
- DATABASE_URL=postgresql://user:pass@db:5432/wizamart_staging
|
||||
- DATABASE_URL=postgresql://user:pass@db:5432/orion_staging
|
||||
ports:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
|
||||
db:
|
||||
image: postgres:15
|
||||
environment:
|
||||
- POSTGRES_DB=wizamart_staging
|
||||
- POSTGRES_DB=orion_staging
|
||||
- POSTGRES_USER=user
|
||||
- POSTGRES_PASSWORD=pass
|
||||
```
|
||||
@@ -572,13 +572,13 @@ services:
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: wizamart-staging
|
||||
name: orion-staging
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: web
|
||||
image: wizamart:latest
|
||||
image: orion:latest
|
||||
env:
|
||||
- name: ENV
|
||||
value: "staging"
|
||||
@@ -599,15 +599,15 @@ spec:
|
||||
**systemd Service:**
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Wizamart Platform
|
||||
Description=Orion Platform
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=wizamart
|
||||
WorkingDirectory=/opt/wizamart
|
||||
User=orion
|
||||
WorkingDirectory=/opt/orion
|
||||
Environment="ENV=production"
|
||||
Environment="DATABASE_URL=postgresql://user:pass@localhost/wizamart_prod"
|
||||
ExecStart=/opt/wizamart/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
|
||||
Environment="DATABASE_URL=postgresql://user:pass@localhost/orion_prod"
|
||||
ExecStart=/opt/orion/venv/bin/uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
@@ -742,42 +742,42 @@ class TestEnvironmentDetection:
|
||||
# Clear any env vars
|
||||
os.environ.pop("ENV", None)
|
||||
os.environ.pop("ENVIRONMENT", None)
|
||||
|
||||
|
||||
assert get_environment() == "development"
|
||||
assert is_development() == True
|
||||
assert is_production() == False
|
||||
assert should_use_secure_cookies() == False
|
||||
|
||||
|
||||
def test_env_variable_production(self, monkeypatch):
|
||||
"""Test ENV=production detection."""
|
||||
monkeypatch.setenv("ENV", "production")
|
||||
|
||||
|
||||
assert get_environment() == "production"
|
||||
assert is_production() == True
|
||||
assert should_use_secure_cookies() == True
|
||||
|
||||
|
||||
def test_environment_variable_staging(self, monkeypatch):
|
||||
"""Test ENVIRONMENT=staging detection."""
|
||||
monkeypatch.setenv("ENVIRONMENT", "staging")
|
||||
|
||||
|
||||
assert get_environment() == "staging"
|
||||
assert is_staging() == True
|
||||
assert should_use_secure_cookies() == True
|
||||
|
||||
|
||||
def test_env_takes_priority_over_environment(self, monkeypatch):
|
||||
"""Test that ENV variable has priority."""
|
||||
monkeypatch.setenv("ENV", "production")
|
||||
monkeypatch.setenv("ENVIRONMENT", "staging")
|
||||
|
||||
|
||||
# ENV should win
|
||||
assert get_environment() == "production"
|
||||
|
||||
|
||||
def test_debug_true_is_development(self, monkeypatch):
|
||||
"""Test that DEBUG=true results in development."""
|
||||
monkeypatch.delenv("ENV", raising=False)
|
||||
monkeypatch.delenv("ENVIRONMENT", raising=False)
|
||||
monkeypatch.setenv("DEBUG", "true")
|
||||
|
||||
|
||||
assert get_environment() == "development"
|
||||
|
||||
|
||||
@@ -786,7 +786,7 @@ class TestCookieSecurity:
|
||||
"""Test cookies are secure in production."""
|
||||
monkeypatch.setenv("ENV", "production")
|
||||
assert should_use_secure_cookies() == True
|
||||
|
||||
|
||||
def test_insecure_cookies_in_development(self):
|
||||
"""Test cookies are not secure in development."""
|
||||
os.environ.pop("ENV", None)
|
||||
@@ -803,21 +803,21 @@ def test_login_cookie_matches_environment(test_client, monkeypatch):
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
})
|
||||
|
||||
|
||||
set_cookie = response.headers.get("set-cookie", "")
|
||||
assert "Secure" not in set_cookie # No Secure in development
|
||||
|
||||
|
||||
# Test production
|
||||
monkeypatch.setenv("ENV", "production")
|
||||
# Clear cache
|
||||
import app.core.environment as env_module
|
||||
env_module._cached_environment = None
|
||||
|
||||
|
||||
response = test_client.post("/api/v1/admin/auth/login", json={
|
||||
"username": "admin",
|
||||
"password": "admin123"
|
||||
})
|
||||
|
||||
|
||||
set_cookie = response.headers.get("set-cookie", "")
|
||||
assert "Secure" in set_cookie # Secure in production
|
||||
```
|
||||
@@ -854,7 +854,7 @@ def test_login_cookie_matches_environment(test_client, monkeypatch):
|
||||
def send_email(to: str, subject: str):
|
||||
"""
|
||||
Send email to recipient.
|
||||
|
||||
|
||||
Environment behavior:
|
||||
- Development: Logs email to console (no actual send)
|
||||
- Staging: Sends to test email address
|
||||
@@ -887,7 +887,7 @@ def test_login_cookie_matches_environment(test_client, monkeypatch):
|
||||
# ❌ Bad
|
||||
if os.getenv("ENV") == "production":
|
||||
use_https = True
|
||||
|
||||
|
||||
# ✅ Good
|
||||
use_https = should_use_secure_cookies()
|
||||
```
|
||||
@@ -896,7 +896,7 @@ def test_login_cookie_matches_environment(test_client, monkeypatch):
|
||||
```python
|
||||
# ❌ Bad - assumes production
|
||||
response.set_cookie(secure=True)
|
||||
|
||||
|
||||
# ✅ Good - adapts to environment
|
||||
response.set_cookie(secure=should_use_secure_cookies())
|
||||
```
|
||||
@@ -907,7 +907,7 @@ def test_login_cookie_matches_environment(test_client, monkeypatch):
|
||||
FORCE_PRODUCTION = True
|
||||
if FORCE_PRODUCTION:
|
||||
...
|
||||
|
||||
|
||||
# ✅ Good - use environment variable
|
||||
# export ENV=production
|
||||
if is_production():
|
||||
@@ -921,7 +921,7 @@ def test_login_cookie_matches_environment(test_client, monkeypatch):
|
||||
log_level = "WARNING"
|
||||
elif is_development():
|
||||
log_level = "DEBUG"
|
||||
|
||||
|
||||
# ✅ Good - consistent
|
||||
env = get_environment()
|
||||
if env == "production":
|
||||
@@ -936,7 +936,7 @@ def test_login_cookie_matches_environment(test_client, monkeypatch):
|
||||
def test_production():
|
||||
os.environ["ENV"] = "production"
|
||||
assert get_environment() == "production" # May fail if cached
|
||||
|
||||
|
||||
# ✅ Good - clear cache
|
||||
def test_production():
|
||||
import app.core.environment as env_module
|
||||
|
||||
@@ -182,7 +182,7 @@ ErrorPageRenderer.render_error_page(
|
||||
|
||||
**Handlers:**
|
||||
|
||||
- `WizamartException` - Custom application exceptions
|
||||
- `OrionException` - Custom application exceptions
|
||||
- `HTTPException` - FastAPI HTTP exceptions
|
||||
- `RequestValidationError` - Pydantic validation errors
|
||||
- `Exception` - Generic Python exceptions
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
▼
|
||||
┌────────────────────────────────────────────────────────┐
|
||||
│ Exception Handler │
|
||||
│ - WizamartException │
|
||||
│ - OrionException │
|
||||
│ - HTTPException │
|
||||
│ - RequestValidationError │
|
||||
│ - Generic Exception │
|
||||
@@ -296,14 +296,14 @@ middleware/
|
||||
|
||||
## Benefits Summary
|
||||
|
||||
✅ **Separation of Concerns**: HTML templates separate from handler logic
|
||||
✅ **Context-Aware**: Different error pages for different areas
|
||||
✅ **Maintainable**: Easy to update individual error pages
|
||||
✅ **Scalable**: Easy to add new contexts or error types
|
||||
✅ **Professional**: Polished error pages matching area design
|
||||
✅ **Flexible**: Fallback mechanism ensures errors always render
|
||||
✅ **Secure**: Debug info only shown to admins
|
||||
✅ **Themed**: Shop errors can use store branding (Phase 3)
|
||||
✅ **Separation of Concerns**: HTML templates separate from handler logic
|
||||
✅ **Context-Aware**: Different error pages for different areas
|
||||
✅ **Maintainable**: Easy to update individual error pages
|
||||
✅ **Scalable**: Easy to add new contexts or error types
|
||||
✅ **Professional**: Polished error pages matching area design
|
||||
✅ **Flexible**: Fallback mechanism ensures errors always render
|
||||
✅ **Secure**: Debug info only shown to admins
|
||||
✅ **Themed**: Shop errors can use store branding (Phase 3)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
## Overview
|
||||
|
||||
The Wizamart API uses a unified custom exception system to provide consistent, meaningful error responses across all endpoints. This system was redesigned to eliminate competing exception handlers and provide a single source of truth for error handling.
|
||||
The Orion API uses a unified custom exception system to provide consistent, meaningful error responses across all endpoints. This system was redesigned to eliminate competing exception handlers and provide a single source of truth for error handling.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Exception Hierarchy
|
||||
|
||||
```
|
||||
WizamartException (Base)
|
||||
OrionException (Base)
|
||||
├── ValidationException (422)
|
||||
├── AuthenticationException (401)
|
||||
├── AuthorizationException (403)
|
||||
@@ -91,7 +91,7 @@ The system handles four categories of exceptions:
|
||||
```python
|
||||
# app/exceptions/handler.py
|
||||
|
||||
@app.exception_handler(WizamartException)
|
||||
@app.exception_handler(OrionException)
|
||||
async def custom_exception_handler(request, exc):
|
||||
"""Handle all custom business exceptions"""
|
||||
return JSONResponse(
|
||||
@@ -99,7 +99,7 @@ async def custom_exception_handler(request, exc):
|
||||
content=exc.to_dict()
|
||||
)
|
||||
|
||||
@app.exception_handler(HTTPException)
|
||||
@app.exception_handler(HTTPException)
|
||||
async def http_exception_handler(request, exc):
|
||||
"""Handle FastAPI HTTP exceptions"""
|
||||
return JSONResponse(
|
||||
@@ -149,11 +149,11 @@ from app.exceptions.admin import UserNotFoundException, CannotModifySelfExceptio
|
||||
|
||||
def toggle_user_status(self, db: Session, user_id: int, current_admin_id: int):
|
||||
user = self._get_user_by_id_or_raise(db, user_id)
|
||||
|
||||
|
||||
# Prevent self-modification
|
||||
if user.id == current_admin_id:
|
||||
raise CannotModifySelfException(user_id, "deactivate account")
|
||||
|
||||
|
||||
# Prevent admin-to-admin modification
|
||||
if user.role == "admin" and user.id != current_admin_id:
|
||||
raise UserStatusChangeException(
|
||||
@@ -214,7 +214,7 @@ from .base import BusinessLogicException, ResourceNotFoundException
|
||||
|
||||
class PaymentNotFoundException(ResourceNotFoundException):
|
||||
"""Raised when payment record is not found."""
|
||||
|
||||
|
||||
def __init__(self, payment_id: str):
|
||||
super().__init__(
|
||||
resource_type="Payment",
|
||||
@@ -225,7 +225,7 @@ class PaymentNotFoundException(ResourceNotFoundException):
|
||||
|
||||
class InsufficientFundsException(BusinessLogicException):
|
||||
"""Raised when account has insufficient funds."""
|
||||
|
||||
|
||||
def __init__(self, required: float, available: float, account_id: str):
|
||||
super().__init__(
|
||||
message=f"Insufficient funds. Required: {required}, Available: {available}",
|
||||
@@ -246,7 +246,7 @@ from .payment import PaymentNotFoundException, InsufficientFundsException
|
||||
|
||||
__all__ = [
|
||||
# ... existing exports
|
||||
"PaymentNotFoundException",
|
||||
"PaymentNotFoundException",
|
||||
"InsufficientFundsException",
|
||||
]
|
||||
```
|
||||
@@ -259,10 +259,10 @@ from app.exceptions import PaymentNotFoundException, InsufficientFundsException
|
||||
|
||||
def process_payment(self, db: Session, payment_id: str, amount: float):
|
||||
payment = self._get_payment_by_id_or_raise(db, payment_id)
|
||||
|
||||
|
||||
if payment.account_balance < amount:
|
||||
raise InsufficientFundsException(amount, payment.account_balance, payment.account_id)
|
||||
|
||||
|
||||
# Process payment...
|
||||
return payment
|
||||
```
|
||||
@@ -280,7 +280,7 @@ from app.exceptions.admin import UserNotFoundException, CannotModifySelfExceptio
|
||||
|
||||
def test_user_not_found_exception():
|
||||
exc = UserNotFoundException("123")
|
||||
|
||||
|
||||
assert exc.error_code == "USER_NOT_FOUND"
|
||||
assert exc.status_code == 404
|
||||
assert "123" in exc.message
|
||||
@@ -288,7 +288,7 @@ def test_user_not_found_exception():
|
||||
|
||||
def test_cannot_modify_self_exception():
|
||||
exc = CannotModifySelfException(456, "deactivate account")
|
||||
|
||||
|
||||
assert exc.error_code == "CANNOT_MODIFY_SELF"
|
||||
assert exc.status_code == 400
|
||||
assert "deactivate account" in exc.message
|
||||
@@ -303,7 +303,7 @@ Test complete error handling flow:
|
||||
def test_toggle_user_status_cannot_modify_self(client, admin_headers, test_admin):
|
||||
"""Test that admin cannot modify their own account"""
|
||||
response = client.put(
|
||||
f"/api/v1/admin/users/{test_admin.id}/status",
|
||||
f"/api/v1/admin/users/{test_admin.id}/status",
|
||||
headers=admin_headers
|
||||
)
|
||||
|
||||
@@ -352,14 +352,14 @@ def test_get_all_users_non_admin(client, auth_headers):
|
||||
- `INVALID_TOKEN`: Malformed or invalid token
|
||||
- `USER_NOT_ACTIVE`: User account is deactivated
|
||||
|
||||
### Authorization (403)
|
||||
### Authorization (403)
|
||||
- `ADMIN_REQUIRED`: Admin privileges required for operation
|
||||
- `INSUFFICIENT_PERMISSIONS`: User lacks required permissions
|
||||
- `UNAUTHORIZED_SHOP_ACCESS`: Cannot access shop (not owner)
|
||||
|
||||
### Resource Not Found (404)
|
||||
- `USER_NOT_FOUND`: User with specified ID not found
|
||||
- `SHOP_NOT_FOUND`: Shop with specified code/ID not found
|
||||
- `SHOP_NOT_FOUND`: Shop with specified code/ID not found
|
||||
- `PRODUCT_NOT_FOUND`: MarketplaceProduct with specified ID not found
|
||||
|
||||
### Business Logic (400)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the implementation of multi-language support for the Wizamart platform. The system supports four languages (English, French, German, Luxembourgish) with flexible configuration at store, user, and customer levels.
|
||||
This document describes the implementation of multi-language support for the Orion platform. The system supports four languages (English, French, German, Luxembourgish) with flexible configuration at store, user, and customer levels.
|
||||
|
||||
## Supported Languages
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ This document tracks the migration of legacy code to the self-contained module a
|
||||
|
||||
## Overview
|
||||
|
||||
The Wizamart platform has been migrating from a monolithic structure with code in centralized locations (`app/api/v1/`, `app/services/`, `models/`) to a fully modular architecture where each module owns all its entities (routes, services, models, schemas, tasks).
|
||||
The Orion platform has been migrating from a monolithic structure with code in centralized locations (`app/api/v1/`, `app/services/`, `models/`) to a fully modular architecture where each module owns all its entities (routes, services, models, schemas, tasks).
|
||||
|
||||
## Migration Goals
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This document establishes consistent naming conventions across the entire Wizamart multi-tenant ecommerce platform. Consistent naming improves code readability, reduces developer confusion, and ensures maintainable architecture.
|
||||
This document establishes consistent naming conventions across the entire Orion multi-tenant ecommerce platform. Consistent naming improves code readability, reduces developer confusion, and ensures maintainable architecture.
|
||||
|
||||
## Core Principles
|
||||
|
||||
@@ -481,4 +481,4 @@ Consider implementing linting rules or pre-commit hooks to enforce:
|
||||
**Last Updated:** November 2025
|
||||
**Maintained By:** Backend Team
|
||||
|
||||
This naming convention guide ensures consistent, maintainable, and intuitive code across the entire Wizamart multi-tenant ecommerce platform.
|
||||
This naming convention guide ensures consistent, maintainable, and intuitive code across the entire Orion multi-tenant ecommerce platform.
|
||||
|
||||
@@ -459,7 +459,7 @@ If you need to work immediately:
|
||||
```
|
||||
Host: localhost
|
||||
Port: 5432
|
||||
Database: wizamart_db
|
||||
Database: orion_db
|
||||
User: [from .env file]
|
||||
Password: [from .env file]
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user