From ef56112711d47ec75d414fadc5ee124470053421 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 03:03:52 +0100 Subject: [PATCH 01/17] reduce code duplication --- storage/bolt/users.go | 39 ++++++++++++++++++--------------------- users/storage.go | 25 +++++-------------------- 2 files changed, 23 insertions(+), 41 deletions(-) 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. From b4708348c680385d1d89f14bea7c7a0a883c6bf8 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Sun, 6 Jan 2019 22:34:56 +0100 Subject: [PATCH 02/17] enable version subcmd and --version flag for root cmd and all subcmds --- cmd/cmds.go | 9 +++++---- cmd/config.go | 9 +++++---- cmd/hash.go | 9 +++++---- cmd/root.go | 13 +++++++++---- cmd/rules.go | 5 +++-- cmd/upgrade.go | 5 +++-- cmd/users.go | 9 +++++---- cmd/version.go | 20 ++++++++++++++++---- 8 files changed, 51 insertions(+), 28 deletions(-) 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/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/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..7e6915cb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -16,7 +16,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,6 +30,9 @@ var ( func init() { cobra.OnInitialize(initConfig) + + rootCmd.SetVersionTemplate("File Browser version {{printf \"%s\" .Version}}\n") + flags := rootCmd.Flags() persistent := rootCmd.PersistentFlags() @@ -87,12 +91,13 @@ func mustGetStringViperFlag(flags *pflag.FlagSet, key string) string { } var rootCmd = &cobra.Command{ - Use: "filebrowser", - Short: "A stylish web-based file browser", + Use: "filebrowser", + Short: "A stylish web-based file browser", + Version: version.Version, 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 diff --git a/cmd/rules.go b/cmd/rules.go index 0d0f030e..a0eab30b 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 diff --git a/cmd/upgrade.go b/cmd/upgrade.go index bdc40a5d..0e3dd290 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.`, 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/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) + } }, } From 7a775c42a1b88fcf7e68bbca76ccacb16eb81e8d Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Sun, 6 Jan 2019 22:06:56 +0100 Subject: [PATCH 03/17] use log.Fatal instead of panic --- cmd/utils.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/utils.go b/cmd/utils.go index 2478c046..bd741998 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) } } From 2ba5a4275af280b5e4ecd7324a0226af4371f7ab Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Tue, 8 Jan 2019 16:09:25 +0000 Subject: [PATCH 04/17] docs: improve some cli docs License: MIT Signed-off-by: Henrique Dias --- cmd/config_export.go | 3 ++- cmd/config_import.go | 3 ++- cmd/root.go | 1 + cmd/users_export.go | 6 ++++-- cmd/users_import.go | 9 +++++---- 5 files changed, 14 insertions(+), 8 deletions(-) diff --git a/cmd/config_export.go b/cmd/config_export.go index 80574b29..e57f0675 100644 --- a/cmd/config_export.go +++ b/cmd/config_export.go @@ -10,7 +10,8 @@ func init() { var configExportCmd = &cobra.Command{ Use: "export ", - Short: "Export the configuration to a file.", + Short: "Export the configuration to a file", + Long: "Export the configuration to a file.", Args: jsonYamlArg, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { settings, err := d.store.Settings.Get() diff --git a/cmd/config_import.go b/cmd/config_import.go index 3463c2f8..5c6b9ed8 100644 --- a/cmd/config_import.go +++ b/cmd/config_import.go @@ -23,7 +23,8 @@ type settingsFile struct { var configImportCmd = &cobra.Command{ Use: "import ", - Short: `Import a configuration file. This will replace all the existing + 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 diff --git a/cmd/root.go b/cmd/root.go index 7e6915cb..fd64b771 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -119,6 +119,7 @@ The precedence of the configuration values are as follows: - flag - environment variable - configuration file +- database values - defaults The environment variables are prefixed by "FB_" followed by the option diff --git a/cmd/users_export.go b/cmd/users_export.go index 711cd420..d7590592 100644 --- a/cmd/users_export.go +++ b/cmd/users_export.go @@ -10,8 +10,10 @@ func init() { var usersExportCmd = &cobra.Command{ Use: "export ", - Short: "Export all users.", - Args: jsonYamlArg, + 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..2c8161f2 100644 --- a/cmd/users_import.go +++ b/cmd/users_import.go @@ -17,7 +17,8 @@ func init() { var usersImportCmd = &cobra.Command{ Use: "import ", - Short: "Import users from a file.", + Short: "Import users from a file", + Long: "Import users from a file.", Args: jsonYamlArg, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { fd, err := os.Open(args[0]) @@ -36,16 +37,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 { From e68af011d47bebd47a4f49faeb029db573acd457 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Tue, 8 Jan 2019 16:37:02 +0000 Subject: [PATCH 05/17] feat: add docs info License: MIT Signed-off-by: Henrique Dias --- cmd/cmds_rm.go | 10 +++++++++- cmd/config_export.go | 8 +++++--- cmd/config_import.go | 7 +++++-- cmd/config_init.go | 2 +- cmd/config_set.go | 2 +- cmd/docs.go | 2 +- cmd/rule_rm.go | 10 +++++++++- cmd/users_export.go | 2 +- cmd/users_import.go | 9 ++++++--- 9 files changed, 38 insertions(+), 14 deletions(-) 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_export.go b/cmd/config_export.go index e57f0675..9d6450f9 100644 --- a/cmd/config_export.go +++ b/cmd/config_export.go @@ -9,10 +9,12 @@ func init() { } var configExportCmd = &cobra.Command{ - Use: "export ", + Use: "export ", Short: "Export the configuration to a file", - Long: "Export the configuration to a file.", - Args: jsonYamlArg, + 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 5c6b9ed8..7182da9a 100644 --- a/cmd/config_import.go +++ b/cmd/config_import.go @@ -22,13 +22,16 @@ type settingsFile struct { } var configImportCmd = &cobra.Command{ - Use: "import ", + 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/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/users_export.go b/cmd/users_export.go index d7590592..c0160f68 100644 --- a/cmd/users_export.go +++ b/cmd/users_export.go @@ -9,7 +9,7 @@ func init() { } var usersExportCmd = &cobra.Command{ - Use: "export ", + 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.`, diff --git a/cmd/users_import.go b/cmd/users_import.go index 2c8161f2..f1c873af 100644 --- a/cmd/users_import.go +++ b/cmd/users_import.go @@ -16,10 +16,13 @@ func init() { } var usersImportCmd = &cobra.Command{ - Use: "import ", + Use: "import ", Short: "Import users from a file", - Long: "Import users from a file.", - Args: jsonYamlArg, + 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) From 66010d877eb68f841cf81bb7567ae909e8a30bfd Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Tue, 8 Jan 2019 17:00:36 +0000 Subject: [PATCH 06/17] feat: quick docs update License: MIT Signed-off-by: Henrique Dias --- cmd/root.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index fd64b771..c9c9f7d1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -116,15 +116,15 @@ 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 From 5a0547b467b58bdd96f189da79e44a41bc1704a9 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 18:17:52 +0100 Subject: [PATCH 07/17] chore: update Dockerfile --- .filebrowser.docker.json => .docker.json | 0 Dockerfile | 3 +-- frontend | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) rename .filebrowser.docker.json => .docker.json (100%) diff --git a/.filebrowser.docker.json b/.docker.json similarity index 100% rename from .filebrowser.docker.json rename to .docker.json 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/frontend b/frontend index 2ed87feb..0e7d4ef1 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit 2ed87febcb71c71588f53d5b6ed560cd5c99f526 +Subproject commit 0e7d4ef110ee550375d4bf15dfa9ded70214076a From d0fd97d943bbb1a50f73203bb3f00883a11648eb Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 19:40:14 +0100 Subject: [PATCH 08/17] chore: style and gofmt (#622) --- cmd/root.go | 24 ++++++++++++--------- cmd/rules.go | 6 +++--- cmd/users_update.go | 6 ++++-- http/auth.go | 2 +- http/static.go | 2 +- storage/bolt/importer/conf.go | 39 +++++++++++++++++++++-------------- 6 files changed, 47 insertions(+), 32 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index c9c9f7d1..e33f11ca 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,7 +2,6 @@ package cmd import ( "crypto/tls" - "errors" "io/ioutil" "log" "net" @@ -92,8 +91,8 @@ func mustGetStringViperFlag(flags *pflag.FlagSet, key string) string { var rootCmd = &cobra.Command{ Use: "filebrowser", - Short: "A stylish web-based file browser", 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. @@ -130,6 +129,8 @@ 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) } @@ -141,22 +142,23 @@ user created with the credentials from options "username" and "password".`, 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) @@ -267,7 +269,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{ @@ -303,7 +305,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/rules.go b/cmd/rules.go index a0eab30b..efd23f7f 100644 --- a/cmd/rules.go +++ b/cmd/rules.go @@ -43,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/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/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 From e0a3ce95f2ef2e2319848a5b5de7739ec842f0c9 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Tue, 8 Jan 2019 18:43:04 +0000 Subject: [PATCH 09/17] feat: add no auth to quick setup (#621) --- auth/none.go | 2 +- cmd/root.go | 53 ++++++++++++++++++++++++++++++++-------------------- frontend | 2 +- 3 files changed, 35 insertions(+), 22 deletions(-) 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/root.go b/cmd/root.go index e33f11ca..de260a5d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -37,6 +37,7 @@ func init() { 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\")") @@ -53,25 +54,27 @@ func addServerFlags(flags *pflag.FlagSet) { flags.StringP("baseurl", "b", "", "base url") } +func isFlagSet(flags *pflag.FlagSet, key string) bool { + set:= false + flags.Visit(func(flag *pflag.Flag) { + if flag.Name == key { + set = true + } + }) + return set +} + // 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 + value, _ := flags.GetString(key) // 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 isFlagSet(flags, key) { + return value, true } // If set through viper (env, config), return it. @@ -80,7 +83,6 @@ func getStringViperFlag(flags *pflag.FlagSet, key string) (string, bool) { } // Otherwise use default value on flags. - value, _ = flags.GetString(key) return value, false } @@ -217,14 +219,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, Defaults: settings.UserDefaults{ Scope: ".", Locale: "en", @@ -241,6 +241,25 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { }, } + noauth, err := flags.GetBool("noauth") + checkErr(err) + + if !isFlagSet(flags, "noauth") && v.IsSet("noauth") { + noauth = v.GetBool("noauth") + } + + if noauth { + set.AuthMethod = auth.MethodNoAuth + err = d.store.Auth.Save(&auth.NoAuth{}) + } else { + set.AuthMethod = auth.MethodJSONAuth + err = d.store.Auth.Save(&auth.JSONAuth{}) + } + + checkErr(err) + err = d.store.Settings.Save(set) + checkErr(err) + ser := &settings.Server{ BaseURL: mustGetStringViperFlag(flags, "baseurl"), Port: mustGetStringViperFlag(flags, "port"), @@ -251,15 +270,9 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { Root: mustGetStringViperFlag(flags, "root"), } - err := d.store.Settings.Save(set) - checkErr(err) - 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") diff --git a/frontend b/frontend index 0e7d4ef1..2ed87feb 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit 0e7d4ef110ee550375d4bf15dfa9ded70214076a +Subproject commit 2ed87febcb71c71588f53d5b6ed560cd5c99f526 From 2c526077c05b298a838b4468881e2c460369d5bc Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 21:10:27 +0100 Subject: [PATCH 10/17] style: rename functions in root.go (#623) * replace isFlagSet with Changed * style: rename mustGetStringViperFlag and getStringViperFlag, use getParamB to read noauth * style * style: move * fix build error * rename getServerWithViper to getRunParams --- cmd/root.go | 118 ++++++++++++++++++++++--------------------------- cmd/upgrade.go | 2 +- cmd/utils.go | 2 +- 3 files changed, 54 insertions(+), 68 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index de260a5d..0c71df09 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -54,43 +54,6 @@ func addServerFlags(flags *pflag.FlagSet) { flags.StringP("baseurl", "b", "", "base url") } -func isFlagSet(flags *pflag.FlagSet, key string) bool { - set:= false - flags.Visit(func(flag *pflag.Flag) { - if flag.Name == key { - set = true - } - }) - return set -} - -// 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, _ := flags.GetString(key) - - // If set on Flags, use it. - if isFlagSet(flags, 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 mustGetStringViperFlag(flags *pflag.FlagSet, key string) string { - val, _ := getStringViperFlag(flags, key) - return val -} - var rootCmd = &cobra.Command{ Use: "filebrowser", Version: version.Version, @@ -137,7 +100,7 @@ user created with the credentials from options "username" and "password".`, 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) @@ -168,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": @@ -223,8 +215,8 @@ func setupLog(logMethod string) { func quickSetup(flags *pflag.FlagSet, d pythonData) { set := &settings.Settings{ - Key: generateRandomBytes(64), // 256 bit - Signup: false, + Key: generateRandomBytes(64), // 256 bit + Signup: false, Defaults: settings.UserDefaults{ Scope: ".", Locale: "en", @@ -241,40 +233,34 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { }, } - noauth, err := flags.GetBool("noauth") - checkErr(err) - - if !isFlagSet(flags, "noauth") && v.IsSet("noauth") { - noauth = v.GetBool("noauth") - } - - if noauth { + 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{}) } - + checkErr(err) err = d.store.Settings.Save(set) checkErr(err) 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"), + 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) - username := mustGetStringViperFlag(flags, "username") - password := mustGetStringViperFlag(flags, "password") + username := getParam(flags, "username") + password := getParam(flags, "password") if password == "" { password, err = users.HashPwd("admin") diff --git a/cmd/upgrade.go b/cmd/upgrade.go index 0e3dd290..d46d4fe9 100644 --- a/cmd/upgrade.go +++ b/cmd/upgrade.go @@ -25,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/utils.go b/cmd/utils.go index bd741998..b52fcf5a 100644 --- a/cmd/utils.go +++ b/cmd/utils.go @@ -66,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) { From f218c2a7910d9d8246a92090269fa4be4872416f Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 21:20:00 +0100 Subject: [PATCH 11/17] fix: wizard release --- wizard.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wizard.sh b/wizard.sh index 1cea042a..88d62c50 100755 --- a/wizard.sh +++ b/wizard.sh @@ -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 From 43e494b0f7c8248987d4eec19497f353659e127b Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 23:54:13 +0100 Subject: [PATCH 12/17] fix: wizard -r requires an argument --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 8c2c298d9dee6003330470d3f2ca816bb8227683 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Wed, 9 Jan 2019 00:37:37 +0100 Subject: [PATCH 13/17] fix: goreleaser main file --- .goreleaser.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 12f309a0..353ff5dc 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 From 27d1a9531064409ded29e720caf3f76e132ad2c2 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Wed, 9 Jan 2019 01:21:27 +0100 Subject: [PATCH 14/17] fix: update to goreleaser dockers changes --- .goreleaser.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index 353ff5dc..6ac6663a 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -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 From 9f6e51b251c156acd75639b2fe5976c72c07d2b0 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Wed, 9 Jan 2019 01:53:23 +0100 Subject: [PATCH 15/17] fix: wizard pushRicebox non-existing envvar --- wizard.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wizard.sh b/wizard.sh index 88d62c50..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" From c1f344e9eb0c52d3b014e4ef6c8424384906f2bb Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 21:22:39 +0100 Subject: [PATCH 16/17] chore: version v2.0.0-rc.1 --- version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/version.go b/version/version.go index e9ae924e..0b4ee232 100644 --- a/version/version.go +++ b/version/version.go @@ -2,5 +2,5 @@ package version const ( // Version is the current File Browser version. - Version = "(untracked)" + Version = "v2.0.0-rc.1" ) From a55e0d24f8742501a159f95e58c792a1a83ab577 Mon Sep 17 00:00:00 2001 From: 1138-4EB <1138-4EB@users.noreply.github.com> Date: Tue, 8 Jan 2019 21:22:48 +0100 Subject: [PATCH 17/17] chore: setting untracked version [ci skip] --- version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/version.go b/version/version.go index 0b4ee232..e9ae924e 100644 --- a/version/version.go +++ b/version/version.go @@ -2,5 +2,5 @@ package version const ( // Version is the current File Browser version. - Version = "v2.0.0-rc.1" + Version = "(untracked)" )