package config import ( "errors" "log" "os" "strings" "github.com/alecthomas/kong" kongtoml "github.com/alecthomas/kong-toml" "github.com/pelletier/go-toml" ) type Config struct { Port string `toml:"port" short:"p" default:"8080" comment:"The port to listen on for the server."` DatabaseFilePath string `toml:"database-file-path" short:"d" default:"plm.db" comment:"Path to sqlite database file."` DemoDataPath string `toml:"demo-data-path" comment:"The path to the sql file to load for demo data."` JWTKey string `toml:"jwt-key" comment:"The key used to encrypt the generated JWT. Encoded in base64. If empty a random one will be generated on every restart."` ImageFolderPath string `toml:"image-folder-path" short:"i" default:"img" comment:"Folder where uploaded files will be stored."` Limit int `toml:"limit" default:"100" comment:"A single API call will return at most this number of records."` InventaireUrl string `toml:"inventaire-url" default:"https://inventaire.io" comment:"An inventaire.io instance URL."` DisableRegistration bool `toml:"disable-registration" short:"n" default:"false" comment:"Disable new account creation."` DemoMode bool `toml:"demo-mode" short:"D" default:"false" comment:"Activate demo mode: anyone connecting to the instance will be logged in as a single user."` DemoUsername string `toml:"demo-username" default:"demo" comment:"Name of the single user used for the demo."` AddUser UserListAsStrings `toml:"add-user" short:"a" comment:"Add an user on startup following htpasswd bcrypt format, example: [\"demo:$2y$10$UHR2646SZo2W.Rhna7bn5eWNLXWJZ/Sa3oLd9RlxlXs57Bwp6isOS\",\"user:$2y$10$3WYUp.VDpzJRywtrxO1s/uWfUIKpTE4yh5B1d2RCef3hvczYbEWTC\"]"` } type UserListAsStrings []string func (u UserListAsStrings) Validate() error { for _, s := range u { if strings.Count(s, ":") != 1 { return errors.New("For adding users, please follow the format [username]:[bcrypt hashed password]") } } return nil } func defaultConfig() Config { return Config{ Port: "8080", DatabaseFilePath: "plm.db", DemoDataPath: "", JWTKey: "", ImageFolderPath: "img", Limit: 100, InventaireUrl: "https://inventaire.io", DisableRegistration: false, DemoMode: false, DemoUsername: "demo", AddUser: []string{}, } } func LoadConfig(configPath string) Config { f, err := os.ReadFile(configPath) var cfg Config configFileNotExist := false if err != nil { if errors.Is(err, os.ErrNotExist) { cfg = defaultConfig() configFileNotExist = true } else { log.Fatal(err) } } else { err = toml.Unmarshal(f, &cfg) if err != nil { panic(err) } } kong.Parse(&cfg, kong.Configuration(kongtoml.Loader, configPath)) if configFileNotExist { b, err := toml.Marshal(cfg) if err != nil { panic(err) } err = os.WriteFile(configPath, b, 0666) if err != nil { log.Fatal(err) } } return cfg }