Files
wfalkowski c177d7981d
Build and publish Docker image / build-and-publish (push) Successful in 2m45s
Refactor backend and add registry build workflow
2026-10-20 16:44:49 +00:00

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)