80 lines
2.3 KiB
Go
80 lines
2.3 KiB
Go
package config
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/base64"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/caarlos0/env/v11"
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
type Config struct {
|
|
Port string `env:"PORT" envDefault:"8080"`
|
|
AdminUsername string `env:"ADMIN_USERNAME" envDefault:"admin"`
|
|
AdminPassword string `env:"ADMIN_PASSWORD" envDefault:"infinite-canvas"`
|
|
JWTSecret string `env:"JWT_SECRET" envDefault:"infinite-canvas"`
|
|
JWTExpireHours int `env:"JWT_EXPIRE_HOURS" envDefault:"168"`
|
|
StorageDriver string `env:"STORAGE_DRIVER" envDefault:"sqlite"`
|
|
DatabaseDSN string `env:"DATABASE_DSN" envDefault:"data/infinite-canvas.db"`
|
|
PublicBaseURL string `env:"PUBLIC_BASE_URL"`
|
|
LinuxDoAuthorizeURL string `env:"LINUX_DO_AUTHORIZE_URL" envDefault:"https://connect.linux.do/oauth2/authorize"`
|
|
LinuxDoTokenURL string `env:"LINUX_DO_TOKEN_URL" envDefault:"https://connect.linux.do/oauth2/token"`
|
|
LinuxDoUserInfoURL string `env:"LINUX_DO_USERINFO_URL" envDefault:"https://connect.linux.do/api/user"`
|
|
}
|
|
|
|
var Cfg Config
|
|
|
|
func Load() error {
|
|
_ = godotenv.Load()
|
|
if err := env.Parse(&Cfg); err != nil {
|
|
return err
|
|
}
|
|
normalizeDockerSQLiteDSN("/app/data")
|
|
if strings.TrimSpace(Cfg.JWTSecret) == "" || Cfg.JWTSecret == "infinite-canvas" {
|
|
secret, err := randomSecret()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
Cfg.JWTSecret = secret
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func normalizeDockerSQLiteDSN(appDataDir string) {
|
|
driver := strings.ToLower(strings.TrimSpace(Cfg.StorageDriver))
|
|
if driver != "" && driver != "sqlite" {
|
|
return
|
|
}
|
|
dsn := strings.TrimSpace(Cfg.DatabaseDSN)
|
|
if dsn == "" || dsn == ":memory:" || strings.HasPrefix(dsn, "file:") {
|
|
return
|
|
}
|
|
pathPart, suffix := dsn, ""
|
|
if index := strings.Index(dsn, "?"); index >= 0 {
|
|
pathPart = dsn[:index]
|
|
suffix = dsn[index:]
|
|
}
|
|
if filepath.IsAbs(pathPart) {
|
|
return
|
|
}
|
|
slashPath := filepath.ToSlash(pathPart)
|
|
if slashPath != "data" && !strings.HasPrefix(slashPath, "data/") {
|
|
return
|
|
}
|
|
if _, err := os.Stat(appDataDir); err != nil {
|
|
return
|
|
}
|
|
Cfg.DatabaseDSN = filepath.Join(filepath.Dir(appDataDir), filepath.FromSlash(slashPath)) + suffix
|
|
}
|
|
|
|
func randomSecret() (string, error) {
|
|
buf := make([]byte, 32)
|
|
if _, err := rand.Read(buf); err != nil {
|
|
return "", err
|
|
}
|
|
return base64.RawURLEncoding.EncodeToString(buf), nil
|
|
}
|