88 lines
3.6 KiB
Python
88 lines
3.6 KiB
Python
"""
|
|
Application Configuration
|
|
Environment-based settings with sensible defaults
|
|
"""
|
|
import os
|
|
import sys
|
|
import logging
|
|
from pathlib import Path
|
|
|
|
# Paths
|
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
FRONTEND_DIR = BASE_DIR / "frontend"
|
|
|
|
# Configure logging
|
|
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
|
|
logging.basicConfig(
|
|
level=getattr(logging, LOG_LEVEL, logging.INFO),
|
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
)
|
|
logger = logging.getLogger("org-parking")
|
|
|
|
# Database
|
|
DATABASE_PATH = os.getenv("DATABASE_PATH", "parking.db")
|
|
|
|
# Fix for local execution: if path is absolute (docker) but dir doesn't exist, fallback to local data/
|
|
if os.path.isabs(DATABASE_PATH) and not os.path.exists(os.path.dirname(DATABASE_PATH)):
|
|
# Check if we are aiming for /app/data but running locally
|
|
if str(DATABASE_PATH).startswith("/app/") or not os.access(os.path.dirname(DATABASE_PATH), os.W_OK):
|
|
logger.warning(f"Configured DATABASE_PATH '{DATABASE_PATH}' folder not found/writable. Switching to local 'data' directory.")
|
|
|
|
local_data_dir = BASE_DIR / "data"
|
|
local_data_dir.mkdir(exist_ok=True)
|
|
|
|
DATABASE_PATH = str(local_data_dir / os.path.basename(DATABASE_PATH))
|
|
logger.info(f"Using local database path: {DATABASE_PATH}")
|
|
|
|
DATABASE_URL = os.getenv("DATABASE_URL", f"sqlite:///{DATABASE_PATH}")
|
|
|
|
# JWT Authentication
|
|
SECRET_KEY = os.getenv("SECRET_KEY", "")
|
|
if not SECRET_KEY:
|
|
logger.error("FATAL: SECRET_KEY environment variable is required")
|
|
sys.exit(1)
|
|
if SECRET_KEY == "change-me-in-production":
|
|
logger.warning("WARNING: Using default SECRET_KEY - change this in production!")
|
|
|
|
ALGORITHM = "HS256"
|
|
ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "1440")) # 24 hours
|
|
|
|
# Server
|
|
HOST = os.getenv("HOST", "0.0.0.0")
|
|
PORT = int(os.getenv("PORT", "8000"))
|
|
|
|
# CORS
|
|
ALLOWED_ORIGINS = os.getenv("ALLOWED_ORIGINS", "http://localhost:8000,http://127.0.0.1:8000,http://lvh.me").split(",")
|
|
|
|
# Authelia Integration
|
|
AUTHELIA_ENABLED = os.getenv("AUTHELIA_ENABLED", "false").lower() == "true"
|
|
# Header names sent by Authelia
|
|
AUTHELIA_HEADER_USER = os.getenv("AUTHELIA_HEADER_USER", "Remote-User")
|
|
AUTHELIA_HEADER_NAME = os.getenv("AUTHELIA_HEADER_NAME", "Remote-Name")
|
|
AUTHELIA_HEADER_EMAIL = os.getenv("AUTHELIA_HEADER_EMAIL", "Remote-Email")
|
|
AUTHELIA_HEADER_GROUPS = os.getenv("AUTHELIA_HEADER_GROUPS", "Remote-Groups")
|
|
# Only parking_admins group is synced from LLDAP -> admin role
|
|
# Manager role and user assignments are managed by admin in the app UI
|
|
AUTHELIA_ADMIN_GROUP = os.getenv("AUTHELIA_ADMIN_GROUP", "parking_admins")
|
|
|
|
# External URLs for Authelia mode
|
|
# When AUTHELIA_ENABLED, login redirects to Authelia and register to external portal
|
|
AUTHELIA_LOGIN_URL = os.getenv("AUTHELIA_LOGIN_URL", "") # e.g., https://auth.rocketscale.it
|
|
REGISTRATION_URL = os.getenv("REGISTRATION_URL", "") # e.g., https://register.rocketscale.it
|
|
|
|
# Email configuration (following org-stack pattern)
|
|
SMTP_ENABLED = os.getenv("SMTP_ENABLED", "false").lower() == "true"
|
|
SMTP_HOST = os.getenv("SMTP_HOST", "localhost")
|
|
SMTP_PORT = int(os.getenv("SMTP_PORT", "587"))
|
|
SMTP_USER = os.getenv("SMTP_USER", "")
|
|
SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "")
|
|
SMTP_FROM = os.getenv("SMTP_FROM", SMTP_USER or "noreply@parking.local")
|
|
SMTP_USE_TLS = os.getenv("SMTP_USE_TLS", "true").lower() == "true"
|
|
EMAIL_LOG_FILE = os.getenv("EMAIL_LOG_FILE", "/tmp/parking-emails.log")
|
|
|
|
# Rate limiting
|
|
RATE_LIMIT_REQUESTS = int(os.getenv("RATE_LIMIT_REQUESTS", "5")) # requests per window
|
|
RATE_LIMIT_WINDOW = int(os.getenv("RATE_LIMIT_WINDOW", "60")) # seconds
|
|
|
|
|