feat: 添加 API Key 锁定功能和请求头规则系统

1. API Key 锁定功能
- 管理员可锁定/解锁用户的 API Key
- 锁定后用户无法使用、修改或删除该 Key
- 前端显示锁定状态并禁用相关操作

2. 请求头规则系统
- 将 endpoint.headers 升级为 header_rules
- 支持 set(设置)、drop(删除)、rename(重命名)操作
- 前端提供可视化规则编辑界面
- 包含数据迁移脚本

Close #37 Close #86 Close #88
This commit is contained in:
fawney19
2026-01-16 01:18:54 +08:00
parent ea45918561
commit 8e11f3864a
22 changed files with 852 additions and 56 deletions

View File

@@ -176,6 +176,7 @@ class ApiKey(Base):
# 状态
is_active = Column(Boolean, default=True, nullable=False)
is_locked = Column(Boolean, default=False, nullable=False) # 管理员锁定,用户无法使用/操作
last_used_at = Column(DateTime(timezone=True), nullable=True)
expires_at = Column(DateTime(timezone=True), nullable=True) # 过期时间
auto_delete_on_expiry = Column(Boolean, default=False, nullable=False) # 过期后是否自动删除
@@ -602,7 +603,7 @@ class ProviderEndpoint(Base):
base_url = Column(String(500), nullable=False)
# 请求配置
headers = Column(JSON, nullable=True) # 额外请求头
header_rules = Column(JSON, nullable=True) # 请求头规则 [{action, key, value, from, to}]
timeout = Column(Integer, default=300) # 超时(秒)
max_retries = Column(Integer, default=2) # 最大重试次数

View File

@@ -10,6 +10,16 @@ from pydantic import BaseModel, ConfigDict, Field, field_validator
from src.models.admin_requests import ProxyConfig
# ========== Header Rule 类型定义 ==========
# 请求头规则支持三种操作:
# - set: 设置/覆盖请求头 {"action": "set", "key": "X-Custom", "value": "val"}
# - drop: 删除请求头 {"action": "drop", "key": "X-Unwanted"}
# - rename: 重命名请求头 {"action": "rename", "from": "X-Old", "to": "X-New"}
# 实际验证在 headers.py 的 apply_rules 中处理
HeaderRule = Dict[str, Any]
# ========== ProviderEndpoint CRUD ==========
@@ -21,8 +31,12 @@ class ProviderEndpointCreate(BaseModel):
base_url: str = Field(..., min_length=1, max_length=500, description="API 基础 URL")
custom_path: Optional[str] = Field(default=None, max_length=200, description="自定义请求路径")
# 请求配置
headers: Optional[Dict[str, str]] = Field(default=None, description="自定义请求头")
# 请求配置
header_rules: Optional[List[HeaderRule]] = Field(
default=None,
description="请求头规则列表,支持 set/drop/rename 操作",
)
timeout: int = Field(default=300, ge=10, le=600, description="超时时间(秒)")
max_retries: int = Field(default=2, ge=0, le=10, description="最大重试次数")
@@ -60,7 +74,13 @@ class ProviderEndpointUpdate(BaseModel):
default=None, min_length=1, max_length=500, description="API 基础 URL"
)
custom_path: Optional[str] = Field(default=None, max_length=200, description="自定义请求路径")
headers: Optional[Dict[str, str]] = Field(default=None, description="自定义请求头")
# 请求头配置
header_rules: Optional[List[HeaderRule]] = Field(
default=None,
description="请求头规则列表,支持 set/drop/rename 操作",
)
timeout: Optional[int] = Field(default=None, ge=10, le=600, description="超时时间(秒)")
max_retries: Optional[int] = Field(default=None, ge=0, le=10, description="最大重试次数")
is_active: Optional[bool] = Field(default=None, description="是否启用")
@@ -92,8 +112,11 @@ class ProviderEndpointResponse(BaseModel):
base_url: str
custom_path: Optional[str] = None
# 请求配置
headers: Optional[Dict[str, str]] = None
# 请求配置
header_rules: Optional[List[HeaderRule]] = Field(
default=None, description="请求头规则列表"
)
timeout: int
max_retries: int