add settings/runtime.go

This commit is contained in:
1138-4EB 2019-01-07 13:44:13 +01:00
parent 25c009a560
commit b178c6af99
12 changed files with 100 additions and 67 deletions

View File

@ -28,7 +28,7 @@ override the options.`,
authMethod, auther := getAuthentication(cmd)
s := &settings.Settings{
Key: generateRandomBytes(64), // 256 bit
Runtime: runtimeNonDefaults(),
Signup: mustGetBool(cmd, "signup"),
Shell: strings.Split(strings.TrimSpace(mustGetString(cmd, "shell")), " "),
AuthMethod: authMethod,

View File

@ -2,13 +2,13 @@ package cmd
import (
"crypto/tls"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/filebrowser/filebrowser/v2/auth"
@ -35,15 +35,16 @@ func init() {
pf.StringVarP(&cfgFile, "config", "c", "", "config file path")
vaddP(pf, "database", "d", "./filebrowser.db", "path to the database")
vaddP(f, "address", "a", "127.0.0.1", "address to listen on")
vaddP(f, "log", "l", "stdout", "log output")
vaddP(f, "port", "p", 8080, "port to listen on")
vaddP(f, "cert", "t", "", "tls certificate")
vaddP(f, "key", "k", "", "tls key")
vaddP(f, "root", "r", ".", "root to prepend to relative paths")
vaddP(f, "baseurl", "b", "", "base url")
vaddP(f, "address", "a", settings.RuntimeDefaults["address"], "address to listen on")
vaddP(f, "log", "l", settings.RuntimeDefaults["log"], "log output")
vaddP(f, "port", "p", settings.RuntimeDefaults["port"], "port to listen on")
vaddP(f, "cert", "t", settings.RuntimeDefaults["cert"], "tls certificate")
vaddP(f, "key", "k", settings.RuntimeDefaults["key"], "tls key")
vaddP(f, "root", "r", settings.RuntimeDefaults["root"], "root path to prepend to all relative paths")
vaddP(f, "baseurl", "b", settings.RuntimeDefaults["baseurl"], "base url")
vadd(f, "username", "admin", "username for the first user when using quick config")
vadd(f, "password", "", "hashed password for the first user when using quick config (default \"admin\")")
vaddP(f, "force", "f", false, "")
if err := v.BindPFlags(f); err != nil {
panic(err)
@ -97,7 +98,7 @@ user created with the credentials from options "username" and "password".`,
log.Println(cfgFile)
switch logMethod := v.GetString("log"); logMethod {
switch logMethod := settings.RuntimeCfg["log"]; logMethod {
case "stdout":
log.SetOutput(os.Stdout)
case "stderr":
@ -117,44 +118,40 @@ user created with the credentials from options "username" and "password".`,
quickSetup(d)
}
// TODO: check if these fields (including baseurl) are available in the DB. proceed according to --force
port := v.GetInt("port")
address := v.GetString("address")
cert := v.GetString("cert")
key := v.GetString("key")
root := v.GetString("root")
root, err := filepath.Abs(root)
checkErr(err)
settings, err := d.store.Settings.Get()
s, err := d.store.Settings.Get()
checkErr(err)
// Despite Base URL and Scope being "server" type of
// variables, we persist them to the database because
// they are needed during the execution and not only
// to start up the server.
settings.BaseURL = v.GetString("baseurl")
settings.Root = root
err = d.store.Settings.Save(settings)
checkErr(err)
if !v.GetBool("force") {
for k := range settings.RuntimeCfg {
if y, ok := s.Runtime[k]; ok {
settings.RuntimeCfg[k] = y
}
}
}
handler, err := fbhttp.NewHandler(d.store)
r, err := filepath.Abs(settings.RuntimeCfg["root"])
checkErr(err)
settings.RuntimeCfg["root"] = r
adr := settings.RuntimeCfg["address"] + ":" + settings.RuntimeCfg["port"]
cert := settings.RuntimeCfg["cert"]
key := settings.RuntimeCfg["key"]
var listener net.Listener
if key != "" && cert != "" {
cer, err := tls.LoadX509KeyPair(cert, key)
checkErr(err)
config := &tls.Config{Certificates: []tls.Certificate{cer}}
listener, err = tls.Listen("tcp", address+":"+strconv.Itoa(port), config)
listener, err = tls.Listen("tcp", adr, &tls.Config{Certificates: []tls.Certificate{cer}})
checkErr(err)
} else {
listener, err = net.Listen("tcp", address+":"+strconv.Itoa(port))
listener, err = net.Listen("tcp", adr)
checkErr(err)
}
handler, err := fbhttp.NewHandler(d.store)
checkErr(err)
log.Println("Listening on", listener.Addr().String())
if err := http.Serve(listener, handler); err != nil {
log.Fatal(err)
@ -162,13 +159,26 @@ user created with the credentials from options "username" and "password".`,
}, pythonConfig{allowNoDB: true}),
}
func runtimeNonDefaults() (m map[string]string) {
for k, d := range settings.RuntimeDefaults {
if x, ok := settings.RuntimeCfg[k]; ok && (x != d) {
log.Println(fmt.Sprintf("Non-default value for key '%s': %s [default: %s]", k, x, d))
m[k] = x
}
}
if settings.RuntimeCfg["key"] == "" {
log.Println("Generate random 256 bit key")
m["key"] = string(generateRandomBytes(64)) // 256 bit
}
return
}
func quickSetup(d pythonData) {
// TODO: save also port, address, cert, key, scope; if their values differ from defaults
log.Println("Executing quick setup...")
set := &settings.Settings{
Key: generateRandomBytes(64), // 256 bit
BaseURL: v.GetString("baseurl"),
Runtime: runtimeNonDefaults(),
Signup: false,
AuthMethod: auth.MethodJSONAuth,
Defaults: settings.UserDefaults{
@ -216,6 +226,8 @@ func quickSetup(d pythonData) {
err = d.store.Users.Save(user)
checkErr(err)
log.Println("Quick setup finished")
}
func initConfig() {
@ -239,6 +251,11 @@ func initConfig() {
panic(err)
}
cfgFile = "No config file used"
} else {
cfgFile = "Using config file: " + v.ConfigFileUsed()
}
for k := range settings.RuntimeDefaults {
settings.RuntimeCfg[k] = v.GetString(k)
}
cfgFile = "Using config file: " + v.ConfigFileUsed()
}

View File

@ -1,9 +1,9 @@
package cmd
import (
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/storage/bolt/importer"
"github.com/spf13/cobra"
v "github.com/spf13/viper"
)
func init() {
@ -26,7 +26,7 @@ this version.`,
oldDB := mustGetString(cmd, "old.database")
oldConf := mustGetString(cmd, "old.config")
err := importer.Import(oldDB, oldConf, v.GetString("database"))
err := importer.Import(oldDB, oldConf, settings.RuntimeCfg["database"])
checkErr(err)
},
}

View File

@ -7,9 +7,10 @@ import (
"strings"
"time"
"github.com/dgrijalva/jwt-go"
jwt "github.com/dgrijalva/jwt-go"
"github.com/dgrijalva/jwt-go/request"
"github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users"
)
@ -50,7 +51,7 @@ func (e extractor) ExtractToken(r *http.Request) (string, error) {
func withUser(fn handleFunc) handleFunc {
return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
keyFunc := func(token *jwt.Token) (interface{}, error) {
return d.settings.Key, nil
return settings.RuntimeCfg["key"], nil
}
var tk authToken
@ -67,7 +68,7 @@ func withUser(fn handleFunc) handleFunc {
w.Header().Add("X-Renew-Token", "true")
}
d.user, err = d.store.Users.Get(d.settings.Root, tk.User.ID)
d.user, err = d.store.Users.Get(settings.RuntimeCfg["root"], tk.User.ID)
if err != nil {
return http.StatusInternalServerError, err
}
@ -169,7 +170,7 @@ func printToken(w http.ResponseWriter, r *http.Request, d *data, user *users.Use
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
signed, err := token.SignedString(d.settings.Key)
signed, err := token.SignedString(settings.RuntimeCfg["key"])
if err != nil {
return http.StatusInternalServerError, err
}

View File

@ -4,6 +4,7 @@ import (
"net/http"
"github.com/filebrowser/filebrowser/v2/files"
"github.com/filebrowser/filebrowser/v2/settings"
)
var withHashFile = func(fn handleFunc) handleFunc {
@ -13,7 +14,7 @@ var withHashFile = func(fn handleFunc) handleFunc {
return errToStatus(err), err
}
user, err := d.store.Users.Get(d.settings.Root, link.UserID)
user, err := d.store.Users.Get(settings.RuntimeCfg["root"], link.UserID)
if err != nil {
return errToStatus(err), err
}

View File

@ -9,6 +9,7 @@ import (
"time"
"github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/share"
)
@ -56,7 +57,7 @@ var sharePostHandler = withPermShare(func(w http.ResponseWriter, r *http.Request
var err error
s, err = d.store.Share.GetPermanent(r.URL.Path, d.user.ID)
if err == nil {
w.Write([]byte(d.settings.BaseURL + "/share/" + s.Hash))
w.Write([]byte(settings.RuntimeCfg["baseurl"] + "/share/" + s.Hash))
return 0, nil
}
}

View File

@ -9,8 +9,9 @@ import (
"strings"
"text/template"
"github.com/GeertJohan/go.rice"
rice "github.com/GeertJohan/go.rice"
"github.com/filebrowser/filebrowser/v2/auth"
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/storage"
"github.com/filebrowser/filebrowser/v2/version"
)
@ -18,12 +19,12 @@ import (
func handleWithStaticData(w http.ResponseWriter, r *http.Request, d *data, box *rice.Box, file, contentType string) (int, error) {
w.Header().Set("Content-Type", contentType)
staticURL := strings.TrimPrefix(d.settings.BaseURL+"/static", "/")
staticURL := strings.TrimPrefix(settings.RuntimeCfg["baseurl"]+"/static", "/")
data := map[string]interface{}{
"Name": d.settings.Branding.Name,
"DisableExternal": d.settings.Branding.DisableExternal,
"BaseURL": d.settings.BaseURL,
"BaseURL": settings.RuntimeCfg["baseurl"],
"Version": version.Version,
"StaticURL": staticURL,
"Signup": d.settings.Signup,

View File

@ -8,6 +8,7 @@ import (
"strings"
"github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users"
"github.com/gorilla/mux"
)
@ -61,7 +62,7 @@ func withSelfOrAdmin(fn handleFunc) handleFunc {
}
var usersGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
users, err := d.store.Users.Gets(d.settings.Root)
users, err := d.store.Users.Gets(settings.RuntimeCfg["root"])
if err != nil {
return http.StatusInternalServerError, err
}
@ -78,7 +79,7 @@ var usersGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d *
})
var userGetHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
u, err := d.store.Users.Get(d.settings.Root, d.raw.(uint))
u, err := d.store.Users.Get(settings.RuntimeCfg["root"], d.raw.(uint))
if err == errors.ErrNotExist {
return http.StatusNotFound, err
}
@ -147,7 +148,7 @@ var userPutHandler = withSelfOrAdmin(func(w http.ResponseWriter, r *http.Request
req.Data.Password, err = users.HashPwd(req.Data.Password)
} else {
var suser *users.User
suser, err = d.store.Users.Get(d.settings.Root, d.raw.(uint))
suser, err = d.store.Users.Get(settings.RuntimeCfg["root"], d.raw.(uint))
req.Data.Password = suser.Password
}

15
settings/runtime.go Normal file
View File

@ -0,0 +1,15 @@
package settings
// RuntimeDefaults defines default values for runtime parameters
var RuntimeDefaults = map[string]string{
"root": ".",
"baseurl": "",
"address": "127.0.0.1",
"port": "8080",
"cert": "",
"key": "",
"log": "stdout",
}
// RuntimeCfg contains parameters to be used at runtime
var RuntimeCfg = map[string]string{}

View File

@ -7,9 +7,7 @@ type AuthMethod string
// Settings contain the main settings of the application.
type Settings struct {
Key []byte `json:"key"`
BaseURL string `json:"baseURL"`
Root string `json:"root"`
Runtime map[string]string `json:"runtime"`
Signup bool `json:"signup"`
Defaults UserDefaults `json:"defaults"`
AuthMethod AuthMethod `json:"authMethod"`

View File

@ -1,9 +1,6 @@
package settings
import (
"strings"
"github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/rules"
"github.com/filebrowser/filebrowser/v2/users"
)
@ -39,12 +36,13 @@ var defaultEvents = []string{
// Save saves the settings for the current instance.
func (s *Storage) Save(set *Settings) error {
set.BaseURL = strings.TrimSuffix(set.BaseURL, "/")
if len(set.Key) == 0 {
return errors.ErrEmptyKey
}
/*
set.BaseURL = strings.TrimSuffix(set.BaseURL, "/")
if len(set.Key) == 0 {
return errors.ErrEmptyKey
}
*/
if set.Defaults.Locale == "" {
set.Defaults.Locale = "en"
}

View File

@ -13,8 +13,8 @@ import (
"github.com/asdine/storm"
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/storage"
"github.com/pelletier/go-toml"
"gopkg.in/yaml.v2"
toml "github.com/pelletier/go-toml"
yaml "gopkg.in/yaml.v2"
)
type oldDefs struct {
@ -109,9 +109,9 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error {
}
s := &settings.Settings{
Key: key,
BaseURL: cfg.BaseURL,
Signup: false,
//Key: key,
//BaseURL: cfg.BaseURL,
Signup: false,
Defaults: settings.UserDefaults{
Scope: cfg.Defaults.Scope,
Commands: cfg.Defaults.Commands,