78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
from functools import lru_cache
|
|
from ipaddress import IPv4Network, IPv6Network, ip_network
|
|
from pathlib import Path
|
|
from typing import Literal
|
|
|
|
from pydantic import Field, SecretStr, field_validator
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
|
|
|
|
|
class AppSettings(BaseSettings):
|
|
model_config = SettingsConfigDict(
|
|
env_file=PROJECT_ROOT / ".env",
|
|
env_prefix="ROTATOR_",
|
|
extra="ignore",
|
|
)
|
|
|
|
app_name: str = "FluxIP"
|
|
environment: Literal["development", "test", "production"] = "development"
|
|
host: str = "127.0.0.1"
|
|
port: int = Field(default=8787, ge=1, le=65535)
|
|
database_path: Path = PROJECT_ROOT / "data" / "fluxip.db"
|
|
master_key_file: Path = PROJECT_ROOT / "data" / "master.key"
|
|
master_key: str | None = None
|
|
bootstrap_token: SecretStr | None = None
|
|
cookie_secure: bool = False
|
|
session_days: int = Field(default=7, ge=1, le=90)
|
|
allowed_origins: str = "http://localhost:8787,http://127.0.0.1:8787"
|
|
trusted_hosts: str = "localhost,127.0.0.1"
|
|
trusted_proxies: str = "127.0.0.1,::1"
|
|
scheduler_enabled: bool = True
|
|
scheduler_tick_seconds: int = Field(default=10, ge=2, le=60)
|
|
log_level: str = "INFO"
|
|
external_timeout_seconds: int = Field(default=20, ge=5, le=60)
|
|
|
|
@field_validator("database_path", "master_key_file", mode="before")
|
|
@classmethod
|
|
def resolve_path(cls, value: str | Path) -> Path:
|
|
path = Path(value)
|
|
return path if path.is_absolute() else PROJECT_ROOT / path
|
|
|
|
@field_validator("bootstrap_token", mode="before")
|
|
@classmethod
|
|
def normalize_optional_secret(cls, value: object) -> object:
|
|
return None if value is None or not str(value).strip() else value
|
|
|
|
@field_validator("trusted_proxies")
|
|
@classmethod
|
|
def validate_trusted_proxies(cls, value: str) -> str:
|
|
for item in value.split(","):
|
|
if item.strip():
|
|
ip_network(item.strip(), strict=False)
|
|
return value
|
|
|
|
@property
|
|
def origins(self) -> list[str]:
|
|
return [value.strip() for value in self.allowed_origins.split(",") if value.strip()]
|
|
|
|
@property
|
|
def hosts(self) -> list[str]:
|
|
return [value.strip() for value in self.trusted_hosts.split(",") if value.strip()]
|
|
|
|
@property
|
|
def proxy_networks(self) -> tuple[IPv4Network | IPv6Network, ...]:
|
|
return tuple(
|
|
ip_network(value.strip(), strict=False)
|
|
for value in self.trusted_proxies.split(",")
|
|
if value.strip()
|
|
)
|
|
|
|
|
|
@lru_cache
|
|
def get_settings() -> AppSettings:
|
|
return AppSettings()
|