Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions storage-tencentyuncos/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Tencent COS Storage (preview)
# Tencent COS Storage

> This plugin can be used to store attachments and avatars to Tencent COS.

Expand All @@ -18,4 +18,3 @@
- `Secret ID` - Secret ID of the Tencent COS storage
- `Secret Key` - Secret Key of the Tencent COS storage
- `Visit Url Prefix` - Prefix of access address for the uploaded file, ending with '/' such as https://example.com/xxx/
- `Max File Size` - Max file size in MB, default is 10MB
5 changes: 0 additions & 5 deletions storage-tencentyuncos/i18n/en_US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ plugin:
other: Access URL prefix
description:
other: prefix of the final access address of the uploaded file, ending with '/' https://example.com/xxx/
max_file_size:
title:
other: Maximum file size(MB)
description:
other: Limit the maximum size of uploaded files, in MB, default is 10MB
err:
mis_storage_config:
other: Wrong storage configuration causes upload failure.
Expand Down
2 changes: 0 additions & 2 deletions storage-tencentyuncos/i18n/translation.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ const (
ConfigSecretKeyDescription = "plugin.tencentyuncos_storage.backend.config.secret_key.description"
ConfigVisitUrlPrefixTitle = "plugin.tencentyuncos_storage.backend.config.visit_url_prefix.title"
ConfigVisitUrlPrefixDescription = "plugin.tencentyuncos_storage.backend.config.visit_url_prefix.description"
ConfigMaxFileSizeTitle = "plugin.tencentyuncos_storage.backend.config.max_file_size.title"
ConfigMaxFileSizeDescription = "plugin.tencentyuncos_storage.backend.config.max_file_size.description"

ErrMisStorageConfig = "plugin.tencentyuncos_storage.backend.err.mis_storage_config"
ErrFileNotFound = "plugin.tencentyuncos_storage.backend.err.file_not_found"
Expand Down
5 changes: 0 additions & 5 deletions storage-tencentyuncos/i18n/zh_CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ plugin:
other: 访问URL前缀
description:
other: 上传文件最终访问地址的前缀,以 '/' 结尾 https://example.com/xxx/
max_file_size:
title:
other: 最大文件大小(MB)
description:
other: 限制上传文件的最大大小,单位为MB,默认为 10MB
err:
mis_storage_config:
other: 错误的存储配置导致上传失败
Expand Down
2 changes: 1 addition & 1 deletion storage-tencentyuncos/info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@

slug_name: tencentyuncos_storage
type: storage
version: 1.0.2
version: 1.0.3
author: Luffy
link: https://github.com/apache/answer-plugins/tree/main/storage-tencentyuncos
64 changes: 31 additions & 33 deletions storage-tencentyuncos/tencentyuncos.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ import (
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/apache/answer/pkg/checker"

"github.com/apache/answer-plugins/storage-tencentyuncos/i18n"
"github.com/apache/answer-plugins/util"
"github.com/apache/answer/plugin"
Expand All @@ -41,11 +42,6 @@ import (
//go:embed info.yaml
var Info embed.FS

const (
// 10MB
defaultMaxFileSize int64 = 10 * 1024 * 1024
)

type Storage struct {
Config *StorageConfig
}
Expand All @@ -57,7 +53,6 @@ type StorageConfig struct {
SecretID string `json:"secret_id"`
SecretKey string `json:"secret_key"`
VisitUrlPrefix string `json:"visit_url_prefix"`
MaxFileSize string `json:"max_file_size"`
}

func init() {
Expand All @@ -80,7 +75,7 @@ func (s *Storage) Info() plugin.Info {
}
}

func (s *Storage) UploadFile(ctx *plugin.GinContext, source plugin.UploadSource) (resp plugin.UploadFileResponse) {
func (s *Storage) UploadFile(ctx *plugin.GinContext, condition plugin.UploadFileCondition) (resp plugin.UploadFileResponse) {
resp = plugin.UploadFileResponse{}

BucketURL, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", s.Config.BucketName, s.Config.Region))
Expand All @@ -106,13 +101,13 @@ func (s *Storage) UploadFile(ctx *plugin.GinContext, source plugin.UploadSource)
return resp
}

if !s.CheckFileType(file.Filename, source) {
if s.IsUnsupportedFileType(file.Filename, condition) {
resp.OriginalError = fmt.Errorf("file type not allowed")
resp.DisplayErrorMsg = plugin.MakeTranslator(i18n.ErrUnsupportedFileType)
return resp
}

if file.Size > s.maxFileSizeLimit() {
if s.ExceedFileSizeLimit(file.Size, condition) {
resp.OriginalError = fmt.Errorf("file size too large")
resp.DisplayErrorMsg = plugin.MakeTranslator(i18n.ErrOverFileSizeLimit)
return resp
Expand All @@ -126,7 +121,7 @@ func (s *Storage) UploadFile(ctx *plugin.GinContext, source plugin.UploadSource)
}
defer openFile.Close()

objectKey := s.createObjectKey(file.Filename, source)
objectKey := s.createObjectKey(file.Filename, condition.Source)
_, err = client.Object.Put(ctx, objectKey, openFile, nil)
if err != nil {
resp.OriginalError = fmt.Errorf("upload file failed: %v", err)
Expand All @@ -137,6 +132,29 @@ func (s *Storage) UploadFile(ctx *plugin.GinContext, source plugin.UploadSource)
return resp
}

func (s *Storage) IsUnsupportedFileType(originalFilename string, condition plugin.UploadFileCondition) bool {
if condition.Source == plugin.AdminBranding || condition.Source == plugin.UserAvatar {
ext := strings.ToLower(filepath.Ext(originalFilename))
if _, ok := plugin.DefaultFileTypeCheckMapping[condition.Source][ext]; ok {
return false
}
return true
}

// check the post image and attachment file type check
if condition.Source == plugin.UserPost {
return checker.IsUnAuthorizedExtension(originalFilename, condition.AuthorizedImageExtensions)
}
return checker.IsUnAuthorizedExtension(originalFilename, condition.AuthorizedAttachmentExtensions)
}

func (s *Storage) ExceedFileSizeLimit(fileSize int64, condition plugin.UploadFileCondition) bool {
if condition.Source == plugin.UserPostAttachment {
return fileSize > int64(condition.MaxAttachmentSize)*1024*1024
}
return fileSize > int64(condition.MaxImageSize)*1024*1024
}

func (s *Storage) createObjectKey(originalFilename string, source plugin.UploadSource) string {
ext := strings.ToLower(filepath.Ext(originalFilename))
randomString := s.randomObjectKey()
Expand All @@ -145,6 +163,8 @@ func (s *Storage) createObjectKey(originalFilename string, source plugin.UploadS
return s.Config.ObjectKeyPrefix + "avatar/" + randomString + ext
case plugin.UserPost:
return s.Config.ObjectKeyPrefix + "post/" + randomString + ext
case plugin.UserPostAttachment:
return s.Config.ObjectKeyPrefix + "attachment/" + randomString + ext
case plugin.AdminBranding:
return s.Config.ObjectKeyPrefix + "branding/" + randomString + ext
default:
Expand All @@ -166,17 +186,6 @@ func (s *Storage) CheckFileType(originalFilename string, source plugin.UploadSou
return false
}

func (s *Storage) maxFileSizeLimit() int64 {
if len(s.Config.MaxFileSize) == 0 {
return defaultMaxFileSize
}
limit, _ := strconv.Atoi(s.Config.MaxFileSize)
if limit <= 0 {
return defaultMaxFileSize
}
return int64(limit) * 1024 * 1024
}

func (s *Storage) ConfigFields() []plugin.ConfigField {
return []plugin.ConfigField{
{
Expand Down Expand Up @@ -245,17 +254,6 @@ func (s *Storage) ConfigFields() []plugin.ConfigField {
},
Value: s.Config.VisitUrlPrefix,
},
{
Name: "max_file_size",
Type: plugin.ConfigTypeInput,
Title: plugin.MakeTranslator(i18n.ConfigMaxFileSizeTitle),
Description: plugin.MakeTranslator(i18n.ConfigMaxFileSizeDescription),
Required: false,
UIOptions: plugin.ConfigFieldUIOptions{
InputType: plugin.InputTypeNumber,
},
Value: s.Config.MaxFileSize,
},
}
}

Expand Down