mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 09:50:21 +08:00
feat: 支持固定类型 Provider OAuth 授权
- 新增 provider_type 字段区分自定义/预置 Provider 类型(claude_code/codex/gemini_cli/antigravity) - 实现完整 OAuth 2.0 授权流程:start(生成授权 URL + PKCE)、complete(换取 token)、refresh - 前端 KeyFormDialog 添加 OAuth 授权 UI,支持开始授权、粘贴回调 URL、完成授权、强制刷新 - 请求时自动检测 token 过期并刷新(120s 预留窗口 + Redis 分布式锁防并发) - 固定类型 Provider 自动创建预置端点并锁定 base_url/custom_path - 数据库迁移:添加 providers.provider_type,扩展 api_key 列为 TEXT - 可选依赖 tls-client 用于 Claude token 请求的 TLS 指纹伪装
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
@@ -20,10 +21,13 @@ from src.core.logger import logger
|
||||
from src.core.model_permissions import match_model_with_pattern, parse_allowed_models_to_list
|
||||
from src.database import get_db
|
||||
from src.models.admin_requests import CreateProviderRequest, UpdateProviderRequest
|
||||
from src.models.database import GlobalModel, Provider, ProviderAPIKey
|
||||
from src.models.database import GlobalModel, Provider, ProviderAPIKey, ProviderEndpoint
|
||||
from src.services.cache.model_cache import ModelCacheService
|
||||
from src.services.cache.provider_cache import ProviderCacheService
|
||||
|
||||
from src.core.provider_templates.fixed_providers import FIXED_PROVIDERS
|
||||
from src.core.provider_templates.types import ProviderType
|
||||
|
||||
router = APIRouter(tags=["Provider CRUD"])
|
||||
pipeline = ApiRequestPipeline()
|
||||
|
||||
@@ -290,6 +294,7 @@ class AdminCreateProviderAdapter(AdminApiAdapter):
|
||||
# 创建 Provider 对象
|
||||
provider = Provider(
|
||||
name=validated_data.name,
|
||||
provider_type=validated_data.provider_type or "custom",
|
||||
description=validated_data.description,
|
||||
website=validated_data.website,
|
||||
billing_type=billing_type,
|
||||
@@ -309,6 +314,37 @@ class AdminCreateProviderAdapter(AdminApiAdapter):
|
||||
)
|
||||
|
||||
db.add(provider)
|
||||
db.flush() # flush 获取 ID,但不提交,保持在同一事务中
|
||||
|
||||
# 固定类型 Provider:自动创建并锁定预置 Endpoints(同一事务)
|
||||
provider_type = (provider.provider_type or "custom").strip()
|
||||
if provider_type != "custom":
|
||||
try:
|
||||
template = FIXED_PROVIDERS.get(ProviderType(provider_type))
|
||||
except Exception:
|
||||
template = None
|
||||
if template:
|
||||
now = datetime.now(timezone.utc)
|
||||
for sig in template.endpoint_signatures:
|
||||
endpoint = ProviderEndpoint(
|
||||
id=str(uuid.uuid4()),
|
||||
provider_id=provider.id,
|
||||
api_format=sig,
|
||||
api_family=sig.split(":", 1)[0],
|
||||
endpoint_kind=sig.split(":", 1)[1],
|
||||
base_url=template.api_base_url,
|
||||
custom_path=None,
|
||||
header_rules=None,
|
||||
max_retries=provider.max_retries or 2,
|
||||
is_active=True,
|
||||
config=None,
|
||||
proxy=None,
|
||||
format_acceptance_config=None,
|
||||
created_at=now,
|
||||
updated_at=now,
|
||||
)
|
||||
db.add(endpoint)
|
||||
|
||||
db.commit()
|
||||
db.refresh(provider)
|
||||
|
||||
@@ -369,6 +405,8 @@ class AdminUpdateProviderAdapter(AdminApiAdapter):
|
||||
if field == "billing_type" and value is not None:
|
||||
# billing_type 需要转换为枚举
|
||||
setattr(provider, field, ProviderBillingType(value))
|
||||
elif field == "provider_type" and value is not None:
|
||||
setattr(provider, field, value)
|
||||
elif field == "proxy" and value is not None:
|
||||
# proxy 需要转换为 dict(如果是 Pydantic 模型)
|
||||
setattr(
|
||||
|
||||
@@ -305,6 +305,7 @@ def _build_provider_summary(db: Session, provider: Provider) -> ProviderWithEndp
|
||||
return ProviderWithEndpointsSummary(
|
||||
id=provider.id,
|
||||
name=provider.name,
|
||||
provider_type=getattr(provider, "provider_type", None),
|
||||
description=provider.description,
|
||||
website=provider.website,
|
||||
provider_priority=provider.provider_priority,
|
||||
|
||||
Reference in New Issue
Block a user