LifeRPG_v2.0/modern/backend/config.py
TLimoges33 2b961611fd
🚀 Major Enhancement: Complete AI-Powered LifeRPG Platform with Git LFS
 New Features:
- AI-powered habit creation with natural language processing
- HuggingFace transformers integration for sentiment analysis (tracked via Git LFS)
- Advanced predictive analytics and behavioral insights
- Voice & image input capabilities for hands-free habit tracking
- Real-time notifications and community features
- Plugin system with extensible architecture

🔧 Technical Improvements:
- Comprehensive FastAPI backend with 30+ endpoints
- React frontend with PWA capabilities
- Advanced authentication with 2FA support
- RBAC authorization system
- Comprehensive security features (CSRF, rate limiting, audit logging)
- Database migrations and health monitoring
- Docker containerization support
- Git LFS configured for large AI model files (2+ GB)

📚 Documentation & DevOps:
- Complete deployment guides for multiple platforms
- Professional README with feature highlights
- GitHub Actions CI/CD workflows
- Comprehensive API documentation
- Security audit roadmap and compliance framework
- Setup scripts for development environment

🧪 Testing & Quality:
- Comprehensive test suite with 20+ test modules
- Setup verification scripts
- Working development environment with both backend and frontend
- Health checks and monitoring systems

🌟 Ready for:
- Portfolio showcasing
- Community contributions
- Production deployment
- Professional presentation
2025-09-28 21:29:19 +00:00

98 lines
3.8 KiB
Python

import os
from typing import List, Dict, Optional
import json
def getenv_bool(name: str, default: bool = False) -> bool:
val = os.getenv(name)
if val is None:
return default
return str(val).strip().lower() in {"1", "true", "yes", "on"}
def parse_csv_env(name: str) -> List[str]:
raw = os.getenv(name)
if not raw:
return []
return [part.strip() for part in raw.split(',') if part.strip()]
class Settings:
def __init__(self) -> None:
# CORS / Origins
origins = parse_csv_env("FRONTEND_ORIGINS")
if not origins:
single = os.getenv("FRONTEND_ORIGIN", "http://localhost:5173")
origins = [single]
self.FRONTEND_ORIGINS: List[str] = origins
# HTTPS and cookies
self.FORCE_HTTPS: bool = getenv_bool("FORCE_HTTPS", False)
self.HSTS_ENABLE: bool = getenv_bool("HSTS_ENABLE", False)
self.COOKIE_SECURE: bool = getenv_bool("COOKIE_SECURE", False)
self.COOKIE_SAMESITE: str = os.getenv("COOKIE_SAMESITE", "lax")
# CSP extras
extra = parse_csv_env("CSP_CONNECT_EXTRA")
if not extra:
extra = ["https://www.googleapis.com"]
self.CSP_CONNECT_EXTRA: List[str] = extra
# CSRF - enable by default for security
self.CSRF_ENABLE: bool = getenv_bool("CSRF_ENABLE", True)
self.CSRF_HEADER_NAME: str = os.getenv("CSRF_HEADER_NAME", "x-csrf-token")
self.CSRF_COOKIE_NAME: str = os.getenv("CSRF_COOKIE_NAME", "csrf_token")
# Integrations behavior
self.INTEGRATION_CLOSE_MODE: str = os.getenv("INTEGRRATION_CLOSE_MODE", "archive").lower() if os.getenv("INTEGRRATION_CLOSE_MODE") else os.getenv("INTEGRATION_CLOSE_MODE", "archive").lower()
# Email / SMTP
self.EMAIL_TRANSPORT: str = os.getenv("LIFERPG_EMAIL_TRANSPORT", "console").lower() # console|smtp|disabled
self.SMTP_HOST: Optional[str] = os.getenv("SMTP_HOST")
self.SMTP_PORT: int = int(os.getenv("SMTP_PORT", "587"))
self.SMTP_USERNAME: Optional[str] = os.getenv("SMTP_USERNAME")
self.SMTP_PASSWORD: Optional[str] = os.getenv("SMTP_PASSWORD")
self.SMTP_USE_TLS: bool = getenv_bool("SMTP_USE_TLS", True)
self.SMTP_FROM: Optional[str] = os.getenv("SMTP_FROM", os.getenv("SMTP_USER", None))
# Provider concurrency caps (optional per-provider overrides)
# Example env: SYNC_PROVIDER_CAPS='{"todoist":2,"github":3}'
caps_raw = os.getenv("SYNC_PROVIDER_CAPS")
caps: Dict[str, int] = {}
if caps_raw:
try:
data = json.loads(caps_raw)
if isinstance(data, dict):
for k, v in data.items():
try:
iv = int(v)
if iv > 0:
caps[str(k)] = iv
except Exception:
continue
except Exception:
caps = {}
self.PROVIDER_CAPS: Dict[str, int] = caps
self.DEFAULT_PROVIDER_CAP: int = int(os.getenv('SYNC_MAX_CONCURRENCY_PER_PROVIDER', '4'))
def csp_header(self) -> str:
connect_src = " ".join(["'self'", *self.CSP_CONNECT_EXTRA])
# Enhanced CSP for better security
csp_directives = [
"default-src 'self'",
"frame-ancestors 'none'",
"base-uri 'self'",
"object-src 'none'",
"img-src 'self' data: https:",
f"connect-src {connect_src}",
"script-src 'self'",
"style-src 'self' 'unsafe-inline'",
"font-src 'self'",
"form-action 'self'",
"upgrade-insecure-requests" if self.FORCE_HTTPS else "",
]
return "; ".join([directive for directive in csp_directives if directive])
settings = Settings()