Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const userSuppliedCodexFingerprintSeed = "22222222-2222-4222-8222-222222222222"
|
||||
|
||||
func requireValidCodexFingerprintSeed(t *testing.T, extra map[string]any) string {
|
||||
t.Helper()
|
||||
seed, ok := codexFingerprintSeed(extra)
|
||||
require.True(t, ok, "expected valid canonical Codex fingerprint seed")
|
||||
return seed
|
||||
}
|
||||
|
||||
func TestAdminCreateAccountStripsUserSeedAndCreatesFreshSeedWhenEnabled(t *testing.T) {
|
||||
repo := &upstreamBillingProbeAccountRepo{}
|
||||
svc := &adminServiceImpl{accountRepo: repo}
|
||||
|
||||
created, err := svc.CreateAccount(context.Background(), &CreateAccountInput{
|
||||
Name: "codex-oauth",
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
SkipDefaultGroupBind: true,
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "session",
|
||||
codexFingerprintSeedExtraKey: userSuppliedCodexFingerprintSeed,
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
seed := requireValidCodexFingerprintSeed(t, created.Extra)
|
||||
require.NotEqual(t, userSuppliedCodexFingerprintSeed, seed)
|
||||
require.Equal(t, "session", created.Extra[codexFingerprintModeExtraKey])
|
||||
}
|
||||
|
||||
func TestAdminUpdateAccountPreservesExistingSeedAndStripsUserSeed(t *testing.T) {
|
||||
accountID := int64(201)
|
||||
repo := &upstreamBillingProbeAccountRepo{accounts: map[int64]*Account{
|
||||
accountID: {
|
||||
ID: accountID,
|
||||
Name: "before",
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
Status: StatusActive,
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "session",
|
||||
codexFingerprintSeedExtraKey: testCodexFingerprintSeed,
|
||||
},
|
||||
},
|
||||
}}
|
||||
svc := &adminServiceImpl{accountRepo: repo}
|
||||
|
||||
updated, err := svc.UpdateAccount(context.Background(), accountID, &UpdateAccountInput{
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "full",
|
||||
codexFingerprintSeedExtraKey: userSuppliedCodexFingerprintSeed,
|
||||
"custom": "value",
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testCodexFingerprintSeed, requireValidCodexFingerprintSeed(t, updated.Extra))
|
||||
require.Equal(t, "full", updated.Extra[codexFingerprintModeExtraKey])
|
||||
require.Equal(t, "value", updated.Extra["custom"])
|
||||
}
|
||||
|
||||
func TestAdminUpdateAccountInitializesSeedWhenFullEditEnables(t *testing.T) {
|
||||
accountID := int64(202)
|
||||
repo := &upstreamBillingProbeAccountRepo{accounts: map[int64]*Account{
|
||||
accountID: {
|
||||
ID: accountID,
|
||||
Name: "before",
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
Status: StatusActive,
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "off",
|
||||
codexFingerprintSeedExtraKey: "not-a-seed",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
updated, err := (&adminServiceImpl{accountRepo: repo}).UpdateAccount(context.Background(), accountID, &UpdateAccountInput{
|
||||
Extra: map[string]any{codexFingerprintModeExtraKey: "device"},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, "not-a-seed", requireValidCodexFingerprintSeed(t, updated.Extra))
|
||||
require.Equal(t, "device", updated.Extra[codexFingerprintModeExtraKey])
|
||||
}
|
||||
|
||||
func TestAdminUpdateAccountDisableReenablePreservesValidSeed(t *testing.T) {
|
||||
accountID := int64(203)
|
||||
repo := &upstreamBillingProbeAccountRepo{accounts: map[int64]*Account{
|
||||
accountID: {
|
||||
ID: accountID,
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
Status: StatusActive,
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "session",
|
||||
codexFingerprintSeedExtraKey: testCodexFingerprintSeed,
|
||||
},
|
||||
},
|
||||
}}
|
||||
svc := &adminServiceImpl{accountRepo: repo}
|
||||
|
||||
disabled, err := svc.UpdateAccount(context.Background(), accountID, &UpdateAccountInput{
|
||||
Extra: map[string]any{codexFingerprintModeExtraKey: "off"},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testCodexFingerprintSeed, requireValidCodexFingerprintSeed(t, disabled.Extra))
|
||||
|
||||
reenabled, err := svc.UpdateAccount(context.Background(), accountID, &UpdateAccountInput{
|
||||
Extra: map[string]any{codexFingerprintModeExtraKey: "session"},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, testCodexFingerprintSeed, requireValidCodexFingerprintSeed(t, reenabled.Extra))
|
||||
}
|
||||
|
||||
func TestAdminUpdateAccountExtraStripsSeedAndLeavesAtomicEnsureToRepository(t *testing.T) {
|
||||
accountID := int64(204)
|
||||
repo := &upstreamBillingProbeAccountRepo{accounts: map[int64]*Account{
|
||||
accountID: {
|
||||
ID: accountID,
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
Extra: map[string]any{},
|
||||
},
|
||||
}}
|
||||
|
||||
err := (&adminServiceImpl{accountRepo: repo}).UpdateAccountExtra(context.Background(), accountID, map[string]any{
|
||||
codexFingerprintModeExtraKey: "device",
|
||||
codexFingerprintSeedExtraKey: userSuppliedCodexFingerprintSeed,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Len(t, repo.updates[accountID], 1)
|
||||
require.Equal(t, "device", repo.updates[accountID][0][codexFingerprintModeExtraKey])
|
||||
require.NotContains(t, repo.updates[accountID][0], codexFingerprintSeedExtraKey)
|
||||
}
|
||||
|
||||
func TestBulkUpdateAccountsDoesNotPrewriteCodexSeed(t *testing.T) {
|
||||
repo := &upstreamBillingProbeAccountRepo{}
|
||||
|
||||
result, err := (&adminServiceImpl{accountRepo: repo}).BulkUpdateAccounts(context.Background(), &BulkUpdateAccountsInput{
|
||||
AccountIDs: []int64{301, 302},
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "session",
|
||||
codexFingerprintSeedExtraKey: userSuppliedCodexFingerprintSeed,
|
||||
},
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 2, result.Success)
|
||||
require.Empty(t, repo.updates, "bulk enable must not loop through UpdateExtra before BulkUpdate")
|
||||
require.Len(t, repo.bulkUpdates, 1)
|
||||
require.True(t, repo.bulkUpdates[0].EnsureCodexFingerprintSeed)
|
||||
require.Equal(t, "session", repo.bulkUpdates[0].Extra[codexFingerprintModeExtraKey])
|
||||
require.NotContains(t, repo.bulkUpdates[0].Extra, codexFingerprintSeedExtraKey)
|
||||
}
|
||||
|
||||
type codexSeedDuplicateRepo struct {
|
||||
*upstreamBillingProbeAccountRepo
|
||||
}
|
||||
|
||||
func (r *codexSeedDuplicateRepo) CreateWithAccountGroups(ctx context.Context, account *Account, _ []AccountGroup) error {
|
||||
return r.Create(ctx, account)
|
||||
}
|
||||
|
||||
func TestDuplicateAccountDoesNotCopyCodexFingerprintSeed(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repo := &codexSeedDuplicateRepo{upstreamBillingProbeAccountRepo: &upstreamBillingProbeAccountRepo{accounts: make(map[int64]*Account)}}
|
||||
svc := &adminServiceImpl{accountRepo: repo, accountDuplicateRepo: repo}
|
||||
source := &Account{
|
||||
Name: "source",
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeAPIKey,
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "session",
|
||||
codexFingerprintSeedExtraKey: testCodexFingerprintSeed,
|
||||
},
|
||||
}
|
||||
require.NoError(t, repo.Create(ctx, source))
|
||||
|
||||
duplicate, err := svc.DuplicateAccount(ctx, source.ID, "admin:1", "")
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, source.ID, duplicate.ID)
|
||||
require.NotContains(t, duplicate.Extra, codexFingerprintSeedExtraKey)
|
||||
require.Equal(t, "session", duplicate.Extra[codexFingerprintModeExtraKey])
|
||||
}
|
||||
|
||||
func TestDuplicateCreatePathMintsFreshSeedWhenEligible(t *testing.T) {
|
||||
extra, err := duplicateAccountExtra(map[string]any{
|
||||
codexFingerprintModeExtraKey: "session",
|
||||
codexFingerprintSeedExtraKey: testCodexFingerprintSeed,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
account, err := buildAccountForCreate(&CreateAccountInput{
|
||||
Name: "eligible-copy",
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
Extra: extra,
|
||||
}, extra)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, testCodexFingerprintSeed, requireValidCodexFingerprintSeed(t, account.Extra))
|
||||
require.Equal(t, "session", account.Extra[codexFingerprintModeExtraKey])
|
||||
}
|
||||
|
||||
func TestAccountServiceCreateAndUpdateCodexSeedLifecycle(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
repo := &upstreamBillingProbeAccountRepo{accounts: make(map[int64]*Account)}
|
||||
svc := NewAccountService(repo, nil)
|
||||
|
||||
created, err := svc.Create(ctx, CreateAccountRequest{
|
||||
Name: "legacy-create",
|
||||
Platform: PlatformOpenAI,
|
||||
Type: AccountTypeOAuth,
|
||||
Extra: map[string]any{
|
||||
codexFingerprintModeExtraKey: "session",
|
||||
codexFingerprintSeedExtraKey: userSuppliedCodexFingerprintSeed,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
createdSeed := requireValidCodexFingerprintSeed(t, created.Extra)
|
||||
require.NotEqual(t, userSuppliedCodexFingerprintSeed, createdSeed)
|
||||
|
||||
updateSeed := userSuppliedCodexFingerprintSeed
|
||||
updated, err := svc.Update(ctx, created.ID, UpdateAccountRequest{
|
||||
Extra: &map[string]any{
|
||||
codexFingerprintModeExtraKey: "full",
|
||||
codexFingerprintSeedExtraKey: updateSeed,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, createdSeed, requireValidCodexFingerprintSeed(t, updated.Extra))
|
||||
require.Equal(t, "full", updated.Extra[codexFingerprintModeExtraKey])
|
||||
}
|
||||
Reference in New Issue
Block a user