diff --git a/app/api/routers/rbac_operator.py b/app/api/routers/rbac_operator.py index f621004..b33fb95 100644 --- a/app/api/routers/rbac_operator.py +++ b/app/api/routers/rbac_operator.py @@ -214,6 +214,37 @@ async def compute_provision( ) +@router.post("/compute/sync-users", summary="同步引擎用户=平台总用户(对账)") +async def sync_compute_users( + request: Request, + db: Database = Depends(get_db), + actor: dict = Depends(require_roles("operator")), +): + """把平台全部用户对账到引擎:建号(幂等) + 缺令牌则签一枚 PAT,保证 engine 用户 = 平台用户。""" + users = await db.users.list() + created = pats = 0 + for u in users: + uname = u.get("username") + if not uname: + continue + try: + await compute_client.ensure_user(uname) + created += 1 + except Exception: # noqa: BLE001 + pass + try: + toks = await compute_client.list_user_tokens(uname) + if not toks: + await compute_client.issue_pat(uname) + pats += 1 + except Exception: # noqa: BLE001 + pass + await write_audit(db, action="compute.sync_users", resource="compute", + resource_id="__all__", detail=f"users={len(users)}", + user=actor, request=request) + return {"total": len(users), "synced": created, "pat_issued": pats} + + @router.api_route( "/compute/proxy/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"], diff --git a/app/services/compute_client.py b/app/services/compute_client.py index 1a0a940..f98094c 100644 --- a/app/services/compute_client.py +++ b/app/services/compute_client.py @@ -119,6 +119,14 @@ async def issue_user_token(username: str, name: str = "") -> dict: return data.get("data") or {} +async def ensure_user(username: str) -> dict: + """幂等建引擎用户:已存在(409/4xx)视为成功,不抛。""" + try: + return await create_user(username) + except ComputeError: + return {"username": username, "already": True} + + async def list_models(status: int = 1) -> list[dict]: """列出引擎 admin 模型(models 表)。返回分页 items 列表。""" data = await _request(