Files
creator-hub/internal/controlplane/api/account_environment.go
T
rogee a9ac84f459
douyin-release-gate / verify (push) Failing after 4m3s
feat(accounts): 创建账号表单支持指纹浏览器环境配置
- 前端创建页折叠区块:平台/品牌/版本/语言/时区/硬件并发/关闭伪装维度,留空使用默认
- 后端 accountRequest 增加 fingerprint,校验前置 400(避免账号已建、绑定失败的中间态)
- seed 服务端从账号派生、proxy 由网络出口管理,两者不接受表单值
- 补建端点支持携带指纹重试;start 自愈补建保持零值指纹
- PG 集成测试:指纹落库/非法值拒绝不建号/补建指纹重试
2026-09-29 14:49:59 +08:00

70 lines
2.7 KiB
Go

package api
import (
"context"
"errors"
hub "git.ipao.vip/rogee/creator-hub/internal/environment"
)
// 账号即环境:账号创建即绑定运行环境。
// 规则:alias = 账号文本 ID、唯一网关自动取、出口直连、seed 由账号 ID 派生。
// soleGateway 返回平台唯一网关;零配置绑定要求恰有一个网关:
// 缺失返回 ErrNotFound,多个返回 ErrConflict(无法自动选择)。
func soleGateway(ctx context.Context, store HubStore) (hub.Gateway, error) {
gateways, err := store.ListGateways(ctx)
if err != nil {
return hub.Gateway{}, err
}
if len(gateways) == 0 {
return hub.Gateway{}, hub.ErrNotFound
}
if len(gateways) > 1 {
return hub.Gateway{}, hub.ErrConflict
}
return gateways[0], nil
}
// ensureAccountEnvironment 幂等补建账号环境:已绑定(任意出口)原样返回;
// 未绑定时以 alias=账号 ID、派生 seed、指定指纹、直连出口创建。
func ensureAccountEnvironment(ctx context.Context, store HubStore, accountID string, fingerprint hub.Fingerprint) (hub.EnvironmentContext, bool, error) {
environment, err := store.GetEnvironmentContextForAccount(ctx, accountID)
if err == nil {
return environment, false, nil
}
if !errors.Is(err, hub.ErrNotFound) {
return hub.EnvironmentContext{}, false, err
}
gateway, err := soleGateway(ctx, store)
if err != nil {
return hub.EnvironmentContext{}, false, err
}
// seed 由 CreateBoundEnv 从账号 bigint id + 1000 派生(数字主键)。
return store.CreateBoundEnv(ctx, hub.Env{
Alias: accountID, Name: accountID, Gateway: gateway.Name, Fingerprint: fingerprint,
}, accountID, "")
}
// startAccountEnvironment 启动账号环境并记录审计对;环境缺失时幂等补建(创建即绑定的自愈路径)。
func startAccountEnvironment(ctx context.Context, store HubStore, accountID string) error {
environment, err := store.GetEnvironmentContextForAccount(ctx, accountID)
if errors.Is(err, hub.ErrNotFound) {
// start 自愈补建时创建表单不可得,零值指纹 = 派生 seed + 浏览器默认参数。
environment, _, err = ensureAccountEnvironment(ctx, store, accountID, hub.Fingerprint{})
}
if err != nil {
return err
}
action := actionForEnvironment("start", environment)
if err := store.AppendEnvironmentAction(ctx, "environment_action_requested", action); err != nil {
return err
}
finish := func(outcome, reason string, current hub.EnvironmentContext) error {
action.Outcome, action.ReasonCode = outcome, reason
action.BindingVersion, action.NetworkExitID = current.BindingVersion, current.Exit.ID
return store.AppendEnvironmentAction(ctx, "environment_action_finished", action)
}
return startBrowserRuntime(ctx, store, defaultNetworkExitProbe(), environment, finish)
}