Files
amb_rag/backend/app/core/config.py
T
2026-09-02 17:08:52 +08:00

85 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""全局配置:pydantic-settings,全部来自环境变量 / .env。
规则:
- 密钥不得硬编码;SECRET_KEY 缺失或仍为模板值时,生产环境拒绝启动。
- DATABASE_URL 支持 MySQL / SQLite。
"""
from functools import lru_cache
from pathlib import Path
from pydantic import Field
from pydantic_settings import BaseSettings, SettingsConfigDict
_TEMPLATE_MARKERS = ("change-me",)
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", extra="ignore")
# --- 基础 ---
environment: str = "local" # local / production
secret_key: str = Field(min_length=16)
# Cookie Secure 标记:默认跟随 environmentproduction→Secure)。
# 站点还是 HTTP 时必须显式设为 false,否则浏览器丢弃 Cookie 导致登录后立即被踢回。
cookie_secure: bool | None = None
# --- 数据库 ---
database_url: str = "mysql+pymysql://admin:Lzcc6-01@47.109.98.44:33306/amb_rag?charset=utf8mb4"
# --- 文件存储 ---
storage_root: str = "./data"
# --- 套餐 ---
default_storage_quota: int = 104_857_600 # 100 MB
default_max_file_size: int = 20_971_520 # 20 MB
# --- 限流 ---
rate_limit_per_token_per_min: int = 60
rate_limit_per_ip_per_min: int = 30
# --- CORS ---
frontend_origin: str = "http://localhost:5173"
@property
def is_production(self) -> bool:
return self.environment == "production"
@property
def use_secure_cookie(self) -> bool:
"""HTTPS 站点才应启用 Secure Cookie;未显式配置时跟随 environment。"""
if self.cookie_secure is not None:
return self.cookie_secure
return self.is_production
@property
def is_mysql(self) -> bool:
return "mysql" in self.database_url
@property
def is_sqlite(self) -> bool:
return "sqlite" in self.database_url
@property
def storage_root_path(self) -> Path:
return Path(self.storage_root).resolve()
def validate_secrets(self) -> None:
"""生产环境禁止携带模板密钥启动。"""
if not self.is_production:
return
for field_name in ("secret_key",):
value = getattr(self, field_name).lower()
if any(marker in value for marker in _TEMPLATE_MARKERS):
raise RuntimeError(
f"配置错误:{field_name} 仍为模板值,生产环境禁止启动。"
"请运行: python -c \"import secrets; print(secrets.token_urlsafe(48))\""
)
@lru_cache
def get_settings() -> Settings:
s = Settings() # type: ignore[call-arg]
s.validate_secrets()
return s