feat: fully snake case environment variables
This commit is contained in:
parent
5479e5465b
commit
2f12539038
35
cmd/cmd_test.go
Normal file
35
cmd/cmd_test.go
Normal file
@ -0,0 +1,35 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// TestEnvCollisions ensures that there are no collisions in the produced environment
|
||||
// variable names for all commands and their flags.
|
||||
func TestEnvCollisions(t *testing.T) {
|
||||
testEnvCollisions(t, rootCmd)
|
||||
}
|
||||
|
||||
func testEnvCollisions(t *testing.T, cmd *cobra.Command) {
|
||||
for _, cmd := range cmd.Commands() {
|
||||
testEnvCollisions(t, cmd)
|
||||
}
|
||||
|
||||
replacements := generateEnvKeyReplacements(cmd)
|
||||
envVariables := []string{}
|
||||
|
||||
for i := range replacements {
|
||||
if i%2 != 0 {
|
||||
envVariables = append(envVariables, replacements[i])
|
||||
}
|
||||
}
|
||||
|
||||
duplicates := lo.FindDuplicates(envVariables)
|
||||
|
||||
if len(duplicates) > 0 {
|
||||
t.Errorf("Found duplicate environment variable keys for command %q: %v", cmd.Name(), duplicates)
|
||||
}
|
||||
}
|
||||
@ -32,9 +32,9 @@ func addConfigFlags(flags *pflag.FlagSet) {
|
||||
addServerFlags(flags)
|
||||
addUserFlags(flags)
|
||||
flags.BoolP("signup", "s", false, "allow users to signup")
|
||||
flags.Bool("hide-login-button", false, "hide login button from public pages")
|
||||
flags.Bool("create-user-dir", false, "generate user's home directory automatically")
|
||||
flags.Uint("minimum-password-length", settings.DefaultMinimumPasswordLength, "minimum password length for new users")
|
||||
flags.Bool("hideLoginButton", false, "hide login button from public pages")
|
||||
flags.Bool("createUserDir", false, "generate user's home directory automatically")
|
||||
flags.Uint("minimumPasswordLength", settings.DefaultMinimumPasswordLength, "minimum password length for new users")
|
||||
flags.String("shell", "", "shell command to which other commands should be appended")
|
||||
|
||||
flags.String("auth.method", string(auth.MethodJSONAuth), "authentication type")
|
||||
@ -53,8 +53,8 @@ func addConfigFlags(flags *pflag.FlagSet) {
|
||||
flags.Bool("branding.disableUsedPercentage", false, "disable used disk percentage graph")
|
||||
// NB: these are string so they can be presented as octal in the help text
|
||||
// as that's the conventional representation for modes in Unix.
|
||||
flags.String("file-mode", fmt.Sprintf("%O", settings.DefaultFileMode), "Mode bits that new files are created with")
|
||||
flags.String("dir-mode", fmt.Sprintf("%O", settings.DefaultDirMode), "Mode bits that new directories are created with")
|
||||
flags.String("fileMode", fmt.Sprintf("%O", settings.DefaultFileMode), "Mode bits that new files 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) {
|
||||
|
||||
@ -25,12 +25,11 @@ override the options.`,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error {
|
||||
defaults := settings.UserDefaults{}
|
||||
flags := cmd.Flags()
|
||||
err := getUserDefaults(&defaults, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authMethod, auther, err := getAuthentication(flags)
|
||||
authMethod, auther, err := getAuthentication()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -38,9 +37,9 @@ override the options.`,
|
||||
s := &settings.Settings{
|
||||
Key: generateKey(),
|
||||
Signup: v.GetBool("signup"),
|
||||
HideLoginButton: v.GetBool("hide-login-button"),
|
||||
CreateUserDir: v.GetBool("create-user-dir"),
|
||||
MinimumPasswordLength: v.GetUint("minimum-password-length"),
|
||||
HideLoginButton: v.GetBool("hideloginbutton"),
|
||||
CreateUserDir: v.GetBool("createuserdir"),
|
||||
MinimumPasswordLength: v.GetUint("minimumpasswordlength"),
|
||||
Shell: convertCmdStrToCmdArray(v.GetString("shell")),
|
||||
AuthMethod: authMethod,
|
||||
Defaults: defaults,
|
||||
@ -53,12 +52,12 @@ override the options.`,
|
||||
},
|
||||
}
|
||||
|
||||
s.FileMode, err = getAndParseMode("file-mode")
|
||||
s.FileMode, err = getAndParseMode("filemode")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.DirMode, err = getAndParseMode("dir-mode")
|
||||
s.DirMode, err = getAndParseMode("dirmode")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@ var configSetCmd = &cobra.Command{
|
||||
you want to change. Other options will remain unchanged.`,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: python(func(cmd *cobra.Command, _ []string, d *pythonData) error {
|
||||
flags := cmd.Flags()
|
||||
set, err := d.store.Settings.Get()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -52,7 +51,7 @@ you want to change. Other options will remain unchanged.`,
|
||||
ser.Port = v.GetString(key)
|
||||
case "log":
|
||||
ser.Log = v.GetString(key)
|
||||
case "hide-login-button":
|
||||
case "hideloginbutton":
|
||||
set.HideLoginButton = v.GetBool(key)
|
||||
case "signup":
|
||||
set.Signup = v.GetBool(key)
|
||||
@ -62,9 +61,9 @@ you want to change. Other options will remain unchanged.`,
|
||||
var shell string
|
||||
shell = v.GetString(key)
|
||||
set.Shell = convertCmdStrToCmdArray(shell)
|
||||
case "create-user-dir":
|
||||
case "createuserdir":
|
||||
set.CreateUserDir = v.GetBool(key)
|
||||
case "minimum-password-length":
|
||||
case "minimumpasswordlength":
|
||||
set.MinimumPasswordLength = v.GetUint(key)
|
||||
case "branding.name":
|
||||
set.Branding.Name = v.GetString(key)
|
||||
@ -78,9 +77,9 @@ you want to change. Other options will remain unchanged.`,
|
||||
set.Branding.DisableUsedPercentage = v.GetBool(key)
|
||||
case "branding.files":
|
||||
set.Branding.Files = v.GetString(key)
|
||||
case "file-mode":
|
||||
case "filemode":
|
||||
set.FileMode, err = getAndParseMode(key)
|
||||
case "dir-mode":
|
||||
case "dirmode":
|
||||
set.DirMode, err = getAndParseMode(key)
|
||||
}
|
||||
|
||||
|
||||
71
cmd/root.go
71
cmd/root.go
@ -13,7 +13,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@ -37,8 +36,33 @@ import (
|
||||
|
||||
var (
|
||||
cfgFile string
|
||||
|
||||
flatNamesMigrations = map[string]string{
|
||||
"file-mode": "fileMode",
|
||||
"dir-mode": "dirMode",
|
||||
"hide-login-button": "hideLoginButton",
|
||||
"create-user-dir": "createUserDir",
|
||||
"minimum-password-length": "minimumPasswordLength",
|
||||
"socket-perm": "socketPerm",
|
||||
"disable-thumbnails": "disableThumbnails",
|
||||
"disable-preview-resize": "disablePreviewResize",
|
||||
"disable-exec": "disableExec",
|
||||
"disable-type-detection-by-header": "disableTypeDetectionByHeader",
|
||||
"img-processors": "imageProcessors",
|
||||
"cache-dir": "cacheDir",
|
||||
"token-expiration-time": "tokenExpirationTime",
|
||||
"baseurl": "baseURL",
|
||||
}
|
||||
)
|
||||
|
||||
func migrateFlagNames(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
if newName, ok := flatNamesMigrations[name]; ok {
|
||||
name = newName
|
||||
}
|
||||
|
||||
return pflag.NormalizedName(name)
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.SilenceUsage = true
|
||||
@ -56,6 +80,8 @@ func init() {
|
||||
flags.String("password", "", "hashed password for the first user when using quick config")
|
||||
|
||||
addServerFlags(flags)
|
||||
|
||||
rootCmd.SetGlobalNormalizationFunc(migrateFlagNames)
|
||||
}
|
||||
|
||||
func addServerFlags(flags *pflag.FlagSet) {
|
||||
@ -66,15 +92,15 @@ func addServerFlags(flags *pflag.FlagSet) {
|
||||
flags.StringP("key", "k", "", "tls key")
|
||||
flags.StringP("root", "r", ".", "root to prepend to relative paths")
|
||||
flags.String("socket", "", "socket to listen to (cannot be used with address, port, cert nor key flags)")
|
||||
flags.Uint32("socket-perm", 0666, "unix socket file permissions")
|
||||
flags.StringP("baseurl", "b", "", "base url")
|
||||
flags.String("cache-dir", "", "file cache directory (disabled if empty)")
|
||||
flags.String("token-expiration-time", "2h", "user session timeout")
|
||||
flags.Int("img-processors", 4, "image processors count")
|
||||
flags.Bool("disable-thumbnails", false, "disable image thumbnails")
|
||||
flags.Bool("disable-preview-resize", false, "disable resize of image previews")
|
||||
flags.Bool("disable-exec", true, "disables Command Runner feature")
|
||||
flags.Bool("disable-type-detection-by-header", false, "disables type detection by reading file headers")
|
||||
flags.Uint32("socketPerm", 0666, "unix socket file permissions")
|
||||
flags.StringP("baseURL", "b", "", "base url")
|
||||
flags.String("cacheDir", "", "file cache directory (disabled if empty)")
|
||||
flags.String("tokenExpirationTime", "2h", "user session timeout")
|
||||
flags.Int("imageProcessors", 4, "image processors count")
|
||||
flags.Bool("disableThumbnails", false, "disable image thumbnails")
|
||||
flags.Bool("disablePreviewResize", false, "disable resize of image previews")
|
||||
flags.Bool("disableExec", true, "disables Command Runner feature")
|
||||
flags.Bool("disableTypeDetectionByHeader", false, "disables type detection by reading file headers")
|
||||
}
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
@ -89,9 +115,8 @@ it. Don't worry: you don't need to setup a separate database server.
|
||||
We're using Bolt DB which is a single file database and all managed
|
||||
by ourselves.
|
||||
|
||||
For this specific command, all the flags you have available (except
|
||||
"config" for the configuration file), can be given either through
|
||||
environment variables or configuration files.
|
||||
All the flags you have available (except "config" for the configuration file),
|
||||
can be given either through environment variables or configuration files.
|
||||
|
||||
If you don't set "config", it will look for a configuration file called
|
||||
.filebrowser.{json, toml, yaml, yml} in the following directories:
|
||||
@ -126,17 +151,14 @@ user created with the credentials from options "username" and "password".`,
|
||||
}
|
||||
|
||||
// build img service
|
||||
workersCount, err := cmd.Flags().GetInt("img-processors")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workersCount := v.GetInt("imageprocessors")
|
||||
if workersCount < 1 {
|
||||
return errors.New("image resize workers count could not be < 1")
|
||||
}
|
||||
imgSvc := img.New(workersCount)
|
||||
|
||||
var fileCache diskcache.Interface = diskcache.NewNoOp()
|
||||
cacheDir, err := cmd.Flags().GetString("cache-dir")
|
||||
cacheDir, err := cmd.Flags().GetString("cachedir")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -169,7 +191,7 @@ user created with the credentials from options "username" and "password".`,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
socketPerm, err := cmd.Flags().GetUint32("socket-perm")
|
||||
socketPerm, err := cmd.Flags().GetUint32("socketperm")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -311,16 +333,16 @@ func getRunParams(st *storage.Storage) (*settings.Server, error) {
|
||||
server.Socket = ""
|
||||
}
|
||||
|
||||
disableThumbnails := v.GetBool("disable-thumbnails")
|
||||
disableThumbnails := v.GetBool("disablethumbnails")
|
||||
server.EnableThumbnails = !disableThumbnails
|
||||
|
||||
disablePreviewResize := v.GetBool("disable-preview-resize")
|
||||
disablePreviewResize := v.GetBool("disablepreviewresize")
|
||||
server.ResizePreview = !disablePreviewResize
|
||||
|
||||
disableTypeDetectionByHeader := v.GetBool("disable-type-detection-by-header")
|
||||
disableTypeDetectionByHeader := v.GetBool("disabletypedetectionbyheader")
|
||||
server.TypeDetectionByHeader = !disableTypeDetectionByHeader
|
||||
|
||||
disableExec := v.GetBool("disable-exec")
|
||||
disableExec := v.GetBool("disableexec")
|
||||
server.EnableExec = !disableExec
|
||||
|
||||
if server.EnableExec {
|
||||
@ -330,7 +352,7 @@ func getRunParams(st *storage.Storage) (*settings.Server, error) {
|
||||
log.Println("WARNING: read https://github.com/filebrowser/filebrowser/issues/5199")
|
||||
}
|
||||
|
||||
if val, set := getStringParamB("token-expiration-time"); set {
|
||||
if val, set := getStringParamB("tokenexpirationtime"); set {
|
||||
server.TokenExpirationTime = val
|
||||
}
|
||||
|
||||
@ -479,7 +501,6 @@ func initConfig() {
|
||||
|
||||
v.SetEnvPrefix("FB")
|
||||
v.AutomaticEnv()
|
||||
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
|
||||
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
var configParseError v.ConfigParseError
|
||||
|
||||
20
cmd/utils.go
20
cmd/utils.go
@ -12,7 +12,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/asdine/storm/v3"
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
v "github.com/spf13/viper"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
|
||||
@ -74,8 +76,26 @@ func dbExists(path string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Generate the replacements for all environment variables. This allows to
|
||||
// use FB_BRANDING_DISABLE_EXTERNAL environment variables, even when the
|
||||
// option name is branding.disableexternal.
|
||||
func generateEnvKeyReplacements(cmd *cobra.Command) []string {
|
||||
replacements := []string{}
|
||||
|
||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
||||
oldName := strings.ToUpper(f.Name)
|
||||
newName := strings.ToUpper(lo.SnakeCase(f.Name))
|
||||
replacements = append(replacements, oldName, newName)
|
||||
})
|
||||
|
||||
return replacements
|
||||
}
|
||||
|
||||
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())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
||||
1
go.mod
1
go.mod
@ -16,6 +16,7 @@ require (
|
||||
github.com/marusama/semaphore/v2 v2.5.0
|
||||
github.com/mholt/archives v0.1.5
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/samber/lo v1.52.0
|
||||
github.com/shirou/gopsutil/v4 v4.25.10
|
||||
github.com/spf13/afero v1.15.0
|
||||
github.com/spf13/cobra v1.10.1
|
||||
|
||||
2
go.sum
2
go.sum
@ -200,6 +200,8 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
|
||||
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
||||
github.com/shirou/gopsutil/v4 v4.25.10 h1:at8lk/5T1OgtuCp+AwrDofFRjnvosn0nkN2OLQ6g8tA=
|
||||
github.com/shirou/gopsutil/v4 v4.25.10/go.mod h1:+kSwyC8DRUD9XXEHCAFjK+0nuArFJM0lva+StQAcskM=
|
||||
github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik=
|
||||
|
||||
@ -132,7 +132,7 @@ Or you can use the web interface to manage them via **Settings** → **Global Se
|
||||
>
|
||||
> The **command execution** functionality has been disabled for all existent and new installations by default from version v2.33.8 and onwards, due to continuous and known security vulnerabilities. You should only use this feature if you are aware of all of the security risks involved. For more up to date information, consult issue [#5199](https://github.com/filebrowser/filebrowser/issues/5199).
|
||||
|
||||
Within File Browser you can toggle the shell (`< >` icon at the top right) and this will open a shell command window at the bottom of the screen. This functionality can be turned on using the environment variable `FB_DISABLE_EXEC=false` or the flag `--disable-exec=false`.
|
||||
Within File Browser you can toggle the shell (`< >` icon at the top right) and this will open a shell command window at the bottom of the screen. This functionality can be turned on using the environment variable `FB_DISABLE_EXEC=false` or the flag `--disableExec=false`.
|
||||
|
||||
By default no commands are available as the command list is empty. To enable commands these need to either be done on a per-user basis (including for the Admin user).
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user