refactor: do not use global viper

This commit is contained in:
Henrique Dias 2025-11-16 08:25:48 +01:00
parent c25a5e9f1d
commit 7de4d83ab1
No known key found for this signature in database
22 changed files with 139 additions and 116 deletions

View File

@ -4,6 +4,7 @@ import (
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
func init() { func init() {
@ -15,7 +16,7 @@ var cmdsAddCmd = &cobra.Command{
Short: "Add a command to run on a specific event", Short: "Add a command to run on a specific event",
Long: `Add a command to run on a specific event.`, Long: `Add a command to run on a specific event.`,
Args: cobra.MinimumNArgs(2), 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() s, err := d.store.Settings.Get()
if err != nil { if err != nil {
return err return err

View File

@ -2,7 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
) )
func init() { func init() {
@ -15,7 +15,7 @@ var cmdsLsCmd = &cobra.Command{
Short: "List all commands for each event", Short: "List all commands for each event",
Long: `List all commands for each event.`, Long: `List all commands for each event.`,
Args: cobra.NoArgs, 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() s, err := d.store.Settings.Get()
if err != nil { if err != nil {
return err return err

View File

@ -4,6 +4,7 @@ import (
"strconv" "strconv"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
func init() { func init() {
@ -35,7 +36,7 @@ including 'index_end'.`,
return nil 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() s, err := d.store.Settings.Get()
if err != nil { if err != nil {
return err return err

View File

@ -10,7 +10,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/auth"
"github.com/filebrowser/filebrowser/v2/errors" "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") 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") methodStr := v.GetString("auth.method")
method := settings.AuthMethod(methodStr) method := settings.AuthMethod(methodStr)
@ -85,7 +85,7 @@ func getAuthMethod(defaults ...interface{}) (settings.AuthMethod, map[string]int
return method, defaultAuther, nil 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") header := v.GetString("auth.header")
if header == "" { if header == "" {
header = defaultAuther["header"].(string) header = defaultAuther["header"].(string)
@ -102,7 +102,7 @@ func getNoAuth() auth.Auther {
return &auth.NoAuth{} 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{} jsonAuth := &auth.JSONAuth{}
host := v.GetString("recaptcha.host") host := v.GetString("recaptcha.host")
key := v.GetString("recaptcha.key") key := v.GetString("recaptcha.key")
@ -130,7 +130,7 @@ func getJSONAuth(defaultAuther map[string]interface{}) (auth.Auther, error) {
return jsonAuth, nil 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") command := v.GetString("auth.command")
if command == "" { if command == "" {
command = defaultAuther["command"].(string) command = defaultAuther["command"].(string)
@ -143,8 +143,8 @@ func getHookAuth(defaultAuther map[string]interface{}) (auth.Auther, error) {
return &auth.HookAuth{Command: command}, nil return &auth.HookAuth{Command: command}, nil
} }
func getAuthentication(defaults ...interface{}) (settings.AuthMethod, auth.Auther, error) { func getAuthentication(v *viper.Viper, defaults ...interface{}) (settings.AuthMethod, auth.Auther, error) {
method, defaultAuther, err := getAuthMethod(defaults...) method, defaultAuther, err := getAuthMethod(v, defaults...)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
@ -152,13 +152,13 @@ func getAuthentication(defaults ...interface{}) (settings.AuthMethod, auth.Authe
var auther auth.Auther var auther auth.Auther
switch method { switch method {
case auth.MethodProxyAuth: case auth.MethodProxyAuth:
auther, err = getProxyAuth(defaultAuther) auther, err = getProxyAuth(v, defaultAuther)
case auth.MethodNoAuth: case auth.MethodNoAuth:
auther = getNoAuth() auther = getNoAuth()
case auth.MethodJSONAuth: case auth.MethodJSONAuth:
auther, err = getJSONAuth(defaultAuther) auther, err = getJSONAuth(v, defaultAuther)
case auth.MethodHookAuth: case auth.MethodHookAuth:
auther, err = getHookAuth(defaultAuther) auther, err = getHookAuth(v, defaultAuther)
default: default:
return "", nil, errors.ErrInvalidAuthMethod return "", nil, errors.ErrInvalidAuthMethod
} }

View File

@ -2,6 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
func init() { func init() {
@ -13,7 +14,7 @@ var configCatCmd = &cobra.Command{
Short: "Prints the configuration", Short: "Prints the configuration",
Long: `Prints the configuration.`, Long: `Prints the configuration.`,
Args: cobra.NoArgs, 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() set, err := d.store.Settings.Get()
if err != nil { if err != nil {
return err return err

View File

@ -2,6 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
func init() { func init() {
@ -15,7 +16,7 @@ var configExportCmd = &cobra.Command{
json or yaml file. This exported configuration can be changed, json or yaml file. This exported configuration can be changed,
and imported again with 'config import' command.`, and imported again with 'config import' command.`,
Args: jsonYamlArg, 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() settings, err := d.store.Settings.Get()
if err != nil { if err != nil {
return err return err

View File

@ -7,6 +7,7 @@ import (
"reflect" "reflect"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/auth"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
@ -34,7 +35,7 @@ database.
The path must be for a json or yaml file.`, The path must be for a json or yaml file.`,
Args: jsonYamlArg, 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 key []byte
var err error var err error
if d.hadDB { if d.hadDB {

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/settings" "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 to the defaults when creating new users and you don't
override the options.`, override the options.`,
Args: cobra.NoArgs, 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{} defaults := settings.UserDefaults{}
err := getUserDefaults(&defaults, true) err := getUserDefaults(v, &defaults, true)
if err != nil { if err != nil {
return err return err
} }
authMethod, auther, err := getAuthentication() authMethod, auther, err := getAuthentication(v)
if err != nil { if err != nil {
return err return err
} }
@ -52,12 +52,12 @@ override the options.`,
}, },
} }
s.FileMode, err = getAndParseMode("filemode") s.FileMode, err = getAndParseMode(v, "filemode")
if err != nil { if err != nil {
return err return err
} }
s.DirMode, err = getAndParseMode("dirmode") s.DirMode, err = getAndParseMode(v, "dirmode")
if err != nil { if err != nil {
return err return err
} }

View File

@ -2,7 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
) )
func init() { func init() {
@ -16,7 +16,7 @@ var configSetCmd = &cobra.Command{
Long: `Updates the configuration. Set the flags for the options Long: `Updates the configuration. Set the flags for the options
you want to change. Other options will remain unchanged.`, you want to change. Other options will remain unchanged.`,
Args: cobra.NoArgs, 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() set, err := d.store.Settings.Get()
if err != nil { if err != nil {
return err return err
@ -78,9 +78,9 @@ you want to change. Other options will remain unchanged.`,
case "branding.files": case "branding.files":
set.Branding.Files = v.GetString(key) set.Branding.Files = v.GetString(key)
case "filemode": case "filemode":
set.FileMode, err = getAndParseMode(key) set.FileMode, err = getAndParseMode(v, key)
case "dirmode": case "dirmode":
set.DirMode, err = getAndParseMode(key) set.DirMode, err = getAndParseMode(v, key)
} }
if err != nil { 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 { if err != nil {
return err 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 // 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 { if err != nil {
return err return err
} }

View File

@ -16,11 +16,10 @@ import (
"syscall" "syscall"
"time" "time"
homedir "github.com/mitchellh/go-homedir"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
v "github.com/spf13/viper" "github.com/spf13/viper"
lumberjack "gopkg.in/natefinch/lumberjack.v2" lumberjack "gopkg.in/natefinch/lumberjack.v2"
"github.com/filebrowser/filebrowser/v2/auth" "github.com/filebrowser/filebrowser/v2/auth"
@ -35,8 +34,6 @@ import (
) )
var ( var (
cfgFile string
flagNamesMigrations = map[string]string{ flagNamesMigrations = map[string]string{
"file-mode": "fileMode", "file-mode": "fileMode",
"dir-mode": "dirMode", "dir-mode": "dirMode",
@ -65,7 +62,6 @@ func migrateFlagNames(f *pflag.FlagSet, name string) pflag.NormalizedName {
} }
func init() { func init() {
cobra.OnInitialize(initConfig)
rootCmd.SilenceUsage = true rootCmd.SilenceUsage = true
cobra.MousetrapHelpText = "" cobra.MousetrapHelpText = ""
@ -74,7 +70,7 @@ func init() {
flags := rootCmd.Flags() flags := rootCmd.Flags()
persistent := rootCmd.PersistentFlags() 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") persistent.StringP("database", "d", "./filebrowser.db", "database path")
flags.Bool("noauth", false, "use the noauth auther when using quick setup") 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") 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 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 the quick setup mode and a new database will be bootstrapped and a new
user created with the credentials from options "username" and "password".`, user created with the credentials from options "username" and "password".`,
RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error { RunE: python(func(cmd *cobra.Command, _ []string, v *viper.Viper, d *pythonData) error {
log.Println(cfgFile)
if !d.hadDB { if !d.hadDB {
err := quickSetup(*d) err := quickSetup(v, *d)
if err != nil { if err != nil {
return err return err
} }
@ -167,7 +161,7 @@ user created with the credentials from options "username" and "password".`,
fileCache = diskcache.New(afero.NewOsFs(), cacheDir) fileCache = diskcache.New(afero.NewOsFs(), cacheDir)
} }
server, err := getRunParams(d.store) server, err := getRunParams(v, d.store)
if err != nil { if err != nil {
return err return err
} }
@ -273,48 +267,48 @@ user created with the credentials from options "username" and "password".`,
}, pythonConfig{allowNoDB: true}), }, 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() server, err := st.Settings.GetServer()
if err != nil { if err != nil {
return nil, err return nil, err
} }
if val, set := getStringParamB("root"); set { if val, set := getStringParamB(v, "root"); set {
server.Root = val server.Root = val
} }
if val, set := getStringParamB("baseurl"); set { if val, set := getStringParamB(v, "baseurl"); set {
server.BaseURL = val server.BaseURL = val
} }
if val, set := getStringParamB("log"); set { if val, set := getStringParamB(v, "log"); set {
server.Log = val server.Log = val
} }
isSocketSet := false isSocketSet := false
isAddrSet := false isAddrSet := false
if val, set := getStringParamB("address"); set { if val, set := getStringParamB(v, "address"); set {
server.Address = val server.Address = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getStringParamB("port"); set { if val, set := getStringParamB(v, "port"); set {
server.Port = val server.Port = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getStringParamB("key"); set { if val, set := getStringParamB(v, "key"); set {
server.TLSKey = val server.TLSKey = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getStringParamB("cert"); set { if val, set := getStringParamB(v, "cert"); set {
server.TLSCert = val server.TLSCert = val
isAddrSet = isAddrSet || set isAddrSet = isAddrSet || set
} }
if val, set := getStringParamB("socket"); set { if val, set := getStringParamB(v, "socket"); set {
server.Socket = val server.Socket = val
isSocketSet = isSocketSet || set 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") 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 server.TokenExpirationTime = val
} }
return server, nil 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) 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") log.Println("Performing quick setup")
set := &settings.Settings{ set := &settings.Settings{
@ -414,7 +408,7 @@ func quickSetup(d pythonData) error {
} }
var err error var err error
if _, noauth := getStringParamB("noauth"); noauth { if _, noauth := getStringParamB(v, "noauth"); noauth {
set.AuthMethod = auth.MethodNoAuth set.AuthMethod = auth.MethodNoAuth
err = d.store.Auth.Save(&auth.NoAuth{}) err = d.store.Auth.Save(&auth.NoAuth{})
} else { } else {
@ -479,31 +473,3 @@ func quickSetup(d pythonData) error {
return d.store.Users.Save(user) 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()
}
}

View File

@ -4,6 +4,7 @@ import (
"strconv" "strconv"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users" "github.com/filebrowser/filebrowser/v2/users"
@ -40,7 +41,7 @@ including 'index_end'.`,
return nil 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]) i, err := strconv.Atoi(args[0])
if err != nil { if err != nil {
return err return err
@ -63,6 +64,6 @@ including 'index_end'.`,
return d.store.Settings.Save(s) return d.store.Settings.Save(s)
} }
return runRules(d.store, cmd, user, global) return runRules(d.store, cmd, v, user, global)
}, pythonConfig{}), }, pythonConfig{}),
} }

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/rules" "github.com/filebrowser/filebrowser/v2/rules"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
@ -29,8 +29,8 @@ rules.`,
Args: cobra.NoArgs, Args: cobra.NoArgs,
} }
func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User) error, globalFn func(*settings.Settings) error) error { 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() id, err := getUserIdentifier(v)
if err != nil { if err != nil {
return err return err
} }
@ -68,7 +68,7 @@ func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User)
return nil return nil
} }
func getUserIdentifier() (interface{}, error) { func getUserIdentifier(v *viper.Viper) (interface{}, error) {
id := v.GetUint("id") id := v.GetUint("id")
username := v.GetString("username") username := v.GetString("username")

View File

@ -4,7 +4,7 @@ import (
"regexp" "regexp"
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/rules" "github.com/filebrowser/filebrowser/v2/rules"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
@ -22,7 +22,7 @@ var rulesAddCmd = &cobra.Command{
Short: "Add a global rule or user rule", Short: "Add a global rule or user rule",
Long: `Add a global rule or user rule.`, Long: `Add a global rule or user rule.`,
Args: cobra.ExactArgs(1), 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") allow := v.GetBool("allow")
regex := v.GetBool("regex") regex := v.GetBool("regex")
exp := args[0] exp := args[0]
@ -52,6 +52,6 @@ var rulesAddCmd = &cobra.Command{
return d.store.Settings.Save(s) return d.store.Settings.Save(s)
} }
return runRules(d.store, cmd, user, global) return runRules(d.store, cmd, v, user, global)
}, pythonConfig{}), }, pythonConfig{}),
} }

