Files
Arkie-Library-Backend/internal/config/config.go
thomas 5226990e64
Some checks failed
Deploy API / deploy (push) Failing after 6s
1
2026-05-19 07:37:25 +08:00

117 lines
3.6 KiB
Go

package config
import (
"os"
"strconv"
"strings"
)
type Config struct {
Addr string
DatabaseURL string
// RunWalletAuthSchema: when true, API startup runs CREATE TABLE for wallet_auth_* (use a DDL-capable DB user).
// Set false on read-only / public API hosts after schema has been applied elsewhere (e.g. admin/migrate host).
RunWalletAuthSchema bool
JWTSecret string
UploadDir string
UploadMaxMem int64 // passed to ParseMultipartForm (file parts buffer before spilling to disk)
SeedAdmin bool
AdminEmail string
AdminPass string
CORSOrigins []string
// S3 (optional). When S3Bucket is set, admin uploads go to S3; use AWS SDK default credentials (env or IAM).
S3Bucket string
AWSRegion string
S3UploadPrefix string
S3PublicBase string // optional CDN / website endpoint base URL for returned object URLs
// S3ObjectACL: optional canned ACL on PutObject (e.g. public-read). Empty = omit ACL (required for Bucket owner enforced buckets).
S3ObjectACL string
}
func Load() Config {
origins := os.Getenv("CORS_ORIGINS")
var cors []string
if origins != "" {
for _, o := range strings.Split(origins, ",") {
o = strings.TrimSpace(o)
if o != "" {
cors = append(cors, o)
}
}
}
addr := os.Getenv("HTTP_ADDR")
if addr == "" {
addr = ":8080"
}
db := os.Getenv("DATABASE_URL")
if db == "" {
db = "postgres://ark:ark@localhost:5432/arkdb?sslmode=disable"
}
secret := os.Getenv("JWT_SECRET")
if secret == "" {
secret = "dev-insecure-change-me"
}
upload := os.Getenv("UPLOAD_DIR")
if upload == "" {
upload = "./uploads"
}
// Memory buffer for multipart file parts (bytes beyond this spill to temp files).
uploadMem := int64(64 << 20)
if s := strings.TrimSpace(os.Getenv("UPLOAD_MULTIPART_MEM_MB")); s != "" {
if mb, err := strconv.ParseInt(s, 10, 64); err == nil && mb > 0 {
uploadMem = mb * 1 << 20
}
}
s3Bucket := strings.TrimSpace(os.Getenv("S3_BUCKET"))
awsRegion := strings.TrimSpace(os.Getenv("AWS_REGION"))
if awsRegion == "" {
awsRegion = strings.TrimSpace(os.Getenv("AWS_DEFAULT_REGION"))
}
if s3Bucket != "" && awsRegion == "" {
awsRegion = "ap-southeast-1"
}
s3Prefix := strings.TrimSpace(os.Getenv("S3_UPLOAD_PREFIX"))
if s3Prefix == "" {
s3Prefix = "uploads"
}
s3Prefix = strings.Trim(s3Prefix, "/")
s3Public := strings.TrimSpace(os.Getenv("S3_PUBLIC_BASE_URL"))
s3ObjectACL := strings.TrimSpace(os.Getenv("S3_OBJECT_ACL"))
return Config{
Addr: addr,
DatabaseURL: db,
RunWalletAuthSchema: envBoolDefaultTrue("RUN_WALLET_AUTH_SCHEMA"),
JWTSecret: secret,
UploadDir: upload,
UploadMaxMem: uploadMem,
SeedAdmin: os.Getenv("SEED_ADMIN") == "1" || os.Getenv("SEED_ADMIN") == "true",
AdminEmail: firstNonEmpty(os.Getenv("ADMIN_EMAIL"), "admin@ark.local"),
AdminPass: firstNonEmpty(os.Getenv("ADMIN_PASSWORD"), "admin123"),
CORSOrigins: cors,
S3Bucket: s3Bucket,
AWSRegion: awsRegion,
S3UploadPrefix: s3Prefix,
S3PublicBase: s3Public,
S3ObjectACL: s3ObjectACL,
}
}
// envBoolDefaultTrue returns true when the env var is unset; false for 0/false/no/off (case-insensitive).
func envBoolDefaultTrue(key string) bool {
s := strings.ToLower(strings.TrimSpace(os.Getenv(key)))
if s == "" {
return true
}
if s == "0" || s == "false" || s == "no" || s == "off" {
return false
}
return s == "1" || s == "true" || s == "yes" || s == "on"
}
func firstNonEmpty(a, b string) string {
if strings.TrimSpace(a) != "" {
return a
}
return b
}