feat: add object storage and points leaderboard

This commit is contained in:
richjohnrambo
2026-10-18 18:11:34 +08:00
parent bce5edfaf5
commit b79b781f15
24 changed files with 359 additions and 212 deletions
+71 -5
View File
@@ -37,8 +37,17 @@ type IMConfig struct {
}
type UploadConfig struct {
Driver string `json:"driver"`
Dir string `json:"dir"`
PublicPath string `json:"public_path"`
AccessKey string `json:"access_key"`
SecretKey string `json:"secret_key"`
Endpoint string `json:"endpoint"`
Secure bool `json:"secure"`
Path string `json:"path"`
Bucket string `json:"bucket"`
Domain string `json:"domain"`
Region string `json:"region"`
}
type MySQLConfig struct {
@@ -100,7 +109,7 @@ func defaultConfig() *Config {
DefaultTenantID: 0,
RequiredAPIKey: true,
},
Upload: UploadConfig{Dir: "storage/uploads", PublicPath: "/uploads"},
Upload: UploadConfig{Driver: "local", Dir: "storage/uploads", PublicPath: "/uploads", Region: "us-east-1"},
IM: IMConfig{
BaseURL: "https://api.118im.com", HTTPAPIURL: "https://api.118im.com/v1/im",
WebSocketURL: "wss://api.118im.com/v0/channels", FileURL: "https://api.118im.com/v0/file",
@@ -130,8 +139,7 @@ func applyEnv(cfg *Config) {
setString(&cfg.Auth.FinanceMasterKey, "OLONS_SERVER_FINANCE_MASTER_KEY")
setBool(&cfg.Auth.AllowDevHeaderAuth, "OLONS_SERVER_ALLOW_DEV_HEADER_AUTH")
setBool(&cfg.Auth.RequiredAPIKey, "OLONS_SERVER_REQUIRED_API_KEY")
setString(&cfg.Upload.Dir, "OLONS_SERVER_UPLOAD_DIR")
setString(&cfg.Upload.PublicPath, "OLONS_SERVER_UPLOAD_PUBLIC_PATH")
ApplyUploadEnv(&cfg.Upload)
setString(&cfg.IM.BaseURL, "OLONS_IM_BASE_URL")
setString(&cfg.IM.HTTPAPIURL, "OLONS_IM_HTTP_API_URL")
setString(&cfg.IM.WebSocketURL, "OLONS_IM_WS_URL")
@@ -172,8 +180,8 @@ func (c *Config) validate() error {
if c.Auth.DefaultTenantID < 0 {
return errors.New("default tenant id must not be negative")
}
if strings.TrimSpace(c.Upload.Dir) == "" || !strings.HasPrefix(c.Upload.PublicPath, "/") {
return errors.New("upload config is invalid")
if err := ValidateUpload(c.Upload); err != nil {
return err
}
if c.IM.Timeout <= 0 {
c.IM.Timeout = 8 * time.Second
@@ -181,6 +189,64 @@ func (c *Config) validate() error {
return nil
}
func ApplyUploadSystemConfig(cfg *UploadConfig, values map[string]string) {
if cfg == nil {
return
}
setMapString(&cfg.Driver, values, "uploadDrive")
setMapString(&cfg.AccessKey, values, "uploadMinioAccessKey")
setMapString(&cfg.SecretKey, values, "uploadMinioSecretKey")
setMapString(&cfg.Endpoint, values, "uploadMinioEndpoint")
setMapString(&cfg.Path, values, "uploadMinioPath")
setMapString(&cfg.Bucket, values, "uploadMinioBucket")
setMapString(&cfg.Domain, values, "uploadMinioDomain")
if value := strings.TrimSpace(values["uploadMinioUseSSL"]); value != "" {
cfg.Secure = value == "1" || strings.EqualFold(value, "true")
}
}
func ApplyUploadEnv(cfg *UploadConfig) {
if cfg == nil {
return
}
setString(&cfg.Driver, "OLONS_SERVER_UPLOAD_DRIVER")
setString(&cfg.Dir, "OLONS_SERVER_UPLOAD_DIR")
setString(&cfg.PublicPath, "OLONS_SERVER_UPLOAD_PUBLIC_PATH")
setString(&cfg.AccessKey, "OLONS_SERVER_MINIO_ACCESS_KEY")
setString(&cfg.SecretKey, "OLONS_SERVER_MINIO_SECRET_KEY")
setString(&cfg.Endpoint, "OLONS_SERVER_MINIO_ENDPOINT")
setString(&cfg.Path, "OLONS_SERVER_MINIO_PATH")
setString(&cfg.Bucket, "OLONS_SERVER_MINIO_BUCKET")
setString(&cfg.Domain, "OLONS_SERVER_MINIO_DOMAIN")
setString(&cfg.Region, "OLONS_SERVER_MINIO_REGION")
if value := strings.TrimSpace(os.Getenv("OLONS_SERVER_MINIO_SECURE")); value != "" {
cfg.Secure = value == "1" || strings.EqualFold(value, "true")
}
}
func ValidateUpload(cfg UploadConfig) error {
switch strings.ToLower(strings.TrimSpace(cfg.Driver)) {
case "local":
if strings.TrimSpace(cfg.Dir) == "" || !strings.HasPrefix(cfg.PublicPath, "/") {
return errors.New("local upload config is invalid")
}
case "minio":
if strings.TrimSpace(cfg.AccessKey) == "" || strings.TrimSpace(cfg.SecretKey) == "" ||
strings.TrimSpace(cfg.Endpoint) == "" || strings.TrimSpace(cfg.Bucket) == "" || strings.TrimSpace(cfg.Domain) == "" {
return errors.New("minio upload config is incomplete")
}
default:
return errors.New("upload driver is unsupported")
}
return nil
}
func setMapString(target *string, values map[string]string, key string) {
if value := strings.TrimSpace(values[key]); value != "" {
*target = value
}
}
func setString(target *string, key string) {
if value := strings.TrimSpace(os.Getenv(key)); value != "" {
*target = value
+26
View File
@@ -19,3 +19,29 @@ func TestConfigRejectsOtherDatabase(t *testing.T) {
t.Fatal("expected non-olons_admin database to be rejected")
}
}
func TestApplyUploadSystemConfig(t *testing.T) {
cfg := UploadConfig{Driver: "local", Region: "us-east-1"}
ApplyUploadSystemConfig(&cfg, map[string]string{
"uploadDrive": "minio",
"uploadMinioAccessKey": "access",
"uploadMinioSecretKey": "secret",
"uploadMinioEndpoint": "minio.example.com",
"uploadMinioUseSSL": "1",
"uploadMinioPath": "images/",
"uploadMinioBucket": "bucket",
"uploadMinioDomain": "https://cdn.example.com",
})
if err := ValidateUpload(cfg); err != nil {
t.Fatal(err)
}
if cfg.Driver != "minio" || !cfg.Secure || cfg.Bucket != "bucket" || cfg.Path != "images/" {
t.Fatalf("unexpected upload config: %+v", cfg)
}
}
func TestValidateUploadRejectsIncompleteMinio(t *testing.T) {
if err := ValidateUpload(UploadConfig{Driver: "minio"}); err == nil {
t.Fatal("expected incomplete minio config to be rejected")
}
}