feat: 品牌重命名 Sub2API -> TianShuAPI
- 前端: 所有界面显示、i18n 文本、组件中的品牌名称 - 后端: 服务层、设置默认值、邮件模板、安装向导 - 数据库: 迁移脚本注释 - 保持功能完全一致,仅更改品牌名称 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,105 +1,105 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrTurnstileVerificationFailed = infraerrors.BadRequest("TURNSTILE_VERIFICATION_FAILED", "turnstile verification failed")
|
||||
ErrTurnstileNotConfigured = infraerrors.ServiceUnavailable("TURNSTILE_NOT_CONFIGURED", "turnstile not configured")
|
||||
ErrTurnstileInvalidSecretKey = infraerrors.BadRequest("TURNSTILE_INVALID_SECRET_KEY", "invalid turnstile secret key")
|
||||
)
|
||||
|
||||
// TurnstileVerifier 验证 Turnstile token 的接口
|
||||
type TurnstileVerifier interface {
|
||||
VerifyToken(ctx context.Context, secretKey, token, remoteIP string) (*TurnstileVerifyResponse, error)
|
||||
}
|
||||
|
||||
// TurnstileService Turnstile 验证服务
|
||||
type TurnstileService struct {
|
||||
settingService *SettingService
|
||||
verifier TurnstileVerifier
|
||||
}
|
||||
|
||||
// TurnstileVerifyResponse Cloudflare Turnstile 验证响应
|
||||
type TurnstileVerifyResponse struct {
|
||||
Success bool `json:"success"`
|
||||
ChallengeTS string `json:"challenge_ts"`
|
||||
Hostname string `json:"hostname"`
|
||||
ErrorCodes []string `json:"error-codes"`
|
||||
Action string `json:"action"`
|
||||
CData string `json:"cdata"`
|
||||
}
|
||||
|
||||
// NewTurnstileService 创建 Turnstile 服务实例
|
||||
func NewTurnstileService(settingService *SettingService, verifier TurnstileVerifier) *TurnstileService {
|
||||
return &TurnstileService{
|
||||
settingService: settingService,
|
||||
verifier: verifier,
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyToken 验证 Turnstile token
|
||||
func (s *TurnstileService) VerifyToken(ctx context.Context, token string, remoteIP string) error {
|
||||
// 检查是否启用 Turnstile
|
||||
if !s.settingService.IsTurnstileEnabled(ctx) {
|
||||
log.Println("[Turnstile] Disabled, skipping verification")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取 Secret Key
|
||||
secretKey := s.settingService.GetTurnstileSecretKey(ctx)
|
||||
if secretKey == "" {
|
||||
log.Println("[Turnstile] Secret key not configured")
|
||||
return ErrTurnstileNotConfigured
|
||||
}
|
||||
|
||||
// 如果 token 为空,返回错误
|
||||
if token == "" {
|
||||
log.Println("[Turnstile] Token is empty")
|
||||
return ErrTurnstileVerificationFailed
|
||||
}
|
||||
|
||||
log.Printf("[Turnstile] Verifying token for IP: %s", remoteIP)
|
||||
result, err := s.verifier.VerifyToken(ctx, secretKey, token, remoteIP)
|
||||
if err != nil {
|
||||
log.Printf("[Turnstile] Request failed: %v", err)
|
||||
return fmt.Errorf("send request: %w", err)
|
||||
}
|
||||
|
||||
if !result.Success {
|
||||
log.Printf("[Turnstile] Verification failed, error codes: %v", result.ErrorCodes)
|
||||
return ErrTurnstileVerificationFailed
|
||||
}
|
||||
|
||||
log.Println("[Turnstile] Verification successful")
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEnabled 检查 Turnstile 是否启用
|
||||
func (s *TurnstileService) IsEnabled(ctx context.Context) bool {
|
||||
return s.settingService.IsTurnstileEnabled(ctx)
|
||||
}
|
||||
|
||||
// ValidateSecretKey 验证 Turnstile Secret Key 是否有效
|
||||
func (s *TurnstileService) ValidateSecretKey(ctx context.Context, secretKey string) error {
|
||||
// 发送一个测试token的验证请求来检查secret_key是否有效
|
||||
result, err := s.verifier.VerifyToken(ctx, secretKey, "test-validation", "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("validate secret key: %w", err)
|
||||
}
|
||||
|
||||
// 检查是否有 invalid-input-secret 错误
|
||||
for _, code := range result.ErrorCodes {
|
||||
if code == "invalid-input-secret" {
|
||||
return ErrTurnstileInvalidSecretKey
|
||||
}
|
||||
}
|
||||
|
||||
// 其他错误(如 invalid-input-response)说明 secret key 是有效的
|
||||
return nil
|
||||
}
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrTurnstileVerificationFailed = infraerrors.BadRequest("TURNSTILE_VERIFICATION_FAILED", "turnstile verification failed")
|
||||
ErrTurnstileNotConfigured = infraerrors.ServiceUnavailable("TURNSTILE_NOT_CONFIGURED", "turnstile not configured")
|
||||
ErrTurnstileInvalidSecretKey = infraerrors.BadRequest("TURNSTILE_INVALID_SECRET_KEY", "invalid turnstile secret key")
|
||||
)
|
||||
|
||||
// TurnstileVerifier 验证 Turnstile token 的接口
|
||||
type TurnstileVerifier interface {
|
||||
VerifyToken(ctx context.Context, secretKey, token, remoteIP string) (*TurnstileVerifyResponse, error)
|
||||
}
|
||||
|
||||
// TurnstileService Turnstile 验证服务
|
||||
type TurnstileService struct {
|
||||
settingService *SettingService
|
||||
verifier TurnstileVerifier
|
||||
}
|
||||
|
||||
// TurnstileVerifyResponse Cloudflare Turnstile 验证响应
|
||||
type TurnstileVerifyResponse struct {
|
||||
Success bool `json:"success"`
|
||||
ChallengeTS string `json:"challenge_ts"`
|
||||
Hostname string `json:"hostname"`
|
||||
ErrorCodes []string `json:"error-codes"`
|
||||
Action string `json:"action"`
|
||||
CData string `json:"cdata"`
|
||||
}
|
||||
|
||||
// NewTurnstileService 创建 Turnstile 服务实例
|
||||
func NewTurnstileService(settingService *SettingService, verifier TurnstileVerifier) *TurnstileService {
|
||||
return &TurnstileService{
|
||||
settingService: settingService,
|
||||
verifier: verifier,
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyToken 验证 Turnstile token
|
||||
func (s *TurnstileService) VerifyToken(ctx context.Context, token string, remoteIP string) error {
|
||||
// 检查是否启用 Turnstile
|
||||
if !s.settingService.IsTurnstileEnabled(ctx) {
|
||||
log.Println("[Turnstile] Disabled, skipping verification")
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取 Secret Key
|
||||
secretKey := s.settingService.GetTurnstileSecretKey(ctx)
|
||||
if secretKey == "" {
|
||||
log.Println("[Turnstile] Secret key not configured")
|
||||
return ErrTurnstileNotConfigured
|
||||
}
|
||||
|
||||
// 如果 token 为空,返回错误
|
||||
if token == "" {
|
||||
log.Println("[Turnstile] Token is empty")
|
||||
return ErrTurnstileVerificationFailed
|
||||
}
|
||||
|
||||
log.Printf("[Turnstile] Verifying token for IP: %s", remoteIP)
|
||||
result, err := s.verifier.VerifyToken(ctx, secretKey, token, remoteIP)
|
||||
if err != nil {
|
||||
log.Printf("[Turnstile] Request failed: %v", err)
|
||||
return fmt.Errorf("send request: %w", err)
|
||||
}
|
||||
|
||||
if !result.Success {
|
||||
log.Printf("[Turnstile] Verification failed, error codes: %v", result.ErrorCodes)
|
||||
return ErrTurnstileVerificationFailed
|
||||
}
|
||||
|
||||
log.Println("[Turnstile] Verification successful")
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsEnabled 检查 Turnstile 是否启用
|
||||
func (s *TurnstileService) IsEnabled(ctx context.Context) bool {
|
||||
return s.settingService.IsTurnstileEnabled(ctx)
|
||||
}
|
||||
|
||||
// ValidateSecretKey 验证 Turnstile Secret Key 是否有效
|
||||
func (s *TurnstileService) ValidateSecretKey(ctx context.Context, secretKey string) error {
|
||||
// 发送一个测试token的验证请求来检查secret_key是否有效
|
||||
result, err := s.verifier.VerifyToken(ctx, secretKey, "test-validation", "")
|
||||
if err != nil {
|
||||
return fmt.Errorf("validate secret key: %w", err)
|
||||
}
|
||||
|
||||
// 检查是否有 invalid-input-secret 错误
|
||||
for _, code := range result.ErrorCodes {
|
||||
if code == "invalid-input-secret" {
|
||||
return ErrTurnstileInvalidSecretKey
|
||||
}
|
||||
}
|
||||
|
||||
// 其他错误(如 invalid-input-response)说明 secret key 是有效的
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user