refactor(media): 资源分发 - 统一资源访问策略与云存储重定向

This commit is contained in:
ddCat committed 2026-09-22 21:41:00 +08:00
1 parent af6633047c
commit 487c34bfeb
50 files changed
+2112 -1266

No files matched your search

+31 -82
View File
@@ -18,6 +18,7 @@ import (
"time"
"infinite-canvas/backend/internal/model"
"infinite-canvas/backend/internal/storage"
"gorm.io/gorm"
)
@@ -34,20 +35,23 @@ const (
)
type OSSSettingRequest struct {
Enabled bool `json:"enabled"`
Provider string `json:"provider"`
Region string `json:"region"`
Endpoint string `json:"endpoint"`
CDNBaseURL string `json:"cdnBaseUrl"`
Bucket string `json:"bucket"`
AccessKeyID string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
PublicBaseURL string `json:"publicBaseUrl"`
PathPrefix string `json:"pathPrefix"`
S3Preset string `json:"s3Preset"`
PathStyle bool `json:"pathStyle"`
SessionToken string `json:"sessionToken"`
AllowUserS3 bool `json:"allowUserS3"`
Enabled bool `json:"enabled"`
Provider string `json:"provider"`
Region string `json:"region"`
Endpoint string `json:"endpoint"`
CDNBaseURL string `json:"cdnBaseUrl"`
Bucket string `json:"bucket"`
AccessKeyID string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
PublicBaseURL string `json:"publicBaseUrl"`
PathPrefix string `json:"pathPrefix"`
S3Preset string `json:"s3Preset"`
PathStyle bool `json:"pathStyle"`
SessionToken string `json:"sessionToken"`
AllowUserS3 bool `json:"allowUserS3"`
CDNAuthMode string `json:"cdnAuthMode"`
RequireCDN bool `json:"requireCDN"`
AllowPrivateProxy bool `json:"allowPrivateProxy"`
}
type PublicOSSSetting struct {
@@ -70,36 +74,14 @@ type PublicOSSSetting struct {
HistoryCount int64 `json:"historyCount"`
ReferencedResourceCount int64 `json:"referencedResourceCount"`
AllowUserS3 bool `json:"allowUserS3"`
CDNAuthMode string `json:"cdnAuthMode"`
RequireCDN bool `json:"requireCDN"`
AllowPrivateProxy bool `json:"allowPrivateProxy"`
UpdatedBy string `json:"updatedBy"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
type ossSettingValue struct {
Enabled bool `json:"enabled"`
Provider string `json:"provider"`
Region string `json:"region"`
Endpoint string `json:"endpoint"`
CDNBaseURL string `json:"cdnBaseUrl"`
Bucket string `json:"bucket"`
AccessKeyID string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
PublicBaseURL string `json:"publicBaseUrl"`
PathPrefix string `json:"pathPrefix"`
S3Preset string `json:"s3Preset"`
PathStyle bool `json:"pathStyle"`
SessionToken string `json:"sessionToken"`
StorageLocationID string `json:"storageLocationId"`
AllowUserS3 bool `json:"allowUserS3"`
// 平台切换云厂商后仍需读取历史资源,因此仅归档非当前厂商的访问密钥。
ArchivedCredentials map[string]ossProviderCredentials `json:"archivedCredentials,omitempty"`
}
type ossProviderCredentials struct {
AccessKeyID string `json:"accessKeyId"`
AccessKeySecret string `json:"accessKeySecret"`
}
func (s *Service) AdminOSSSetting(actor *model.User) (*PublicOSSSetting, error) {
if err := s.RequireAdmin(actor); err != nil {
return nil, err
@@ -563,7 +545,11 @@ func ossSettingFromRequest(req OSSSettingRequest, current ossSettingValue) (ossS
PathStyle: req.PathStyle,
SessionToken: strings.TrimSpace(req.SessionToken),
AllowUserS3: req.AllowUserS3,
Delivery: storage.DeliverySettings{CDNAuthMode: strings.ToLower(strings.TrimSpace(req.CDNAuthMode)), RequireCDN: req.RequireCDN, AllowPrivateProxy: req.AllowPrivateProxy},
})
if next.Delivery.CDNAuthMode != "" && next.Delivery.CDNAuthMode != "public" && next.Delivery.CDNAuthMode != "qiniu" {
return next, BadAuthRequest("CDN 鉴权方式无效,仅支持 public 或 qiniu")
}
if next.Provider != aliyunOSSProvider && next.Provider != tencentCOSProvider && next.Provider != qiniuKodoProvider && next.Provider != s3Provider {
return next, BadAuthRequest("仅支持阿里云 OSS、腾讯云 COS、七牛云 Kodo 和通用 S3")
}
@@ -640,49 +626,6 @@ func archiveOSSProviderCredentials(next ossSettingValue, current ossSettingValue
return next
}
func cloneOSSProviderCredentials(source map[string]ossProviderCredentials) map[string]ossProviderCredentials {
if len(source) == 0 {
return nil
}
cloned := make(map[string]ossProviderCredentials, len(source))
for provider, credentials := range source {
cloned[strings.ToLower(strings.TrimSpace(provider))] = ossProviderCredentials{
AccessKeyID: strings.TrimSpace(credentials.AccessKeyID),
AccessKeySecret: strings.TrimSpace(credentials.AccessKeySecret),
}
}
return cloned
}
func normalizeOSSSetting(value ossSettingValue) ossSettingValue {
value.Provider = strings.ToLower(strings.TrimSpace(value.Provider))
if value.Provider == "" {
value.Provider = aliyunOSSProvider
}
value.Region = strings.TrimSpace(value.Region)
value.Endpoint = strings.TrimRight(strings.TrimSpace(value.Endpoint), "/")
if value.Provider == tencentCOSProvider && value.Endpoint == "" && value.Region != "" {
value.Endpoint = "https://cos." + value.Region + ".myqcloud.com"
}
value.CDNBaseURL = strings.TrimRight(strings.TrimSpace(value.CDNBaseURL), "/")
value.Bucket = strings.TrimSpace(value.Bucket)
value.AccessKeyID = strings.TrimSpace(value.AccessKeyID)
value.AccessKeySecret = strings.TrimSpace(value.AccessKeySecret)
value.PublicBaseURL = strings.TrimRight(strings.TrimSpace(value.PublicBaseURL), "/")
value.PathPrefix = strings.Trim(strings.TrimSpace(value.PathPrefix), "/")
if value.PathPrefix == "" {
value.PathPrefix = defaultOSSPathPrefix
}
value.S3Preset = strings.ToLower(strings.TrimSpace(value.S3Preset))
if value.S3Preset == "" {
value.S3Preset = "custom"
}
value.SessionToken = strings.TrimSpace(value.SessionToken)
value.StorageLocationID = strings.TrimSpace(value.StorageLocationID)
value.ArchivedCredentials = cloneOSSProviderCredentials(value.ArchivedCredentials)
return value
}
func defaultOSSSetting() ossSettingValue {
return ossSettingValue{Provider: aliyunOSSProvider, PathPrefix: defaultOSSPathPrefix}
}
@@ -704,6 +647,9 @@ func (s *Service) publicOSSSetting(setting *model.SystemSetting, value ossSettin
HasSessionToken: value.SessionToken != "",
StorageLocationID: value.StorageLocationID,
AllowUserS3: value.AllowUserS3,
CDNAuthMode: value.Delivery.CDNAuthMode,
RequireCDN: value.Delivery.RequireCDN,
AllowPrivateProxy: value.Delivery.AllowPrivateProxy,
}
if setting != nil {
result.UpdatedBy = setting.UpdatedBy
@@ -733,6 +679,9 @@ func (s *Service) publicUserOSSSetting(setting *model.UserOSSSetting, value ossS
HasSessionToken: value.SessionToken != "",
StorageLocationID: value.StorageLocationID,
AllowUserS3: allowUserS3,
CDNAuthMode: value.Delivery.CDNAuthMode,
RequireCDN: value.Delivery.RequireCDN,
AllowPrivateProxy: value.Delivery.AllowPrivateProxy,
}
if value.Provider == s3Provider && !allowUserS3 {
result.Enabled = false