Files
sub2api/backend/internal/service/admin_service_credentials_merge_test.go
T
李建琦 6d655c9903
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
Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
2026-08-21 18:30:13 +08:00

118 lines
3.2 KiB
Go

//go:build unit
package service
import (
"context"
"testing"
"github.com/stretchr/testify/require"
)
type updateAccountCredsRepoStub struct {
mockAccountRepoForGemini
account *Account
updateCalls int
}
func (r *updateAccountCredsRepoStub) GetByID(ctx context.Context, id int64) (*Account, error) {
return r.account, nil
}
func (r *updateAccountCredsRepoStub) Update(ctx context.Context, account *Account) error {
r.updateCalls++
r.account = account
return nil
}
func TestUpdateAccount_PreservesSensitiveCredsWhenIncomingOmits(t *testing.T) {
accountID := int64(202)
repo := &updateAccountCredsRepoStub{
account: &Account{
ID: accountID,
Platform: PlatformAnthropic,
Type: AccountTypeOAuth,
Status: StatusActive,
Credentials: map[string]any{
"refresh_token": "rt-existing",
"access_token": "at-existing",
"id_token": "id-existing",
"base_url": "https://old.example.com",
},
},
}
svc := &adminServiceImpl{accountRepo: repo}
// 模拟前端编辑:仅修改 base_url,没有传 token(脱敏后前端 spread 拿不到敏感键)
updated, err := svc.UpdateAccount(context.Background(), accountID, &UpdateAccountInput{
Credentials: map[string]any{
"base_url": "https://new.example.com",
},
})
require.NoError(t, err)
require.NotNil(t, updated)
require.Equal(t, 1, repo.updateCalls)
// 敏感键应保留
require.Equal(t, "rt-existing", repo.account.Credentials["refresh_token"])
require.Equal(t, "at-existing", repo.account.Credentials["access_token"])
require.Equal(t, "id-existing", repo.account.Credentials["id_token"])
// 非敏感键被替换
require.Equal(t, "https://new.example.com", repo.account.Credentials["base_url"])
}
func TestUpdateAccount_ExplicitNewTokenOverwrites(t *testing.T) {
accountID := int64(203)
repo := &updateAccountCredsRepoStub{
account: &Account{
ID: accountID,
Platform: PlatformAnthropic,
Type: AccountTypeOAuth,
Status: StatusActive,
Credentials: map[string]any{
"refresh_token": "rt-old",
"api_key": "sk-old",
},
},
}
svc := &adminServiceImpl{accountRepo: repo}
updated, err := svc.UpdateAccount(context.Background(), accountID, &UpdateAccountInput{
Credentials: map[string]any{
"refresh_token": "rt-new",
// api_key 没传 → 应保留旧值
},
})
require.NoError(t, err)
require.NotNil(t, updated)
require.Equal(t, "rt-new", repo.account.Credentials["refresh_token"])
require.Equal(t, "sk-old", repo.account.Credentials["api_key"])
}
func TestUpdateAccount_EmptyCredentialsSkipsUpdate(t *testing.T) {
accountID := int64(204)
repo := &updateAccountCredsRepoStub{
account: &Account{
ID: accountID,
Platform: PlatformAnthropic,
Type: AccountTypeOAuth,
Status: StatusActive,
Credentials: map[string]any{
"refresh_token": "rt-existing",
},
},
}
svc := &adminServiceImpl{accountRepo: repo}
_, err := svc.UpdateAccount(context.Background(), accountID, &UpdateAccountInput{
Credentials: map[string]any{}, // len == 0 → 闸门跳过
Name: "renamed",
})
require.NoError(t, err)
require.Equal(t, "rt-existing", repo.account.Credentials["refresh_token"], "空 credentials 不应触碰已有 token")
require.Equal(t, "renamed", repo.account.Name)
}