78 lines
2.4 KiB
Python
78 lines
2.4 KiB
Python
# app/core/settings/app.py
|
||
import logging
|
||
import sys
|
||
from typing import Any, Dict, List, Tuple, Optional
|
||
|
||
from loguru import logger
|
||
from pydantic import PostgresDsn, SecretStr, EmailStr
|
||
|
||
from app.core.logging import InterceptHandler
|
||
from app.core.settings.base import BaseAppSettings
|
||
|
||
|
||
class AppSettings(BaseAppSettings):
|
||
# ===== 基本 FastAPI 设置 =====
|
||
debug: bool = False
|
||
docs_url: str = "/docs"
|
||
openapi_prefix: str = ""
|
||
openapi_url: str = "/openapi.json"
|
||
redoc_url: str = "/redoc"
|
||
title: str = "FastAPI example application"
|
||
version: str = "0.0.0"
|
||
|
||
# ===== 数据库 =====
|
||
database_url: PostgresDsn
|
||
max_connection_count: int = 10
|
||
min_connection_count: int = 10
|
||
|
||
# ===== 安全/JWT =====
|
||
secret_key: SecretStr
|
||
api_prefix: str = "/api"
|
||
jwt_token_prefix: str = "Token"
|
||
|
||
# ===== CORS/Host =====
|
||
allowed_hosts: List[str] = ["*"]
|
||
|
||
# ===== 日志 =====
|
||
logging_level: int = logging.INFO
|
||
loggers: Tuple[str, str] = ("uvicorn.asgi", "uvicorn.access")
|
||
|
||
# ===== 邮件/验证码(新增配置) =====
|
||
mail_from: EmailStr = "no-reply@example.com"
|
||
|
||
# SMTP 基础(兼容 Py3.9:使用 Optional[...])
|
||
smtp_host: str = "localhost"
|
||
smtp_port: int = 25
|
||
smtp_user: Optional[SecretStr] = None
|
||
smtp_password: Optional[SecretStr] = None
|
||
smtp_tls: bool = False # True 时将尝试 STARTTLS
|
||
|
||
# 验证码配置
|
||
email_code_expires_minutes: int = 10
|
||
email_code_scenes: Tuple[str, ...] = ("register", "reset", "login")
|
||
|
||
# ===== 管理员自动信任的邮箱(逗号分隔,登录后自动授予 admin <20>?=====
|
||
admin_emails: List[str] = []
|
||
|
||
class Config:
|
||
validate_assignment = True
|
||
|
||
@property
|
||
def fastapi_kwargs(self) -> Dict[str, Any]:
|
||
return {
|
||
"debug": self.debug,
|
||
"docs_url": self.docs_url,
|
||
"openapi_prefix": self.openapi_prefix,
|
||
"openapi_url": self.openapi_url,
|
||
"redoc_url": self.redoc_url,
|
||
"title": self.title,
|
||
"version": self.version,
|
||
}
|
||
|
||
def configure_logging(self) -> None:
|
||
logging.getLogger().handlers = [InterceptHandler()]
|
||
for logger_name in self.loggers:
|
||
logging_logger = logging.getLogger(logger_name)
|
||
logging_logger.handlers = [InterceptHandler(level=self.logging_level)]
|
||
logger.configure(handlers=[{"sink": sys.stderr, "level": self.logging_level}])
|