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,117 @@
|
||||
//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)
|
||||
}
|
||||
Reference in New Issue
Block a user