diff --git a/.filebrowser.docker.json b/.docker.json similarity index 100% rename from .filebrowser.docker.json rename to .docker.json diff --git a/.goreleaser.yml b/.goreleaser.yml index 12f309a0..6ac6663a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -3,7 +3,7 @@ project_name: filebrowser build: env: - CGO_ENABLED=0 - main: cli/main.go + main: main.go binary: filebrowser goos: - darwin @@ -50,8 +50,9 @@ dockers: goos: linux goarch: amd64 goarm: '' - image: filebrowser/filebrowser + image_templates: + - "filebrowser/filebrowser:latest" + - "filebrowser/filebrowser:{{ .Tag }}" skip_push: true - tag_templates: - - "{{ .Tag }}" - - latest + extra_files: + - .docker.json diff --git a/.travis.yml b/.travis.yml index 2dcefc89..9d73b3bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ jobs: repo: filebrowser/filebrowser branch: master - stage: release - script: ./wizard.sh -r + script: ./wizard.sh -r "$TRAVIS_TAG" if: tag IS present deploy: provider: releases diff --git a/Dockerfile b/Dockerfile index 5409c2d3..b1ded66c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,11 +2,10 @@ FROM scratch COPY --from=filebrowser/dev /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -VOLUME /tmp VOLUME /srv EXPOSE 80 -COPY .filebrowser.docker.json /.filebrowser.json +COPY .docker.json /.filebrowser.json COPY filebrowser /filebrowser ENTRYPOINT [ "/filebrowser" ] diff --git a/auth/none.go b/auth/none.go index f10d065a..a206157f 100644 --- a/auth/none.go +++ b/auth/none.go @@ -15,5 +15,5 @@ type NoAuth struct{} // Auth uses authenticates user 1. func (a NoAuth) Auth(r *http.Request, sto *users.Storage, root string) (*users.User, error) { - return sto.Get(root, 1) + return sto.Get(root, uint(1)) } diff --git a/cmd/cmds.go b/cmd/cmds.go index cf951995..81613d02 100644 --- a/cmd/cmds.go +++ b/cmd/cmds.go @@ -11,10 +11,11 @@ func init() { } var cmdsCmd = &cobra.Command{ - Use: "cmds", - Short: "Command runner management utility", - Long: `Command runner management utility.`, - Args: cobra.NoArgs, + Use: "cmds", + Version: rootCmd.Version, + Short: "Command runner management utility", + Long: `Command runner management utility.`, + Args: cobra.NoArgs, } func printEvents(m map[string][]string) { diff --git a/cmd/cmds_rm.go b/cmd/cmds_rm.go index e0a32d39..2a863213 100644 --- a/cmd/cmds_rm.go +++ b/cmd/cmds_rm.go @@ -13,7 +13,15 @@ func init() { var cmdsRmCmd = &cobra.Command{ Use: "rm [index_end]", Short: "Removes a command from an event hooker", - Long: `Removes a command from an event hooker.`, + Long: `Removes a command from an event hooker. The provided index +is the same that's printed when you run 'cmds ls'. Note +that after each removal/addition, the index of the +commands change. So be careful when removing them after each +other. + +You can also specify an optional parameter (index_end) so +you can remove all commands from 'index' to 'index_end', +including 'index_end'.`, Args: func(cmd *cobra.Command, args []string) error { if err := cobra.RangeArgs(2, 3)(cmd, args); err != nil { return err diff --git a/cmd/config.go b/cmd/config.go index db97cf10..755b7139 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -20,10 +20,11 @@ func init() { } var configCmd = &cobra.Command{ - Use: "config", - Short: "Configuration management utility", - Long: `Configuration management utility.`, - Args: cobra.NoArgs, + Use: "config", + Version: rootCmd.Version, + Short: "Configuration management utility", + Long: `Configuration management utility.`, + Args: cobra.NoArgs, } func addConfigFlags(flags *pflag.FlagSet) { diff --git a/cmd/config_export.go b/cmd/config_export.go index 80574b29..9d6450f9 100644 --- a/cmd/config_export.go +++ b/cmd/config_export.go @@ -9,9 +9,12 @@ func init() { } var configExportCmd = &cobra.Command{ - Use: "export ", - Short: "Export the configuration to a file.", - Args: jsonYamlArg, + Use: "export ", + Short: "Export the configuration to a file", + Long: `Export the configuration to a file. The path must be for a +json or yaml file. This exported configuration can be changed, +and imported again with 'config import' command.`, + Args: jsonYamlArg, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { settings, err := d.store.Settings.Get() checkErr(err) diff --git a/cmd/config_import.go b/cmd/config_import.go index 3463c2f8..7182da9a 100644 --- a/cmd/config_import.go +++ b/cmd/config_import.go @@ -22,12 +22,16 @@ type settingsFile struct { } var configImportCmd = &cobra.Command{ - Use: "import ", - Short: `Import a configuration file. This will replace all the existing + Use: "import ", + Short: "Import a configuration file", + Long: `Import a configuration file. This will replace all the existing configuration. Can be used with or without unexisting databases. + If used with a nonexisting database, a key will be generated automatically. Otherwise the key will be kept the same as in the -database.`, +database. + +The path must be for a json or yaml file.`, Args: jsonYamlArg, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { var key []byte diff --git a/cmd/config_init.go b/cmd/config_init.go index 86098376..f4794cb6 100644 --- a/cmd/config_init.go +++ b/cmd/config_init.go @@ -18,7 +18,7 @@ var configInitCmd = &cobra.Command{ Short: "Initialize a new database", Long: `Initialize a new database to use with File Browser. All of this options can be changed in the future with the command -"filebrowser config set". The user related flags apply +'filebrowser config set'. The user related flags apply to the defaults when creating new users and you don't override the options.`, Args: cobra.NoArgs, diff --git a/cmd/config_set.go b/cmd/config_set.go index 7ccf7e43..f725fd45 100644 --- a/cmd/config_set.go +++ b/cmd/config_set.go @@ -17,7 +17,7 @@ var configSetCmd = &cobra.Command{ Use: "set", Short: "Updates the configuration", Long: `Updates the configuration. Set the flags for the options -you want to change.`, +you want to change. Other options will remain unchanged.`, Args: cobra.NoArgs, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { flags := cmd.Flags() diff --git a/cmd/docs.go b/cmd/docs.go index 49f5f3f7..2e199b29 100644 --- a/cmd/docs.go +++ b/cmd/docs.go @@ -9,8 +9,8 @@ import ( "sort" "strings" - "github.com/spf13/pflag" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) func init() { diff --git a/cmd/hash.go b/cmd/hash.go index e92203e4..b85144aa 100644 --- a/cmd/hash.go +++ b/cmd/hash.go @@ -12,10 +12,11 @@ func init() { } var hashCmd = &cobra.Command{ - Use: "hash ", - Short: "Hashes a password", - Long: `Hashes a password using bcrypt algorithm.`, - Args: cobra.ExactArgs(1), + Use: "hash ", + Version: rootCmd.Version, + Short: "Hashes a password", + Long: `Hashes a password using bcrypt algorithm.`, + Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { pwd, err := users.HashPwd(args[0]) checkErr(err) diff --git a/cmd/root.go b/cmd/root.go index b662e2a2..0c71df09 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,7 +2,6 @@ package cmd import ( "crypto/tls" - "errors" "io/ioutil" "log" "net" @@ -16,7 +15,8 @@ import ( "github.com/filebrowser/filebrowser/v2/settings" "github.com/filebrowser/filebrowser/v2/storage" "github.com/filebrowser/filebrowser/v2/users" - "github.com/mitchellh/go-homedir" + "github.com/filebrowser/filebrowser/v2/version" + homedir "github.com/mitchellh/go-homedir" "github.com/spf13/cobra" "github.com/spf13/pflag" v "github.com/spf13/viper" @@ -29,11 +29,15 @@ var ( func init() { cobra.OnInitialize(initConfig) + + rootCmd.SetVersionTemplate("File Browser version {{printf \"%s\" .Version}}\n") + flags := rootCmd.Flags() persistent := rootCmd.PersistentFlags() persistent.StringVarP(&cfgFile, "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") flags.String("password", "", "hashed password for the first user when using quick config (default \"admin\")") @@ -50,49 +54,14 @@ func addServerFlags(flags *pflag.FlagSet) { flags.StringP("baseurl", "b", "", "base url") } -// NOTE: we could simply bind the flags to viper and use IsSet. -// Although there is a bug on Viper that always returns true on IsSet -// if a flag is binded. Our alternative way is to manually check -// the flag and then the value from env/config/gotten by viper. -// https://github.com/spf13/viper/pull/331 -func getStringViperFlag(flags *pflag.FlagSet, key string) (string, bool) { - value := "" - set := false - - // If set on Flags, use it. - flags.Visit(func(flag *pflag.Flag) { - if flag.Name == key { - set = true - value, _ = flags.GetString(key) - } - }) - - if set { - return value, set - } - - // If set through viper (env, config), return it. - if v.IsSet(key) { - return v.GetString(key), true - } - - // Otherwise use default value on flags. - value, _ = flags.GetString(key) - return value, false -} - -func mustGetStringViperFlag(flags *pflag.FlagSet, key string) string { - val, _ := getStringViperFlag(flags, key) - return val -} - var rootCmd = &cobra.Command{ - Use: "filebrowser", - Short: "A stylish web-based file browser", + Use: "filebrowser", + Version: version.Version, + Short: "A stylish web-based file browser", Long: `File Browser CLI lets you create the database to use with File Browser, manage your users and all the configurations without acessing the web interface. - + If you've never run File Browser, you'll need to have a database for 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 @@ -111,46 +80,50 @@ If you don't set "config", it will look for a configuration file called The precedence of the configuration values are as follows: -- flag -- environment variable +- flags +- environment variables - configuration file +- database values - defaults The environment variables are prefixed by "FB_" followed by the option name in caps. So to set "database" via an env variable, you should -set FB_DATABASE equals to the path. +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 bootstraped and a new user created with the credentials from options "username" and "password".`, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + log.Println(cfgFile) + if !d.hadDB { quickSetup(cmd.Flags(), d) } - server := getServerWithViper(cmd.Flags(), d.store) + server := getRunParams(cmd.Flags(), d.store) setupLog(server.Log) root, err := filepath.Abs(server.Root) checkErr(err) server.Root = root - handler, err := fbhttp.NewHandler(d.store, server) - checkErr(err) + adr := server.Address + ":" + server.Port var listener net.Listener if server.TLSKey != "" && server.TLSCert != "" { cer, err := tls.LoadX509KeyPair(server.TLSCert, server.TLSKey) checkErr(err) - config := &tls.Config{Certificates: []tls.Certificate{cer}} - listener, err = tls.Listen("tcp", server.Address+":"+server.Port, config) + listener, err = tls.Listen("tcp", adr, &tls.Config{Certificates: []tls.Certificate{cer}}) checkErr(err) } else { - listener, err = net.Listen("tcp", server.Address+":"+server.Port) + listener, err = net.Listen("tcp", adr) checkErr(err) } + handler, err := fbhttp.NewHandler(d.store, server) + checkErr(err) + log.Println("Listening on", listener.Addr().String()) if err := http.Serve(listener, handler); err != nil { log.Fatal(err) @@ -158,41 +131,70 @@ user created with the credentials from options "username" and "password".`, }, pythonConfig{allowNoDB: true}), } -func getServerWithViper(flags *pflag.FlagSet, st *storage.Storage) *settings.Server { +func getRunParams(flags *pflag.FlagSet, st *storage.Storage) *settings.Server { server, err := st.Settings.GetServer() checkErr(err) - if val, set := getStringViperFlag(flags, "root"); set { + if val, set := getParamB(flags, "root"); set { server.Root = val } - if val, set := getStringViperFlag(flags, "baseurl"); set { + if val, set := getParamB(flags, "baseurl"); set { server.BaseURL = val } - if val, set := getStringViperFlag(flags, "address"); set { + if val, set := getParamB(flags, "address"); set { server.Address = val } - if val, set := getStringViperFlag(flags, "port"); set { + if val, set := getParamB(flags, "port"); set { server.Port = val } - if val, set := getStringViperFlag(flags, "log"); set { + if val, set := getParamB(flags, "log"); set { server.Log = val } - if val, set := getStringViperFlag(flags, "key"); set { + if val, set := getParamB(flags, "key"); set { server.TLSKey = val } - if val, set := getStringViperFlag(flags, "cert"); set { + if val, set := getParamB(flags, "cert"); set { server.TLSCert = val } return server } +// getParamB returns a parameter as a string and a boolean to tell if it is different from the default +// +// NOTE: we could simply bind the flags to viper and use IsSet. +// Although there is a bug on Viper that always returns true on IsSet +// if a flag is binded. Our alternative way is to manually check +// the flag and then the value from env/config/gotten by viper. +// https://github.com/spf13/viper/pull/331 +func getParamB(flags *pflag.FlagSet, key string) (string, bool) { + value, _ := flags.GetString(key) + + // If set on Flags, use it. + if flags.Changed(key) { + return value, true + } + + // If set through viper (env, config), return it. + if v.IsSet(key) { + return v.GetString(key), true + } + + // Otherwise use default value on flags. + return value, false +} + +func getParam(flags *pflag.FlagSet, key string) string { + val, _ := getParamB(flags, key) + return val +} + func setupLog(logMethod string) { switch logMethod { case "stdout": @@ -209,14 +211,12 @@ func setupLog(logMethod string) { MaxBackups: 10, }) } - } func quickSetup(flags *pflag.FlagSet, d pythonData) { set := &settings.Settings{ - Key: generateRandomBytes(64), // 256 bit - Signup: false, - AuthMethod: auth.MethodJSONAuth, + Key: generateRandomBytes(64), // 256 bit + Signup: false, Defaults: settings.UserDefaults{ Scope: ".", Locale: "en", @@ -233,27 +233,34 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { }, } - ser := &settings.Server{ - BaseURL: mustGetStringViperFlag(flags, "baseurl"), - Port: mustGetStringViperFlag(flags, "port"), - Log: mustGetStringViperFlag(flags, "log"), - TLSKey: mustGetStringViperFlag(flags, "key"), - TLSCert: mustGetStringViperFlag(flags, "cert"), - Address: mustGetStringViperFlag(flags, "address"), - Root: mustGetStringViperFlag(flags, "root"), + var err error + if _, noauth := getParamB(flags, "noauth"); noauth { + set.AuthMethod = auth.MethodNoAuth + err = d.store.Auth.Save(&auth.NoAuth{}) + } else { + set.AuthMethod = auth.MethodJSONAuth + err = d.store.Auth.Save(&auth.JSONAuth{}) } - err := d.store.Settings.Save(set) checkErr(err) + err = d.store.Settings.Save(set) + checkErr(err) + + ser := &settings.Server{ + BaseURL: getParam(flags, "baseurl"), + Port: getParam(flags, "port"), + Log: getParam(flags, "log"), + TLSKey: getParam(flags, "key"), + TLSCert: getParam(flags, "cert"), + Address: getParam(flags, "address"), + Root: getParam(flags, "root"), + } err = d.store.Settings.SaveServer(ser) checkErr(err) - err = d.store.Auth.Save(&auth.JSONAuth{}) - checkErr(err) - - username := mustGetStringViperFlag(flags, "username") - password := mustGetStringViperFlag(flags, "password") + username := getParam(flags, "username") + password := getParam(flags, "password") if password == "" { password, err = users.HashPwd("admin") @@ -261,7 +268,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { } if username == "" || password == "" { - checkErr(errors.New("username and password cannot be empty during quick setup")) + log.Fatal("username and password cannot be empty during quick setup") } user := &users.User{ @@ -297,7 +304,9 @@ func initConfig() { if _, ok := err.(v.ConfigParseError); ok { panic(err) } - // TODO: log.Println("No config file provided") + cfgFile = "No config file used" + } else { + cfgFile = "Using config file: " + v.ConfigFileUsed() } - // else TODO: log.Println("Using config file:", v.ConfigFileUsed()) + } diff --git a/cmd/rule_rm.go b/cmd/rule_rm.go index 20e9d1e8..862eff51 100644 --- a/cmd/rule_rm.go +++ b/cmd/rule_rm.go @@ -17,7 +17,15 @@ func init() { var rulesRmCommand = &cobra.Command{ Use: "rm [index_end]", Short: "Remove a global rule or user rule", - Long: `Remove a global rule or user rule.`, + Long: `Remove a global rule or user rule. The provided index +is the same that's printed when you run 'rules ls'. Note +that after each removal/addition, the index of the +commands change. So be careful when removing them after each +other. + +You can also specify an optional parameter (index_end) so +you can remove all commands from 'index' to 'index_end', +including 'index_end'.`, Args: func(cmd *cobra.Command, args []string) error { if err := cobra.RangeArgs(1, 2)(cmd, args); err != nil { return err diff --git a/cmd/rules.go b/cmd/rules.go index 0d0f030e..efd23f7f 100644 --- a/cmd/rules.go +++ b/cmd/rules.go @@ -18,8 +18,9 @@ func init() { } var rulesCmd = &cobra.Command{ - Use: "rules", - Short: "Rules management utility", + Use: "rules", + Version: rootCmd.Version, + Short: "Rules management utility", Long: `On each subcommand you'll have available at least two flags: "username" and "id". You must either set only one of them or none. If you set one of them, the command will apply to @@ -42,14 +43,14 @@ func runRules(st *storage.Storage, cmd *cobra.Command, users func(*users.User), return } - settings, err := st.Settings.Get() + s, err := st.Settings.Get() checkErr(err) if global != nil { - global(settings) + global(s) } - printRules(settings.Rules, id) + printRules(s.Rules, id) } func getUserIdentifier(flags *pflag.FlagSet) interface{} { diff --git a/cmd/upgrade.go b/cmd/upgrade.go index bdc40a5d..d46d4fe9 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -14,8 +14,9 @@ func init() { } var upgradeCmd = &cobra.Command{ - Use: "upgrade", - Short: "Upgrades an old configuration", + Use: "upgrade", + Version: rootCmd.Version, + Short: "Upgrades an old configuration", Long: `Upgrades an old configuration. This command DOES NOT import share links because they are incompatible with this version.`, @@ -24,7 +25,7 @@ this version.`, flags := cmd.Flags() oldDB := mustGetString(flags, "old.database") oldConf := mustGetString(flags, "old.config") - err := importer.Import(oldDB, oldConf, mustGetStringViperFlag(flags, "database")) + err := importer.Import(oldDB, oldConf, getParam(flags, "database")) checkErr(err) }, } diff --git a/cmd/users.go b/cmd/users.go index 74c1c185..b7ec4a8e 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -18,10 +18,11 @@ func init() { } var usersCmd = &cobra.Command{ - Use: "users", - Short: "Users management utility", - Long: `Users management utility.`, - Args: cobra.NoArgs, + Use: "users", + Version: rootCmd.Version, + Short: "Users management utility", + Long: `Users management utility.`, + Args: cobra.NoArgs, } func printUsers(users []*users.User) { diff --git a/cmd/users_export.go b/cmd/users_export.go index 711cd420..c0160f68 100644 --- a/cmd/users_export.go +++ b/cmd/users_export.go @@ -9,9 +9,11 @@ func init() { } var usersExportCmd = &cobra.Command{ - Use: "export ", - Short: "Export all users.", - Args: jsonYamlArg, + Use: "export ", + Short: "Export all users to a file.", + 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, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { list, err := d.store.Users.Gets("") checkErr(err) diff --git a/cmd/users_import.go b/cmd/users_import.go index 67f32f75..f1c873af 100644 --- a/cmd/users_import.go +++ b/cmd/users_import.go @@ -16,9 +16,13 @@ func init() { } var usersImportCmd = &cobra.Command{ - Use: "import ", - Short: "Import users from a file.", - Args: jsonYamlArg, + Use: "import ", + Short: "Import users from a file", + Long: `Import users from a file. The path must be for a json or yaml +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, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { fd, err := os.Open(args[0]) checkErr(err) @@ -36,16 +40,16 @@ var usersImportCmd = &cobra.Command{ if mustGetBool(cmd.Flags(), "replace") { oldUsers, err := d.store.Users.Gets("") checkErr(err) - + err = marshal("users.backup.json", list) checkErr(err) - + for _, user := range oldUsers { err = d.store.Users.Delete(user.ID) checkErr(err) } } - + overwrite := mustGetBool(cmd.Flags(), "overwrite") for _, user := range list { diff --git a/cmd/users_update.go b/cmd/users_update.go index 65b281af..cf7cd2ac 100644 --- a/cmd/users_update.go +++ b/cmd/users_update.go @@ -26,8 +26,10 @@ options you want to change.`, password := mustGetString(flags, "password") newUsername := mustGetString(flags, "username") - var err error - var user *users.User + var ( + err error + user *users.User + ) if id != 0 { user, err = d.store.Users.Get("", id) diff --git a/cmd/utils.go b/cmd/utils.go index 2478c046..b52fcf5a 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -19,8 +19,7 @@ import ( func checkErr(err error) { if err != nil { - fmt.Println(err) - os.Exit(1) + log.Fatal(err) } } @@ -67,7 +66,7 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc { return func(cmd *cobra.Command, args []string) { data := pythonData{hadDB: true} - path := mustGetStringViperFlag(cmd.Flags(), "database") + path := getParam(cmd.Flags(), "database") _, err := os.Stat(path) if os.IsNotExist(err) { diff --git a/cmd/version.go b/cmd/version.go index b23b928f..61f5b4b4 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,20 +1,32 @@ package cmd import ( - "fmt" + "text/template" - "github.com/filebrowser/filebrowser/v2/version" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(versionCmd) + cmdsCmd.AddCommand(versionCmd) + configCmd.AddCommand(versionCmd) + hashCmd.AddCommand(versionCmd) + upgradeCmd.AddCommand(versionCmd) + rulesCmd.AddCommand(versionCmd) + usersCmd.AddCommand(versionCmd) } var versionCmd = &cobra.Command{ Use: "version", - Short: "Print the version number", + Short: "Print the version number of File Browser", + Long: `All software has versions. This is File Browser's`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("File Browser Version " + version.Version) + // https://github.com/spf13/cobra/issues/724 + t := template.New("version") + template.Must(t.Parse(rootCmd.VersionTemplate())) + err := t.Execute(rootCmd.OutOrStdout(), rootCmd) + if err != nil { + rootCmd.Println(err) + } }, } diff --git a/http/auth.go b/http/auth.go index d2c4792f..db58bba1 100644 --- a/http/auth.go +++ b/http/auth.go @@ -7,7 +7,7 @@ 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/users" diff --git a/http/static.go b/http/static.go index 2f0fe657..053c7654 100644 --- a/http/static.go +++ b/http/static.go @@ -9,7 +9,7 @@ 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" diff --git a/storage/bolt/importer/conf.go b/storage/bolt/importer/conf.go index 618a7766..d0348310 100644 --- a/storage/bolt/importer/conf.go +++ b/storage/bolt/importer/conf.go @@ -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 { @@ -33,7 +33,7 @@ type oldAuth struct { } type oldConf struct { - Port string `json:"port" yaml:"port" toml:"port"` + Port string `json:"port" yaml:"port" toml:"port"` BaseURL string `json:"baseURL" yaml:"baseURL" toml:"baseURL"` Log string `json:"log" yaml:"log" toml:"log"` Address string `json:"address" yaml:"address" toml:"address"` @@ -62,14 +62,14 @@ var defaults = &oldConf{ }, } -func importConf(db *storm.DB, path string, sto *storage.Storage) error { +func readConf(path string) (*oldConf, error) { cfg := &oldConf{} if path != "" { ext := filepath.Ext(path) fd, err := os.Open(path) if err != nil { - return err + return nil, err } defer fd.Close() @@ -81,23 +81,32 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { case ".yaml", ".yml": err = yaml.NewDecoder(fd).Decode(cfg) default: - return errors.New("unsupported config extension " + ext) + return nil, errors.New("unsupported config extension " + ext) } if err != nil { - return err + return nil, err } } else { cfg = defaults path, err := filepath.Abs(".") if err != nil { - return err + return nil, err } cfg.Defaults.Scope = path } + return cfg, nil +} + +func importConf(db *storm.DB, path string, sto *storage.Storage) error { + + cfg, err := readConf(path) + if err != nil { + return err + } commands := map[string][]string{} - err := db.Get("config", "commands", &commands) + err = db.Get("config", "commands", &commands) if err != nil { return err } @@ -109,8 +118,8 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { } s := &settings.Settings{ - Key: key, - Signup: false, + Key: key, + Signup: false, Defaults: settings.UserDefaults{ Scope: cfg.Defaults.Scope, Commands: cfg.Defaults.Commands, @@ -130,10 +139,10 @@ func importConf(db *storm.DB, path string, sto *storage.Storage) error { } server := &settings.Server{ - BaseURL : cfg.BaseURL, - Port : cfg.Port, - Address : cfg.Address, - Log : cfg.Log, + BaseURL: cfg.BaseURL, + Port: cfg.Port, + Address: cfg.Address, + Log: cfg.Log, } var auther auth.Auther diff --git a/storage/bolt/users.go b/storage/bolt/users.go index 0ffa7164..cfd12f74 100644 --- a/storage/bolt/users.go +++ b/storage/bolt/users.go @@ -12,32 +12,29 @@ type usersBackend struct { db *storm.DB } -func (st usersBackend) GetByID(id uint) (*users.User, error) { - user := &users.User{} - err := st.db.One("ID", id, user) - if err == storm.ErrNotFound { - return nil, errors.ErrNotExist +func (st usersBackend) GetBy(i interface{}) (user *users.User, err error) { + user = &users.User{} + + var arg string + switch i.(type) { + case uint: + arg = "ID" + case string: + arg = "Username" + default: + return nil, errors.ErrInvalidDataType } + err = st.db.One(arg, i, user) + if err != nil { + if err == storm.ErrNotFound { + return nil, errors.ErrNotExist + } return nil, err } - return user, nil -} - -func (st usersBackend) GetByUsername(username string) (*users.User, error) { - user := &users.User{} - err := st.db.One("Username", username, user) - if err == storm.ErrNotFound { - return nil, errors.ErrNotExist - } - - if err != nil { - return nil, err - } - - return user, nil + return } func (st usersBackend) Gets() ([]*users.User, error) { @@ -82,7 +79,7 @@ func (st usersBackend) DeleteByID(id uint) error { } func (st usersBackend) DeleteByUsername(username string) error { - user, err := st.GetByUsername(username) + user, err := st.GetBy(username) if err != nil { return err } diff --git a/users/storage.go b/users/storage.go index ce3e7514..7656d0fc 100644 --- a/users/storage.go +++ b/users/storage.go @@ -9,8 +9,7 @@ import ( // StorageBackend is the interface to implement for a users storage. type StorageBackend interface { - GetByID(uint) (*User, error) - GetByUsername(string) (*User, error) + GetBy(interface{}) (*User, error) Gets() ([]*User, error) Save(u *User) error Update(u *User, fields ...string) error @@ -36,27 +35,13 @@ func NewStorage(back StorageBackend) *Storage { // Get allows you to get a user by its name or username. The provided // id must be a string for username lookup or a uint for id lookup. If id // is neither, a ErrInvalidDataType will be returned. -func (s *Storage) Get(baseScope string, id interface{}) (*User, error) { - var ( - user *User - err error - ) - - switch id.(type) { - case string: - user, err = s.back.GetByUsername(id.(string)) - case uint: - user, err = s.back.GetByID(id.(uint)) - default: - return nil, errors.ErrInvalidDataType - } - +func (s *Storage) Get(baseScope string, id interface{}) (user *User, err error) { + user, err = s.back.GetBy(id) if err != nil { - return nil, err + return } - user.Clean(baseScope) - return user, err + return } // Gets gets a list of all users. diff --git a/wizard.sh b/wizard.sh index 1cea042a..ad6b6edf 100755 --- a/wizard.sh +++ b/wizard.sh @@ -131,7 +131,7 @@ pushRicebox () { git clone git@github.com:filebrowser/caddy caddy cd caddy - cp $base/http/rice-box.go ./ + cp ../http/rice-box.go ./ sed -i 's/package lib/package caddy/g' ./rice-box.go git checkout -b update-rice-box origin/master git config --local user.name "Filebrowser Bot" @@ -238,8 +238,11 @@ release () { exit 1 fi + set +e git rev-parse --verify --quiet release - if [ $? -ne 0 ]; then + exitcode=$? + set -e + if [ $exitcode -ne 0 ]; then git checkout -b release "$semver" else git checkout release