first commit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import model_validator
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
model_config = SettingsConfigDict(
|
||||
env_file=".env",
|
||||
env_file_encoding="utf-8",
|
||||
extra="ignore",
|
||||
)
|
||||
|
||||
app_name: str = "OpenCloud API"
|
||||
environment: Literal["development", "test", "production"] = "development"
|
||||
api_v1_prefix: str = "/api/v1"
|
||||
debug: bool = False
|
||||
|
||||
database_url: str
|
||||
database_pool_size: int = 10
|
||||
database_max_overflow: int = 20
|
||||
|
||||
secret_key: str
|
||||
jwt_algorithm: str = "HS256"
|
||||
access_token_expire_minutes: int = 15
|
||||
refresh_token_expire_days: int = 30
|
||||
|
||||
refresh_cookie_name: str = "opencloud_refresh"
|
||||
cookie_secure: bool = False
|
||||
cookie_samesite: Literal["lax", "strict", "none"] = "lax"
|
||||
cookie_domain: str | None = None
|
||||
|
||||
frontend_url: str = "http://localhost:5173"
|
||||
public_base_url: str = "http://localhost:8000"
|
||||
cors_origins: str = "http://localhost:5173"
|
||||
|
||||
upload_dir: Path = Path("data/uploads")
|
||||
max_upload_bytes: int = 20 * 1024 * 1024
|
||||
max_image_pixels: int = 50_000_000
|
||||
thumbnail_max_edge: int = 640
|
||||
|
||||
email_delivery_mode: Literal["console", "smtp"] = "console"
|
||||
smtp_host: str | None = None
|
||||
smtp_port: int = 587
|
||||
smtp_username: str | None = None
|
||||
smtp_password: str | None = None
|
||||
smtp_starttls: bool = True
|
||||
email_from: str = "OpenCloud <no-reply@opencloud.local>"
|
||||
email_confirmation_expire_hours: int = 24
|
||||
password_reset_expire_minutes: int = 30
|
||||
|
||||
admin_email: str | None = None
|
||||
admin_password: str | None = None
|
||||
admin_username: str = "管理员"
|
||||
|
||||
@property
|
||||
def cors_origin_list(self) -> list[str]:
|
||||
return [item.strip() for item in self.cors_origins.split(",") if item.strip()]
|
||||
|
||||
@property
|
||||
def media_base_url(self) -> str:
|
||||
return f"{self.public_base_url.rstrip('/')}/media"
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_production_settings(self) -> "Settings":
|
||||
if self.environment == "production":
|
||||
if self.secret_key.startswith("change-me") or len(self.secret_key) < 32:
|
||||
raise ValueError("生产环境必须配置至少 32 个字符的 SECRET_KEY")
|
||||
if not self.cookie_secure:
|
||||
raise ValueError("生产环境必须启用 COOKIE_SECURE")
|
||||
if self.email_delivery_mode == "smtp" and not self.smtp_host:
|
||||
raise ValueError("SMTP 模式必须配置 SMTP_HOST")
|
||||
return self
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_settings() -> Settings:
|
||||
return Settings()
|
||||
|
||||
|
||||
settings = get_settings()
|
||||
Reference in New Issue
Block a user