130 lines
2.7 KiB
Go
130 lines
2.7 KiB
Go
package config
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"errors"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
type Config struct {
|
|
AppEnv string
|
|
AppPort string
|
|
|
|
PublicBaseURL string
|
|
|
|
AdminInitUsername string
|
|
AdminInitPassword string
|
|
|
|
JWTSecret string
|
|
|
|
APIKey string
|
|
APIKeyHash string
|
|
|
|
DBHost string
|
|
DBPort string
|
|
DBName string
|
|
DBUser string
|
|
DBPassword string
|
|
DBParams string
|
|
|
|
RedisAddr string
|
|
RedisPassword string
|
|
RedisDB int
|
|
|
|
UploadDir string
|
|
MaxUploadMB int64
|
|
|
|
CORSAllowOrigins []string
|
|
|
|
AMapKey string
|
|
}
|
|
|
|
func Load() (Config, error) {
|
|
_ = godotenv.Load()
|
|
|
|
cfg := Config{
|
|
AppEnv: getenv("APP_ENV", "dev"),
|
|
AppPort: getenv("APP_PORT", "8080"),
|
|
|
|
PublicBaseURL: getenv("PUBLIC_BASE_URL", "http://localhost:8080"),
|
|
|
|
AdminInitUsername: getenv("ADMIN_INIT_USERNAME", "admin"),
|
|
AdminInitPassword: getenv("ADMIN_INIT_PASSWORD", "admin123456"),
|
|
|
|
JWTSecret: getenv("JWT_SECRET", ""),
|
|
|
|
APIKey: strings.TrimSpace(os.Getenv("API_KEY")),
|
|
APIKeyHash: strings.ToLower(strings.TrimSpace(os.Getenv("API_KEY_HASH"))),
|
|
|
|
DBHost: getenv("DB_HOST", "127.0.0.1"),
|
|
DBPort: getenv("DB_PORT", "3306"),
|
|
DBName: getenv("DB_NAME", "mydb"),
|
|
DBUser: getenv("DB_USER", "root"),
|
|
DBPassword: strings.TrimSpace(os.Getenv("DB_PASSWORD")),
|
|
DBParams: getenv("DB_PARAMS", "charset=utf8mb4&parseTime=True&loc=Local"),
|
|
|
|
RedisAddr: getenv("REDIS_ADDR", "127.0.0.1:6379"),
|
|
RedisPassword: strings.TrimSpace(os.Getenv("REDIS_PASSWORD")),
|
|
RedisDB: mustAtoi(getenv("REDIS_DB", "0")),
|
|
|
|
UploadDir: getenv("UPLOAD_DIR", "./static/upload"),
|
|
MaxUploadMB: int64(mustAtoi(getenv("MAX_UPLOAD_MB", "10"))),
|
|
|
|
CORSAllowOrigins: splitCSV(getenv("CORS_ALLOW_ORIGINS", "http://localhost:5173")),
|
|
|
|
AMapKey: strings.TrimSpace(os.Getenv("AMAP_KEY")),
|
|
}
|
|
|
|
if cfg.JWTSecret == "" {
|
|
return Config{}, errors.New("JWT_SECRET is required")
|
|
}
|
|
if cfg.APIKey == "" && cfg.APIKeyHash == "" {
|
|
return Config{}, errors.New("API_KEY or API_KEY_HASH is required")
|
|
}
|
|
if cfg.APIKeyHash != "" && len(cfg.APIKeyHash) != 64 {
|
|
return Config{}, errors.New("API_KEY_HASH must be sha256 hex (64 chars)")
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func (c Config) ExpectedAPIKeyHash() string {
|
|
if c.APIKeyHash != "" {
|
|
return c.APIKeyHash
|
|
}
|
|
sum := sha256.Sum256([]byte(c.APIKey))
|
|
return hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
func getenv(key, def string) string {
|
|
if v := strings.TrimSpace(os.Getenv(key)); v != "" {
|
|
return v
|
|
}
|
|
return def
|
|
}
|
|
|
|
func mustAtoi(s string) int {
|
|
n, err := strconv.Atoi(strings.TrimSpace(s))
|
|
if err != nil {
|
|
return 0
|
|
}
|
|
return n
|
|
}
|
|
|
|
func splitCSV(s string) []string {
|
|
var out []string
|
|
for _, part := range strings.Split(s, ",") {
|
|
v := strings.TrimSpace(part)
|
|
if v != "" {
|
|
out = append(out, v)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|