feat(privacy): 创建/批量创建 OpenAI OAuth 账号时异步设置隐私模式
参照 Antigravity 的模式,单个创建时同步调用 ForceOpenAIPrivacy, 批量创建时收集 OpenAI OAuth 账号后异步 goroutine 设置,避免阻塞请求。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dcc341b846
commit
ee23e67c85
@ -9,6 +9,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -536,6 +537,10 @@ func (h *AccountHandler) Create(c *gin.Context) {
|
|||||||
if execErr != nil {
|
if execErr != nil {
|
||||||
return nil, execErr
|
return nil, execErr
|
||||||
}
|
}
|
||||||
|
// Antigravity OAuth: 新账号直接设置隐私
|
||||||
|
h.adminService.ForceAntigravityPrivacy(ctx, account)
|
||||||
|
// OpenAI OAuth: 新账号直接设置隐私
|
||||||
|
h.adminService.ForceOpenAIPrivacy(ctx, account)
|
||||||
return h.buildAccountResponseWithRuntime(ctx, account), nil
|
return h.buildAccountResponseWithRuntime(ctx, account), nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -782,6 +787,8 @@ func (h *AccountHandler) refreshSingleAccount(ctx context.Context, account *serv
|
|||||||
if account.IsOpenAI() {
|
if account.IsOpenAI() {
|
||||||
tokenInfo, err := h.openaiOAuthService.RefreshAccountToken(ctx, account)
|
tokenInfo, err := h.openaiOAuthService.RefreshAccountToken(ctx, account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// 刷新失败但 access_token 可能仍有效,尝试设置隐私
|
||||||
|
h.adminService.EnsureOpenAIPrivacy(ctx, account)
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -883,6 +890,8 @@ func (h *AccountHandler) refreshSingleAccount(ctx context.Context, account *serv
|
|||||||
|
|
||||||
// OpenAI OAuth: 刷新成功后检查并设置 privacy_mode
|
// OpenAI OAuth: 刷新成功后检查并设置 privacy_mode
|
||||||
h.adminService.EnsureOpenAIPrivacy(ctx, updatedAccount)
|
h.adminService.EnsureOpenAIPrivacy(ctx, updatedAccount)
|
||||||
|
// Antigravity OAuth: 刷新成功后检查并设置 privacy_mode
|
||||||
|
h.adminService.EnsureAntigravityPrivacy(ctx, updatedAccount)
|
||||||
|
|
||||||
return updatedAccount, "", nil
|
return updatedAccount, "", nil
|
||||||
}
|
}
|
||||||
@ -1154,6 +1163,9 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
|||||||
success := 0
|
success := 0
|
||||||
failed := 0
|
failed := 0
|
||||||
results := make([]gin.H, 0, len(req.Accounts))
|
results := make([]gin.H, 0, len(req.Accounts))
|
||||||
|
// 收集需要异步设置隐私的 OAuth 账号
|
||||||
|
var antigravityPrivacyAccounts []*service.Account
|
||||||
|
var openaiPrivacyAccounts []*service.Account
|
||||||
|
|
||||||
for _, item := range req.Accounts {
|
for _, item := range req.Accounts {
|
||||||
if item.RateMultiplier != nil && *item.RateMultiplier < 0 {
|
if item.RateMultiplier != nil && *item.RateMultiplier < 0 {
|
||||||
@ -1196,6 +1208,15 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
// 收集需要异步设置隐私的 OAuth 账号
|
||||||
|
if account.Type == service.AccountTypeOAuth {
|
||||||
|
switch account.Platform {
|
||||||
|
case service.PlatformAntigravity:
|
||||||
|
antigravityPrivacyAccounts = append(antigravityPrivacyAccounts, account)
|
||||||
|
case service.PlatformOpenAI:
|
||||||
|
openaiPrivacyAccounts = append(openaiPrivacyAccounts, account)
|
||||||
|
}
|
||||||
|
}
|
||||||
success++
|
success++
|
||||||
results = append(results, gin.H{
|
results = append(results, gin.H{
|
||||||
"name": item.Name,
|
"name": item.Name,
|
||||||
@ -1204,6 +1225,37 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 异步设置隐私,避免批量创建时阻塞请求
|
||||||
|
adminSvc := h.adminService
|
||||||
|
if len(antigravityPrivacyAccounts) > 0 {
|
||||||
|
accounts := antigravityPrivacyAccounts
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
slog.Error("batch_create_antigravity_privacy_panic", "recover", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
bgCtx := context.Background()
|
||||||
|
for _, acc := range accounts {
|
||||||
|
adminSvc.ForceAntigravityPrivacy(bgCtx, acc)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
if len(openaiPrivacyAccounts) > 0 {
|
||||||
|
accounts := openaiPrivacyAccounts
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
slog.Error("batch_create_openai_privacy_panic", "recover", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
bgCtx := context.Background()
|
||||||
|
for _, acc := range accounts {
|
||||||
|
adminSvc.ForceOpenAIPrivacy(bgCtx, acc)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
return gin.H{
|
return gin.H{
|
||||||
"success": success,
|
"success": success,
|
||||||
"failed": failed,
|
"failed": failed,
|
||||||
@ -1869,6 +1921,51 @@ func (h *AccountHandler) GetAvailableModels(c *gin.Context) {
|
|||||||
response.Success(c, models)
|
response.Success(c, models)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPrivacy handles setting privacy for a single OpenAI/Antigravity OAuth account
|
||||||
|
// POST /api/v1/admin/accounts/:id/set-privacy
|
||||||
|
func (h *AccountHandler) SetPrivacy(c *gin.Context) {
|
||||||
|
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
response.BadRequest(c, "Invalid account ID")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
account, err := h.adminService.GetAccount(c.Request.Context(), accountID)
|
||||||
|
if err != nil {
|
||||||
|
response.NotFound(c, "Account not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if account.Type != service.AccountTypeOAuth {
|
||||||
|
response.BadRequest(c, "Only OAuth accounts support privacy setting")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var mode string
|
||||||
|
switch account.Platform {
|
||||||
|
case service.PlatformOpenAI:
|
||||||
|
mode = h.adminService.ForceOpenAIPrivacy(c.Request.Context(), account)
|
||||||
|
case service.PlatformAntigravity:
|
||||||
|
mode = h.adminService.ForceAntigravityPrivacy(c.Request.Context(), account)
|
||||||
|
default:
|
||||||
|
response.BadRequest(c, "Only OpenAI and Antigravity OAuth accounts support privacy setting")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if mode == "" {
|
||||||
|
response.BadRequest(c, "Cannot set privacy: missing access_token")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 从 DB 重新读取以确保返回最新状态
|
||||||
|
updated, err := h.adminService.GetAccount(c.Request.Context(), accountID)
|
||||||
|
if err != nil {
|
||||||
|
// 隐私已设置成功但读取失败,回退到内存更新
|
||||||
|
if account.Extra == nil {
|
||||||
|
account.Extra = make(map[string]any)
|
||||||
|
}
|
||||||
|
account.Extra["privacy_mode"] = mode
|
||||||
|
response.Success(c, h.buildAccountResponseWithRuntime(c.Request.Context(), account))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
response.Success(c, h.buildAccountResponseWithRuntime(c.Request.Context(), updated))
|
||||||
|
}
|
||||||
|
|
||||||
// RefreshTier handles refreshing Google One tier for a single account
|
// RefreshTier handles refreshing Google One tier for a single account
|
||||||
// POST /api/v1/admin/accounts/:id/refresh-tier
|
// POST /api/v1/admin/accounts/:id/refresh-tier
|
||||||
func (h *AccountHandler) RefreshTier(c *gin.Context) {
|
func (h *AccountHandler) RefreshTier(c *gin.Context) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user