206 lines
4.8 KiB
Go
206 lines
4.8 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"smoop-api/internal/vault"
|
|
)
|
|
|
|
type Config struct {
|
|
DB struct {
|
|
DSN string
|
|
}
|
|
MinIO struct {
|
|
Endpoint string
|
|
AccessKey string
|
|
SecretKey string
|
|
UseSSL bool
|
|
RecordsBucket string
|
|
LivestreamBucket string
|
|
PresignTTL time.Duration
|
|
}
|
|
JWTSecret []byte
|
|
}
|
|
|
|
func Load() (*Config, error) {
|
|
addr := os.Getenv("VAULT_ADDR")
|
|
token := os.Getenv("VAULT_TOKEN")
|
|
|
|
// New style: explicit KV v2 mount + key
|
|
mount := os.Getenv("VAULT_KV_MOUNT") // e.g. "kv" or "secret"
|
|
key := os.Getenv("VAULT_KV_KEY") // e.g. "snoop"
|
|
|
|
// Back-compat: allow legacy VAULT_KV_PATH like "kv/data/snoop" and derive mount+key
|
|
if (mount == "" || key == "") && os.Getenv("VAULT_KV_PATH") != "" {
|
|
legacy := strings.Trim(os.Getenv("VAULT_KV_PATH"), "/")
|
|
parts := strings.Split(legacy, "/")
|
|
if len(parts) >= 2 {
|
|
mount = parts[0]
|
|
key = parts[len(parts)-1]
|
|
}
|
|
}
|
|
|
|
if addr == "" || token == "" || mount == "" || key == "" {
|
|
return nil, fmt.Errorf("VAULT_ADDR, VAULT_TOKEN, VAULT_KV_MOUNT and VAULT_KV_KEY must be set (or provide legacy VAULT_KV_PATH)")
|
|
}
|
|
|
|
raw, err := vault.ReadKVv2(addr, token, mount, key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
getStr := func(k string) (string, error) {
|
|
v, ok := raw[k].(string)
|
|
if !ok || v == "" {
|
|
return "", fmt.Errorf("missing secret key: %s", k)
|
|
}
|
|
return v, nil
|
|
}
|
|
getBool := func(k string) (bool, error) {
|
|
v, ok := raw[k]
|
|
if !ok {
|
|
return false, fmt.Errorf("missing secret key: %s", k)
|
|
}
|
|
switch t := v.(type) {
|
|
case bool:
|
|
return t, nil
|
|
case string:
|
|
if t == "true" || t == "1" {
|
|
return true, nil
|
|
}
|
|
return false, nil
|
|
default:
|
|
return false, fmt.Errorf("invalid bool for key %s", k)
|
|
}
|
|
}
|
|
|
|
dbDSN, err := getStr("db_dsn")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
endpoint, err := getStr("minio_endpoint")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ak, err := getStr("minio_access_key")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sk, err := getStr("minio_secret_key")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
useSSL, err := getBool("minio_use_ssl")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
jwt, err := getStr("jwt_secret")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
recordsBucket := "records"
|
|
if v, ok := raw["minio_records_bucket"].(string); ok && v != "" {
|
|
recordsBucket = v
|
|
}
|
|
liveBucket := "livestream"
|
|
if v, ok := raw["minio_livestream_bucket"].(string); ok && v != "" {
|
|
liveBucket = v
|
|
}
|
|
presignTTL := 15 * time.Minute
|
|
if v, ok := raw["minio_presign_ttl_seconds"].(string); ok && v != "" {
|
|
var sec int
|
|
fmt.Sscanf(v, "%d", &sec)
|
|
if sec > 0 {
|
|
presignTTL = time.Duration(sec) * time.Second
|
|
}
|
|
}
|
|
|
|
cfg := &Config{}
|
|
cfg.DB.DSN = dbDSN
|
|
cfg.MinIO.Endpoint = endpoint
|
|
cfg.MinIO.AccessKey = ak
|
|
cfg.MinIO.SecretKey = sk
|
|
cfg.MinIO.UseSSL = useSSL
|
|
cfg.MinIO.RecordsBucket = recordsBucket
|
|
cfg.MinIO.LivestreamBucket = liveBucket
|
|
cfg.MinIO.PresignTTL = presignTTL
|
|
cfg.JWTSecret = []byte(jwt)
|
|
return cfg, nil
|
|
}
|
|
|
|
func LoadDev() (*Config, error) {
|
|
getRequired := func(k string) (string, error) {
|
|
v := os.Getenv(k)
|
|
if v == "" {
|
|
return "", fmt.Errorf("missing required env %s", k)
|
|
}
|
|
return v, nil
|
|
}
|
|
getBoolEnv := func(k string, def bool) bool {
|
|
v := strings.ToLower(strings.TrimSpace(os.Getenv(k)))
|
|
if v == "true" || v == "1" || v == "yes" {
|
|
return true
|
|
}
|
|
if v == "false" || v == "0" || v == "no" {
|
|
return false
|
|
}
|
|
return def
|
|
}
|
|
getIntEnv := func(k string, def int) int {
|
|
if v := strings.TrimSpace(os.Getenv(k)); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil {
|
|
return n
|
|
}
|
|
}
|
|
return def
|
|
}
|
|
dbDSN, err := getRequired("DB_DSN")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
endpoint, err := getRequired("MINIO_ENDPOINT")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ak, err := getRequired("MINIO_ACCESS_KEY")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sk, err := getRequired("MINIO_SECRET_KEY")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
jwt, err := getRequired("JWT_SECRET")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
useSSL := getBoolEnv("MINIO_USE_SSL", false)
|
|
recordsBucket := os.Getenv("MINIO_RECORDS_BUCKET")
|
|
if recordsBucket == "" {
|
|
recordsBucket = "records"
|
|
}
|
|
liveBucket := os.Getenv("MINIO_LIVESTREAM_BUCKET")
|
|
if liveBucket == "" {
|
|
liveBucket = "livestream"
|
|
}
|
|
presignTTL := time.Duration(getIntEnv("MINIO_PRESIGN_TTL_SECONDS", 900)) * time.Second
|
|
|
|
cfg := &Config{}
|
|
cfg.DB.DSN = dbDSN
|
|
cfg.MinIO.Endpoint = endpoint
|
|
cfg.MinIO.AccessKey = ak
|
|
cfg.MinIO.SecretKey = sk
|
|
cfg.MinIO.UseSSL = useSSL
|
|
cfg.MinIO.RecordsBucket = recordsBucket
|
|
cfg.MinIO.LivestreamBucket = liveBucket
|
|
cfg.MinIO.PresignTTL = presignTTL
|
|
cfg.JWTSecret = []byte(jwt)
|
|
return cfg, nil
|
|
}
|