优化结构

This commit is contained in:
Yvan
2026-08-24 13:25:16 +08:00
parent 7a9a738c6a
commit 0b6b8ddf1a
72 changed files with 2475 additions and 1443 deletions
+6 -8
View File
@@ -13,18 +13,16 @@ import (
"strings"
"time"
"kra/internal/conf"
"kra/internal/config"
)
type emailRepo struct {
runtime *conf.Runtime
}
type emailRepo struct{ runtime *config.Store }
func NewEmailRepo(runtime *conf.Runtime) system.EmailRepo {
func NewEmailRepo(runtime *config.Store) system.EmailRepo {
return &emailRepo{runtime: runtime}
}
func (r *emailRepo) email() *conf.AdminBackend_Email {
func (r *emailRepo) email() *config.Email {
if r.runtime == nil {
return nil
}
@@ -47,7 +45,7 @@ func (r *emailRepo) DefaultRecipients() []string {
return []string{strings.TrimSpace(config.To)}
}
func emailEnabled(config *conf.AdminBackend_Email) bool {
func emailEnabled(config *config.Email) bool {
return config != nil && strings.TrimSpace(config.Host) != "" &&
strings.TrimSpace(config.From) != "" && strings.TrimSpace(config.Secret) != "" && config.Port > 0
}
@@ -82,7 +80,7 @@ func (r *emailRepo) Send(ctx context.Context, to []string, subject, body string)
dialer := &net.Dialer{Timeout: 10 * time.Second}
var conn net.Conn
var err error
if config.IsSsl {
if config.IsSSL {
conn, err = (&tls.Dialer{NetDialer: dialer, Config: &tls.Config{ServerName: config.Host, MinVersion: tls.VersionTLS12}}).DialContext(ctx, "tcp", address)
} else {
conn, err = dialer.DialContext(ctx, "tcp", address)
+3 -3
View File
@@ -4,11 +4,11 @@ import (
"context"
"testing"
"kra/internal/conf"
"kra/internal/config"
)
func TestDefaultRecipientsIgnoreEmptyConfiguration(t *testing.T) {
runtime := conf.NewRuntime(&conf.Data{}, &conf.AdminBackend{Email: &conf.AdminBackend_Email{To: " "}})
runtime := config.NewStore(&config.Config{Data: &config.Data{}, Admin: &config.Admin{Email: &config.Email{To: " "}}})
repo := &emailRepo{runtime: runtime}
if got := repo.DefaultRecipients(); len(got) != 0 {
t.Fatalf("DefaultRecipients() = %#v, want empty", got)
@@ -16,7 +16,7 @@ func TestDefaultRecipientsIgnoreEmptyConfiguration(t *testing.T) {
}
func TestSendRejectsEmptyRecipientsBeforeNetworkDial(t *testing.T) {
runtime := conf.NewRuntime(&conf.Data{}, &conf.AdminBackend{Email: &conf.AdminBackend_Email{Host: "smtp.example.com", From: "from@example.com", Secret: "secret", Port: 25}})
runtime := config.NewStore(&config.Config{Data: &config.Data{}, Admin: &config.Admin{Email: &config.Email{Host: "smtp.example.com", From: "from@example.com", Secret: "secret", Port: 25}}})
repo := &emailRepo{runtime: runtime}
if err := repo.Send(context.Background(), []string{" ", ""}, "subject", "body"); err == nil {
t.Fatal("Send() accepted empty recipients")
@@ -8,7 +8,7 @@ import (
"path"
"strings"
"kra/internal/conf"
"kra/internal/config"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
@@ -18,7 +18,7 @@ type aliyunStorage struct {
baseURL, prefix string
}
func newAliyunStorage(config *conf.AdminBackend_ObjectStore) (system.FileStorage, error) {
func newAliyunStorage(config *config.ObjectStore) (system.FileStorage, error) {
if config == nil || config.Endpoint == "" || config.Bucket == "" || config.AccessKey == "" || config.SecretKey == "" {
return nil, fmt.Errorf("aliyun-oss storage configuration is incomplete")
}
@@ -30,7 +30,7 @@ func newAliyunStorage(config *conf.AdminBackend_ObjectStore) (system.FileStorage
if err != nil {
return nil, err
}
return &aliyunStorage{bucket: bucket, baseURL: strings.TrimSuffix(config.BaseUrl, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
return &aliyunStorage{bucket: bucket, baseURL: strings.TrimSuffix(config.BaseURL, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
}
func (s *aliyunStorage) key(name string) string {
if s.prefix == "" {
+6 -6
View File
@@ -8,7 +8,7 @@ import (
"path"
"strings"
"kra/internal/conf"
"kra/internal/config"
"github.com/aws/aws-sdk-go-v2/aws"
awsconfig "github.com/aws/aws-sdk-go-v2/config"
@@ -22,7 +22,7 @@ type awsStorage struct {
bucket, baseURL, prefix string
}
func newAWSStorage(provider string, config *conf.AdminBackend_ObjectStore) (system.FileStorage, error) {
func newAWSStorage(provider string, config *config.ObjectStore) (system.FileStorage, error) {
if config == nil || config.Bucket == "" || config.AccessKey == "" || config.SecretKey == "" {
return nil, fmt.Errorf("%s storage configuration is incomplete", provider)
}
@@ -31,10 +31,10 @@ func newAWSStorage(provider string, config *conf.AdminBackend_ObjectStore) (syst
if provider == "cloudflare-r2" {
region = "auto"
if endpoint == "" {
if config.AccountId == "" {
if config.AccountID == "" {
return nil, fmt.Errorf("cloudflare-r2 account id is required")
}
endpoint = fmt.Sprintf("https://%s.r2.cloudflarestorage.com", config.AccountId)
endpoint = fmt.Sprintf("https://%s.r2.cloudflarestorage.com", config.AccountID)
}
}
if region == "" {
@@ -47,7 +47,7 @@ func newAWSStorage(provider string, config *conf.AdminBackend_ObjectStore) (syst
client := s3.NewFromConfig(loaded, func(options *s3.Options) {
if endpoint != "" {
if !strings.HasPrefix(endpoint, "http://") && !strings.HasPrefix(endpoint, "https://") {
if config.UseSsl {
if config.UseSSL {
endpoint = "https://" + endpoint
} else {
endpoint = "http://" + endpoint
@@ -57,7 +57,7 @@ func newAWSStorage(provider string, config *conf.AdminBackend_ObjectStore) (syst
}
options.UsePathStyle = config.ForcePathStyle
})
return &awsStorage{client: client, bucket: config.Bucket, baseURL: strings.TrimSuffix(config.BaseUrl, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
return &awsStorage{client: client, bucket: config.Bucket, baseURL: strings.TrimSuffix(config.BaseURL, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
}
func (s *awsStorage) key(name string) string {
@@ -8,7 +8,7 @@ import (
"path"
"strings"
"kra/internal/conf"
"kra/internal/config"
"github.com/huaweicloud/huaweicloud-sdk-go-obs/obs"
)
@@ -18,7 +18,7 @@ type huaweiStorage struct {
bucket, baseURL, prefix string
}
func newHuaweiStorage(config *conf.AdminBackend_ObjectStore) (system.FileStorage, error) {
func newHuaweiStorage(config *config.ObjectStore) (system.FileStorage, error) {
if config == nil || config.Endpoint == "" || config.Bucket == "" || config.AccessKey == "" || config.SecretKey == "" {
return nil, fmt.Errorf("huawei-obs storage configuration is incomplete")
}
@@ -26,7 +26,7 @@ func newHuaweiStorage(config *conf.AdminBackend_ObjectStore) (system.FileStorage
if err != nil {
return nil, err
}
return &huaweiStorage{client: client, bucket: config.Bucket, baseURL: strings.TrimSuffix(config.BaseUrl, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
return &huaweiStorage{client: client, bucket: config.Bucket, baseURL: strings.TrimSuffix(config.BaseURL, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
}
func (s *huaweiStorage) key(name string) string {
if s.prefix == "" {
+17 -17
View File
@@ -11,7 +11,7 @@ import (
"sort"
"strings"
"kra/internal/conf"
"kra/internal/config"
)
type fileStorage struct {
@@ -19,41 +19,41 @@ type fileStorage struct {
urlPrefix string
}
func New(config *conf.AdminBackend) (system.FileStorage, error) {
func New(admin *config.Admin) (system.FileStorage, error) {
storageType := "local"
if config != nil && config.Storage != nil && config.Storage.Type != "" {
storageType = strings.ToLower(config.Storage.Type)
if admin != nil && admin.Storage != nil && admin.Storage.Type != "" {
storageType = strings.ToLower(admin.Storage.Type)
}
if storageType == "qiniu" {
return newQiniuStorage(config.Storage.Qiniu)
return newQiniuStorage(admin.Storage.Qiniu)
}
if storageType != "local" {
var object *conf.AdminBackend_ObjectStore
var object *config.ObjectStore
switch storageType {
case "aliyun-oss":
return newAliyunStorage(config.Storage.AliyunOss)
return newAliyunStorage(admin.Storage.AliyunOSS)
case "huawei-obs":
return newHuaweiStorage(config.Storage.HuaweiObs)
return newHuaweiStorage(admin.Storage.HuaweiOBS)
case "tencent-cos":
return newTencentStorage(config.Storage.TencentCos)
return newTencentStorage(admin.Storage.TencentCOS)
case "aws-s3":
return newAWSStorage(storageType, config.Storage.AwsS3)
return newAWSStorage(storageType, admin.Storage.AWSS3)
case "cloudflare-r2":
return newAWSStorage(storageType, config.Storage.CloudflareR2)
return newAWSStorage(storageType, admin.Storage.CloudflareR2)
case "minio":
object = config.Storage.Minio
object = admin.Storage.Minio
default:
return nil, fmt.Errorf("unsupported storage type %q", storageType)
}
return newS3Storage(storageType, object)
}
root, prefix := "uploads/file", "uploads/file"
if config != nil && config.Local != nil {
if config.Local.StorePath != "" {
root = config.Local.StorePath
if admin != nil && admin.Local != nil {
if admin.Local.StorePath != "" {
root = admin.Local.StorePath
}
if config.Local.PathPrefix != "" {
prefix = config.Local.PathPrefix
if admin.Local.PathPrefix != "" {
prefix = admin.Local.PathPrefix
}
}
root = filepath.Clean(root)
@@ -11,24 +11,24 @@ import (
"strings"
"time"
"kra/internal/conf"
"kra/internal/config"
"github.com/qiniu/go-sdk/v7/auth/qbox"
qstorage "github.com/qiniu/go-sdk/v7/storage"
)
type qiniuStorage struct {
config *conf.AdminBackend_Qiniu
config *config.Qiniu
upload *qstorage.FormUploader
manager *qstorage.BucketManager
mac *qbox.Mac
}
func newQiniuStorage(config *conf.AdminBackend_Qiniu) (system.FileStorage, error) {
func newQiniuStorage(config *config.Qiniu) (system.FileStorage, error) {
if config == nil || config.Bucket == "" || config.AccessKey == "" || config.SecretKey == "" {
return nil, fmt.Errorf("qiniu storage configuration is incomplete")
}
cfg := qstorage.Config{UseHTTPS: config.UseHttps, UseCdnDomains: config.UseCdnDomains}
cfg := qstorage.Config{UseHTTPS: config.UseHTTPS, UseCdnDomains: config.UseCDNDomains}
switch config.Zone {
case "ZoneHuadong":
cfg.Zone = &qstorage.ZoneHuadong
@@ -51,7 +51,7 @@ func (s *qiniuStorage) uploadToken() string {
}
func (s *qiniuStorage) file(key string, size int64) *system.StoredFile {
return &system.StoredFile{Name: path.Base(key), Path: key, URL: strings.TrimSuffix(s.config.BaseUrl, "/") + "/" + key, Size: size}
return &system.StoredFile{Name: path.Base(key), Path: key, URL: strings.TrimSuffix(s.config.BaseURL, "/") + "/" + key, Size: size}
}
func (s *qiniuStorage) Put(ctx context.Context, name string, reader io.Reader) (*system.StoredFile, error) {
temporary, err := os.CreateTemp("", "kra-qiniu-upload-*")
@@ -77,7 +77,7 @@ func (s *qiniuStorage) Put(ctx context.Context, name string, reader io.Reader) (
return s.file(ret.Key, size), nil
}
func (s *qiniuStorage) Open(ctx context.Context, name string) (io.ReadCloser, error) {
downloadURL := qstorage.MakePrivateURL(s.mac, strings.TrimSuffix(s.config.BaseUrl, "/"), strings.TrimPrefix(name, "/"), time.Now().Add(time.Hour).Unix())
downloadURL := qstorage.MakePrivateURL(s.mac, strings.TrimSuffix(s.config.BaseURL, "/"), strings.TrimPrefix(name, "/"), time.Now().Add(time.Hour).Unix())
req, err := http.NewRequestWithContext(ctx, http.MethodGet, downloadURL, nil)
if err != nil {
return nil, err
+4 -4
View File
@@ -7,7 +7,7 @@ import (
"kra/internal/biz/system"
"sync"
"kra/internal/conf"
"kra/internal/config"
)
type Reloadable struct {
@@ -15,15 +15,15 @@ type Reloadable struct {
current system.FileStorage
}
func NewFileStorage(runtime *conf.Runtime) (*Reloadable, error) {
var config *conf.AdminBackend
func NewFileStorage(runtime *config.Store) (*Reloadable, error) {
var config *config.Admin
if runtime != nil {
config = runtime.Admin()
}
return NewReloadable(config)
}
func NewReloadable(config *conf.AdminBackend) (*Reloadable, error) {
func NewReloadable(config *config.Admin) (*Reloadable, error) {
current, err := New(config)
if err != nil {
return nil, err
+5 -5
View File
@@ -9,7 +9,7 @@ import (
"path"
"strings"
"kra/internal/conf"
"kra/internal/config"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
@@ -20,7 +20,7 @@ type s3Storage struct {
bucket, baseURL, prefix string
}
func newS3Storage(provider string, config *conf.AdminBackend_ObjectStore) (system.FileStorage, error) {
func newS3Storage(provider string, config *config.ObjectStore) (system.FileStorage, error) {
if config == nil || config.Bucket == "" || config.AccessKey == "" || config.SecretKey == "" {
return nil, fmt.Errorf("%s storage configuration is incomplete", provider)
}
@@ -30,7 +30,7 @@ func newS3Storage(provider string, config *conf.AdminBackend_ObjectStore) (syste
case "aws-s3":
endpoint = "s3." + config.Region + ".amazonaws.com"
case "cloudflare-r2":
endpoint = config.AccountId + ".r2.cloudflarestorage.com"
endpoint = config.AccountID + ".r2.cloudflarestorage.com"
case "aliyun-oss":
endpoint = "oss-" + config.Region + ".aliyuncs.com"
case "huawei-obs":
@@ -39,7 +39,7 @@ func newS3Storage(provider string, config *conf.AdminBackend_ObjectStore) (syste
endpoint = "cos." + config.Region + ".myqcloud.com"
}
}
secure := config.UseSsl
secure := config.UseSSL
if parsed, err := url.Parse(endpoint); err == nil && parsed.Host != "" {
secure = parsed.Scheme == "https"
endpoint = parsed.Host
@@ -56,7 +56,7 @@ func newS3Storage(provider string, config *conf.AdminBackend_ObjectStore) (syste
if err != nil {
return nil, err
}
return &s3Storage{client: client, bucket: config.Bucket, baseURL: strings.TrimSuffix(config.BaseUrl, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
return &s3Storage{client: client, bucket: config.Bucket, baseURL: strings.TrimSuffix(config.BaseURL, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
}
func (s *s3Storage) key(name string) string {
if s.prefix == "" {
@@ -11,7 +11,7 @@ import (
"strings"
"time"
"kra/internal/conf"
"kra/internal/config"
cos "github.com/tencentyun/cos-go-sdk-v5"
)
@@ -21,7 +21,7 @@ type tencentStorage struct {
baseURL, prefix string
}
func newTencentStorage(config *conf.AdminBackend_ObjectStore) (system.FileStorage, error) {
func newTencentStorage(config *config.ObjectStore) (system.FileStorage, error) {
if config == nil || config.Bucket == "" || config.Region == "" || config.AccessKey == "" || config.SecretKey == "" {
return nil, fmt.Errorf("tencent-cos storage configuration is incomplete")
}
@@ -29,7 +29,7 @@ func newTencentStorage(config *conf.AdminBackend_ObjectStore) (system.FileStorag
if endpoint == "" {
endpoint = fmt.Sprintf("https://%s.cos.%s.myqcloud.com", config.Bucket, config.Region)
} else if !strings.HasPrefix(endpoint, "http://") && !strings.HasPrefix(endpoint, "https://") {
if config.UseSsl {
if config.UseSSL {
endpoint = "https://" + endpoint
} else {
endpoint = "http://" + endpoint
@@ -40,7 +40,7 @@ func newTencentStorage(config *conf.AdminBackend_ObjectStore) (system.FileStorag
return nil, err
}
client := cos.NewClient(&cos.BaseURL{BucketURL: bucketURL}, &http.Client{Transport: &cos.AuthorizationTransport{SecretID: config.AccessKey, SecretKey: config.SecretKey}})
return &tencentStorage{client: client, baseURL: strings.TrimSuffix(config.BaseUrl, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
return &tencentStorage{client: client, baseURL: strings.TrimSuffix(config.BaseURL, "/"), prefix: strings.Trim(config.PathPrefix, "/")}, nil
}
func (s *tencentStorage) key(name string) string {
if s.prefix == "" {