| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- //go:build unit
- package service
- import (
- "context"
- "errors"
- "testing"
- "github.com/Wei-Shaw/sub2api/internal/config"
- "github.com/stretchr/testify/require"
- )
- type tencentCaptchaVerifierStub struct {
- response *TencentCaptchaVerifyResponse
- err error
- calls int
- proof TencentCaptchaProof
- remoteIP string
- credentials TencentCaptchaCredentials
- }
- func (s *tencentCaptchaVerifierStub) VerifyTicket(_ context.Context, credentials TencentCaptchaCredentials, proof TencentCaptchaProof, remoteIP string) (*TencentCaptchaVerifyResponse, error) {
- s.calls++
- s.credentials = credentials
- s.proof = proof
- s.remoteIP = remoteIP
- return s.response, s.err
- }
- func newTencentCaptchaTestService(verifier TencentCaptchaVerifier) *TencentCaptchaService {
- return newTencentCaptchaTestServiceWithRegion(verifier, "")
- }
- func newTencentCaptchaTestServiceWithRegion(verifier TencentCaptchaVerifier, region string) *TencentCaptchaService {
- values := map[string]string{
- SettingKeyTencentCaptchaEnabled: "true",
- SettingKeyTencentCaptchaAppID: "123456789",
- SettingKeyTencentCaptchaAppSecretKey: "app-secret",
- SettingKeyTencentCaptchaCloudSecretID: "cloud-secret-id",
- SettingKeyTencentCaptchaCloudSecretKey: "cloud-secret-key",
- }
- if region != "" {
- values[SettingKeyTencentCaptchaRegion] = region
- }
- settings := NewSettingService(&settingPublicRepoStub{values: values}, &config.Config{})
- return NewTencentCaptchaService(settings, verifier)
- }
- // 站点决定服务端票据校验接入点:国际站账号的密钥在国内站接入点上无法通过鉴权,
- // 因此这条映射一旦错位,国际站验证码会整体失效。
- func TestTencentCaptchaServiceRoutesVerifyEndpointByRegion(t *testing.T) {
- cases := []struct {
- name string
- region string
- wantEndpoint string
- }{
- {"未配置回落中国站", "", "captcha.tencentcloudapi.com"},
- {"中国站", TencentCaptchaRegionCN, "captcha.tencentcloudapi.com"},
- {"国际站", TencentCaptchaRegionINTL, "captcha.intl.tencentcloudapi.com"},
- {"非法值回落中国站", "sgp", "captcha.tencentcloudapi.com"},
- }
- for _, tc := range cases {
- t.Run(tc.name, func(t *testing.T) {
- verifier := &tencentCaptchaVerifierStub{response: &TencentCaptchaVerifyResponse{CaptchaCode: 1}}
- svc := newTencentCaptchaTestServiceWithRegion(verifier, tc.region)
- require.NoError(t, svc.VerifyTicket(context.Background(), "ticket", "@rand", "203.0.113.10"))
- require.Equal(t, tc.wantEndpoint, verifier.credentials.Endpoint)
- })
- }
- }
- func TestTencentCaptchaServiceAcceptsCaptchaCodeOne(t *testing.T) {
- verifier := &tencentCaptchaVerifierStub{response: &TencentCaptchaVerifyResponse{CaptchaCode: 1}}
- svc := newTencentCaptchaTestService(verifier)
- err := svc.VerifyTicket(context.Background(), "ticket", "@rand", "203.0.113.10")
- require.NoError(t, err)
- require.Equal(t, 1, verifier.calls)
- require.Equal(t, TencentCaptchaProof{Ticket: "ticket", Randstr: "@rand"}, verifier.proof)
- require.Equal(t, "203.0.113.10", verifier.remoteIP)
- }
- func TestTencentCaptchaServiceRejectsDisasterRecoveryTicketWithoutCallingVerifier(t *testing.T) {
- verifier := &tencentCaptchaVerifierStub{response: &TencentCaptchaVerifyResponse{CaptchaCode: 1}}
- svc := newTencentCaptchaTestService(verifier)
- err := svc.VerifyTicket(context.Background(), "trerror_1001_123456789_1", "@rand", "203.0.113.10")
- require.ErrorIs(t, err, ErrTencentCaptchaVerificationFailed)
- require.Zero(t, verifier.calls)
- }
- func TestTencentCaptchaServiceRejectsEveryNonOneCode(t *testing.T) {
- for _, code := range []int64{0, 7, 8, 9, 15, 16, 21, 100} {
- t.Run(string(rune(code)), func(t *testing.T) {
- verifier := &tencentCaptchaVerifierStub{response: &TencentCaptchaVerifyResponse{CaptchaCode: code}}
- svc := newTencentCaptchaTestService(verifier)
- err := svc.VerifyTicket(context.Background(), "ticket", "@rand", "203.0.113.10")
- require.ErrorIs(t, err, ErrTencentCaptchaVerificationFailed)
- })
- }
- }
- func TestTencentCaptchaServiceFailsClosedOnVerifierError(t *testing.T) {
- verifier := &tencentCaptchaVerifierStub{err: errors.New("sdk unavailable")}
- svc := newTencentCaptchaTestService(verifier)
- err := svc.VerifyTicket(context.Background(), "ticket", "@rand", "203.0.113.10")
- require.Error(t, err)
- require.ErrorIs(t, err, ErrTencentCaptchaVerificationFailed)
- }
- func TestTencentCaptchaServiceRejectsIncompleteConfiguration(t *testing.T) {
- settings := NewSettingService(&settingPublicRepoStub{values: map[string]string{
- SettingKeyTencentCaptchaEnabled: "true",
- SettingKeyTencentCaptchaAppID: "123456789",
- }}, &config.Config{})
- verifier := &tencentCaptchaVerifierStub{response: &TencentCaptchaVerifyResponse{CaptchaCode: 1}}
- svc := NewTencentCaptchaService(settings, verifier)
- err := svc.VerifyTicket(context.Background(), "ticket", "@rand", "203.0.113.10")
- require.ErrorIs(t, err, ErrTencentCaptchaNotConfigured)
- require.Zero(t, verifier.calls)
- }
- func TestTencentCaptchaServiceFailsClosedOnSettingsReadError(t *testing.T) {
- settings := NewSettingService(&settingPublicRepoStub{err: errors.New("settings unavailable")}, &config.Config{})
- verifier := &tencentCaptchaVerifierStub{response: &TencentCaptchaVerifyResponse{CaptchaCode: 1}}
- svc := NewTencentCaptchaService(settings, verifier)
- err := svc.VerifyTicket(context.Background(), "ticket", "@rand", "203.0.113.10")
- require.ErrorIs(t, err, ErrServiceUnavailable)
- require.Zero(t, verifier.calls)
- }
|