diff --git a/cmd/cmds_add.go b/cmd/cmds_add.go index a4d17061..5f34630f 100644 --- a/cmd/cmds_add.go +++ b/cmd/cmds_add.go @@ -4,6 +4,7 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { @@ -15,7 +16,7 @@ var cmdsAddCmd = &cobra.Command{ Short: "Add a command to run on a specific event", Long: `Add a command to run on a specific event.`, Args: cobra.MinimumNArgs(2), - RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(_ *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { s, err := d.store.Settings.Get() if err != nil { return err diff --git a/cmd/cmds_ls.go b/cmd/cmds_ls.go index fe1459e6..15a8f0e7 100644 --- a/cmd/cmds_ls.go +++ b/cmd/cmds_ls.go @@ -2,7 +2,7 @@ package cmd import ( "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" ) func init() { @@ -15,7 +15,7 @@ var cmdsLsCmd = &cobra.Command{ Short: "List all commands for each event", Long: `List all commands for each event.`, Args: cobra.NoArgs, - RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, _ []string, v *viper.Viper, d *pythonData) error { s, err := d.store.Settings.Get() if err != nil { return err diff --git a/cmd/cmds_rm.go b/cmd/cmds_rm.go index 34089388..8cfa5a29 100644 --- a/cmd/cmds_rm.go +++ b/cmd/cmds_rm.go @@ -4,6 +4,7 @@ import ( "strconv" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { @@ -35,7 +36,7 @@ including 'index_end'.`, return nil }, - RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(_ *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { s, err := d.store.Settings.Get() if err != nil { return err diff --git a/cmd/config.go b/cmd/config.go index cbf044ed..a9ad3c85 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -10,7 +10,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/errors" @@ -57,7 +57,7 @@ func addConfigFlags(flags *pflag.FlagSet) { flags.String("dirMode", fmt.Sprintf("%O", settings.DefaultDirMode), "Mode bits that new directories are created with") } -func getAuthMethod(defaults ...interface{}) (settings.AuthMethod, map[string]interface{}, error) { +func getAuthMethod(v *viper.Viper, defaults ...interface{}) (settings.AuthMethod, map[string]interface{}, error) { methodStr := v.GetString("auth.method") method := settings.AuthMethod(methodStr) @@ -85,7 +85,7 @@ func getAuthMethod(defaults ...interface{}) (settings.AuthMethod, map[string]int return method, defaultAuther, nil } -func getProxyAuth(defaultAuther map[string]interface{}) (auth.Auther, error) { +func getProxyAuth(v *viper.Viper, defaultAuther map[string]interface{}) (auth.Auther, error) { header := v.GetString("auth.header") if header == "" { header = defaultAuther["header"].(string) @@ -102,7 +102,7 @@ func getNoAuth() auth.Auther { return &auth.NoAuth{} } -func getJSONAuth(defaultAuther map[string]interface{}) (auth.Auther, error) { +func getJSONAuth(v *viper.Viper, defaultAuther map[string]interface{}) (auth.Auther, error) { jsonAuth := &auth.JSONAuth{} host := v.GetString("recaptcha.host") key := v.GetString("recaptcha.key") @@ -130,7 +130,7 @@ func getJSONAuth(defaultAuther map[string]interface{}) (auth.Auther, error) { return jsonAuth, nil } -func getHookAuth(defaultAuther map[string]interface{}) (auth.Auther, error) { +func getHookAuth(v *viper.Viper, defaultAuther map[string]interface{}) (auth.Auther, error) { command := v.GetString("auth.command") if command == "" { command = defaultAuther["command"].(string) @@ -143,8 +143,8 @@ func getHookAuth(defaultAuther map[string]interface{}) (auth.Auther, error) { return &auth.HookAuth{Command: command}, nil } -func getAuthentication(defaults ...interface{}) (settings.AuthMethod, auth.Auther, error) { - method, defaultAuther, err := getAuthMethod(defaults...) +func getAuthentication(v *viper.Viper, defaults ...interface{}) (settings.AuthMethod, auth.Auther, error) { + method, defaultAuther, err := getAuthMethod(v, defaults...) if err != nil { return "", nil, err } @@ -152,13 +152,13 @@ func getAuthentication(defaults ...interface{}) (settings.AuthMethod, auth.Authe var auther auth.Auther switch method { case auth.MethodProxyAuth: - auther, err = getProxyAuth(defaultAuther) + auther, err = getProxyAuth(v, defaultAuther) case auth.MethodNoAuth: auther = getNoAuth() case auth.MethodJSONAuth: - auther, err = getJSONAuth(defaultAuther) + auther, err = getJSONAuth(v, defaultAuther) case auth.MethodHookAuth: - auther, err = getHookAuth(defaultAuther) + auther, err = getHookAuth(v, defaultAuther) default: return "", nil, errors.ErrInvalidAuthMethod } diff --git a/cmd/config_cat.go b/cmd/config_cat.go index 39b1f664..094a3ccd 100644 --- a/cmd/config_cat.go +++ b/cmd/config_cat.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { @@ -13,7 +14,7 @@ var configCatCmd = &cobra.Command{ Short: "Prints the configuration", Long: `Prints the configuration.`, Args: cobra.NoArgs, - RunE: python(func(_ *cobra.Command, _ []string, d *pythonData) error { + RunE: python(func(_ *cobra.Command, _ []string, v *viper.Viper, d *pythonData) error { set, err := d.store.Settings.Get() if err != nil { return err diff --git a/cmd/config_export.go b/cmd/config_export.go index 9877fb63..a33d6aad 100644 --- a/cmd/config_export.go +++ b/cmd/config_export.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { @@ -15,7 +16,7 @@ var configExportCmd = &cobra.Command{ json or yaml file. This exported configuration can be changed, and imported again with 'config import' command.`, Args: jsonYamlArg, - RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(_ *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { settings, err := d.store.Settings.Get() if err != nil { return err diff --git a/cmd/config_import.go b/cmd/config_import.go index 7763517d..35023863 100644 --- a/cmd/config_import.go +++ b/cmd/config_import.go @@ -7,6 +7,7 @@ import ( "reflect" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/settings" @@ -34,7 +35,7 @@ database. The path must be for a json or yaml file.`, Args: jsonYamlArg, - RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(_ *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { var key []byte var err error if d.hadDB { diff --git a/cmd/config_init.go b/cmd/config_init.go index e44c868d..cc85f601 100644 --- a/cmd/config_init.go +++ b/cmd/config_init.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/settings" ) @@ -23,13 +23,13 @@ this options can be changed in the future with the command to the defaults when creating new users and you don't override the options.`, Args: cobra.NoArgs, - RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, _ []string, v *viper.Viper, d *pythonData) error { defaults := settings.UserDefaults{} - err := getUserDefaults(&defaults, true) + err := getUserDefaults(v, &defaults, true) if err != nil { return err } - authMethod, auther, err := getAuthentication() + authMethod, auther, err := getAuthentication(v) if err != nil { return err } @@ -52,12 +52,12 @@ override the options.`, }, } - s.FileMode, err = getAndParseMode("filemode") + s.FileMode, err = getAndParseMode(v, "filemode") if err != nil { return err } - s.DirMode, err = getAndParseMode("dirmode") + s.DirMode, err = getAndParseMode(v, "dirmode") if err != nil { return err } diff --git a/cmd/config_set.go b/cmd/config_set.go index fd51bc6f..300cf136 100644 --- a/cmd/config_set.go +++ b/cmd/config_set.go @@ -2,7 +2,7 @@ package cmd import ( "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" ) func init() { @@ -16,7 +16,7 @@ var configSetCmd = &cobra.Command{ Long: `Updates the configuration. Set the flags for the options you want to change. Other options will remain unchanged.`, Args: cobra.NoArgs, - RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, _ []string, v *viper.Viper, d *pythonData) error { set, err := d.store.Settings.Get() if err != nil { return err @@ -78,9 +78,9 @@ you want to change. Other options will remain unchanged.`, case "branding.files": set.Branding.Files = v.GetString(key) case "filemode": - set.FileMode, err = getAndParseMode(key) + set.FileMode, err = getAndParseMode(v, key) case "dirmode": - set.DirMode, err = getAndParseMode(key) + set.DirMode, err = getAndParseMode(v, key) } if err != nil { @@ -88,7 +88,7 @@ you want to change. Other options will remain unchanged.`, } } - err = getUserDefaults(&set.Defaults, false) + err = getUserDefaults(v, &set.Defaults, false) if err != nil { return err } @@ -100,7 +100,7 @@ you want to change. Other options will remain unchanged.`, } // check if there are new flags for existing auth method - set.AuthMethod, auther, err = getAuthentication(hasAuth, set, auther) + set.AuthMethod, auther, err = getAuthentication(v, hasAuth, set, auther) if err != nil { return err } diff --git a/cmd/root.go b/cmd/root.go index e139ce29..e57e3c54 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,11 +16,10 @@ import ( "syscall" "time" - homedir "github.com/mitchellh/go-homedir" "github.com/spf13/afero" "github.com/spf13/cobra" "github.com/spf13/pflag" - v "github.com/spf13/viper" + "github.com/spf13/viper" lumberjack "gopkg.in/natefinch/lumberjack.v2" "github.com/filebrowser/filebrowser/v2/auth" @@ -35,8 +34,6 @@ import ( ) var ( - cfgFile string - flagNamesMigrations = map[string]string{ "file-mode": "fileMode", "dir-mode": "dirMode", @@ -65,7 +62,6 @@ func migrateFlagNames(f *pflag.FlagSet, name string) pflag.NormalizedName { } func init() { - cobra.OnInitialize(initConfig) rootCmd.SilenceUsage = true cobra.MousetrapHelpText = "" @@ -74,7 +70,7 @@ func init() { flags := rootCmd.Flags() persistent := rootCmd.PersistentFlags() - persistent.StringVarP(&cfgFile, "config", "c", "", "config file path") + persistent.StringP("config", "c", "", "config file path") persistent.StringP("database", "d", "./filebrowser.db", "database path") flags.Bool("noauth", false, "use the noauth auther when using quick setup") flags.String("username", "admin", "username for the first user when using quick config") @@ -141,11 +137,9 @@ set FB_DATABASE. Also, if the database path doesn't exist, File Browser will enter into the quick setup mode and a new database will be bootstrapped and a new user created with the credentials from options "username" and "password".`, - RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error { - log.Println(cfgFile) - + RunE: python(func(cmd *cobra.Command, _ []string, v *viper.Viper, d *pythonData) error { if !d.hadDB { - err := quickSetup(*d) + err := quickSetup(v, *d) if err != nil { return err } @@ -167,7 +161,7 @@ user created with the credentials from options "username" and "password".`, fileCache = diskcache.New(afero.NewOsFs(), cacheDir) } - server, err := getRunParams(d.store) + server, err := getRunParams(v, d.store) if err != nil { return err } @@ -273,48 +267,48 @@ user created with the credentials from options "username" and "password".`, }, pythonConfig{allowNoDB: true}), } -func getRunParams(st *storage.Storage) (*settings.Server, error) { +func getRunParams(v *viper.Viper, st *storage.Storage) (*settings.Server, error) { server, err := st.Settings.GetServer() if err != nil { return nil, err } - if val, set := getStringParamB("root"); set { + if val, set := getStringParamB(v, "root"); set { server.Root = val } - if val, set := getStringParamB("baseurl"); set { + if val, set := getStringParamB(v, "baseurl"); set { server.BaseURL = val } - if val, set := getStringParamB("log"); set { + if val, set := getStringParamB(v, "log"); set { server.Log = val } isSocketSet := false isAddrSet := false - if val, set := getStringParamB("address"); set { + if val, set := getStringParamB(v, "address"); set { server.Address = val isAddrSet = isAddrSet || set } - if val, set := getStringParamB("port"); set { + if val, set := getStringParamB(v, "port"); set { server.Port = val isAddrSet = isAddrSet || set } - if val, set := getStringParamB("key"); set { + if val, set := getStringParamB(v, "key"); set { server.TLSKey = val isAddrSet = isAddrSet || set } - if val, set := getStringParamB("cert"); set { + if val, set := getStringParamB(v, "cert"); set { server.TLSCert = val isAddrSet = isAddrSet || set } - if val, set := getStringParamB("socket"); set { + if val, set := getStringParamB(v, "socket"); set { server.Socket = val isSocketSet = isSocketSet || set } @@ -347,14 +341,14 @@ func getRunParams(st *storage.Storage) (*settings.Server, error) { log.Println("WARNING: read https://github.com/filebrowser/filebrowser/issues/5199") } - if val, set := getStringParamB("tokenExpirationTime"); set { + if val, set := getStringParamB(v, "tokenExpirationTime"); set { server.TokenExpirationTime = val } return server, nil } -func getStringParamB(key string) (string, bool) { +func getStringParamB(v *viper.Viper, key string) (string, bool) { return v.GetString(key), v.IsSet(key) } @@ -376,7 +370,7 @@ func setupLog(logMethod string) { } } -func quickSetup(d pythonData) error { +func quickSetup(v *viper.Viper, d pythonData) error { log.Println("Performing quick setup") set := &settings.Settings{ @@ -414,7 +408,7 @@ func quickSetup(d pythonData) error { } var err error - if _, noauth := getStringParamB("noauth"); noauth { + if _, noauth := getStringParamB(v, "noauth"); noauth { set.AuthMethod = auth.MethodNoAuth err = d.store.Auth.Save(&auth.NoAuth{}) } else { @@ -479,31 +473,3 @@ func quickSetup(d pythonData) error { return d.store.Users.Save(user) } - -func initConfig() { - if cfgFile == "" { - home, err := homedir.Dir() - if err != nil { - panic(err) - } - v.AddConfigPath(".") - v.AddConfigPath(home) - v.AddConfigPath("/etc/filebrowser/") - v.SetConfigName(".filebrowser") - } else { - v.SetConfigFile(cfgFile) - } - - v.SetEnvPrefix("FB") - v.AutomaticEnv() - - if err := v.ReadInConfig(); err != nil { - var configParseError v.ConfigParseError - if errors.As(err, &configParseError) { - panic(err) - } - cfgFile = "No config file used" - } else { - cfgFile = "Using config file: " + v.ConfigFileUsed() - } -} diff --git a/cmd/rule_rm.go b/cmd/rule_rm.go index 26e801ae..3be13622 100644 --- a/cmd/rule_rm.go +++ b/cmd/rule_rm.go @@ -4,6 +4,7 @@ import ( "strconv" "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/users" @@ -40,7 +41,7 @@ including 'index_end'.`, return nil }, - RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { i, err := strconv.Atoi(args[0]) if err != nil { return err @@ -63,6 +64,6 @@ including 'index_end'.`, return d.store.Settings.Save(s) } - return runRules(d.store, cmd, user, global) + return runRules(d.store, cmd, v, user, global) }, pythonConfig{}), } diff --git a/cmd/rules.go b/cmd/rules.go index 23bdf673..d045cc0f 100644 --- a/cmd/rules.go +++ b/cmd/rules.go @@ -4,7 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/rules" "github.com/filebrowser/filebrowser/v2/settings" @@ -29,8 +29,8 @@ rules.`, Args: cobra.NoArgs, } -func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User) error, globalFn func(*settings.Settings) error) error { - id, err := getUserIdentifier() +func runRules(st *storage.Storage, cmd *cobra.Command, v *viper.Viper, usersFn func(*users.User) error, globalFn func(*settings.Settings) error) error { + id, err := getUserIdentifier(v) if err != nil { return err } @@ -68,7 +68,7 @@ func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User) return nil } -func getUserIdentifier() (interface{}, error) { +func getUserIdentifier(v *viper.Viper) (interface{}, error) { id := v.GetUint("id") username := v.GetString("username") diff --git a/cmd/rules_add.go b/cmd/rules_add.go index 7f57856b..de6c70fb 100644 --- a/cmd/rules_add.go +++ b/cmd/rules_add.go @@ -4,7 +4,7 @@ import ( "regexp" "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/rules" "github.com/filebrowser/filebrowser/v2/settings" @@ -22,7 +22,7 @@ var rulesAddCmd = &cobra.Command{ Short: "Add a global rule or user rule", Long: `Add a global rule or user rule.`, Args: cobra.ExactArgs(1), - RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { allow := v.GetBool("allow") regex := v.GetBool("regex") exp := args[0] @@ -52,6 +52,6 @@ var rulesAddCmd = &cobra.Command{ return d.store.Settings.Save(s) } - return runRules(d.store, cmd, user, global) + return runRules(d.store, cmd, v, user, global) }, pythonConfig{}), } diff --git a/cmd/rules_ls.go b/cmd/rules_ls.go index 67a279dc..728faae8 100644 --- a/cmd/rules_ls.go +++ b/cmd/rules_ls.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { @@ -13,7 +14,7 @@ var rulesLsCommand = &cobra.Command{ Short: "List global rules or user specific rules", Long: `List global rules or user specific rules.`, Args: cobra.NoArgs, - RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error { - return runRules(d.store, cmd, nil, nil) + RunE: python(func(cmd *cobra.Command, _ []string, v *viper.Viper, d *pythonData) error { + return runRules(d.store, cmd, v, nil, nil) }, pythonConfig{}), } diff --git a/cmd/users.go b/cmd/users.go index f0d58a24..59726ca4 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/users" @@ -83,7 +83,7 @@ func addUserFlags(flags *pflag.FlagSet) { flags.String("aceEditorTheme", "", "ace editor's syntax highlighting theme for users") } -func getAndParseViewMode() (users.ViewMode, error) { +func getAndParseViewMode(v *viper.Viper) (users.ViewMode, error) { viewModeStr := v.GetString("viewMode") viewMode := users.ViewMode(viewModeStr) if viewMode != users.ListViewMode && viewMode != users.MosaicViewMode { @@ -92,7 +92,7 @@ func getAndParseViewMode() (users.ViewMode, error) { return viewMode, nil } -func getUserDefaults(defaults *settings.UserDefaults, all bool) error { +func getUserDefaults(v *viper.Viper, defaults *settings.UserDefaults, all bool) error { keys := v.AllKeys() for _, key := range keys { @@ -107,7 +107,7 @@ func getUserDefaults(defaults *settings.UserDefaults, all bool) error { case "locale": defaults.Locale = v.GetString(key) case "viewmode": - defaults.ViewMode, err = getAndParseViewMode() + defaults.ViewMode, err = getAndParseViewMode(v) case "singleclick": defaults.SingleClick = v.GetBool(key) case "aceeditortheme": diff --git a/cmd/users_add.go b/cmd/users_add.go index e44fdc94..98230496 100644 --- a/cmd/users_add.go +++ b/cmd/users_add.go @@ -2,7 +2,7 @@ package cmd import ( "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/users" ) @@ -17,12 +17,12 @@ var usersAddCmd = &cobra.Command{ Short: "Create a new user", Long: `Create a new user and add it to the database.`, Args: cobra.ExactArgs(2), - RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { s, err := d.store.Settings.Get() if err != nil { return err } - err = getUserDefaults(&s.Defaults, false) + err = getUserDefaults(v, &s.Defaults, false) if err != nil { return err } diff --git a/cmd/users_export.go b/cmd/users_export.go index d6009a37..cdc15a8b 100644 --- a/cmd/users_export.go +++ b/cmd/users_export.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { @@ -14,7 +15,7 @@ var usersExportCmd = &cobra.Command{ Long: `Export all users to a json or yaml file. Please indicate the path to the file where you want to write the users.`, Args: jsonYamlArg, - RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(_ *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { list, err := d.store.Users.Gets("") if err != nil { return err diff --git a/cmd/users_find.go b/cmd/users_find.go index 0dea071a..73aad57d 100644 --- a/cmd/users_find.go +++ b/cmd/users_find.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/users" ) @@ -26,7 +27,7 @@ var usersLsCmd = &cobra.Command{ RunE: findUsers, } -var findUsers = python(func(_ *cobra.Command, args []string, d *pythonData) error { +var findUsers = python(func(_ *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { var ( list []*users.User user *users.User diff --git a/cmd/users_import.go b/cmd/users_import.go index a7ad2cdf..7f15d8f6 100644 --- a/cmd/users_import.go +++ b/cmd/users_import.go @@ -7,7 +7,7 @@ import ( "strconv" "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/users" ) @@ -26,7 +26,7 @@ file. You can use this command to import new users to your installation. For that, just don't place their ID on the files list or set it to 0.`, Args: jsonYamlArg, - RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { fd, err := os.Open(args[0]) if err != nil { return err diff --git a/cmd/users_rm.go b/cmd/users_rm.go index 55b973f4..d4ebdbe9 100644 --- a/cmd/users_rm.go +++ b/cmd/users_rm.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/spf13/viper" ) func init() { @@ -15,7 +16,7 @@ var usersRmCmd = &cobra.Command{ Short: "Delete a user by username or id", Long: `Delete a user by username or id`, Args: cobra.ExactArgs(1), - RunE: python(func(_ *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(_ *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { username, id := parseUsernameOrID(args[0]) var err error diff --git a/cmd/users_update.go b/cmd/users_update.go index 0f69106e..6758c114 100644 --- a/cmd/users_update.go +++ b/cmd/users_update.go @@ -2,7 +2,7 @@ package cmd import ( "github.com/spf13/cobra" - v "github.com/spf13/viper" + "github.com/spf13/viper" "github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/users" @@ -22,7 +22,7 @@ var usersUpdateCmd = &cobra.Command{ Long: `Updates an existing user. Set the flags for the options you want to change.`, Args: cobra.ExactArgs(1), - RunE: python(func(cmd *cobra.Command, args []string, d *pythonData) error { + RunE: python(func(cmd *cobra.Command, args []string, v *viper.Viper, d *pythonData) error { username, id := parseUsernameOrID(args[0]) password := v.GetString("password") newUsername := v.GetString("username") @@ -55,7 +55,7 @@ options you want to change.`, Sorting: user.Sorting, Commands: user.Commands, } - err = getUserDefaults(&defaults, false) + err = getUserDefaults(v, &defaults, false) if err != nil { return err } diff --git a/cmd/utils.go b/cmd/utils.go index 5d45a4ed..0712b2d2 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -12,10 +12,11 @@ import ( "strings" "github.com/asdine/storm/v3" + homedir "github.com/mitchellh/go-homedir" "github.com/samber/lo" "github.com/spf13/cobra" "github.com/spf13/pflag" - v "github.com/spf13/viper" + "github.com/spf13/viper" yaml "gopkg.in/yaml.v3" "github.com/filebrowser/filebrowser/v2/settings" @@ -25,7 +26,7 @@ import ( const dbPerms = 0640 -func getAndParseMode(param string) (fs.FileMode, error) { +func getAndParseMode(v *viper.Viper, param string) (fs.FileMode, error) { s := v.GetString(param) b, err := strconv.ParseUint(s, 0, 32) if err != nil { @@ -43,7 +44,7 @@ func generateKey() []byte { } type cobraFunc func(cmd *cobra.Command, args []string) error -type pythonFunc func(cmd *cobra.Command, args []string, data *pythonData) error +type pythonFunc func(cmd *cobra.Command, args []string, v *viper.Viper, data *pythonData) error type pythonConfig struct { noDB bool @@ -91,14 +92,60 @@ func generateEnvKeyReplacements(cmd *cobra.Command) []string { return replacements } +func initViper(cmd *cobra.Command) (*viper.Viper, error) { + v := viper.New() + + // Get config file from flag + cfgFile, err := cmd.Flags().GetString("config") + if err != nil { + return nil, err + } + + // Configuration file + if cfgFile == "" { + home, err := homedir.Dir() + if err != nil { + return nil, err + } + v.AddConfigPath(".") + v.AddConfigPath(home) + v.AddConfigPath("/etc/filebrowser/") + v.SetConfigName(".filebrowser") + } else { + v.SetConfigFile(cfgFile) + } + + // Environment variables + v.SetEnvPrefix("FB") + v.AutomaticEnv() + v.SetEnvKeyReplacer(strings.NewReplacer(generateEnvKeyReplacements(cmd)...)) + + // Bind the flags + err = v.BindPFlags(cmd.Flags()) + if err != nil { + return nil, err + } + + // Read in configuration + if err := v.ReadInConfig(); err != nil { + if errors.Is(err, viper.ConfigParseError{}) { + return nil, err + } + + log.Println("No config file used") + } else { + log.Printf("Using config file: %s", v.ConfigFileUsed()) + } + + // Return Viper + return v, nil +} + func python(fn pythonFunc, cfg pythonConfig) cobraFunc { return func(cmd *cobra.Command, args []string) error { - v.SetEnvKeyReplacer(strings.NewReplacer(generateEnvKeyReplacements(cmd)...)) - - // Bind the flags - err := v.BindPFlags(cmd.Flags()) + v, err := initViper(cmd) if err != nil { - panic(err) + return err } data := &pythonData{hadDB: true} @@ -131,7 +178,7 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc { if err != nil { return err } - return fn(cmd, args, data) + return fn(cmd, args, v, data) } }