refactoring (config): separate config loading and saving

The idea is that we can now plug and play different logic for loading
and saving configuration data via a go generator built from plugins
This commit is contained in:
Mickael Kerjean 2022-02-04 00:51:57 +11:00
parent 448d2bcd6c
commit 9171b6fb5e
3 changed files with 64 additions and 30 deletions

View file

@ -5,18 +5,15 @@ import (
"fmt"
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
"io/ioutil"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
"sync"
)
var (
Config Configuration
configPath string = filepath.Join(GetCurrentDir(), CONFIG_PATH+"config.json")
Config Configuration
)
type Configuration struct {
@ -54,7 +51,6 @@ type FormElement struct {
func init() {
Config = NewConfiguration()
Config.Load()
Config.Save()
Config.Initialise()
}
@ -206,16 +202,9 @@ func (this *Form) Iterator() []FormIterator {
}
func (this *Configuration) Load() {
file, err := os.OpenFile(configPath, os.O_RDONLY, os.ModePerm)
cFile, err := LoadConfig()
if err != nil {
Log.Warning("Can't read from config file")
return
}
defer file.Close()
cFile, err := ioutil.ReadAll(file)
if err != nil {
Log.Warning("Can't parse config file")
Log.Error("config::load %s", err)
return
}
@ -283,13 +272,17 @@ func (this *Configuration) Debug() *FormElement {
}
func (this *Configuration) Initialise() {
shouldSave := false
if env := os.Getenv("ADMIN_PASSWORD"); env != "" {
shouldSave = true
this.Get("auth.admin").Set(env)
}
if env := os.Getenv("APPLICATION_URL"); env != "" {
shouldSave = true
this.Get("general.host").Set(env).String()
}
if this.Get("general.secret_key").String() == "" {
shouldSave = true
key := RandomString(16)
this.Get("general.secret_key").Set(key)
}
@ -325,6 +318,9 @@ func (this *Configuration) Initialise() {
"label": "Drive",
},
}
shouldSave = true
}
if shouldSave {
this.Save()
}
InitSecretDerivate(this.Get("general.secret_key").String())
@ -342,14 +338,9 @@ func (this Configuration) Save() Configuration {
})
v, _ = sjson.Set(v, "connections", this.Conn)
// deploy the config in our config.json
file, err := os.Create(configPath)
if err != nil {
Log.Error("Filestash needs to be able to create/edit its own configuration which it can't at the moment. Change the permission for filestash to create and edit `%s`", configPath)
return this
if err := SaveConfig(PrettyPrint([]byte(v))); err != nil {
Log.Error("config::save %s", err.Error())
}
defer file.Close()
file.Write(PrettyPrint([]byte(v)))
return this
}

View file

@ -0,0 +1,51 @@
package common
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNI
* WARNING - CHANGE IN THIS FILE CAN SILENTLY BREAK OTHER INSTALLATION - WARNING
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARN
*
* Some contributors wanted to be able to load and persist config in other system
* like S3 and provide custom encryption layer on top of it. Those contributors have
* custom plugins which run generators that override this file before the build is
* generated. Indeed for that specific use case we couldn't extend the runtime plugin
* mechanism so had to fallback to this approach which would set the config loader at
* build time, hence this warning.
*/
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
)
var (
configPath string = filepath.Join(GetCurrentDir(), CONFIG_PATH+"config.json")
)
func LoadConfig() ([]byte, error) {
file, err := os.OpenFile(configPath, os.O_RDONLY, os.ModePerm)
if err != nil {
return nil, err
}
cFile, err := ioutil.ReadAll(file)
file.Close()
if err != nil {
return nil, err
}
return cFile, nil
}
func SaveConfig(v []byte) error {
file, err := os.Create(configPath)
if err != nil {
return fmt.Errorf(
"Filestash needs to be able to create/edit its own configuration which it can't at the moment. "+
"Change the permission for filestash to create and edit `%s`",
configPath,
)
}
file.Write(PrettyPrint([]byte(v)))
return file.Close()
}

View file

@ -53,18 +53,10 @@ func PrivateConfigHandler(ctx App, res http.ResponseWriter, req *http.Request) {
func PrivateConfigUpdateHandler(ctx App, res http.ResponseWriter, req *http.Request) {
b, _ := ioutil.ReadAll(req.Body)
b = PrettyPrint(b)
file, err := os.Create(configpath)
if err != nil {
if err := SaveConfig(b); err != nil {
SendErrorResult(res, err)
return
}
defer file.Close()
if _, err := file.Write(b); err != nil {
SendErrorResult(res, err)
return
}
file.Close()
Config.Load()
SendSuccessResult(res, nil)
}