88 lines
3.2 KiB
Python
88 lines
3.2 KiB
Python
"""Application settings and process-local state shared by services."""
|
|
|
|
import logging
|
|
import os
|
|
import secrets
|
|
import sys
|
|
import unicodedata
|
|
from threading import Lock
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
|
|
class TerminalFormatter(logging.Formatter):
|
|
"""Use readable, color-coded terminal logs without decorative symbols."""
|
|
|
|
_COLORS = {
|
|
logging.DEBUG: "\033[36m",
|
|
logging.INFO: "\033[32m",
|
|
logging.WARNING: "\033[33m",
|
|
logging.ERROR: "\033[31m",
|
|
logging.CRITICAL: "\033[1;31m",
|
|
}
|
|
_RESET = "\033[0m"
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__("%(asctime)s %(levelname)s %(name)s: %(message)s", "%H:%M:%S")
|
|
self._use_color = sys.stderr.isatty() and "NO_COLOR" not in os.environ
|
|
|
|
def format(self, record: logging.LogRecord) -> str:
|
|
line = super().format(record)
|
|
line = "".join(char for char in line if unicodedata.category(char) != "So")
|
|
if self._use_color:
|
|
return f"{self._COLORS.get(record.levelno, '')}{line}{self._RESET}"
|
|
return line
|
|
|
|
|
|
def _configure_logging() -> None:
|
|
handler = logging.StreamHandler()
|
|
handler.setFormatter(TerminalFormatter())
|
|
logging.basicConfig(level=logging.INFO, handlers=[handler], force=True)
|
|
|
|
|
|
load_dotenv()
|
|
_configure_logging()
|
|
logger = logging.getLogger("anchorhost")
|
|
|
|
JWT_SECRET = os.environ.get("JWT_SECRET")
|
|
if not JWT_SECRET:
|
|
JWT_SECRET = secrets.token_urlsafe(48)
|
|
logger.warning("JWT_SECRET is not configured; issued tokens will be invalidated on restart")
|
|
elif JWT_SECRET == "change-me-in-production" or len(JWT_SECRET) < 32:
|
|
raise RuntimeError("JWT_SECRET must be a non-placeholder value of at least 32 characters")
|
|
|
|
ALLOWED_ORIGINS = (
|
|
"http://localhost:3000",
|
|
"https://anchorhost.eu",
|
|
"https://www.anchorhost.eu",
|
|
)
|
|
SALT_ROUNDS = 12
|
|
PORT = int(os.environ.get("PORT", 8080))
|
|
WS_PORT = int(os.environ.get("WS_PORT", 8081))
|
|
DATABASE_URL = os.environ.get("DATABASE_URL", "anchorhost.db")
|
|
STRIPE_SECRET_KEY = os.environ.get("STRIPE_SECRET_KEY", "")
|
|
STRIPE_WEBHOOK_SECRET = os.environ.get("STRIPE_WEBHOOK_SECRET", "")
|
|
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", "")
|
|
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", "")
|
|
GOOGLE_REDIRECT_URI = os.environ.get("GOOGLE_REDIRECT_URI", "https://anchorhost.eu/api/auth/google/callback")
|
|
APPLE_CLIENT_ID = os.environ.get("APPLE_CLIENT_ID", "")
|
|
APPLE_TEAM_ID = os.environ.get("APPLE_TEAM_ID", "")
|
|
APPLE_KEY_ID = os.environ.get("APPLE_KEY_ID", "")
|
|
APPLE_PRIVATE_KEY = os.environ.get("APPLE_PRIVATE_KEY", "").replace("\\n", "\n")
|
|
APPLE_REDIRECT_URI = os.environ.get("APPLE_REDIRECT_URI", "https://anchorhost.eu/api/auth/apple/callback")
|
|
NODE_IP = os.environ.get("NODE_IP", "IP")
|
|
MODRINTH_API_BASE = "https://api.modrinth.com/v2"
|
|
EXCHANGE_RATE_CACHE = {
|
|
"rates": {"EUR": 0.92, "GBP": 0.79, "PLN": 4.15, "PHP": 56.8, "CZK": 23.2},
|
|
"last_updated": None,
|
|
}
|
|
EXCHANGE_RATE_LOCK = Lock()
|
|
CACHE_DURATION = 3600
|
|
STRIPE_CURRENCY_MAP = {"USD": "usd", "EUR": "eur", "GBP": "gbp", "PLN": "pln", "PHP": "php", "CZK": "czk"}
|
|
connected_clients = {}
|
|
ssh_sessions = {}
|
|
node_sessions = {}
|
|
chunked_uploads = {}
|
|
CHUNK_UPLOAD_DIR = "/tmp/chunk_uploads"
|
|
os.makedirs(CHUNK_UPLOAD_DIR, exist_ok=True)
|