Files
orion/app/core/config.py
Samir Boulahtit e9253fbd84 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>
2026-02-14 16:46:56 +01:00

367 lines
13 KiB
Python

# app/core/config.py
"""
Application configuration using Pydantic Settings.
This module provides classes and functions for:
- Configuration management via environment variables
- Database settings
- JWT and authentication configuration
- Platform domain and multi-tenancy settings
- Admin initialization settings
Note: Environment detection is handled by app.core.environment module.
This module focuses purely on configuration storage and validation.
"""
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
"""
Settings class for application configuration.
Environment detection is delegated to app.core.environment.
This class focuses on configuration values only.
"""
# =============================================================================
# PROJECT INFORMATION
# =============================================================================
project_name: str = "Orion - Multi-Store Marketplace Platform"
version: str = "2.2.0"
# Clean description without HTML
description: str = """
Marketplace product import and management system with multi-store support.
**Features:**
- JWT Authentication with role-based access
- Multi-marketplace product import (CSV processing)
- Inventory management across multiple locations
- Store management with individual configurations
**Documentation:** Visit /documentation for complete guides
**API Testing:** Use /docs for interactive API exploration
"""
# =============================================================================
# DATABASE (PostgreSQL only)
# =============================================================================
database_url: str = "postgresql://orion_user:secure_password@localhost:5432/orion_db"
# =============================================================================
# ADMIN INITIALIZATION (for init_production.py)
# =============================================================================
admin_email: str = "admin@orion.lu"
admin_username: str = "admin"
admin_password: str = "admin123" # CHANGE IN PRODUCTION!
admin_first_name: str = "Platform"
admin_last_name: str = "Administrator"
# =============================================================================
# JWT AUTHENTICATION
# =============================================================================
jwt_secret_key: str = "change-this-in-production"
jwt_expire_hours: int = 24
jwt_expire_minutes: int = 30
# =============================================================================
# API SERVER
# =============================================================================
api_host: str = "0.0.0.0"
api_port: int = 8000
debug: bool = True
# =============================================================================
# DOCUMENTATION
# =============================================================================
documentation_url: str = "http://localhost:8001"
# =============================================================================
# MIDDLEWARE & SECURITY
# =============================================================================
allowed_hosts: list[str] = ["*"] # Configure for production
# Rate Limiting
rate_limit_enabled: bool = True
rate_limit_requests: int = 100
rate_limit_window: int = 3600
# =============================================================================
# LOGGING
# =============================================================================
log_level: str = "INFO"
log_file: str | None = None
# =============================================================================
# PLATFORM DOMAIN CONFIGURATION
# =============================================================================
platform_domain: str = "orion.lu"
# Custom domain features
allow_custom_domains: bool = True
require_domain_verification: bool = True
# SSL/TLS configuration for custom domains
ssl_provider: str = "letsencrypt" # or "cloudflare", "manual"
auto_provision_ssl: bool = False
# DNS verification
dns_verification_prefix: str = "_orion-verify"
dns_verification_ttl: int = 3600
# =============================================================================
# PLATFORM LIMITS
# =============================================================================
max_stores_per_user: int = 5
max_team_members_per_store: int = 50
invitation_expiry_days: int = 7
# =============================================================================
# STRIPE BILLING
# =============================================================================
stripe_secret_key: str = ""
stripe_publishable_key: str = ""
stripe_webhook_secret: str = ""
stripe_trial_days: int = 30 # 1-month free trial (card collected upfront but not charged)
# =============================================================================
# EMAIL CONFIGURATION
# =============================================================================
# Provider: smtp, sendgrid, mailgun, ses
email_provider: str = "smtp"
email_from_address: str = "noreply@orion.lu"
email_from_name: str = "Orion"
email_reply_to: str = "" # Optional reply-to address
# SMTP Settings (used when email_provider=smtp)
smtp_host: str = "localhost"
smtp_port: int = 587
smtp_user: str = ""
smtp_password: str = ""
smtp_use_tls: bool = True
smtp_use_ssl: bool = False # For port 465
# SendGrid (used when email_provider=sendgrid)
sendgrid_api_key: str = ""
# Mailgun (used when email_provider=mailgun)
mailgun_api_key: str = ""
mailgun_domain: str = ""
# Amazon SES (used when email_provider=ses)
aws_access_key_id: str = ""
aws_secret_access_key: str = ""
aws_region: str = "eu-west-1"
# Email behavior
email_enabled: bool = True # Set to False to disable all emails
email_debug: bool = False # Log emails instead of sending (for development)
# =============================================================================
# STOREFRONT DEFAULTS
# =============================================================================
# These can be overridden by AdminSetting in the database
default_storefront_locale: str = "fr-LU" # Currency/number formatting locale
default_currency: str = "EUR" # Default currency code
# =============================================================================
# DEMO/SEED DATA CONFIGURATION
# =============================================================================
# Controls for demo data seeding
seed_demo_stores: int = 3 # Number of demo stores to create
seed_customers_per_store: int = 15 # Customers per store
seed_products_per_store: int = 20 # Products per store
seed_orders_per_store: int = 10 # Orders per store
# =============================================================================
# CELERY / REDIS TASK QUEUE
# =============================================================================
# Redis URL for Celery broker and result backend
redis_url: str = "redis://localhost:6379/0"
# Feature flag: enable Celery for background tasks (False = use FastAPI BackgroundTasks)
use_celery: bool = False
# Flower monitoring dashboard
flower_url: str = "http://localhost:5555"
flower_password: str = "changeme" # CHANGE IN PRODUCTION!
# =============================================================================
# SENTRY ERROR TRACKING
# =============================================================================
sentry_dsn: str | None = None # Set to enable Sentry
sentry_environment: str = "development" # development, staging, production
sentry_traces_sample_rate: float = 0.1 # 10% of transactions for performance monitoring
# =============================================================================
# CLOUDFLARE R2 STORAGE
# =============================================================================
storage_backend: str = "local" # "local" or "r2"
r2_account_id: str | None = None
r2_access_key_id: str | None = None
r2_secret_access_key: str | None = None
r2_bucket_name: str = "orion-media"
r2_public_url: str | None = None # Custom domain for public access (e.g., https://media.yoursite.com)
# =============================================================================
# CLOUDFLARE CDN / PROXY
# =============================================================================
cloudflare_enabled: bool = False # Set to True when using CloudFlare proxy
model_config = {"env_file": ".env"}
# Singleton settings instance
settings = Settings()
# =============================================================================
# ENVIRONMENT UTILITIES - Module-level functions
# =============================================================================
# Import environment detection utilities
from app.core.environment import (
get_environment,
is_development,
is_production,
is_staging,
should_use_secure_cookies,
)
def get_current_environment() -> str:
"""
Get current environment.
Convenience function that delegates to app.core.environment.
Use this when you need just the environment string.
"""
return get_environment()
def is_production_environment() -> bool:
"""
Check if running in production.
Convenience function that delegates to app.core.environment.
Use this for production-specific logic.
"""
return is_production()
def is_development_environment() -> bool:
"""
Check if running in development.
Convenience function that delegates to app.core.environment.
Use this for development-specific logic.
"""
return is_development()
def is_staging_environment() -> bool:
"""
Check if running in staging.
Convenience function that delegates to app.core.environment.
Use this for staging-specific logic.
"""
return is_staging()
# =============================================================================
# VALIDATION FUNCTIONS
# =============================================================================
def validate_database_url() -> None:
"""
Validate that database URL is PostgreSQL.
Raises:
ValueError: If database URL is not PostgreSQL
"""
if settings.database_url.startswith("sqlite"):
raise ValueError(
"SQLite is not supported. Please use PostgreSQL.\n"
"Set DATABASE_URL environment variable to a PostgreSQL connection string.\n"
"Example: postgresql://user:password@localhost:5432/dbname\n"
"For local development, run: docker-compose up -d db"
)
if not settings.database_url.startswith("postgresql"):
raise ValueError(
f"Unsupported database: {settings.database_url.split(':')[0]}\n"
"Only PostgreSQL is supported."
)
def validate_production_settings() -> list[str]:
"""
Validate settings for production environment.
Returns:
List of warning messages if configuration is insecure
"""
warnings = []
if is_production():
# Check for default/insecure values
if settings.admin_password == "admin123":
warnings.append("⚠️ Using default admin password in production!")
if settings.jwt_secret_key == "change-this-in-production":
warnings.append("⚠️ Using default JWT secret key in production!")
if settings.debug:
warnings.append("⚠️ Debug mode enabled in production!")
if "*" in settings.allowed_hosts:
warnings.append("⚠️ ALLOWED_HOSTS is set to wildcard (*) in production!")
return warnings
def print_environment_info():
"""Print current environment configuration."""
print("\n" + "=" * 70)
print(f" ENVIRONMENT: {get_environment().upper()}")
print("=" * 70)
print(f" Database: {settings.database_url}")
print(f" Debug mode: {settings.debug}")
print(f" API port: {settings.api_port}")
print(f" Platform: {settings.platform_domain}")
print(f" Secure cookies: {should_use_secure_cookies()}")
print("=" * 70 + "\n")
# Show warnings if in production
if is_production():
warnings = validate_production_settings()
if warnings:
print("\n⚠️ PRODUCTION WARNINGS:")
for warning in warnings:
print(f" {warning}")
print()
# =============================================================================
# PUBLIC API
# =============================================================================
__all__ = [
# Settings singleton
"settings",
# Environment detection (re-exported from app.core.environment)
"get_environment",
"is_development",
"is_production",
"is_staging",
"should_use_secure_cookies",
# Convenience functions
"get_current_environment",
"is_production_environment",
"is_development_environment",
"is_staging_environment",
# Validation
"validate_database_url",
"validate_production_settings",
"print_environment_info",
]