fix(core): stabilize editor lifecycle, transactional versions, and runtime config
This commit is contained in:
@@ -1,29 +1,32 @@
|
||||
from pydantic import Field, model_validator
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
app_name: str = "svg-service"
|
||||
app_env: str = "development"
|
||||
app_port: int = 9020
|
||||
api_v1_prefix: str = "/api/v1"
|
||||
app_name: str = Field(..., validation_alias="APP_NAME")
|
||||
app_env: str = Field(..., validation_alias="APP_ENV")
|
||||
app_port: int = Field(..., validation_alias="BACKEND_PORT")
|
||||
api_v1_prefix: str = Field(..., validation_alias="API_V1_PREFIX")
|
||||
|
||||
auth_header_name: str = "X-API-Key"
|
||||
admin_api_key: str = "admin-local-dev-key"
|
||||
viewer_api_key: str = "viewer-local-dev-key"
|
||||
auth_header_name: str = Field(..., validation_alias="AUTH_HEADER_NAME")
|
||||
api_keys_admin: str = Field(..., validation_alias="API_KEYS_ADMIN")
|
||||
api_keys_operator: str = Field(..., validation_alias="API_KEYS_OPERATOR")
|
||||
api_keys_viewer: str = Field(..., validation_alias="API_KEYS_VIEWER")
|
||||
|
||||
postgres_host: str = "postgres"
|
||||
postgres_port: int = 5432
|
||||
postgres_db: str = "svg_service"
|
||||
postgres_user: str = "svg_service"
|
||||
postgres_password: str = "svg_service_dev_password"
|
||||
postgres_host: str = Field(..., validation_alias="POSTGRES_HOST")
|
||||
postgres_port: int = Field(..., validation_alias="POSTGRES_PORT")
|
||||
postgres_db: str = Field(..., validation_alias="POSTGRES_DB")
|
||||
postgres_user: str = Field(..., validation_alias="POSTGRES_USER")
|
||||
postgres_password: str = Field(..., validation_alias="POSTGRES_PASSWORD")
|
||||
database_url_raw: str | None = Field(default=None, validation_alias="DATABASE_URL")
|
||||
|
||||
svg_max_file_size_bytes: int = 10 * 1024 * 1024
|
||||
svg_max_elements: int = 25000
|
||||
svg_max_file_size_bytes: int = Field(10 * 1024 * 1024, validation_alias="SVG_MAX_FILE_SIZE_BYTES")
|
||||
svg_max_elements: int = Field(25000, validation_alias="SVG_MAX_ELEMENTS")
|
||||
|
||||
svg_allow_internal_use_references_only: bool = True
|
||||
svg_forbid_foreign_object_v1: bool = True
|
||||
svg_forbid_style_v1: bool = False
|
||||
svg_forbid_image_v1: bool = True
|
||||
svg_allow_internal_use_references_only: bool = Field(True, validation_alias="SVG_ALLOW_INTERNAL_USE_REFERENCES_ONLY")
|
||||
svg_forbid_foreign_object_v1: bool = Field(True, validation_alias="SVG_FORBID_FOREIGN_OBJECT_V1")
|
||||
svg_forbid_style_v1: bool = Field(False, validation_alias="SVG_FORBID_STYLE_V1")
|
||||
svg_forbid_image_v1: bool = Field(True, validation_alias="SVG_FORBID_IMAGE_V1")
|
||||
|
||||
svg_display_enabled: bool = True
|
||||
svg_display_mode: str = "passthrough"
|
||||
@@ -34,7 +37,7 @@ class Settings(BaseSettings):
|
||||
svg_display_force_viewbox: bool = True
|
||||
svg_display_technical_text_patterns: str = "debug,tech,helper,tmp,service"
|
||||
|
||||
storage_root_dir: str = "/data"
|
||||
storage_root_dir: str = Field(..., validation_alias="STORAGE_ROOT")
|
||||
publish_preview_retention_per_variant: int = 2
|
||||
publish_require_full_pricing_coverage: bool = False
|
||||
|
||||
@@ -45,16 +48,32 @@ class Settings(BaseSettings):
|
||||
extra="ignore",
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_database_config(self) -> "Settings":
|
||||
assembled_database_url = (
|
||||
f"postgresql+asyncpg://{self.postgres_user}:{self.postgres_password}"
|
||||
f"@{self.postgres_host}:{self.postgres_port}/{self.postgres_db}"
|
||||
)
|
||||
if self.database_url_raw and self.database_url_raw != assembled_database_url:
|
||||
raise ValueError("DATABASE_URL must match POSTGRES_HOST/PORT/DB/USER/PASSWORD")
|
||||
return self
|
||||
|
||||
@property
|
||||
def admin_keys(self) -> set[str]:
|
||||
return {item.strip() for item in self.admin_api_key.split(",") if item.strip()}
|
||||
return {item.strip() for item in self.api_keys_admin.split(",") if item.strip()}
|
||||
|
||||
@property
|
||||
def operator_keys(self) -> set[str]:
|
||||
return {item.strip() for item in self.api_keys_operator.split(",") if item.strip()}
|
||||
|
||||
@property
|
||||
def viewer_keys(self) -> set[str]:
|
||||
return {item.strip() for item in self.viewer_api_key.split(",") if item.strip()}
|
||||
return {item.strip() for item in self.api_keys_viewer.split(",") if item.strip()}
|
||||
|
||||
@property
|
||||
def database_url(self) -> str:
|
||||
if self.database_url_raw:
|
||||
return self.database_url_raw
|
||||
return (
|
||||
f"postgresql+asyncpg://{self.postgres_user}:{self.postgres_password}"
|
||||
f"@{self.postgres_host}:{self.postgres_port}/{self.postgres_db}"
|
||||
|
||||
Reference in New Issue
Block a user