```
refactor: 移除审批和回写功能模块 移除了整个审批(approvals)和官方回写(writebacks)功能模块, 包括相关模型、路由、服务和配置项。更新了数据库迁移文件, 删除了相关的审批请求表和官方回写运行表。同时从API路由器中 移除了相应的路由,并调整了安全常量和字段验证器以匹配变更。 ```
This commit is contained in:
@@ -21,6 +21,7 @@ class Settings(BaseSettings):
|
||||
app_name: str = "Company AI Management Platform"
|
||||
app_env: str = "local"
|
||||
debug: bool = False
|
||||
read_only_mode: bool = True
|
||||
api_prefix: str = "/api/v1"
|
||||
api_key: str | None = None
|
||||
api_actor: str = ActorValue.API
|
||||
@@ -28,9 +29,6 @@ class Settings(BaseSettings):
|
||||
audit_api_key: str | None = None
|
||||
audit_api_actor: str = ActorValue.AUDITOR
|
||||
audit_api_keys: list[dict[str, Any]] = Field(default_factory=list)
|
||||
approval_api_key: str | None = None
|
||||
approval_api_actor: str = ActorValue.APPROVER
|
||||
approval_api_keys: list[dict[str, Any]] = Field(default_factory=list)
|
||||
cors_origins: list[str] = Field(default_factory=lambda: ["*"])
|
||||
mask_sensitive_responses: bool = True
|
||||
masked_response_fields: list[str] = Field(default_factory=list)
|
||||
@@ -50,8 +48,6 @@ class Settings(BaseSettings):
|
||||
feishu_verification_token: str | None = None
|
||||
feishu_encrypt_key: str | None = None
|
||||
feishu_default_chat_id: str | None = None
|
||||
feishu_approval_approver_ids: Annotated[list[str], NoDecode] = Field(default_factory=list)
|
||||
|
||||
model_provider: str = DEFAULT_MODEL_PROVIDER
|
||||
openclaw_base_url: str = "http://127.0.0.1:2070"
|
||||
openclaw_http_url: str | None = None
|
||||
@@ -84,11 +80,6 @@ class Settings(BaseSettings):
|
||||
legacy_project_sync_cron_minute: int = 0
|
||||
legacy_task_sync_cron_hour: int = 2
|
||||
legacy_task_sync_cron_minute: int = 30
|
||||
official_writeback_enabled: bool = False
|
||||
official_api_base_url: str | None = None
|
||||
official_api_token: str | None = None
|
||||
official_api_timeout_seconds: float = 10.0
|
||||
|
||||
@field_validator("cors_origins", mode="before")
|
||||
@classmethod
|
||||
def parse_cors_origins(cls, value: Any) -> list[str]:
|
||||
@@ -107,7 +98,6 @@ class Settings(BaseSettings):
|
||||
@field_validator(
|
||||
"openclaw_allowed_tools",
|
||||
"openclaw_allowed_actions",
|
||||
"feishu_approval_approver_ids",
|
||||
mode="before",
|
||||
)
|
||||
@classmethod
|
||||
@@ -143,7 +133,7 @@ class Settings(BaseSettings):
|
||||
return [str(item).strip() for item in data if str(item).strip()]
|
||||
return [item.strip() for item in text.split(",") if item.strip()]
|
||||
|
||||
@field_validator("api_keys", "audit_api_keys", "approval_api_keys", mode="before")
|
||||
@field_validator("api_keys", "audit_api_keys", mode="before")
|
||||
@classmethod
|
||||
def parse_service_keys(cls, value: Any) -> list[dict[str, Any]]:
|
||||
if value is None or value == "":
|
||||
|
||||
@@ -4,7 +4,6 @@ from enum import StrEnum
|
||||
class ActorValue(StrEnum):
|
||||
API = "api"
|
||||
AUDITOR = "auditor"
|
||||
APPROVER = "approver"
|
||||
SYSTEM = "system"
|
||||
SCHEDULER = "scheduler"
|
||||
FEISHU = "feishu"
|
||||
@@ -14,7 +13,6 @@ class HttpHeader(StrEnum):
|
||||
AUTHORIZATION = "Authorization"
|
||||
X_API_KEY = "X-API-Key"
|
||||
X_AUDIT_API_KEY = "X-Audit-API-Key"
|
||||
X_APPROVAL_API_KEY = "X-Approval-API-Key"
|
||||
X_REQUEST_ID = "X-Request-ID"
|
||||
|
||||
|
||||
@@ -29,8 +27,6 @@ class ApiStatus(StrEnum):
|
||||
class SecurityErrorDetail(StrEnum):
|
||||
API_KEY_REQUIRED = "API_KEY is required"
|
||||
INVALID_API_KEY = "Invalid API key"
|
||||
APPROVAL_API_KEY_REQUIRED = "APPROVAL_API_KEY is required"
|
||||
INVALID_APPROVAL_API_KEY = "Invalid approval API key"
|
||||
AUDIT_API_KEY_REQUIRED = "AUDIT_API_KEY is required"
|
||||
INVALID_AUDIT_API_KEY = "Invalid audit API key"
|
||||
|
||||
|
||||
16
app/core/operation_guard.py
Normal file
16
app/core/operation_guard.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from fastapi import HTTPException, status
|
||||
|
||||
from app.core.config import get_settings
|
||||
|
||||
|
||||
READ_ONLY_OPERATION_DISABLED = "This service is read-only; data mutation operations are disabled"
|
||||
|
||||
|
||||
def require_operations_enabled(detail: str = READ_ONLY_OPERATION_DISABLED) -> None:
|
||||
"""Reject mutation-oriented endpoints when the product is running read-only."""
|
||||
|
||||
if get_settings().read_only_mode:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
|
||||
detail=detail,
|
||||
)
|
||||
@@ -40,34 +40,6 @@ def require_api_key(
|
||||
return principal
|
||||
|
||||
|
||||
def require_approval_api_key(
|
||||
x_approval_api_key: str | None = Header(
|
||||
default=None,
|
||||
alias=HttpHeader.X_APPROVAL_API_KEY,
|
||||
),
|
||||
) -> ApiPrincipal:
|
||||
"""Validate the approval API key and return the approval principal."""
|
||||
|
||||
settings = get_settings()
|
||||
if not settings.approval_api_key and not _has_enabled_keys(settings.approval_api_keys):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
||||
detail=SecurityErrorDetail.APPROVAL_API_KEY_REQUIRED,
|
||||
)
|
||||
principal = _match_service_key(
|
||||
x_approval_api_key,
|
||||
settings.approval_api_key,
|
||||
settings.approval_api_actor,
|
||||
settings.approval_api_keys,
|
||||
)
|
||||
if principal is None:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||
detail=SecurityErrorDetail.INVALID_APPROVAL_API_KEY,
|
||||
)
|
||||
return principal
|
||||
|
||||
|
||||
def require_audit_api_key(
|
||||
x_audit_api_key: str | None = Header(
|
||||
default=None,
|
||||
|
||||
Reference in New Issue
Block a user