feat(proj): init
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from pydantic import field_validator
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
class ApiSettings(BaseSettings):
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=BASE_DIR / ".env",
|
||||
env_file_encoding="utf-8",
|
||||
extra="ignore",
|
||||
)
|
||||
|
||||
database_path: Path = BASE_DIR / "data" / "budget.db"
|
||||
bot_token: str
|
||||
# Shared secret for bot (/api/auth/internal) and admin /api/budgets/*
|
||||
api_token: str | None = None
|
||||
jwt_secret: str | None = None
|
||||
jwt_ttl_seconds: int = 60 * 60 * 24 * 14
|
||||
telegram_auth_max_age_seconds: int = 60 * 60 * 24
|
||||
cors_origins: str = "*"
|
||||
host: str = "0.0.0.0"
|
||||
port: int = 8000
|
||||
|
||||
@field_validator("bot_token", mode="before")
|
||||
@classmethod
|
||||
def require_bot_token(cls, value: object) -> object:
|
||||
if value is None or (isinstance(value, str) and not value.strip()):
|
||||
raise ValueError("BOT_TOKEN is required for Telegram login")
|
||||
return value
|
||||
|
||||
@field_validator("api_token", "jwt_secret", mode="before")
|
||||
@classmethod
|
||||
def empty_as_none(cls, value: object) -> object:
|
||||
if isinstance(value, str) and not value.strip():
|
||||
return None
|
||||
return value
|
||||
|
||||
@property
|
||||
def session_secret(self) -> str:
|
||||
return self.jwt_secret or f"ppm-jwt::{self.bot_token}"
|
||||
|
||||
@property
|
||||
def cors_origin_list(self) -> list[str]:
|
||||
return [item.strip() for item in self.cors_origins.split(",") if item.strip()]
|
||||
|
||||
|
||||
settings = ApiSettings()
|
||||
Reference in New Issue
Block a user