feat: sync upstream keys and reorder priorities

This commit is contained in:
SmartUp Developer
2026-06-03 17:03:11 +08:00
parent a42bcba483
commit b866b387e0
8 changed files with 415 additions and 57 deletions
+130
View File
@@ -637,6 +637,136 @@ def test_new_api_create_token_fetches_plaintext_key(monkeypatch):
assert created_bodies[0]["expired_time"] > 0
def test_new_api_list_tokens_uses_full_list_and_fetches_plaintext_when_search_misses():
"""New-API search 可能不匹配前缀;应拉完整 token 列表并按 id 回填明文。"""
from app.services.upstream_client import UpstreamClient
client = UpstreamClient(
base_url="http://newapi.local",
api_prefix="",
auth_type="cookie",
auth_config={"cookie_string": "session=abc", "new_api_user": "7"},
)
class FakeResponse:
def __init__(self, payload):
self._payload = payload
self.cookies = {}
self.headers = {"content-type": "application/json"}
self.content = b"{}"
self.text = "{}"
def raise_for_status(self):
return None
def json(self):
return self._payload
class FakeHttpClient:
def request(self, method, url, **kwargs):
path = url.replace("http://newapi.local", "")
params = kwargs.get("params") or {}
if method == "GET" and path == "/api/token/search":
assert params["keyword"] == "SmartUp"
return FakeResponse({
"success": True,
"data": {"page": 1, "page_size": 100, "total": 0, "items": []},
})
if method == "GET" and path == "/api/token/":
return FakeResponse({
"success": True,
"data": {
"page": 1,
"page_size": 100,
"total": 4,
"items": [
{"id": 447, "name": "SmartUp-4-gptpro-gpt pro", "group": "gpt pro", "key": "sk-XE2o********WWh"},
{"id": 446, "name": "SmartUp-4-gptplus-gpt plus", "group": "gpt plus", "key": "sk-JRi1********rtum"},
{"id": 445, "name": "SmartUp-4-claude特价kiro-claude 特价kiro", "group": "claude 特价kiro", "key": "sk-Aldb********08W2"},
{"id": 56, "name": "plus", "group": "gpt plus", "key": "sk-20cB********pEfE"},
],
},
})
if method == "POST" and path == "/api/token/447/key":
return FakeResponse({"success": True, "data": {"key": "sk-gptpro-plain"}})
if method == "POST" and path == "/api/token/446/key":
return FakeResponse({"success": True, "data": {"key": "sk-gptplus-plain"}})
if method == "POST" and path == "/api/token/445/key":
return FakeResponse({"success": True, "data": {"key": "sk-claude-plain"}})
raise AssertionError(f"unexpected request {method} {path} {params}")
client._client = FakeHttpClient()
rows = client.list_api_keys(search="SmartUp", status="active")
assert [row["id"] for row in rows] == [447, 446, 445]
assert [row["group_id"] for row in rows] == ["gpt pro", "gpt plus", "claude 特价kiro"]
assert [row["key"] for row in rows] == ["sk-gptpro-plain", "sk-gptplus-plain", "sk-claude-plain"]
def test_generated_keys_persists_new_api_tokens_with_plaintext(db_session, monkeypatch):
"""generated-keys 应把 New-API 远端 token 回填成本地可导入记录。"""
from app.routers import upstreams as upstreams_router
from app.models.upstream_key import UpstreamGeneratedKey
upstream = Upstream(
name="NewAPI",
base_url="http://newapi.local",
api_prefix="",
auth_type="cookie",
auth_config_json=json.dumps({"cookie_string": "session=abc", "new_api_user": "7"}),
groups_endpoint="/api/user/self/groups",
rate_endpoint="/api/user/self/groups",
)
db_session.add(upstream)
db_session.commit()
db_session.refresh(upstream)
class FakeClient:
def __init__(self, **kwargs):
self.kwargs = kwargs
def __enter__(self):
return self
def __exit__(self, *args):
return None
def login(self):
return None
def list_api_keys(self, search="", status="active"):
assert search == "SmartUp"
return [
{
"id": 447,
"name": "SmartUp-4-gptpro-gpt pro",
"group": "gpt pro",
"group_id": "gpt pro",
"key": "sk-gptpro-plain",
"masked_key": "sk-g********lain",
}
]
monkeypatch.setattr(upstreams_router, "UpstreamClient", FakeClient)
response = upstreams_router.list_generated_keys(upstream.id, db_session, object())
assert len(response) == 1
assert response[0].has_key_value is True
assert response[0].id is not None
assert response[0].key_name == "SmartUp-4-gptpro-gpt pro"
row = db_session.query(UpstreamGeneratedKey).filter(
UpstreamGeneratedKey.upstream_id == upstream.id,
UpstreamGeneratedKey.key_id == "447",
).one()
assert row.group_id == "gpt pro"
assert row.group_name == "gpt pro"
assert row.key_value == "sk-gptpro-plain"
assert row.managed_prefix == "SmartUp"
def test_generate_keys_allows_new_api_user_upstream(db_session, monkeypatch):
"""New-API 普通账号上游应允许按分组生成 token。"""
from app.routers import upstreams as upstreams_router