feat: add file safety config integration
This commit is contained in:
@@ -38,11 +38,13 @@ type ossConfig struct {
|
||||
AccessKeySecret string `json:"access_key_secret"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
BucketName string `json:"bucket"`
|
||||
RegionID string `json:"region_id"`
|
||||
CorsOrigins []string `json:"cors_origins"`
|
||||
ServeURL string `json:"serve_url"`
|
||||
PresignTTL int `json:"presign_ttl"`
|
||||
CacheControl string `json:"cache_control"`
|
||||
VerifyBucket bool `json:"verify_bucket"`
|
||||
UseSysConfig bool `json:"use_sys_config"`
|
||||
}
|
||||
|
||||
type ossHandler struct {
|
||||
@@ -69,6 +71,9 @@ func (oh *ossHandler) Init(jsconf string) error {
|
||||
if err = json.Unmarshal([]byte(jsconf), &oh.conf); err != nil {
|
||||
return errors.New("failed to parse config: " + err.Error())
|
||||
}
|
||||
if err = oh.loadSysConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if oh.conf.AccessKeyID == "" {
|
||||
return errors.New("missing Access Key ID")
|
||||
@@ -114,6 +119,59 @@ func (oh *ossHandler) Init(jsconf string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (oh *ossHandler) loadSysConfig() error {
|
||||
if !oh.conf.UseSysConfig {
|
||||
return nil
|
||||
}
|
||||
values, err := store.ThirdPartyConfig.Get("im_third_party",
|
||||
"oss_enabled",
|
||||
"oss_provider",
|
||||
"oss_endpoint",
|
||||
"oss_bucket",
|
||||
"oss_region_id",
|
||||
"oss_access_key_id",
|
||||
"oss_access_key_secret",
|
||||
"oss_presign_ttl",
|
||||
)
|
||||
if err != nil {
|
||||
return errors.New("failed to load OSS config from sys config: " + err.Error())
|
||||
}
|
||||
if !truthy(values["oss_enabled"]) {
|
||||
return errors.New("OSS is disabled in sys config")
|
||||
}
|
||||
if provider := strings.TrimSpace(values["oss_provider"]); provider != "" && provider != handlerName {
|
||||
return errors.New("unsupported storage provider in sys config: " + provider)
|
||||
}
|
||||
applyString(&oh.conf.Endpoint, values["oss_endpoint"])
|
||||
applyString(&oh.conf.BucketName, values["oss_bucket"])
|
||||
applyString(&oh.conf.RegionID, values["oss_region_id"])
|
||||
applyString(&oh.conf.AccessKeyID, values["oss_access_key_id"])
|
||||
applyString(&oh.conf.AccessKeySecret, values["oss_access_key_secret"])
|
||||
if ttl := strings.TrimSpace(values["oss_presign_ttl"]); ttl != "" {
|
||||
parsed, err := strconv.Atoi(ttl)
|
||||
if err != nil {
|
||||
return errors.New("invalid OSS presign TTL in sys config: " + err.Error())
|
||||
}
|
||||
oh.conf.PresignTTL = parsed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyString(target *string, value string) {
|
||||
if value = strings.TrimSpace(value); value != "" {
|
||||
*target = value
|
||||
}
|
||||
}
|
||||
|
||||
func truthy(value string) bool {
|
||||
switch strings.ToLower(strings.TrimSpace(value)) {
|
||||
case "1", "true", "yes", "on":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Headers adds CORS headers and redirects GET and HEAD requests to OSS.
|
||||
func (oh *ossHandler) Headers(tenantID types.TenantID, method string, url *url.URL, headers http.Header, serve bool) (http.Header, int, error) {
|
||||
headers, status := media.CORSHandler(method, headers, oh.corsOrigins, serve)
|
||||
|
||||
@@ -4,9 +4,22 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tinode/chat/server/store"
|
||||
"github.com/tinode/chat/server/store/types"
|
||||
)
|
||||
|
||||
type fakeThirdPartyConfig map[string]string
|
||||
|
||||
func (f fakeThirdPartyConfig) Get(group string, keys ...string) (map[string]string, error) {
|
||||
result := map[string]string{}
|
||||
for _, key := range keys {
|
||||
if value, ok := f[key]; ok {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func TestTenantObjectKey(t *testing.T) {
|
||||
got, err := tenantObjectKey(types.TenantID(42), "abc123", time.Date(2026, 8, 11, 9, 0, 0, 0, time.UTC))
|
||||
if err != nil {
|
||||
@@ -32,3 +45,29 @@ func TestGetIdFromUrl(t *testing.T) {
|
||||
t.Fatalf("GetIdFromUrl = %v, want %v", got, fid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadSysConfig(t *testing.T) {
|
||||
original := store.ThirdPartyConfig
|
||||
store.ThirdPartyConfig = fakeThirdPartyConfig{
|
||||
"oss_enabled": "1",
|
||||
"oss_provider": "oss",
|
||||
"oss_endpoint": "oss-cn-shenzhen.aliyuncs.com",
|
||||
"oss_bucket": "im-files",
|
||||
"oss_region_id": "cn-shenzhen",
|
||||
"oss_access_key_id": "ak",
|
||||
"oss_access_key_secret": "sk",
|
||||
"oss_presign_ttl": "300",
|
||||
}
|
||||
defer func() { store.ThirdPartyConfig = original }()
|
||||
|
||||
handler := ossHandler{conf: ossConfig{UseSysConfig: true}}
|
||||
if err := handler.loadSysConfig(); err != nil {
|
||||
t.Fatalf("loadSysConfig failed: %v", err)
|
||||
}
|
||||
if handler.conf.Endpoint != "oss-cn-shenzhen.aliyuncs.com" || handler.conf.BucketName != "im-files" {
|
||||
t.Fatalf("unexpected OSS config: %+v", handler.conf)
|
||||
}
|
||||
if handler.conf.RegionID != "cn-shenzhen" || handler.conf.PresignTTL != 300 {
|
||||
t.Fatalf("unexpected OSS region or ttl: %+v", handler.conf)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user