feat: track imported accounts per upstream key across platforms

Add upstream_key_account_links table mapping generated keys to remote
accounts per website/platform, surface imported_accounts on key
responses, and update website sync/routers to manage the links.
This commit is contained in:
liujing
2026-07-23 17:52:58 +08:00
parent ee89cd6119
commit df7e400e7b
17 changed files with 1081 additions and 537 deletions
+10 -2
View File
@@ -15,7 +15,7 @@ from sqlalchemy.orm import Session
from app.database import SessionLocal, get_db
from app.models.admin_user import AdminUser
from app.models.upstream import Upstream
from app.models.upstream_key import UpstreamGeneratedKey
from app.models.upstream_key import UpstreamGeneratedKey, UpstreamKeyAccountLink
from app.models.upstream_recharge_event import UpstreamRechargeEvent
from app.models.snapshot import UpstreamRateSnapshot
from app.schemas.upstream import (
@@ -25,6 +25,7 @@ from app.schemas.upstream import (
UpstreamCreate, UpstreamUpdate, UpstreamResponse, SnapshotResponse, TestResult,
UpstreamBatchActionItem, UpstreamBatchActionSummary, UpstreamBatchActionResponse,
UpstreamRechargeCreate, UpstreamRechargeUpdate, UpstreamRechargeResponse,
UpstreamKeyAccountLinkResponse,
)
from app.services.upstream_client import UpstreamClient, UpstreamError, _PendingKeyError, build_snapshot, build_new_api_token_name, mask_secret, _extract_key_value
from app.services.auth_config import MASK, mask_auth_config, normalize_auth_config
@@ -49,7 +50,13 @@ def _group_name(group: dict, gid: str) -> str:
return str(group.get("name") or group.get("group_name") or gid)
def _key_response(row: UpstreamGeneratedKey, include_value: bool = False) -> GeneratedUpstreamKeyResponse:
def _key_response(row: UpstreamGeneratedKey, include_value: bool = False, db: Session | None = None) -> GeneratedUpstreamKeyResponse:
sess = db or Session.object_session(row)
imported_accounts = []
if sess and row.id is not None:
links = sess.query(UpstreamKeyAccountLink).filter(UpstreamKeyAccountLink.upstream_key_id == row.id).all()
imported_accounts = [UpstreamKeyAccountLinkResponse.model_validate(l) for l in links]
return GeneratedUpstreamKeyResponse(
id=row.id,
upstream_id=row.upstream_id,
@@ -67,6 +74,7 @@ def _key_response(row: UpstreamGeneratedKey, include_value: bool = False) -> Gen
created_at=row.created_at,
updated_at=row.updated_at,
has_key_value=bool(row.key_value),
imported_accounts=imported_accounts,
)