Files
nl-blogs/server/handlers/attachment.go
2026-01-19 20:21:09 +08:00

1017 lines
27 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handlers
import (
"log"
"strconv"
"github.com/gin-gonic/gin"
"github.com/niangaodev/art-code/models"
"github.com/niangaodev/art-code/repositories"
"github.com/niangaodev/art-code/utils"
)
// AdminUploadAttachment 上传附件
func AdminUploadAttachment(c *gin.Context) {
// 获取文件
file, err := c.FormFile("file")
if err != nil {
utils.Error(c, 400, "No file uploaded")
return
}
// 获取分类ID可选
categoryIDStr := c.PostForm("categoryId")
var categoryID *uint
if categoryIDStr != "" {
if id, err := strconv.ParseUint(categoryIDStr, 10, 32); err == nil {
idUint := uint(id)
categoryID = &idUint
}
}
// 获取存储类型
storageType := c.DefaultPostForm("storageType", "local")
// 打开文件
src, err := file.Open()
if err != nil {
utils.Error(c, 500, "Failed to open file")
return
}
defer src.Close()
// 获取OSS配置
var ossConfig *models.OSSConfig
if storageType != "local" {
ossConfig, err = repositories.GetActiveOSSConfig(storageType)
if err != nil || ossConfig == nil {
utils.Error(c, 400, "OSS config not found or not active")
return
}
}
// 创建OSS配置对象
config := &utils.OSSConfig{
StorageType: storageType,
}
if ossConfig != nil {
// 根据存储类型从专用字段或通用字段读取配置
var accessKey, secretKey, bucket, region, domain string
switch ossConfig.StorageType {
case "aliyun":
// 优先使用专用字段
if ossConfig.OSSAccessKeyID != "" {
decrypted, err := utils.DecryptAES(ossConfig.OSSAccessKeyID)
if err == nil {
accessKey = decrypted
}
}
if ossConfig.OSSAccessKeySecret != "" {
decrypted, err := utils.DecryptAES(ossConfig.OSSAccessKeySecret)
if err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.OSSBucket
domain = ossConfig.OSSDomain
// 如果专用字段为空,使用通用字段(向后兼容)
if accessKey == "" && ossConfig.AccessKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.AccessKey)
if err == nil {
accessKey = decrypted
}
}
if secretKey == "" && ossConfig.SecretKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.SecretKey)
if err == nil {
secretKey = decrypted
}
}
if bucket == "" {
bucket = ossConfig.Bucket
}
if domain == "" {
domain = ossConfig.Domain
}
case "qcloud":
// 优先使用专用字段
if ossConfig.QCloudSecretID != "" {
decrypted, err := utils.DecryptAES(ossConfig.QCloudSecretID)
if err == nil {
accessKey = decrypted
}
}
if ossConfig.QCloudSecretKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.QCloudSecretKey)
if err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.QCloudBucket
region = ossConfig.QCloudRegion
domain = ossConfig.QCloudDomain
// 向后兼容
if accessKey == "" && ossConfig.AccessKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.AccessKey)
if err == nil {
accessKey = decrypted
}
}
if secretKey == "" && ossConfig.SecretKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.SecretKey)
if err == nil {
secretKey = decrypted
}
}
if bucket == "" {
bucket = ossConfig.Bucket
}
if region == "" {
region = ossConfig.Region
}
if domain == "" {
domain = ossConfig.Domain
}
case "qiniu":
// 优先使用专用字段
if ossConfig.QiniuAccessKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.QiniuAccessKey)
if err == nil {
accessKey = decrypted
}
}
if ossConfig.QiniuSecretKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.QiniuSecretKey)
if err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.QiniuBucket
region = ossConfig.QiniuRegion
domain = ossConfig.QiniuDomain
// 向后兼容
if accessKey == "" && ossConfig.AccessKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.AccessKey)
if err == nil {
accessKey = decrypted
}
}
if secretKey == "" && ossConfig.SecretKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.SecretKey)
if err == nil {
secretKey = decrypted
}
}
if bucket == "" {
bucket = ossConfig.Bucket
}
if region == "" {
region = ossConfig.Region
}
if domain == "" {
domain = ossConfig.Domain
}
default:
// 使用通用字段
if ossConfig.AccessKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.AccessKey)
if err == nil {
accessKey = decrypted
}
}
if ossConfig.SecretKey != "" {
decrypted, err := utils.DecryptAES(ossConfig.SecretKey)
if err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.Bucket
region = ossConfig.Region
domain = ossConfig.Domain
}
config.AccessKey = accessKey
config.SecretKey = secretKey
config.Bucket = bucket
config.Region = region
config.Domain = domain
// 填充专用字段
switch ossConfig.StorageType {
case "aliyun":
config.OSSAccessKeyID = accessKey
config.OSSAccessKeySecret = secretKey
config.OSSEndpoint = ossConfig.OSSEndpoint
config.OSSBucket = bucket
config.OSSDomain = domain
case "qcloud":
config.QCloudSecretID = accessKey
config.QCloudSecretKey = secretKey
config.QCloudRegion = region
config.QCloudBucket = bucket
config.QCloudDomain = domain
case "qiniu":
config.QiniuAccessKey = accessKey
config.QiniuSecretKey = secretKey
config.QiniuBucket = bucket
config.QiniuRegion = region
config.QiniuDomain = domain
}
}
// 获取上传器
uploader, err := utils.GetOSSUploader(config)
if err != nil {
utils.Error(c, 500, err.Error())
return
}
// 上传文件
filePath, fileURL, err := uploader.Upload(src, file.Filename, file.Size)
if err != nil {
utils.Error(c, 500, "Failed to upload file: "+err.Error())
return
}
// 获取文件类型
fileType := utils.GetFileType(file.Header.Get("Content-Type"))
// 创建附件记录
attachment := &models.Attachment{
CategoryID: categoryID,
OriginalName: file.Filename,
StoredName: file.Filename,
FilePath: filePath,
FileURL: fileURL,
FileSize: file.Size,
FileType: fileType,
MimeType: file.Header.Get("Content-Type"),
StorageType: storageType,
}
if ossConfig != nil {
ossConfigID := ossConfig.ID
attachment.OSSConfigID = &ossConfigID
}
if err := repositories.CreateAttachment(attachment); err != nil {
// 如果数据库保存失败,尝试删除已上传的文件
uploader.Delete(filePath)
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "File uploaded successfully", attachment)
}
// AdminGetAttachments 获取附件列表
func AdminGetAttachments(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
categoryIDStr := c.Query("categoryId")
fileType := c.Query("fileType")
var categoryID *uint
if categoryIDStr != "" {
if id, err := strconv.ParseUint(categoryIDStr, 10, 32); err == nil {
idUint := uint(id)
categoryID = &idUint
}
}
attachments, total, err := repositories.GetAttachments(page, pageSize, categoryID, fileType)
if err != nil {
utils.ServerError(c, err)
return
}
res := gin.H{
"list": attachments,
"total": total,
"page": page,
"size": pageSize,
}
utils.Success(c, res)
}
// AdminDeleteAttachment 删除附件
func AdminDeleteAttachment(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid attachment ID")
return
}
// 获取附件信息
attachment, err := repositories.GetAttachmentByID(id)
if err != nil || attachment == nil {
utils.Error(c, 404, "Attachment not found")
return
}
// 获取OSS配置并删除文件
if attachment.StorageType != "" {
var ossConfig *models.OSSConfig
if attachment.OSSConfigID != nil {
ossConfig, err = repositories.GetOSSConfigByID(*attachment.OSSConfigID)
} else {
ossConfig, err = repositories.GetActiveOSSConfig(attachment.StorageType)
}
if err == nil && ossConfig != nil {
config := &utils.OSSConfig{
StorageType: attachment.StorageType,
}
// 根据存储类型从专用字段或通用字段读取配置
var accessKey, secretKey, bucket, region, domain string
switch ossConfig.StorageType {
case "aliyun":
if ossConfig.OSSAccessKeyID != "" {
if decrypted, err := utils.DecryptAES(ossConfig.OSSAccessKeyID); err == nil {
accessKey = decrypted
}
}
if ossConfig.OSSAccessKeySecret != "" {
if decrypted, err := utils.DecryptAES(ossConfig.OSSAccessKeySecret); err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.OSSBucket
domain = ossConfig.OSSDomain
// 向后兼容
if accessKey == "" && ossConfig.AccessKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.AccessKey); err == nil {
accessKey = decrypted
}
}
if secretKey == "" && ossConfig.SecretKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.SecretKey); err == nil {
secretKey = decrypted
}
}
if bucket == "" {
bucket = ossConfig.Bucket
}
if domain == "" {
domain = ossConfig.Domain
}
case "qcloud":
if ossConfig.QCloudSecretID != "" {
if decrypted, err := utils.DecryptAES(ossConfig.QCloudSecretID); err == nil {
accessKey = decrypted
}
}
if ossConfig.QCloudSecretKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.QCloudSecretKey); err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.QCloudBucket
region = ossConfig.QCloudRegion
domain = ossConfig.QCloudDomain
// 向后兼容
if accessKey == "" && ossConfig.AccessKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.AccessKey); err == nil {
accessKey = decrypted
}
}
if secretKey == "" && ossConfig.SecretKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.SecretKey); err == nil {
secretKey = decrypted
}
}
if bucket == "" {
bucket = ossConfig.Bucket
}
if region == "" {
region = ossConfig.Region
}
if domain == "" {
domain = ossConfig.Domain
}
case "qiniu":
if ossConfig.QiniuAccessKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.QiniuAccessKey); err == nil {
accessKey = decrypted
}
}
if ossConfig.QiniuSecretKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.QiniuSecretKey); err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.QiniuBucket
region = ossConfig.QiniuRegion
domain = ossConfig.QiniuDomain
// 向后兼容
if accessKey == "" && ossConfig.AccessKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.AccessKey); err == nil {
accessKey = decrypted
}
}
if secretKey == "" && ossConfig.SecretKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.SecretKey); err == nil {
secretKey = decrypted
}
}
if bucket == "" {
bucket = ossConfig.Bucket
}
if region == "" {
region = ossConfig.Region
}
if domain == "" {
domain = ossConfig.Domain
}
default:
if ossConfig.AccessKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.AccessKey); err == nil {
accessKey = decrypted
}
}
if ossConfig.SecretKey != "" {
if decrypted, err := utils.DecryptAES(ossConfig.SecretKey); err == nil {
secretKey = decrypted
}
}
bucket = ossConfig.Bucket
region = ossConfig.Region
domain = ossConfig.Domain
}
config.AccessKey = accessKey
config.SecretKey = secretKey
config.Bucket = bucket
config.Region = region
config.Domain = domain
uploader, err := utils.GetOSSUploader(config)
if err == nil {
uploader.Delete(attachment.FilePath)
}
}
}
// 删除数据库记录
if err := repositories.DeleteAttachment(id); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Attachment deleted successfully", nil)
}
// AdminUpdateAttachment 更新附件
func AdminUpdateAttachment(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid attachment ID")
return
}
// 获取现有附件
attachment, err := repositories.GetAttachmentByID(id)
if err != nil || attachment == nil {
utils.Error(c, 404, "Attachment not found")
return
}
// 解析请求体
var req struct {
CategoryID *uint `json:"categoryId"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
// 更新分类ID
if req.CategoryID != nil {
if *req.CategoryID == 0 {
// 如果categoryId为0设置为nil无分类
attachment.CategoryID = nil
} else {
attachment.CategoryID = req.CategoryID
}
}
// 更新附件
if err := repositories.UpdateAttachment(attachment); err != nil {
utils.ServerError(c, err)
return
}
// 重新获取更新后的附件(包含关联的分类信息)
updatedAttachment, err := repositories.GetAttachmentByID(id)
if err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Attachment updated successfully", updatedAttachment)
}
// AdminGetAttachmentCategories 获取附件分类列表
func AdminGetAttachmentCategories(c *gin.Context) {
categories, err := repositories.GetAttachmentCategories()
if err != nil {
utils.ServerError(c, err)
return
}
utils.Success(c, categories)
}
// AdminCreateAttachmentCategory 创建附件分类
func AdminCreateAttachmentCategory(c *gin.Context) {
var category models.AttachmentCategory
if err := c.ShouldBindJSON(&category); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
if err := repositories.CreateAttachmentCategory(&category); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Category created successfully", category)
}
// AdminUpdateAttachmentCategory 更新附件分类
func AdminUpdateAttachmentCategory(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid category ID")
return
}
var category models.AttachmentCategory
if err := c.ShouldBindJSON(&category); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
category.ID = id
if err := repositories.UpdateAttachmentCategory(&category); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Category updated successfully", nil)
}
// AdminDeleteAttachmentCategory 删除附件分类
func AdminDeleteAttachmentCategory(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid category ID")
return
}
if err := repositories.DeleteAttachmentCategory(id); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "Category deleted successfully", nil)
}
// AdminGetOSSConfigs 获取OSS配置列表
func AdminGetOSSConfigs(c *gin.Context) {
// 检查是否存在默认本地存储配置,如果不存在则创建
defaultConfig, err := repositories.GetDefaultLocalOSSConfig()
if err != nil {
log.Printf("Error checking default local OSS config: %v", err)
} else if defaultConfig == nil {
// 创建默认本地存储配置
// 本地存储不需要AccessKey和SecretKey直接使用空字符串不加密
defaultOSSConfig := &models.OSSConfig{
Name: "本地存储",
StorageType: "local",
AccessKey: "", // 空字符串,不加密
SecretKey: "", // 空字符串,不加密
Bucket: "",
Region: "",
Domain: "",
IsActive: 1,
}
if err := repositories.CreateOSSConfig(defaultOSSConfig); err != nil {
log.Printf("Error creating default local OSS config: %v", err)
}
}
configs, err := repositories.GetOSSConfigs()
if err != nil {
utils.ServerError(c, err)
return
}
// 不返回加密的密钥
for i := range configs {
configs[i].AccessKey = "***"
configs[i].SecretKey = "***"
configs[i].OSSAccessKeyID = "***"
configs[i].OSSAccessKeySecret = "***"
configs[i].QCloudSecretID = "***"
configs[i].QCloudSecretKey = "***"
configs[i].QiniuAccessKey = "***"
configs[i].QiniuSecretKey = "***"
}
utils.Success(c, configs)
}
// AdminCreateOSSConfig 创建OSS配置
func AdminCreateOSSConfig(c *gin.Context) {
var req struct {
Name string `json:"name" binding:"required"`
StorageType string `json:"storageType" binding:"required"`
// 通用字段(向后兼容)
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
Bucket string `json:"bucket"`
Region string `json:"region"`
Domain string `json:"domain"`
// 阿里云OSS专用字段
OSSAccessKeyID string `json:"ossAccessKeyId"`
OSSAccessKeySecret string `json:"ossAccessKeySecret"`
OSSEndpoint string `json:"ossEndpoint"`
OSSBucket string `json:"ossBucket"`
OSSDomain string `json:"ossDomain"`
// 腾讯云COS专用字段
QCloudSecretID string `json:"qcloudSecretId"`
QCloudSecretKey string `json:"qcloudSecretKey"`
QCloudRegion string `json:"qcloudRegion"`
QCloudBucket string `json:"qcloudBucket"`
QCloudDomain string `json:"qcloudDomain"`
// 七牛云专用字段
QiniuAccessKey string `json:"qiniuAccessKey"`
QiniuSecretKey string `json:"qiniuSecretKey"`
QiniuBucket string `json:"qiniuBucket"`
QiniuRegion string `json:"qiniuRegion"`
QiniuDomain string `json:"qiniuDomain"`
IsActive int `json:"isActive"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
// 加密函数
encryptKey := func(key string) (string, error) {
if key == "" {
return "", nil
}
return utils.EncryptAES(key)
}
// 加密通用密钥(向后兼容)
encryptedAccessKey, err := encryptKey(req.AccessKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt access key: "+err.Error())
return
}
encryptedSecretKey, err := encryptKey(req.SecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt secret key: "+err.Error())
return
}
// 加密阿里云密钥
encryptedOSSAccessKeyID, err := encryptKey(req.OSSAccessKeyID)
if err != nil {
utils.Error(c, 500, "Failed to encrypt OSS access key ID: "+err.Error())
return
}
encryptedOSSAccessKeySecret, err := encryptKey(req.OSSAccessKeySecret)
if err != nil {
utils.Error(c, 500, "Failed to encrypt OSS access key secret: "+err.Error())
return
}
// 加密腾讯云密钥
encryptedQCloudSecretID, err := encryptKey(req.QCloudSecretID)
if err != nil {
utils.Error(c, 500, "Failed to encrypt QCloud secret ID: "+err.Error())
return
}
encryptedQCloudSecretKey, err := encryptKey(req.QCloudSecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt QCloud secret key: "+err.Error())
return
}
// 加密七牛云密钥
encryptedQiniuAccessKey, err := encryptKey(req.QiniuAccessKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt Qiniu access key: "+err.Error())
return
}
encryptedQiniuSecretKey, err := encryptKey(req.QiniuSecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt Qiniu secret key: "+err.Error())
return
}
ossConfig := &models.OSSConfig{
Name: req.Name,
StorageType: req.StorageType,
// 通用字段(向后兼容)
AccessKey: encryptedAccessKey,
SecretKey: encryptedSecretKey,
Bucket: req.Bucket,
Region: req.Region,
Domain: req.Domain,
// 阿里云OSS专用字段
OSSAccessKeyID: encryptedOSSAccessKeyID,
OSSAccessKeySecret: encryptedOSSAccessKeySecret,
OSSEndpoint: req.OSSEndpoint,
OSSBucket: req.OSSBucket,
OSSDomain: req.OSSDomain,
// 腾讯云COS专用字段
QCloudSecretID: encryptedQCloudSecretID,
QCloudSecretKey: encryptedQCloudSecretKey,
QCloudRegion: req.QCloudRegion,
QCloudBucket: req.QCloudBucket,
QCloudDomain: req.QCloudDomain,
// 七牛云专用字段
QiniuAccessKey: encryptedQiniuAccessKey,
QiniuSecretKey: encryptedQiniuSecretKey,
QiniuBucket: req.QiniuBucket,
QiniuRegion: req.QiniuRegion,
QiniuDomain: req.QiniuDomain,
IsActive: req.IsActive,
}
if err := repositories.CreateOSSConfig(ossConfig); err != nil {
utils.ServerError(c, err)
return
}
// 不返回加密的密钥
ossConfig.AccessKey = "***"
ossConfig.SecretKey = "***"
ossConfig.OSSAccessKeyID = "***"
ossConfig.OSSAccessKeySecret = "***"
ossConfig.QCloudSecretID = "***"
ossConfig.QCloudSecretKey = "***"
ossConfig.QiniuAccessKey = "***"
ossConfig.QiniuSecretKey = "***"
utils.SuccessWithMsg(c, "OSS config created successfully", ossConfig)
}
// AdminUpdateOSSConfig 更新OSS配置
func AdminUpdateOSSConfig(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid OSS config ID")
return
}
var req struct {
Name string `json:"name"`
StorageType string `json:"storageType"`
// 通用字段(向后兼容)
AccessKey string `json:"accessKey"`
SecretKey string `json:"secretKey"`
Bucket string `json:"bucket"`
Region string `json:"region"`
Domain string `json:"domain"`
// 阿里云OSS专用字段
OSSAccessKeyID string `json:"ossAccessKeyId"`
OSSAccessKeySecret string `json:"ossAccessKeySecret"`
OSSEndpoint string `json:"ossEndpoint"`
OSSBucket string `json:"ossBucket"`
OSSDomain string `json:"ossDomain"`
// 腾讯云COS专用字段
QCloudSecretID string `json:"qcloudSecretId"`
QCloudSecretKey string `json:"qcloudSecretKey"`
QCloudRegion string `json:"qcloudRegion"`
QCloudBucket string `json:"qcloudBucket"`
QCloudDomain string `json:"qcloudDomain"`
// 七牛云专用字段
QiniuAccessKey string `json:"qiniuAccessKey"`
QiniuSecretKey string `json:"qiniuSecretKey"`
QiniuBucket string `json:"qiniuBucket"`
QiniuRegion string `json:"qiniuRegion"`
QiniuDomain string `json:"qiniuDomain"`
IsActive int `json:"isActive"`
}
if err := c.ShouldBindJSON(&req); err != nil {
utils.Error(c, 400, "Invalid request")
return
}
// 获取现有配置
existingConfig, err := repositories.GetOSSConfigByID(id)
if err != nil || existingConfig == nil {
utils.Error(c, 404, "OSS config not found")
return
}
// 检查是否要启用配置如果是非local类型需要验证AccessKey和SecretKey
if req.IsActive == 1 && existingConfig.IsActive == 0 {
// 检查当前配置的AccessKey和SecretKey需要解密
var accessKey, secretKey string
if existingConfig.AccessKey != "" {
decrypted, err := utils.DecryptAES(existingConfig.AccessKey)
if err == nil {
accessKey = decrypted
}
}
if existingConfig.SecretKey != "" {
decrypted, err := utils.DecryptAES(existingConfig.SecretKey)
if err == nil {
secretKey = decrypted
}
}
// 如果提供了新的AccessKey或SecretKey使用新的
if req.AccessKey != "" && req.AccessKey != "***" {
accessKey = req.AccessKey
}
if req.SecretKey != "" && req.SecretKey != "***" {
secretKey = req.SecretKey
}
// 对于非local类型必须填写AccessKey和SecretKey
if existingConfig.StorageType != "local" && (accessKey == "" || secretKey == "") {
utils.Error(c, 400, "启用非本地存储配置前必须填写AccessKey和SecretKey")
return
}
}
// 加密函数
encryptKey := func(key string) (string, error) {
if key == "" {
return "", nil
}
return utils.EncryptAES(key)
}
// 更新字段
if req.Name != "" {
existingConfig.Name = req.Name
}
if req.StorageType != "" {
existingConfig.StorageType = req.StorageType
}
// 处理通用字段(向后兼容)
if req.AccessKey != "***" {
encrypted, err := encryptKey(req.AccessKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt access key: "+err.Error())
return
}
existingConfig.AccessKey = encrypted
}
if req.SecretKey != "***" {
encrypted, err := encryptKey(req.SecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt secret key: "+err.Error())
return
}
existingConfig.SecretKey = encrypted
}
// 更新通用字段(允许空字符串)
existingConfig.Bucket = req.Bucket
existingConfig.Region = req.Region
existingConfig.Domain = req.Domain
// 处理阿里云OSS专用字段
if req.OSSAccessKeyID != "***" {
encrypted, err := encryptKey(req.OSSAccessKeyID)
if err != nil {
utils.Error(c, 500, "Failed to encrypt OSS access key ID: "+err.Error())
return
}
existingConfig.OSSAccessKeyID = encrypted
}
if req.OSSAccessKeySecret != "***" {
encrypted, err := encryptKey(req.OSSAccessKeySecret)
if err != nil {
utils.Error(c, 500, "Failed to encrypt OSS access key secret: "+err.Error())
return
}
existingConfig.OSSAccessKeySecret = encrypted
}
existingConfig.OSSEndpoint = req.OSSEndpoint
existingConfig.OSSBucket = req.OSSBucket
existingConfig.OSSDomain = req.OSSDomain
// 处理腾讯云COS专用字段
if req.QCloudSecretID != "***" {
encrypted, err := encryptKey(req.QCloudSecretID)
if err != nil {
utils.Error(c, 500, "Failed to encrypt QCloud secret ID: "+err.Error())
return
}
existingConfig.QCloudSecretID = encrypted
}
if req.QCloudSecretKey != "***" {
encrypted, err := encryptKey(req.QCloudSecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt QCloud secret key: "+err.Error())
return
}
existingConfig.QCloudSecretKey = encrypted
}
existingConfig.QCloudRegion = req.QCloudRegion
existingConfig.QCloudBucket = req.QCloudBucket
existingConfig.QCloudDomain = req.QCloudDomain
// 处理七牛云专用字段
if req.QiniuAccessKey != "***" {
encrypted, err := encryptKey(req.QiniuAccessKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt Qiniu access key: "+err.Error())
return
}
existingConfig.QiniuAccessKey = encrypted
}
if req.QiniuSecretKey != "***" {
encrypted, err := encryptKey(req.QiniuSecretKey)
if err != nil {
utils.Error(c, 500, "Failed to encrypt Qiniu secret key: "+err.Error())
return
}
existingConfig.QiniuSecretKey = encrypted
}
existingConfig.QiniuBucket = req.QiniuBucket
existingConfig.QiniuRegion = req.QiniuRegion
existingConfig.QiniuDomain = req.QiniuDomain
existingConfig.IsActive = req.IsActive
if err := repositories.UpdateOSSConfig(existingConfig); err != nil {
utils.ServerError(c, err)
return
}
// 不返回加密的密钥
existingConfig.AccessKey = "***"
existingConfig.SecretKey = "***"
existingConfig.OSSAccessKeyID = "***"
existingConfig.OSSAccessKeySecret = "***"
existingConfig.QCloudSecretID = "***"
existingConfig.QCloudSecretKey = "***"
existingConfig.QiniuAccessKey = "***"
existingConfig.QiniuSecretKey = "***"
utils.SuccessWithMsg(c, "OSS config updated successfully", existingConfig)
}
// AdminDeleteOSSConfig 删除OSS配置
func AdminDeleteOSSConfig(c *gin.Context) {
idStr := c.Param("id")
var id uint
if _, err := strconv.ParseUint(idStr, 10, 32); err != nil {
utils.Error(c, 400, "Invalid OSS config ID")
return
}
// 获取配置信息,检查是否为默认本地存储配置
ossConfig, err := repositories.GetOSSConfigByID(id)
if err != nil {
utils.ServerError(c, err)
return
}
if ossConfig == nil {
utils.Error(c, 404, "OSS config not found")
return
}
// 检查是否为默认本地存储配置,不允许删除
if ossConfig.Name == "本地存储" && ossConfig.StorageType == "local" {
utils.Error(c, 400, "默认本地存储配置不能删除")
return
}
if err := repositories.DeleteOSSConfig(id); err != nil {
utils.ServerError(c, err)
return
}
utils.SuccessWithMsg(c, "OSS config deleted successfully", nil)
}