79 lines
2.4 KiB
Python
79 lines
2.4 KiB
Python
from pydantic_settings import BaseSettings
|
|
from typing import Optional
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
# App
|
|
APP_NAME: str = "企迹-政企周报管理系统"
|
|
ENVIRONMENT: str = "production"
|
|
DEBUG: bool = False
|
|
SECRET_KEY: str = ""
|
|
|
|
# Database
|
|
# A syntactically valid non-working placeholder keeps tooling imports side-effect free.
|
|
DATABASE_URL: str = "postgresql+asyncpg://qiji_app:invalid@localhost:5432/qiji"
|
|
|
|
# JWT
|
|
JWT_ALGORITHM: str = "HS256"
|
|
JWT_EXPIRE_MINUTES: int = 480
|
|
|
|
# Casdoor
|
|
CASDOOR_ENDPOINT: str = "http://localhost:8001"
|
|
CASDOOR_CLIENT_ID: str = ""
|
|
CASDOOR_CLIENT_SECRET: str = ""
|
|
CASDOOR_CERTIFICATE: Optional[str] = None
|
|
CASDOOR_ORG_NAME: str = "qiji"
|
|
CASDOOR_APPLICATION: str = "qiji-weekly-report"
|
|
|
|
# MinIO
|
|
MINIO_ENDPOINT: str = ""
|
|
MINIO_ACCESS_KEY: str = ""
|
|
MINIO_SECRET_KEY: str = ""
|
|
MINIO_BUCKET: str = "qiji-photos"
|
|
MINIO_SECURE: bool = True
|
|
|
|
# WeChat Work
|
|
WECOM_CORP_ID: str = ""
|
|
WECOM_AGENT_ID: str = ""
|
|
WECOM_SECRET: str = ""
|
|
WECOM_TOKEN: str = ""
|
|
WECOM_ENCODING_AES_KEY: str = ""
|
|
WECOM_API_BASE: str = "https://qyapi.weixin.qq.com"
|
|
|
|
# AI / LLM (OpenAI-compatible)
|
|
AI_API_URL: str = ""
|
|
AI_API_KEY: str = ""
|
|
AI_MODEL: str = "gpt-4o"
|
|
AI_MAX_TOKENS: int = 2000
|
|
|
|
# CORS
|
|
CORS_ORIGINS: list[str] = ["http://localhost:5173", "http://localhost:3000"]
|
|
|
|
class Config:
|
|
env_file = ".env"
|
|
env_file_encoding = "utf-8"
|
|
|
|
|
|
settings = Settings()
|
|
|
|
|
|
def validate_security_settings() -> None:
|
|
"""Reject unsafe or incomplete configuration before the application starts."""
|
|
if settings.ENVIRONMENT.lower() == "development":
|
|
return
|
|
|
|
invalid = []
|
|
if len(settings.SECRET_KEY) < 32 or settings.SECRET_KEY in {"change-me-in-production", ""}:
|
|
invalid.append("SECRET_KEY")
|
|
if not settings.DATABASE_URL or "postgres:postgres@" in settings.DATABASE_URL or ":invalid@" in settings.DATABASE_URL:
|
|
invalid.append("DATABASE_URL")
|
|
if not settings.MINIO_ENDPOINT or not settings.MINIO_ACCESS_KEY or not settings.MINIO_SECRET_KEY:
|
|
invalid.append("MINIO configuration")
|
|
if settings.MINIO_ACCESS_KEY == "minioadmin" or settings.MINIO_SECRET_KEY == "minioadmin":
|
|
invalid.append("MINIO default credentials")
|
|
if not settings.MINIO_SECURE:
|
|
invalid.append("MINIO_SECURE")
|
|
|
|
if invalid:
|
|
raise RuntimeError(f"Unsafe production configuration: {', '.join(invalid)}")
|