Merge pull request #608 from filebrowser/dont-persist

feat: don't persist server data on database
Former-commit-id: 768c9ce33d1f24626f94f1de558624382ebb4d97 [formerly de47b48b656299e3e9918e302257b031fd73bc34] [formerly 0304ed3fe19248a7635c06db5367478e5c5ac7bc [formerly 02c34ef8be2068d45cd892bedb33d2bf89f9f6ef]]
Former-commit-id: a780a2b2f96b2650c35cd65e3ece26cc1c58eb41 [formerly 4cac4d8b2e52632711d50e59c07107d677ce1616]
Former-commit-id: 930d1650c381ce4e02c79d29b2d3bcd9062828b7
This commit is contained in:
Henrique Dias 2019-01-06 12:29:31 +00:00 committed by GitHub
commit 36bd2907f8
7 changed files with 53 additions and 136 deletions

View File

@ -35,12 +35,6 @@ func addConfigFlags(cmd *cobra.Command) {
cmd.Flags().BoolP("signup", "s", false, "allow users to signup") cmd.Flags().BoolP("signup", "s", false, "allow users to signup")
cmd.Flags().String("shell", "", "shell command to which other commands should be appended") cmd.Flags().String("shell", "", "shell command to which other commands should be appended")
cmd.Flags().StringP("address", "a", "127.0.0.1", "default address to listen to")
cmd.Flags().StringP("log", "l", "stderr", "log output")
cmd.Flags().IntP("port", "p", 0, "default port to listen to")
cmd.Flags().String("tls.cert", "", "tls certificate path")
cmd.Flags().String("tls.key", "", "tls key path")
cmd.Flags().String("auth.method", string(auth.MethodJSONAuth), "authentication type") cmd.Flags().String("auth.method", string(auth.MethodJSONAuth), "authentication type")
cmd.Flags().String("auth.header", "", "HTTP header for auth.method=proxy") cmd.Flags().String("auth.header", "", "HTTP header for auth.method=proxy")
@ -101,12 +95,6 @@ func printSettings(s *settings.Settings, auther auth.Auther) {
fmt.Fprintf(w, "Sign up:\t%t\n", s.Signup) fmt.Fprintf(w, "Sign up:\t%t\n", s.Signup)
fmt.Fprintf(w, "Auth method:\t%s\n", s.AuthMethod) fmt.Fprintf(w, "Auth method:\t%s\n", s.AuthMethod)
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(s.Shell, " ")) fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(s.Shell, " "))
fmt.Fprintf(w, "Log:\t%s\t\n", s.Log)
fmt.Fprintln(w, "\nServer:")
fmt.Fprintf(w, "\tAddress:\t%s\n", s.Server.Address)
fmt.Fprintf(w, "\tPort:\t%d\n", s.Server.Port)
fmt.Fprintf(w, "\tTLS Cert:\t%s\n", s.Server.TLSCert)
fmt.Fprintf(w, "\tTLS Key:\t%s\n", s.Server.TLSKey)
fmt.Fprintln(w, "\nBranding:") fmt.Fprintln(w, "\nBranding:")
fmt.Fprintf(w, "\tName:\t%s\n", s.Branding.Name) fmt.Fprintf(w, "\tName:\t%s\n", s.Branding.Name)
fmt.Fprintf(w, "\tFiles override:\t%s\n", s.Branding.Files) fmt.Fprintf(w, "\tFiles override:\t%s\n", s.Branding.Files)

View File

