新增功能: - 支持 Google Authenticator 等应用进行 TOTP 二次验证 - 用户可在个人设置中启用/禁用 2FA - 登录时支持 TOTP 验证流程 - 管理后台可全局开关 TOTP 功能 安全增强: - TOTP 密钥使用 AES-256-GCM 加密存储 - 添加 TOTP_ENCRYPTION_KEY 配置项,必须手动配置才能启用功能 - 防止服务重启导致加密密钥变更使用户无法登录 - 验证失败次数限制,防止暴力破解 配置说明: - Docker 部署:在 .env 中设置 TOTP_ENCRYPTION_KEY - 非 Docker 部署:在 config.yaml 中设置 totp.encryption_key - 生成密钥命令:openssl rand -hex 32
276 lines
8.7 KiB
Go
276 lines
8.7 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"time"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
|
"github.com/google/wire"
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
// BuildInfo contains build information
|
|
type BuildInfo struct {
|
|
Version string
|
|
BuildType string
|
|
}
|
|
|
|
// ProvidePricingService creates and initializes PricingService
|
|
func ProvidePricingService(cfg *config.Config, remoteClient PricingRemoteClient) (*PricingService, error) {
|
|
svc := NewPricingService(cfg, remoteClient)
|
|
if err := svc.Initialize(); err != nil {
|
|
// Pricing service initialization failure should not block startup, use fallback prices
|
|
println("[Service] Warning: Pricing service initialization failed:", err.Error())
|
|
}
|
|
return svc, nil
|
|
}
|
|
|
|
// ProvideUpdateService creates UpdateService with BuildInfo
|
|
func ProvideUpdateService(cache UpdateCache, githubClient GitHubReleaseClient, buildInfo BuildInfo) *UpdateService {
|
|
return NewUpdateService(cache, githubClient, buildInfo.Version, buildInfo.BuildType)
|
|
}
|
|
|
|
// ProvideEmailQueueService creates EmailQueueService with default worker count
|
|
func ProvideEmailQueueService(emailService *EmailService) *EmailQueueService {
|
|
return NewEmailQueueService(emailService, 3)
|
|
}
|
|
|
|
// ProvideTokenRefreshService creates and starts TokenRefreshService
|
|
func ProvideTokenRefreshService(
|
|
accountRepo AccountRepository,
|
|
oauthService *OAuthService,
|
|
openaiOAuthService *OpenAIOAuthService,
|
|
geminiOAuthService *GeminiOAuthService,
|
|
antigravityOAuthService *AntigravityOAuthService,
|
|
cacheInvalidator TokenCacheInvalidator,
|
|
cfg *config.Config,
|
|
) *TokenRefreshService {
|
|
svc := NewTokenRefreshService(accountRepo, oauthService, openaiOAuthService, geminiOAuthService, antigravityOAuthService, cacheInvalidator, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideDashboardAggregationService 创建并启动仪表盘聚合服务
|
|
func ProvideDashboardAggregationService(repo DashboardAggregationRepository, timingWheel *TimingWheelService, cfg *config.Config) *DashboardAggregationService {
|
|
svc := NewDashboardAggregationService(repo, timingWheel, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideUsageCleanupService 创建并启动使用记录清理任务服务
|
|
func ProvideUsageCleanupService(repo UsageCleanupRepository, timingWheel *TimingWheelService, dashboardAgg *DashboardAggregationService, cfg *config.Config) *UsageCleanupService {
|
|
svc := NewUsageCleanupService(repo, timingWheel, dashboardAgg, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideAccountExpiryService creates and starts AccountExpiryService.
|
|
func ProvideAccountExpiryService(accountRepo AccountRepository) *AccountExpiryService {
|
|
svc := NewAccountExpiryService(accountRepo, time.Minute)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideSubscriptionExpiryService creates and starts SubscriptionExpiryService.
|
|
func ProvideSubscriptionExpiryService(userSubRepo UserSubscriptionRepository) *SubscriptionExpiryService {
|
|
svc := NewSubscriptionExpiryService(userSubRepo, time.Minute)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideTimingWheelService creates and starts TimingWheelService
|
|
func ProvideTimingWheelService() (*TimingWheelService, error) {
|
|
svc, err := NewTimingWheelService()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
svc.Start()
|
|
return svc, nil
|
|
}
|
|
|
|
// ProvideDeferredService creates and starts DeferredService
|
|
func ProvideDeferredService(accountRepo AccountRepository, timingWheel *TimingWheelService) *DeferredService {
|
|
svc := NewDeferredService(accountRepo, timingWheel, 10*time.Second)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideConcurrencyService creates ConcurrencyService and starts slot cleanup worker.
|
|
func ProvideConcurrencyService(cache ConcurrencyCache, accountRepo AccountRepository, cfg *config.Config) *ConcurrencyService {
|
|
svc := NewConcurrencyService(cache)
|
|
if cfg != nil {
|
|
svc.StartSlotCleanupWorker(accountRepo, cfg.Gateway.Scheduling.SlotCleanupInterval)
|
|
}
|
|
return svc
|
|
}
|
|
|
|
// ProvideSchedulerSnapshotService creates and starts SchedulerSnapshotService.
|
|
func ProvideSchedulerSnapshotService(
|
|
cache SchedulerCache,
|
|
outboxRepo SchedulerOutboxRepository,
|
|
accountRepo AccountRepository,
|
|
groupRepo GroupRepository,
|
|
cfg *config.Config,
|
|
) *SchedulerSnapshotService {
|
|
svc := NewSchedulerSnapshotService(cache, outboxRepo, accountRepo, groupRepo, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideRateLimitService creates RateLimitService with optional dependencies.
|
|
func ProvideRateLimitService(
|
|
accountRepo AccountRepository,
|
|
usageRepo UsageLogRepository,
|
|
cfg *config.Config,
|
|
geminiQuotaService *GeminiQuotaService,
|
|
tempUnschedCache TempUnschedCache,
|
|
timeoutCounterCache TimeoutCounterCache,
|
|
settingService *SettingService,
|
|
tokenCacheInvalidator TokenCacheInvalidator,
|
|
) *RateLimitService {
|
|
svc := NewRateLimitService(accountRepo, usageRepo, cfg, geminiQuotaService, tempUnschedCache)
|
|
svc.SetTimeoutCounterCache(timeoutCounterCache)
|
|
svc.SetSettingService(settingService)
|
|
svc.SetTokenCacheInvalidator(tokenCacheInvalidator)
|
|
return svc
|
|
}
|
|
|
|
// ProvideOpsMetricsCollector creates and starts OpsMetricsCollector.
|
|
func ProvideOpsMetricsCollector(
|
|
opsRepo OpsRepository,
|
|
settingRepo SettingRepository,
|
|
accountRepo AccountRepository,
|
|
concurrencyService *ConcurrencyService,
|
|
db *sql.DB,
|
|
redisClient *redis.Client,
|
|
cfg *config.Config,
|
|
) *OpsMetricsCollector {
|
|
collector := NewOpsMetricsCollector(opsRepo, settingRepo, accountRepo, concurrencyService, db, redisClient, cfg)
|
|
collector.Start()
|
|
return collector
|
|
}
|
|
|
|
// ProvideOpsAggregationService creates and starts OpsAggregationService (hourly/daily pre-aggregation).
|
|
func ProvideOpsAggregationService(
|
|
opsRepo OpsRepository,
|
|
settingRepo SettingRepository,
|
|
db *sql.DB,
|
|
redisClient *redis.Client,
|
|
cfg *config.Config,
|
|
) *OpsAggregationService {
|
|
svc := NewOpsAggregationService(opsRepo, settingRepo, db, redisClient, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideOpsAlertEvaluatorService creates and starts OpsAlertEvaluatorService.
|
|
func ProvideOpsAlertEvaluatorService(
|
|
opsService *OpsService,
|
|
opsRepo OpsRepository,
|
|
emailService *EmailService,
|
|
redisClient *redis.Client,
|
|
cfg *config.Config,
|
|
) *OpsAlertEvaluatorService {
|
|
svc := NewOpsAlertEvaluatorService(opsService, opsRepo, emailService, redisClient, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideOpsCleanupService creates and starts OpsCleanupService (cron scheduled).
|
|
func ProvideOpsCleanupService(
|
|
opsRepo OpsRepository,
|
|
db *sql.DB,
|
|
redisClient *redis.Client,
|
|
cfg *config.Config,
|
|
) *OpsCleanupService {
|
|
svc := NewOpsCleanupService(opsRepo, db, redisClient, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideOpsScheduledReportService creates and starts OpsScheduledReportService.
|
|
func ProvideOpsScheduledReportService(
|
|
opsService *OpsService,
|
|
userService *UserService,
|
|
emailService *EmailService,
|
|
redisClient *redis.Client,
|
|
cfg *config.Config,
|
|
) *OpsScheduledReportService {
|
|
svc := NewOpsScheduledReportService(opsService, userService, emailService, redisClient, cfg)
|
|
svc.Start()
|
|
return svc
|
|
}
|
|
|
|
// ProvideAPIKeyAuthCacheInvalidator 提供 API Key 认证缓存失效能力
|
|
func ProvideAPIKeyAuthCacheInvalidator(apiKeyService *APIKeyService) APIKeyAuthCacheInvalidator {
|
|
// Start Pub/Sub subscriber for L1 cache invalidation across instances
|
|
apiKeyService.StartAuthCacheInvalidationSubscriber(context.Background())
|
|
return apiKeyService
|
|
}
|
|
|
|
// ProviderSet is the Wire provider set for all services
|
|
var ProviderSet = wire.NewSet(
|
|
// Core services
|
|
NewAuthService,
|
|
NewUserService,
|
|
NewAPIKeyService,
|
|
ProvideAPIKeyAuthCacheInvalidator,
|
|
NewGroupService,
|
|
NewAccountService,
|
|
NewProxyService,
|
|
NewRedeemService,
|
|
NewPromoService,
|
|
NewUsageService,
|
|
NewDashboardService,
|
|
ProvidePricingService,
|
|
NewBillingService,
|
|
NewBillingCacheService,
|
|
NewAdminService,
|
|
NewGatewayService,
|
|
NewOpenAIGatewayService,
|
|
NewOAuthService,
|
|
NewOpenAIOAuthService,
|
|
NewGeminiOAuthService,
|
|
NewGeminiQuotaService,
|
|
NewCompositeTokenCacheInvalidator,
|
|
wire.Bind(new(TokenCacheInvalidator), new(*CompositeTokenCacheInvalidator)),
|
|
NewAntigravityOAuthService,
|
|
NewGeminiTokenProvider,
|
|
NewGeminiMessagesCompatService,
|
|
NewAntigravityTokenProvider,
|
|
NewOpenAITokenProvider,
|
|
NewClaudeTokenProvider,
|
|
NewAntigravityGatewayService,
|
|
ProvideRateLimitService,
|
|
NewAccountUsageService,
|
|
NewAccountTestService,
|
|
NewSettingService,
|
|
NewOpsService,
|
|
ProvideOpsMetricsCollector,
|
|
ProvideOpsAggregationService,
|
|
ProvideOpsAlertEvaluatorService,
|
|
ProvideOpsCleanupService,
|
|
ProvideOpsScheduledReportService,
|
|
NewEmailService,
|
|
ProvideEmailQueueService,
|
|
NewTurnstileService,
|
|
NewSubscriptionService,
|
|
ProvideConcurrencyService,
|
|
ProvideSchedulerSnapshotService,
|
|
NewIdentityService,
|
|
NewCRSSyncService,
|
|
ProvideUpdateService,
|
|
ProvideTokenRefreshService,
|
|
ProvideAccountExpiryService,
|
|
ProvideSubscriptionExpiryService,
|
|
ProvideTimingWheelService,
|
|
ProvideDashboardAggregationService,
|
|
ProvideUsageCleanupService,
|
|
ProvideDeferredService,
|
|
NewAntigravityQuotaFetcher,
|
|
NewUserAttributeService,
|
|
NewUsageCache,
|
|
NewTotpService,
|
|
)
|