feat: sync upstream keys and reorder priorities
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user