@ -43,17 +43,10 @@ override the options.`,
s := &settings.Settings{ s := &settings.Settings{
Key: generateRandomBytes(64), // 256 bit Key: generateRandomBytes(64), // 256 bit
BaseURL: mustGetString(cmd, "baseURL"), BaseURL: mustGetString(cmd, "baseURL"),
Log: mustGetString(cmd, "log"),
Signup: mustGetBool(cmd, "signup"), Signup: mustGetBool(cmd, "signup"),
Shell: strings.Split(strings.TrimSpace(mustGetString(cmd, "shell")), " "), Shell: strings.Split(strings.TrimSpace(mustGetString(cmd, "shell")), " "),
AuthMethod: authMethod, AuthMethod: authMethod,
Defaults: defaults, Defaults: defaults,
Server: settings.Server{
Address: mustGetString(cmd, "address"),
Port: mustGetInt(cmd, "port"),
TLSCert: mustGetString(cmd, "tls.cert"),
TLSKey: mustGetString(cmd, "tls.key"),
},
Branding: settings.Branding{ Branding: settings.Branding{
Name: mustGetString(cmd, "branding.name"), Name: mustGetString(cmd, "branding.name"),
DisableExternal: mustGetBool(cmd, "branding.disableExternal"), DisableExternal: mustGetBool(cmd, "branding.disableExternal"),

View File

@ -44,16 +44,6 @@ you want to change.`,
s.Branding.DisableExternal = mustGetBool(cmd, flag.Name) s.Branding.DisableExternal = mustGetBool(cmd, flag.Name)
case "branding.files": case "branding.files":
s.Branding.Files = mustGetString(cmd, flag.Name) s.Branding.Files = mustGetString(cmd, flag.Name)
case "log":
s.Log = mustGetString(cmd, flag.Name)
case "address":
s.Server.Address = mustGetString(cmd, flag.Name)
case "port":
s.Server.Port = mustGetInt(cmd, flag.Name)
case "tls.cert":
s.Server.TLSCert = mustGetString(cmd, flag.Name)
case "tls.key":
s.Server.TLSKey = mustGetString(cmd, flag.Name)
} }
}) })

View File