View File

@ -2,6 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
func init() { func init() {
@ -13,7 +14,7 @@ var rulesLsCommand = &cobra.Command{
Short: "List global rules or user specific rules", Short: "List global rules or user specific rules",
Long: `List global rules or user specific rules.`, Long: `List global rules or user specific rules.`,
Args: cobra.NoArgs, 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 {
return runRules(d.store, cmd, nil, nil) return runRules(d.store, cmd, v, nil, nil)
}, pythonConfig{}), }, pythonConfig{}),
} }

View File

@ -9,7 +9,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users" "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") 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") viewModeStr := v.GetString("viewMode")
viewMode := users.ViewMode(viewModeStr) viewMode := users.ViewMode(viewModeStr)
if viewMode != users.ListViewMode && viewMode != users.MosaicViewMode { if viewMode != users.ListViewMode && viewMode != users.MosaicViewMode {
@ -92,7 +92,7 @@ func getAndParseViewMode() (users.ViewMode, error) {
return viewMode, nil 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() keys := v.AllKeys()
for _, key := range keys { for _, key := range keys {
@ -107,7 +107,7 @@ func getUserDefaults(defaults *settings.UserDefaults, all bool) error {
case "locale": case "locale":
defaults.Locale = v.GetString(key) defaults.Locale = v.GetString(key)
case "viewmode": case "viewmode":
defaults.ViewMode, err = getAndParseViewMode() defaults.ViewMode, err = getAndParseViewMode(v)
case "singleclick": case "singleclick":
defaults.SingleClick = v.GetBool(key) defaults.SingleClick = v.GetBool(key)
case "aceeditortheme": case "aceeditortheme":

View File

@ -2,7 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/users" "github.com/filebrowser/filebrowser/v2/users"
) )
@ -17,12 +17,12 @@ var usersAddCmd = &cobra.Command{
Short: "Create a new user", Short: "Create a new user",
Long: `Create a new user and add it to the database.`, Long: `Create a new user and add it to the database.`,
Args: cobra.ExactArgs(2), 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() s, err := d.store.Settings.Get()
if err != nil { if err != nil {
return err return err
} }
err = getUserDefaults(&s.Defaults, false) err = getUserDefaults(v, &s.Defaults, false)
if err != nil { if err != nil {
return err return err
} }

View File

@ -2,6 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
func init() { func init() {
@ -14,7 +15,7 @@ var usersExportCmd = &cobra.Command{
Long: `Export all users to a json or yaml file. Please indicate the Long: `Export all users to a json or yaml file. Please indicate the
path to the file where you want to write the users.`, path to the file where you want to write the users.`,
Args: jsonYamlArg, 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("") list, err := d.store.Users.Gets("")
if err != nil { if err != nil {
return err return err

View File

@ -2,6 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/users" "github.com/filebrowser/filebrowser/v2/users"
) )
@ -26,7 +27,7 @@ var usersLsCmd = &cobra.Command{
RunE: findUsers, 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 ( var (
list []*users.User list []*users.User
user *users.User user *users.User

View File

@ -7,7 +7,7 @@ import (
"strconv" "strconv"
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/users" "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 installation. For that, just don't place their ID on the files
list or set it to 0.`, list or set it to 0.`,
Args: jsonYamlArg, 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]) fd, err := os.Open(args[0])
if err != nil { if err != nil {
return err return err

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper"
) )
func init() { func init() {
@ -15,7 +16,7 @@ var usersRmCmd = &cobra.Command{
Short: "Delete a user by username or id", Short: "Delete a user by username or id",
Long: `Delete a user by username or id`, Long: `Delete a user by username or id`,
Args: cobra.ExactArgs(1), 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]) username, id := parseUsernameOrID(args[0])
var err error var err error

View File

@ -2,7 +2,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
v "github.com/spf13/viper" "github.com/spf13/viper"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users" "github.com/filebrowser/filebrowser/v2/users"
@ -22,7 +22,7 @@ var usersUpdateCmd = &cobra.Command{
Long: `Updates an existing user. Set the flags for the Long: `Updates an existing user. Set the flags for the
options you want to change.`, options you want to change.`,
Args: cobra.ExactArgs(1), 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]) username, id := parseUsernameOrID(args[0])
password := v.GetString("password") password := v.GetString("password")
newUsername := v.GetString("username") newUsername := v.GetString("username")
@ -55,7 +55,7 @@ options you want to change.`,
Sorting: user.Sorting, Sorting: user.Sorting,
Commands: user.Commands, Commands: user.Commands,
} }
err = getUserDefaults(&defaults, false) err = getUserDefaults(v, &defaults, false)
if err != nil { if err != nil {
return err return err
} }

View File

@ -12,10 +12,11 @@ import (
"strings" "strings"
"github.com/asdine/storm/v3" "github.com/asdine/storm/v3"
homedir "github.com/mitchellh/go-homedir"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/pflag" "github.com/spf13/pflag"
v "github.com/spf13/viper" "github.com/spf13/viper"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
"github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/settings"
@ -25,7 +26,7 @@ import (
const dbPerms = 0640 const dbPerms = 0640
func getAndParseMode(param string) (fs.FileMode, error) { func getAndParseMode(v *viper.Viper, param string) (fs.FileMode, error) {
s := v.GetString(param) s := v.GetString(param)
b, err := strconv.ParseUint(s, 0, 32) b, err := strconv.ParseUint(s, 0, 32)
if err != nil { if err != nil {
@ -43,7 +44,7 @@ func generateKey() []byte {
} }
type cobraFunc func(cmd *cobra.Command, args []string) error 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 { type pythonConfig struct {
noDB bool noDB bool
@ -91,14 +92,60 @@ func generateEnvKeyReplacements(cmd *cobra.Command) []string {
return replacements 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 { func python(fn pythonFunc, cfg pythonConfig) cobraFunc {
return func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error {
v.SetEnvKeyReplacer(strings.NewReplacer(generateEnvKeyReplacements(cmd)...)) v, err := initViper(cmd)
// Bind the flags
err := v.BindPFlags(cmd.Flags())
if err != nil { if err != nil {
panic(err) return err
} }
data := &pythonData{hadDB: true} data := &pythonData{hadDB: true}
@ -131,7 +178,7 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc {
if err != nil { if err != nil {
return err return err
} }
return fn(cmd, args, data) return fn(cmd, args, v, data)
} }
} }