64 lines
4.2 KiB
Python
64 lines
4.2 KiB
Python
import logging
|
|
import os
|
|
from datetime import datetime, timezone
|
|
from typing import Optional
|
|
|
|
|
|
def utcnow() -> datetime:
|
|
"""Return the current UTC time as a timezone-naive datetime.
|
|
|
|
SQLite (and SQLAlchemy's default column handling) stores datetimes without
|
|
timezone info. Using this helper keeps all DB timestamps and comparisons
|
|
consistent and avoids TypeError on offset-naive vs offset-aware comparisons.
|
|
"""
|
|
return datetime.now(timezone.utc).replace(tzinfo=None)
|
|
|
|
|
|
# ── Paths ─────────────────────────────────────────────────────────────────────
|
|
_HERE = os.path.dirname(os.path.abspath(__file__)) # src/core/
|
|
_SRC_DIR = os.path.dirname(_HERE) # src/
|
|
_PROJECT_ROOT = os.path.dirname(_SRC_DIR) # project root
|
|
DATA_DIR: str = os.path.join(_PROJECT_ROOT, "data")
|
|
|
|
# ── Logging ───────────────────────────────────────────────────────────────────
|
|
# LOG_LEVEL: one of DEBUG, INFO, WARNING, ERROR, CRITICAL (default: INFO)
|
|
LOG_LEVEL: int = getattr(logging, os.environ.get("LOG_LEVEL", "INFO").upper(), logging.INFO)
|
|
# LOG_FILE: set to empty string to disable file logging
|
|
LOG_FILE: str = os.environ.get("LOG_FILE", "")
|
|
|
|
# ── Security ──────────────────────────────────────────────────────────────────
|
|
SECRET_KEY: str = os.environ.get("SECRET_KEY") or ""
|
|
if not SECRET_KEY:
|
|
raise RuntimeError("SECRET_KEY environment variable must be set")
|
|
|
|
# ── Database ──────────────────────────────────────────────────────────────────
|
|
DATABASE_URL: str = os.environ.get(
|
|
"DATABASE_URL",
|
|
f"sqlite:///{os.path.join(DATA_DIR, 'gates.db')}",
|
|
)
|
|
|
|
# ── CORS ──────────────────────────────────────────────────────────────────────
|
|
# Comma-separated list of allowed origins, e.g. "https://example.com,https://app.example.com"
|
|
# Default to empty list (no cross-origin requests allowed) when not set.
|
|
_cors_env = os.environ.get("CORS_ORIGINS", "")
|
|
CORS_ORIGINS: list[str] = [o.strip() for o in _cors_env.split(",") if o.strip()]
|
|
|
|
# ── Proxy ─────────────────────────────────────────────────────────────────────
|
|
# Comma-separated list of trusted reverse-proxy IPs for X-Forwarded-For propagation.
|
|
# e.g. "127.0.0.1,10.0.0.1"
|
|
_proxy_env = os.environ.get("TRUSTED_PROXY_IPS", "127.0.0.1")
|
|
TRUSTED_PROXY_IPS: list[str] = [ip.strip() for ip in _proxy_env.split(",") if ip.strip()]
|
|
|
|
# ── Admin seed ────────────────────────────────────────────────────────────────
|
|
ADMIN_USERNAME: str = os.environ.get("ADMIN_USERNAME", "admin")
|
|
ADMIN_PASSWORD: Optional[str] = os.environ.get("ADMIN_PASSWORD") or None
|
|
|
|
# ── Server ────────────────────────────────────────────────────────────────────
|
|
APP_PORT: int = int(os.environ.get("APP_PORT", 8000))
|
|
|
|
# ── Map / home location ───────────────────────────────────────────────────────
|
|
# Optional WGS-84 coordinates for the "home" marker shown on the frontend map.
|
|
HOME_LAT: Optional[float] = float(os.environ["HOME_LAT"]) if os.environ.get("HOME_LAT") else None
|
|
HOME_LON: Optional[float] = float(os.environ["HOME_LON"]) if os.environ.get("HOME_LON") else None
|
|
HOME_NAME: str = os.environ.get("HOME_NAME", "Home")
|