@ -1,7 +1,6 @@
package cmd package cmd
import ( import (
"crypto/rand"
"crypto/tls" "crypto/tls"
"errors" "errors"
"io/ioutil" "io/ioutil"
@ -14,12 +13,10 @@ import (
"github.com/asdine/storm" "github.com/asdine/storm"
"github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/auth"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/storage"
"github.com/filebrowser/filebrowser/v2/users" "github.com/filebrowser/filebrowser/v2/users"
fbhttp "github.com/filebrowser/filebrowser/v2/http" fbhttp "github.com/filebrowser/filebrowser/v2/http"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag"
lumberjack "gopkg.in/natefinch/lumberjack.v2" lumberjack "gopkg.in/natefinch/lumberjack.v2"
) )
@ -30,12 +27,12 @@ var (
func init() { func init() {
rootCmd.PersistentFlags().StringVarP(&databasePath, "database", "d", "./filebrowser.db", "path to the database") rootCmd.PersistentFlags().StringVarP(&databasePath, "database", "d", "./filebrowser.db", "path to the database")
rootCmd.Flags().StringP("address", "a", "", "address to listen on (default comes from database)") rootCmd.Flags().StringP("address", "a", "127.0.0.1", "address to listen on")
rootCmd.Flags().StringP("log", "l", "", "log output (default comes from database)") rootCmd.Flags().StringP("log", "l", "stdout", "log output")
rootCmd.Flags().IntP("port", "p", 0, "port to listen on (default comes from database)") rootCmd.Flags().IntP("port", "p", 80, "port to listen on")
rootCmd.Flags().StringP("cert", "c", "", "tls certificate (default comes from database)") rootCmd.Flags().StringP("cert", "c", "", "tls certificate")
rootCmd.Flags().StringP("key", "k", "", "tls key (default comes from database)") rootCmd.Flags().StringP("key", "k", "", "tls key")
rootCmd.Flags().StringP("scope", "s", "", "scope for users") rootCmd.Flags().StringP("scope", "s", "", "root scope to which user's scope are relative too")
} }
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
@ -46,29 +43,12 @@ manage your user and all the configurations without accessing the
web interface. web interface.
If you've never run File Browser, you will need to create the database. If you've never run File Browser, you will need to create the database.
See 'filebrowser help config init' for more information. See 'filebrowser help config init' for more information.`,
Run: serveAndListen,
This command is used to start up the server. By default it starts listening
on localhost on a random port unless specified otherwise in the database or
via flags.
Use the available flags to override the database/default options. These flags
values won't be persisted to the database. To persist configuration to the database
use the command 'filebrowser config set'.`,
Run: func(cmd *cobra.Command, args []string) {
if _, err := os.Stat(databasePath); os.IsNotExist(err) {
quickSetup(cmd)
}
db := getDB()
defer db.Close()
st := getStorage(db)
startServer(cmd, st)
},
} }
func setupLogger(s *settings.Settings) { func serveAndListen(cmd *cobra.Command, args []string) {
switch s.Log { switch logMethod := mustGetString(cmd, "log"); logMethod {
case "stdout": case "stdout":
log.SetOutput(os.Stdout) log.SetOutput(os.Stdout)
case "stderr": case "stderr":
@ -77,29 +57,46 @@ func setupLogger(s *settings.Settings) {
log.SetOutput(ioutil.Discard) log.SetOutput(ioutil.Discard)
default: default:
log.SetOutput(&lumberjack.Logger{ log.SetOutput(&lumberjack.Logger{
Filename: s.Log, Filename: logMethod,
MaxSize: 100, MaxSize: 100,
MaxAge: 14, MaxAge: 14,
MaxBackups: 10, MaxBackups: 10,
}) })
} }
}
func serverVisitAndReplace(cmd *cobra.Command, s *settings.Settings) { if _, err := os.Stat(databasePath); os.IsNotExist(err) {
cmd.Flags().Visit(func(flag *pflag.Flag) { quickSetup(cmd)
switch flag.Name { }
case "log":
s.Log = mustGetString(cmd, flag.Name) db := getDB()
case "address": defer db.Close()
s.Server.Address = mustGetString(cmd, flag.Name) st := getStorage(db)
case "port":
s.Server.Port = mustGetInt(cmd, flag.Name) port := mustGetInt(cmd, "port")
case "cert": address := mustGetString(cmd, "address")
s.Server.TLSCert = mustGetString(cmd, flag.Name) cert := mustGetString(cmd, "cert")
case "key": key := mustGetString(cmd, "key")
s.Server.TLSKey = mustGetString(cmd, flag.Name)
} handler, err := fbhttp.NewHandler(st)
}) checkErr(err)
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)
checkErr(err)
} else {
listener, err = net.Listen("tcp", address+":"+strconv.Itoa(port))
checkErr(err)
}
log.Println("Listening on", listener.Addr().String())
if err := http.Serve(listener, handler); err != nil {
log.Fatal(err)
}
} }
func quickSetup(cmd *cobra.Command) { func quickSetup(cmd *cobra.Command) {
@ -115,15 +112,8 @@ func quickSetup(cmd *cobra.Command) {
set := &settings.Settings{ set := &settings.Settings{
Key: generateRandomBytes(64), // 256 bit Key: generateRandomBytes(64), // 256 bit
BaseURL: "", BaseURL: "",
Log: "stderr",
Signup: false, Signup: false,
AuthMethod: auth.MethodJSONAuth, AuthMethod: auth.MethodJSONAuth,
Server: settings.Server{
Port: 0,
Address: "127.0.0.1",
TLSCert: mustGetString(cmd, "cert"),
TLSKey: mustGetString(cmd, "key"),
},
Defaults: settings.UserDefaults{ Defaults: settings.UserDefaults{
Scope: scope, Scope: scope,
Locale: "en", Locale: "en",
@ -140,7 +130,6 @@ func quickSetup(cmd *cobra.Command) {
}, },
} }
serverVisitAndReplace(cmd, set)
st := getStorage(db) st := getStorage(db)
err = st.Settings.Save(set) err = st.Settings.Save(set)
@ -164,40 +153,3 @@ func quickSetup(cmd *cobra.Command) {
err = st.Users.Save(user) err = st.Users.Save(user)
checkErr(err) checkErr(err)
} }
func startServer(cmd *cobra.Command, st *storage.Storage) {
settings, err := st.Settings.Get()
checkErr(err)
serverVisitAndReplace(cmd, settings)
setupLogger(settings)
handler, err := fbhttp.NewHandler(st)
checkErr(err)
var listener net.Listener
if settings.Server.TLSKey != "" && settings.Server.TLSCert != "" {
cer, err := tls.LoadX509KeyPair(settings.Server.TLSCert, settings.Server.TLSKey)
checkErr(err)
config := &tls.Config{Certificates: []tls.Certificate{cer}}
listener, err = tls.Listen("tcp", settings.Server.Address+":"+strconv.Itoa(settings.Server.Port), config)
checkErr(err)
} else {
listener, err = net.Listen("tcp", settings.Server.Address+":"+strconv.Itoa(settings.Server.Port))
checkErr(err)
}
log.Println("Listening on", listener.Addr().String())
if err := http.Serve(listener, handler); err != nil {
log.Fatal(err)
}
}
func generateRandomBytes(n int) []byte {
b := make([]byte, n)
_, err := rand.Read(b)
checkErr(err)
// Note that err == nil only if we read len(b) bytes.
return b
}

View File

@ -1,6 +1,7 @@
package cmd package cmd
import ( import (
"crypto/rand"
"errors" "errors"
"os" "os"
@ -53,3 +54,11 @@ func getDB() *storm.DB {
func getStorage(db *storm.DB) *storage.Storage { func getStorage(db *storm.DB) *storage.Storage {
return bolt.NewStorage(db) return bolt.NewStorage(db)
} }
func generateRandomBytes(n int) []byte {
b := make([]byte, n)
_, err := rand.Read(b)
checkErr(err)
// Note that err == nil only if we read len(b) bytes.
return b
}

View File

@ -9,8 +9,6 @@ type AuthMethod string
type Settings struct { type Settings struct {
Key []byte `json:"key"` Key []byte `json:"key"`
BaseURL string `json:"baseURL"` BaseURL string `json:"baseURL"`
Log string `json:"log"`
Server Server `json:"server"`
Signup bool `json:"signup"` Signup bool `json:"signup"`
Defaults UserDefaults `json:"defaults"` Defaults UserDefaults `json:"defaults"`
AuthMethod AuthMethod `json:"authMethod"` AuthMethod AuthMethod `json:"authMethod"`
@ -20,14 +18,6 @@ type Settings struct {
Rules []rules.Rule `json:"rules"` Rules []rules.Rule `json:"rules"`
} }
// Server settings.
type Server struct {
Port int `json:"port"`
Address string `json:"address"`
TLSCert string `json:"tlsCert"`
TLSKey string `json:"tlsKey"`
}
// GetRules implements rules.Provider. // GetRules implements rules.Provider.
func (s *Settings) GetRules() []rules.Rule { func (s *Settings) GetRules() []rules.Rule {
return s.Rules return s.Rules

View File

@ -111,7 +111,6 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error {
s := &settings.Settings{ s := &settings.Settings{
Key: key, Key: key,
BaseURL: cfg.BaseURL, BaseURL: cfg.BaseURL,
Log: cfg.Log,
Signup: false, Signup: false,
Defaults: settings.UserDefaults{ Defaults: settings.UserDefaults{
Scope: cfg.Defaults.Scope, Scope: cfg.Defaults.Scope,
@ -129,10 +128,6 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error {
Download: true, Download: true,
}, },
}, },
Server: settings.Server{
Address: cfg.Address,
Port: cfg.Port,
},
} }
var auther auth.Auther var auther auth.Auther