refactor: Implement dependency injection for handlers and services
- Refactored AuthHandler, UserHandler, TextureHandler, ProfileHandler, CaptchaHandler, and YggdrasilHandler to use dependency injection. - Removed direct instantiation of services and repositories within handlers, replacing them with constructor injection. - Updated the container to initialize service instances and provide them to handlers. - Enhanced code structure for better testability and adherence to Go best practices.
This commit is contained in:
@@ -74,27 +74,38 @@ func ValidateFileName(fileName string, fileType FileType) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateAvatarUploadURL 生成头像上传URL
|
||||
// uploadStorageClient 为上传服务定义的最小依赖接口,便于单元测试注入 mock
|
||||
type uploadStorageClient interface {
|
||||
GetBucket(name string) (string, error)
|
||||
GeneratePresignedPostURL(ctx context.Context, bucketName, objectName string, minSize, maxSize int64, expires time.Duration) (*storage.PresignedPostPolicyResult, error)
|
||||
}
|
||||
|
||||
// GenerateAvatarUploadURL 生成头像上传URL(对外导出)
|
||||
func GenerateAvatarUploadURL(ctx context.Context, storageClient *storage.StorageClient, userID int64, fileName string) (*storage.PresignedPostPolicyResult, error) {
|
||||
return generateAvatarUploadURLWithClient(ctx, storageClient, userID, fileName)
|
||||
}
|
||||
|
||||
// generateAvatarUploadURLWithClient 使用接口类型的内部实现,方便测试
|
||||
func generateAvatarUploadURLWithClient(ctx context.Context, storageClient uploadStorageClient, userID int64, fileName string) (*storage.PresignedPostPolicyResult, error) {
|
||||
// 1. 验证文件名
|
||||
if err := ValidateFileName(fileName, FileTypeAvatar); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
// 2. 获取上传配置
|
||||
uploadConfig := GetUploadConfig(FileTypeAvatar)
|
||||
|
||||
|
||||
// 3. 获取存储桶名称
|
||||
bucketName, err := storageClient.GetBucket("avatars")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取存储桶失败: %w", err)
|
||||
}
|
||||
|
||||
|
||||
// 4. 生成对象名称(路径)
|
||||
// 格式: user_{userId}/timestamp_{originalFileName}
|
||||
timestamp := time.Now().Format("20060102150405")
|
||||
objectName := fmt.Sprintf("user_%d/%s_%s", userID, timestamp, fileName)
|
||||
|
||||
|
||||
// 5. 生成预签名POST URL (使用存储客户端内置的 PublicURL)
|
||||
result, err := storageClient.GeneratePresignedPostURL(
|
||||
ctx,
|
||||
@@ -107,37 +118,42 @@ func GenerateAvatarUploadURL(ctx context.Context, storageClient *storage.Storage
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("生成上传URL失败: %w", err)
|
||||
}
|
||||
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GenerateTextureUploadURL 生成材质上传URL
|
||||
// GenerateTextureUploadURL 生成材质上传URL(对外导出)
|
||||
func GenerateTextureUploadURL(ctx context.Context, storageClient *storage.StorageClient, userID int64, fileName, textureType string) (*storage.PresignedPostPolicyResult, error) {
|
||||
return generateTextureUploadURLWithClient(ctx, storageClient, userID, fileName, textureType)
|
||||
}
|
||||
|
||||
// generateTextureUploadURLWithClient 使用接口类型的内部实现,方便测试
|
||||
func generateTextureUploadURLWithClient(ctx context.Context, storageClient uploadStorageClient, userID int64, fileName, textureType string) (*storage.PresignedPostPolicyResult, error) {
|
||||
// 1. 验证文件名
|
||||
if err := ValidateFileName(fileName, FileTypeTexture); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
// 2. 验证材质类型
|
||||
if textureType != "SKIN" && textureType != "CAPE" {
|
||||
return nil, fmt.Errorf("无效的材质类型: %s", textureType)
|
||||
}
|
||||
|
||||
|
||||
// 3. 获取上传配置
|
||||
uploadConfig := GetUploadConfig(FileTypeTexture)
|
||||
|
||||
|
||||
// 4. 获取存储桶名称
|
||||
bucketName, err := storageClient.GetBucket("textures")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("获取存储桶失败: %w", err)
|
||||
}
|
||||
|
||||
|
||||
// 5. 生成对象名称(路径)
|
||||
// 格式: user_{userId}/{textureType}/timestamp_{originalFileName}
|
||||
timestamp := time.Now().Format("20060102150405")
|
||||
textureTypeFolder := strings.ToLower(textureType)
|
||||
objectName := fmt.Sprintf("user_%d/%s/%s_%s", userID, textureTypeFolder, timestamp, fileName)
|
||||
|
||||
|
||||
// 6. 生成预签名POST URL (使用存储客户端内置的 PublicURL)
|
||||
result, err := storageClient.GeneratePresignedPostURL(
|
||||
ctx,
|
||||
@@ -150,6 +166,6 @@ func GenerateTextureUploadURL(ctx context.Context, storageClient *storage.Storag
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("生成上传URL失败: %w", err)
|
||||
}
|
||||
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user