package container import ( "carrotskin/internal/repository" "carrotskin/internal/service" "carrotskin/pkg/auth" "carrotskin/pkg/database" "carrotskin/pkg/email" "carrotskin/pkg/redis" "carrotskin/pkg/storage" "time" "go.uber.org/zap" "gorm.io/gorm" ) // Container 依赖注入容器 // 集中管理所有依赖,便于测试和维护 type Container struct { // 基础设施依赖 DB *gorm.DB Redis *redis.Client Logger *zap.Logger JWT *auth.JWTService Casbin *auth.CasbinService Storage *storage.StorageClient CacheManager *database.CacheManager // Repository层 UserRepo repository.UserRepository ProfileRepo repository.ProfileRepository TextureRepo repository.TextureRepository ClientRepo repository.ClientRepository YggdrasilRepo repository.YggdrasilRepository // Service层 UserService service.UserService ProfileService service.ProfileService TextureService service.TextureService TokenService service.TokenService YggdrasilService service.YggdrasilService VerificationService service.VerificationService SecurityService service.SecurityService CaptchaService service.CaptchaService SignatureService *service.SignatureService } // NewContainer 创建依赖容器 func NewContainer( db *gorm.DB, redisClient *redis.Client, logger *zap.Logger, jwtService *auth.JWTService, casbinService *auth.CasbinService, storageClient *storage.StorageClient, emailService interface{}, // 接受 email.Service 但使用 interface{} 避免循环依赖 ) *Container { // 创建缓存管理器 cacheManager := database.NewCacheManager(redisClient, database.CacheConfig{ Prefix: "carrotskin:", Expiration: 5 * time.Minute, Enabled: true, Policy: database.CachePolicy{ UserTTL: 5 * time.Minute, UserEmailTTL: 5 * time.Minute, ProfileTTL: 5 * time.Minute, ProfileListTTL: 3 * time.Minute, TextureTTL: 5 * time.Minute, TextureListTTL: 2 * time.Minute, }, }) c := &Container{ DB: db, Redis: redisClient, Logger: logger, JWT: jwtService, Casbin: casbinService, Storage: storageClient, CacheManager: cacheManager, } // 初始化Repository c.UserRepo = repository.NewUserRepository(db) c.ProfileRepo = repository.NewProfileRepository(db) c.TextureRepo = repository.NewTextureRepository(db) c.ClientRepo = repository.NewClientRepository(db) c.YggdrasilRepo = repository.NewYggdrasilRepository(db) // 初始化SignatureService(作为依赖注入,避免在容器中创建并立即调用) // 将SignatureService添加到容器中,供其他服务使用 c.SignatureService = service.NewSignatureService(c.ProfileRepo, redisClient, logger) // 初始化Service(注入缓存管理器) c.UserService = service.NewUserService(c.UserRepo, jwtService, redisClient, cacheManager, storageClient, logger) c.ProfileService = service.NewProfileService(c.ProfileRepo, c.UserRepo, cacheManager, logger) c.TextureService = service.NewTextureService(c.TextureRepo, c.UserRepo, storageClient, cacheManager, logger) // 获取Yggdrasil私钥并创建JWT服务(TokenService需要) // 注意:这里仍然需要预先初始化,因为TokenService在创建时需要YggdrasilJWT // 但SignatureService已经作为依赖注入,降低了耦合度 _, privateKey, err := c.SignatureService.GetOrCreateYggdrasilKeyPair() if err != nil { logger.Fatal("获取Yggdrasil私钥失败", zap.Error(err)) } yggdrasilJWT := auth.NewYggdrasilJWTService(privateKey, "carrotskin") // 创建Redis Token存储(必须使用Redis,包括miniredis回退) if redisClient == nil { logger.Fatal("Redis客户端未初始化,无法创建Token服务") } tokenStore := auth.NewTokenStoreRedis( redisClient, logger, auth.WithKeyPrefix("token:"), auth.WithDefaultTTL(24*time.Hour), auth.WithStaleTTL(30*24*time.Hour), auth.WithMaxTokensPerUser(10), ) c.TokenService = service.NewTokenServiceRedis(tokenStore, c.ClientRepo, c.ProfileRepo, yggdrasilJWT, logger) // 使用组合服务(内部包含认证、会话、序列化、证书服务) c.YggdrasilService = service.NewYggdrasilServiceComposite(db, c.UserRepo, c.ProfileRepo, c.YggdrasilRepo, c.SignatureService, redisClient, logger, c.TokenService) // 初始化其他服务 c.SecurityService = service.NewSecurityService(redisClient) c.CaptchaService = service.NewCaptchaService(redisClient, logger) // 初始化VerificationService(需要email.Service) if emailService != nil { if emailSvc, ok := emailService.(*email.Service); ok { c.VerificationService = service.NewVerificationService(redisClient, emailSvc) } } return c } // NewTestContainer 创建测试用容器(可注入mock依赖) func NewTestContainer(opts ...Option) *Container { c := &Container{} for _, opt := range opts { opt(c) } return c } // Option 容器配置选项 type Option func(*Container) // WithDB 设置数据库连接 func WithDB(db *gorm.DB) Option { return func(c *Container) { c.DB = db } } // WithRedis 设置Redis客户端 func WithRedis(redis *redis.Client) Option { return func(c *Container) { c.Redis = redis } } // WithLogger 设置日志 func WithLogger(logger *zap.Logger) Option { return func(c *Container) { c.Logger = logger } } // WithJWT 设置JWT服务 func WithJWT(jwt *auth.JWTService) Option { return func(c *Container) { c.JWT = jwt } } // WithStorage 设置存储客户端 func WithStorage(storage *storage.StorageClient) Option { return func(c *Container) { c.Storage = storage } } // WithUserRepo 设置用户仓储 func WithUserRepo(repo repository.UserRepository) Option { return func(c *Container) { c.UserRepo = repo } } // WithProfileRepo 设置档案仓储 func WithProfileRepo(repo repository.ProfileRepository) Option { return func(c *Container) { c.ProfileRepo = repo } } // WithTextureRepo 设置材质仓储 func WithTextureRepo(repo repository.TextureRepository) Option { return func(c *Container) { c.TextureRepo = repo } } // WithUserService 设置用户服务 func WithUserService(svc service.UserService) Option { return func(c *Container) { c.UserService = svc } } // WithProfileService 设置档案服务 func WithProfileService(svc service.ProfileService) Option { return func(c *Container) { c.ProfileService = svc } } // WithTextureService 设置材质服务 func WithTextureService(svc service.TextureService) Option { return func(c *Container) { c.TextureService = svc } } // WithTokenService 设置令牌服务 func WithTokenService(svc service.TokenService) Option { return func(c *Container) { c.TokenService = svc } } // WithYggdrasilRepo 设置Yggdrasil仓储 func WithYggdrasilRepo(repo repository.YggdrasilRepository) Option { return func(c *Container) { c.YggdrasilRepo = repo } } // WithYggdrasilService 设置Yggdrasil服务 func WithYggdrasilService(svc service.YggdrasilService) Option { return func(c *Container) { c.YggdrasilService = svc } } // WithVerificationService 设置验证码服务 func WithVerificationService(svc service.VerificationService) Option { return func(c *Container) { c.VerificationService = svc } } // WithSecurityService 设置安全服务 func WithSecurityService(svc service.SecurityService) Option { return func(c *Container) { c.SecurityService = svc } } // WithCaptchaService 设置验证码服务 func WithCaptchaService(svc service.CaptchaService) Option { return func(c *Container) { c.CaptchaService = svc } }