From 43bf5b6f51a9d432b34ef3c1a8bea2c196fdd105 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 10:52:34 -0500 Subject: [PATCH 01/11] updated --- backend/auth/hook.go | 18 +-- backend/cmd/cmd.go | 12 -- backend/cmd/cmds.go | 26 --- backend/cmd/cmds_add.go | 27 ---- backend/cmd/cmds_ls.go | 31 ---- backend/cmd/cmds_rm.go | 56 ------- backend/cmd/config.go | 30 ++-- backend/cmd/config_set.go | 2 +- backend/cmd/root.go | 4 +- backend/cmd/upgrade.go | 31 ---- backend/cmd/users.go | 4 +- backend/cmd/users_add.go | 4 +- backend/http/auth.go | 4 +- backend/http/settings.go | 4 +- backend/settings/storage.go | 12 +- backend/settings/structs.go | 100 ++++-------- backend/storage/bolt/importer/conf.go | 187 ---------------------- backend/storage/bolt/importer/importer.go | 41 ----- backend/storage/bolt/importer/users.go | 114 ------------- backend/users/users.go | 11 +- 20 files changed, 78 insertions(+), 640 deletions(-) delete mode 100644 backend/cmd/cmd.go delete mode 100644 backend/cmd/cmds.go delete mode 100644 backend/cmd/cmds_add.go delete mode 100644 backend/cmd/cmds_ls.go delete mode 100644 backend/cmd/cmds_rm.go delete mode 100644 backend/cmd/upgrade.go delete mode 100644 backend/storage/bolt/importer/conf.go delete mode 100644 backend/storage/bolt/importer/importer.go delete mode 100644 backend/storage/bolt/importer/users.go diff --git a/backend/auth/hook.go b/backend/auth/hook.go index 00b2a625..def9d3bc 100644 --- a/backend/auth/hook.go +++ b/backend/auth/hook.go @@ -155,14 +155,14 @@ func (a *HookAuth) SaveUser() (*users.User, error) { d := &users.User{ Username: a.Cred.Username, Password: pass, - Scope: a.Settings.Defaults.Scope, - Locale: a.Settings.Defaults.Locale, - ViewMode: a.Settings.Defaults.ViewMode, - SingleClick: a.Settings.Defaults.SingleClick, - Sorting: a.Settings.Defaults.Sorting, - Perm: a.Settings.Defaults.Perm, - Commands: a.Settings.Defaults.Commands, - HideDotfiles: a.Settings.Defaults.HideDotfiles, + Scope: a.Settings.UserDefaults.Scope, + Locale: a.Settings.UserDefaults.Locale, + ViewMode: a.Settings.UserDefaults.ViewMode, + SingleClick: a.Settings.UserDefaults.SingleClick, + Sorting: a.Settings.UserDefaults.Sorting, + Perm: a.Settings.UserDefaults.Perm, + Commands: a.Settings.UserDefaults.Commands, + HideDotfiles: a.Settings.UserDefaults.HideDotfiles, } u = a.GetUser(d) @@ -219,7 +219,7 @@ func (a *HookAuth) GetUser(d *users.User) *users.User { Password: d.Password, Scope: a.Fields.GetString("user.scope", d.Scope), Locale: a.Fields.GetString("user.locale", d.Locale), - ViewMode: users.ViewMode(a.Fields.GetString("user.viewMode", string(d.ViewMode))), + ViewMode: d.ViewMode, SingleClick: a.Fields.GetBoolean("user.singleClick", d.SingleClick), Sorting: files.Sorting{ Asc: a.Fields.GetBoolean("user.sorting.asc", d.Sorting.Asc), diff --git a/backend/cmd/cmd.go b/backend/cmd/cmd.go deleted file mode 100644 index 18f52337..00000000 --- a/backend/cmd/cmd.go +++ /dev/null @@ -1,12 +0,0 @@ -package cmd - -import ( - "log" -) - -// Execute executes the commands. -func Execute() { - if err := rootCmd.Execute(); err != nil { - log.Fatal(err) - } -} diff --git a/backend/cmd/cmds.go b/backend/cmd/cmds.go deleted file mode 100644 index cf951995..00000000 --- a/backend/cmd/cmds.go +++ /dev/null @@ -1,26 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func init() { - rootCmd.AddCommand(cmdsCmd) -} - -var cmdsCmd = &cobra.Command{ - Use: "cmds", - Short: "Command runner management utility", - Long: `Command runner management utility.`, - Args: cobra.NoArgs, -} - -func printEvents(m map[string][]string) { - for evt, cmds := range m { - for i, cmd := range cmds { - fmt.Printf("%s(%d): %s\n", evt, i, cmd) - } - } -} diff --git a/backend/cmd/cmds_add.go b/backend/cmd/cmds_add.go deleted file mode 100644 index fd2c0dc5..00000000 --- a/backend/cmd/cmds_add.go +++ /dev/null @@ -1,27 +0,0 @@ -package cmd - -import ( - "strings" - - "github.com/spf13/cobra" -) - -func init() { - cmdsCmd.AddCommand(cmdsAddCmd) -} - -var cmdsAddCmd = &cobra.Command{ - Use: "add ", - Short: "Add a command to run on a specific event", - Long: `Add a command to run on a specific event.`, - Args: cobra.MinimumNArgs(2), //nolint:gomnd - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - s, err := d.store.Settings.Get() - checkErr(err) - command := strings.Join(args[1:], " ") - s.Commands[args[0]] = append(s.Commands[args[0]], command) - err = d.store.Settings.Save(s) - checkErr(err) - printEvents(s.Commands) - }, pythonConfig{}), -} diff --git a/backend/cmd/cmds_ls.go b/backend/cmd/cmds_ls.go deleted file mode 100644 index 71f36382..00000000 --- a/backend/cmd/cmds_ls.go +++ /dev/null @@ -1,31 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - cmdsCmd.AddCommand(cmdsLsCmd) - cmdsLsCmd.Flags().StringP("event", "e", "", "event name, without 'before' or 'after'") -} - -var cmdsLsCmd = &cobra.Command{ - Use: "ls", - Short: "List all commands for each event", - Long: `List all commands for each event.`, - Args: cobra.NoArgs, - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - s, err := d.store.Settings.Get() - checkErr(err) - evt := mustGetString(cmd.Flags(), "event") - - if evt == "" { - printEvents(s.Commands) - } else { - show := map[string][]string{} - show["before_"+evt] = s.Commands["before_"+evt] - show["after_"+evt] = s.Commands["after_"+evt] - printEvents(show) - } - }, pythonConfig{}), -} diff --git a/backend/cmd/cmds_rm.go b/backend/cmd/cmds_rm.go deleted file mode 100644 index e1f78863..00000000 --- a/backend/cmd/cmds_rm.go +++ /dev/null @@ -1,56 +0,0 @@ -package cmd - -import ( - "strconv" - - "github.com/spf13/cobra" -) - -func init() { - cmdsCmd.AddCommand(cmdsRmCmd) -} - -var cmdsRmCmd = &cobra.Command{ - Use: "rm [index_end]", - Short: "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 { //nolint:gomnd - return err - } - - for _, arg := range args[1:] { - if _, err := strconv.Atoi(arg); err != nil { - return err - } - } - - return nil - }, - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - s, err := d.store.Settings.Get() - checkErr(err) - evt := args[0] - - i, err := strconv.Atoi(args[1]) - checkErr(err) - f := i - if len(args) == 3 { //nolint:gomnd - f, err = strconv.Atoi(args[2]) - checkErr(err) - } - - s.Commands[evt] = append(s.Commands[evt][:i], s.Commands[evt][f+1:]...) - err = d.store.Settings.Save(s) - checkErr(err) - printEvents(s.Commands) - }, pythonConfig{}), -} diff --git a/backend/cmd/config.go b/backend/cmd/config.go index 21d69d2a..9ee88b85 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -138,23 +138,23 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintf(w, "\tTLS Key:\t%s\n", ser.TLSKey) fmt.Fprintf(w, "\tExec Enabled:\t%t\n", ser.EnableExec) fmt.Fprintln(w, "\nDefaults:") - fmt.Fprintf(w, "\tScope:\t%s\n", set.Defaults.Scope) - fmt.Fprintf(w, "\tLocale:\t%s\n", set.Defaults.Locale) - fmt.Fprintf(w, "\tView mode:\t%s\n", set.Defaults.ViewMode) - fmt.Fprintf(w, "\tSingle Click:\t%t\n", set.Defaults.SingleClick) - fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.Defaults.Commands, " ")) + fmt.Fprintf(w, "\tScope:\t%s\n", set.UserDefaults.Scope) + fmt.Fprintf(w, "\tLocale:\t%s\n", set.UserDefaults.Locale) + fmt.Fprintf(w, "\tView mode:\t%s\n", set.UserDefaults.ViewMode) + fmt.Fprintf(w, "\tSingle Click:\t%t\n", set.UserDefaults.SingleClick) + fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.UserDefaults.Commands, " ")) fmt.Fprintf(w, "\tSorting:\n") - fmt.Fprintf(w, "\t\tBy:\t%s\n", set.Defaults.Sorting.By) - fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.Defaults.Sorting.Asc) + fmt.Fprintf(w, "\t\tBy:\t%s\n", set.UserDefaults.Sorting.By) + fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.UserDefaults.Sorting.Asc) fmt.Fprintf(w, "\tPermissions:\n") - fmt.Fprintf(w, "\t\tAdmin:\t%t\n", set.Defaults.Perm.Admin) - fmt.Fprintf(w, "\t\tExecute:\t%t\n", set.Defaults.Perm.Execute) - fmt.Fprintf(w, "\t\tCreate:\t%t\n", set.Defaults.Perm.Create) - fmt.Fprintf(w, "\t\tRename:\t%t\n", set.Defaults.Perm.Rename) - fmt.Fprintf(w, "\t\tModify:\t%t\n", set.Defaults.Perm.Modify) - fmt.Fprintf(w, "\t\tDelete:\t%t\n", set.Defaults.Perm.Delete) - fmt.Fprintf(w, "\t\tShare:\t%t\n", set.Defaults.Perm.Share) - fmt.Fprintf(w, "\t\tDownload:\t%t\n", set.Defaults.Perm.Download) + fmt.Fprintf(w, "\t\tAdmin:\t%t\n", set.UserDefaults.Perm.Admin) + fmt.Fprintf(w, "\t\tExecute:\t%t\n", set.UserDefaults.Perm.Execute) + fmt.Fprintf(w, "\t\tCreate:\t%t\n", set.UserDefaults.Perm.Create) + fmt.Fprintf(w, "\t\tRename:\t%t\n", set.UserDefaults.Perm.Rename) + fmt.Fprintf(w, "\t\tModify:\t%t\n", set.UserDefaults.Perm.Modify) + fmt.Fprintf(w, "\t\tDelete:\t%t\n", set.UserDefaults.Perm.Delete) + fmt.Fprintf(w, "\t\tShare:\t%t\n", set.UserDefaults.Perm.Share) + fmt.Fprintf(w, "\t\tDownload:\t%t\n", set.UserDefaults.Perm.Download) w.Flush() b, err := json.MarshalIndent(auther, "", " ") diff --git a/backend/cmd/config_set.go b/backend/cmd/config_set.go index d7bb80d9..f30dd088 100644 --- a/backend/cmd/config_set.go +++ b/backend/cmd/config_set.go @@ -59,7 +59,7 @@ you want to change. Other options will remain unchanged.`, } }) - getUserDefaults(flags, &set.Defaults, false) + getUserDefaults(flags, &set.UserDefaults, false) // read the defaults _, auther := getAuthentication() diff --git a/backend/cmd/root.go b/backend/cmd/root.go index 774211ed..e5b10c08 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -209,7 +209,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { Signup: false, CreateUserDir: false, UserHomeBasePath: settings.DefaultUsersHomeBasePath, - Defaults: settings.UserDefaults{ + UserDefaults: settings.UserDefaults{ Scope: ".", Locale: "en", SingleClick: false, @@ -268,7 +268,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { LockPassword: false, } - set.Defaults.Apply(user) + set.UserDefaults.Apply(user) user.Perm.Admin = true err = d.store.Users.Save(user) diff --git a/backend/cmd/upgrade.go b/backend/cmd/upgrade.go deleted file mode 100644 index be9769c2..00000000 --- a/backend/cmd/upgrade.go +++ /dev/null @@ -1,31 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/storage/bolt/importer" -) - -func init() { - rootCmd.AddCommand(upgradeCmd) - - upgradeCmd.Flags().String("old.database", "", "") - upgradeCmd.Flags().String("old.config", "", "") - _ = upgradeCmd.MarkFlagRequired("old.database") -} - -var upgradeCmd = &cobra.Command{ - Use: "upgrade", - Short: "Upgrades an old configuration", - Long: `Upgrades an old configuration. This command DOES NOT -import share links because they are incompatible with -this version.`, - Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { - flags := cmd.Flags() - oldDB := mustGetString(flags, "old.database") - oldConf := mustGetString(flags, "old.config") - err := importer.Import(oldDB, oldConf, getParam(flags, "database")) - checkErr(err) - }, -} diff --git a/backend/cmd/users.go b/backend/cmd/users.go index 3c835a18..1f50cf74 100644 --- a/backend/cmd/users.go +++ b/backend/cmd/users.go @@ -79,8 +79,8 @@ func addUserFlags(flags *pflag.FlagSet) { flags.Bool("singleClick", false, "use single clicks only") } -func getViewMode(flags *pflag.FlagSet) users.ViewMode { - viewMode := users.ViewMode(mustGetString(flags, "viewMode")) +func getViewMode(flags *pflag.FlagSet) string { + viewMode := settings.GlobalConfiguration.UserDefaults.ViewMode if viewMode != users.ListViewMode && viewMode != users.MosaicViewMode { checkErr(errors.New("view mode must be \"" + string(users.ListViewMode) + "\" or \"" + string(users.MosaicViewMode) + "\"")) } diff --git a/backend/cmd/users_add.go b/backend/cmd/users_add.go index f133a464..eac81240 100644 --- a/backend/cmd/users_add.go +++ b/backend/cmd/users_add.go @@ -19,7 +19,7 @@ var usersAddCmd = &cobra.Command{ Run: python(func(cmd *cobra.Command, args []string, d pythonData) { s, err := d.store.Settings.Get() checkErr(err) - getUserDefaults(cmd.Flags(), &s.Defaults, false) + getUserDefaults(cmd.Flags(), &s.UserDefaults, false) password, err := users.HashPwd(args[1]) checkErr(err) @@ -30,7 +30,7 @@ var usersAddCmd = &cobra.Command{ LockPassword: mustGetBool(cmd.Flags(), "lockPassword"), } - s.Defaults.Apply(user) + s.UserDefaults.Apply(user) servSettings, err := d.store.Settings.GetServer() checkErr(err) diff --git a/backend/http/auth.go b/backend/http/auth.go index a47baec5..5ff0f656 100644 --- a/backend/http/auth.go +++ b/backend/http/auth.go @@ -22,7 +22,7 @@ const ( type userInfo struct { ID uint `json:"id"` Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` + ViewMode string `json:"viewMode"` SingleClick bool `json:"singleClick"` Perm users.Permissions `json:"perm"` Commands []string `json:"commands"` @@ -145,7 +145,7 @@ var signupHandler = func(w http.ResponseWriter, r *http.Request, d *data) (int, Username: info.Username, } - d.settings.Defaults.Apply(user) + d.settings.UserDefaults.Apply(user) pwd, err := users.HashPwd(info.Password) if err != nil { diff --git a/backend/http/settings.go b/backend/http/settings.go index 49c77326..9591df5d 100644 --- a/backend/http/settings.go +++ b/backend/http/settings.go @@ -24,7 +24,7 @@ var settingsGetHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, Signup: d.settings.Signup, CreateUserDir: d.settings.CreateUserDir, UserHomeBasePath: d.settings.UserHomeBasePath, - Defaults: d.settings.Defaults, + Defaults: d.settings.UserDefaults, Rules: d.settings.Rules, Frontend: d.settings.Frontend, Shell: d.settings.Shell, @@ -44,7 +44,7 @@ var settingsPutHandler = withAdmin(func(w http.ResponseWriter, r *http.Request, d.settings.Signup = req.Signup d.settings.CreateUserDir = req.CreateUserDir d.settings.UserHomeBasePath = req.UserHomeBasePath - d.settings.Defaults = req.Defaults + d.settings.UserDefaults = req.Defaults d.settings.Rules = req.Rules d.settings.Frontend = req.Frontend d.settings.Shell = req.Shell diff --git a/backend/settings/storage.go b/backend/settings/storage.go index a027b4b3..19c8fdcc 100644 --- a/backend/settings/storage.go +++ b/backend/settings/storage.go @@ -50,16 +50,16 @@ func (s *Storage) Save(set *Settings) error { return errors.ErrEmptyKey } - if set.Defaults.Locale == "" { - set.Defaults.Locale = "en" + if set.UserDefaults.Locale == "" { + set.UserDefaults.Locale = "en" } - if set.Defaults.Commands == nil { - set.Defaults.Commands = []string{} + if set.UserDefaults.Commands == nil { + set.UserDefaults.Commands = []string{} } - if set.Defaults.ViewMode == "" { - set.Defaults.ViewMode = users.MosaicViewMode + if set.UserDefaults.ViewMode == "" { + set.UserDefaults.ViewMode = users.MosaicViewMode } if set.Rules == nil { diff --git a/backend/settings/structs.go b/backend/settings/structs.go index fba392e7..7b05b531 100644 --- a/backend/settings/structs.go +++ b/backend/settings/structs.go @@ -1,7 +1,6 @@ package settings import ( - "github.com/gtsteffaniak/filebrowser/files" "github.com/gtsteffaniak/filebrowser/rules" "github.com/gtsteffaniak/filebrowser/users" ) @@ -24,31 +23,28 @@ type Settings struct { Signup bool `json:"signup"` CreateUserDir bool `json:"createUserDir"` UserHomeBasePath string `json:"userHomeBasePath"` - Defaults UserDefaults `json:"defaults"` Commands map[string][]string `json:"commands"` Shell []string `json:"shell"` Rules []rules.Rule `json:"rules"` Server Server `json:"server"` Auth Auth `json:"auth"` - - Frontend Frontend `json:"frontend"` - - UserDefaults UserDefaults `json:"userDefaults"` + Frontend Frontend `json:"frontend"` + UserDefaults UserDefaults `json:"userDefaults"` } type Auth struct { - Recaptcha Recaptcha - Header string `json:"header"` - Method string `json:"method"` - Command string `json:"command"` - Signup bool `json:"signup"` - Shell string `json:"shell"` + Recaptcha Recaptcha `json:"recaptcha"` + Header string `json:"header"` + Method string `json:"method"` + Command string `json:"command"` + Signup bool `json:"signup"` + Shell string `json:"shell"` } type Recaptcha struct { - Host string - Key string - Secret string + Host string `json:"host"` + Key string `json:"key"` + Secret string `json:"secret"` } type Server struct { @@ -68,7 +64,7 @@ type Server struct { Log string `json:"log"` Database string `json:"database"` Root string `json:"root"` - EnablePreviewResize bool `json:"disable-preview-resize"` + EnablePreviewResize bool `json:"enablePreviewResize"` } type Frontend struct { @@ -83,55 +79,25 @@ type Frontend struct { // UserDefaults is a type that holds the default values // for some fields on User. type UserDefaults struct { - Scope string `json:"scope"` - Locale string `json:"locale"` - ViewMode users.ViewMode `json:"viewMode"` - SingleClick bool `json:"singleClick"` - Sorting files.Sorting `json:"sorting"` - Perm users.Permissions `json:"perm"` - Commands []string `json:"commands"` - HideDotfiles bool `json:"hideDotfiles"` - DateFormat bool `json:"dateFormat"` + Scope string `json:"scope"` + Locale string `json:"locale"` + ViewMode string `json:"viewMode"` + SingleClick bool `json:"singleClick"` + Sorting struct { + By string `json:"by"` + Asc bool `json:"asc"` + } `json:"sorting"` + Perm struct { + Admin bool `json:"admin"` + Execute bool `json:"execute"` + Create bool `json:"create"` + Rename bool `json:"rename"` + Modify bool `json:"modify"` + Delete bool `json:"delete"` + Share bool `json:"share"` + Download bool `json:"download"` + } `json:"perm"` + Commands []string `json:"commands"` + HideDotfiles bool `json:"hideDotfiles"` + DateFormat bool `json:"dateFormat"` } - -//{ -// "server":{ -// "port":8080, -// "baseURL":"", -// "address":"", -// "log":"stdout", -// "database":"./database.db", -// "root":"/srv", -// "disable-thumbnails":false, -// "disable-preview-resize":false, -// "disable-exec":false, -// "disable-type-detection-by-header":false -// }, -// "auth":{ -// "header":"", -// "method":"", -// "command":"", -// "signup":false, -// "shell":"" -// }, -// "branding":{ -// "name":"", -// "color":"", -// "files":"", -// "disableExternal":"", -// "disableUsedPercentage":"" -// }, -// "permissions":{ -// "Admin":false, -// "Execute":true, -// "Create":true, -// "Rename":true, -// "Modify":true, -// "Delete":true, -// "Share":true, -// "Download":true -// }, -// "commands":{}, -// "shell":{}, -// "rules":{} -// } diff --git a/backend/storage/bolt/importer/conf.go b/backend/storage/bolt/importer/conf.go deleted file mode 100644 index a6d84a21..00000000 --- a/backend/storage/bolt/importer/conf.go +++ /dev/null @@ -1,187 +0,0 @@ -package importer - -import ( - "encoding/json" - "errors" - "fmt" - "os" - "path/filepath" - - "github.com/asdine/storm/v3" - "github.com/pelletier/go-toml/v2" - "gopkg.in/yaml.v2" - - "github.com/gtsteffaniak/filebrowser/auth" - "github.com/gtsteffaniak/filebrowser/settings" - "github.com/gtsteffaniak/filebrowser/storage" - "github.com/gtsteffaniak/filebrowser/users" -) - -type oldDefs struct { - Commands []string `json:"commands" yaml:"commands" toml:"commands"` - Scope string `json:"scope" yaml:"scope" toml:"scope"` - ViewMode string `json:"viewMode" yaml:"viewMode" toml:"viewMode"` - Locale string `json:"locale" yaml:"locale" toml:"locale"` - AllowCommands bool `json:"allowCommands" yaml:"allowCommands" toml:"allowCommands"` - AllowEdit bool `json:"allowEdit" yaml:"allowEdit" toml:"allowEdit"` - AllowNew bool `json:"allowNew" yaml:"allowNew" toml:"allowNew"` -} - -type oldAuth struct { - Method string `json:"method" yaml:"method" toml:"method"` // default none proxy - Header string `json:"header" yaml:"header" toml:"header"` - Command string `json:"command" yaml:"command" toml:"command"` -} - -type oldConf struct { - 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"` - Defaults oldDefs `json:"defaults" yaml:"defaults" toml:"defaults"` - ReCaptcha struct { - Key string `json:"key" yaml:"key" toml:"key"` - Secret string `json:"secret" yaml:"secret" toml:"secret"` - Host string `json:"host" yaml:"host" toml:"host"` - } `json:"recaptcha" yaml:"recaptcha" toml:"recaptcha"` - Auth oldAuth `json:"auth" yaml:"auth" toml:"auth"` -} - -var defaults = &oldConf{ - Port: "0", - Log: "stdout", - Defaults: oldDefs{ - Commands: []string{"git", "svn", "hg"}, - ViewMode: string(users.MosaicViewMode), - AllowCommands: true, - AllowEdit: true, - AllowNew: true, - Locale: "en", - }, - Auth: oldAuth{ - Method: "default", - }, -} - -func readConf(path string) (*oldConf, error) { - cfg := &oldConf{} - if path != "" { - ext := filepath.Ext(path) - - fd, err := os.Open(path) - if err != nil { - return nil, err - } - defer fd.Close() - - switch ext { - case ".json": - err = json.NewDecoder(fd).Decode(cfg) - case ".toml": - err = toml.NewDecoder(fd).Decode(cfg) - case ".yaml", ".yml": - err = yaml.NewDecoder(fd).Decode(cfg) - default: - return nil, errors.New("unsupported config extension " + ext) - } - - if err != nil { - return nil, err - } - } else { - cfg = defaults - path, err := filepath.Abs(".") - if err != nil { - 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) - if err != nil { - return err - } - - key := []byte{} - err = db.Get("config", "key", &key) - if err != nil { - return err - } - - s := &settings.Settings{ - Key: key, - Signup: false, - Defaults: settings.UserDefaults{ - Scope: cfg.Defaults.Scope, - Commands: cfg.Defaults.Commands, - ViewMode: users.ViewMode(cfg.Defaults.ViewMode), - Locale: cfg.Defaults.Locale, - Perm: users.Permissions{ - Admin: false, - Execute: cfg.Defaults.AllowCommands, - Create: cfg.Defaults.AllowNew, - Rename: cfg.Defaults.AllowEdit, - Modify: cfg.Defaults.AllowEdit, - Delete: cfg.Defaults.AllowEdit, - Share: true, - Download: true, - }, - }, - } - - server := &settings.Server{ - BaseURL: cfg.BaseURL, - Port: 8080, - Address: cfg.Address, - Log: cfg.Log, - } - fmt.Println("config.go", server) - var auther auth.Auther - switch cfg.Auth.Method { - case "proxy": - auther = &auth.ProxyAuth{Header: cfg.Auth.Header} - s.Auth.Method = "proxy" - case "hook": - auther = &auth.HookAuth{Command: cfg.Auth.Command} - s.Auth.Method = "hoook" - case "none": - auther = &auth.NoAuth{} - s.Auth.Method = "noauth" - default: - auther = &auth.JSONAuth{ - ReCaptcha: &auth.ReCaptcha{ - Host: cfg.ReCaptcha.Host, - Key: cfg.ReCaptcha.Key, - Secret: cfg.ReCaptcha.Secret, - }, - } - s.Auth.Method = "password" - } - - err = sto.Auth.Save(auther) - if err != nil { - return err - } - - err = sto.Settings.Save(s) - if err != nil { - return err - } - - err = sto.Settings.SaveServer(server) - if err != nil { - return err - } - - fmt.Println("Configuration successfully imported.") - return nil -} diff --git a/backend/storage/bolt/importer/importer.go b/backend/storage/bolt/importer/importer.go deleted file mode 100644 index 36b60283..00000000 --- a/backend/storage/bolt/importer/importer.go +++ /dev/null @@ -1,41 +0,0 @@ -package importer - -import ( - "github.com/asdine/storm/v3" - "log" - - "github.com/gtsteffaniak/filebrowser/storage/bolt" -) - -// Import imports an old configuration to a newer database. -func Import(oldDBPath, oldConf, newDBPath string) error { - log.Println(oldDBPath, oldConf, newDBPath) - oldDB, err := storm.Open(oldDBPath) - if err != nil { - return err - } - defer oldDB.Close() - - newDB, err := storm.Open(newDBPath) - if err != nil { - return err - } - defer newDB.Close() - - sto, err := bolt.NewStorage(newDB) - if err != nil { - return err - } - - err = importUsers(oldDB, sto) - if err != nil { - return err - } - - err = importConf(oldDB, oldConf, sto) - if err != nil { - return err - } - - return err -} diff --git a/backend/storage/bolt/importer/users.go b/backend/storage/bolt/importer/users.go deleted file mode 100644 index 4606fc2e..00000000 --- a/backend/storage/bolt/importer/users.go +++ /dev/null @@ -1,114 +0,0 @@ -package importer - -import ( - "encoding/json" - "fmt" - - "github.com/asdine/storm/v3" - bolt "go.etcd.io/bbolt" - - "github.com/gtsteffaniak/filebrowser/rules" - "github.com/gtsteffaniak/filebrowser/storage" - "github.com/gtsteffaniak/filebrowser/users" -) - -type oldUser struct { - ID int `storm:"id,increment"` - Admin bool `json:"admin"` - AllowCommands bool `json:"allowCommands"` // Execute commands - AllowEdit bool `json:"allowEdit"` // Edit/rename files - AllowNew bool `json:"allowNew"` // Create files and folders - AllowPublish bool `json:"allowPublish"` // Publish content (to use with static gen) - LockPassword bool `json:"lockPassword"` - Commands []string `json:"commands"` - Locale string `json:"locale"` - Password string `json:"password"` - Rules []*rules.Rule `json:"rules"` - Scope string `json:"filesystem"` - Username string `json:"username" storm:"index,unique"` - ViewMode string `json:"viewMode"` -} - -func readOldUsers(db *storm.DB) ([]*oldUser, error) { - var oldUsers []*oldUser - err := db.Bolt.View(func(tx *bolt.Tx) error { - return tx.Bucket([]byte("User")).ForEach(func(k []byte, v []byte) error { - if len(v) > 0 && string(v)[0] == '{' { - user := &oldUser{} - err := json.Unmarshal(v, user) - - if err != nil { - return err - } - - oldUsers = append(oldUsers, user) - } - - return nil - }) - }) - - return oldUsers, err -} - -func convertUsersToNew(old []*oldUser) ([]*users.User, error) { - list := []*users.User{} - - for _, oldUser := range old { - user := &users.User{ - Username: oldUser.Username, - Password: oldUser.Password, - Scope: oldUser.Scope, - Locale: oldUser.Locale, - LockPassword: oldUser.LockPassword, - ViewMode: users.ViewMode(oldUser.ViewMode), - Commands: oldUser.Commands, - Rules: []rules.Rule{}, - Perm: users.Permissions{ - Admin: oldUser.Admin, - Execute: oldUser.AllowCommands, - Create: oldUser.AllowNew, - Rename: oldUser.AllowEdit, - Modify: oldUser.AllowEdit, - Delete: oldUser.AllowEdit, - Share: true, - Download: true, - }, - } - - for _, rule := range oldUser.Rules { - user.Rules = append(user.Rules, *rule) - } - - err := user.Clean("") - if err != nil { - return nil, err - } - - list = append(list, user) - } - - return list, nil -} - -func importUsers(old *storm.DB, sto *storage.Storage) error { - oldUsers, err := readOldUsers(old) - if err != nil { - return err - } - - newUsers, err := convertUsersToNew(oldUsers) - if err != nil { - return err - } - - for _, user := range newUsers { - err = sto.Users.Save(user) - if err != nil { - return err - } - } - - fmt.Printf("%d users successfully imported into the new DB.\n", len(newUsers)) - return nil -} diff --git a/backend/users/users.go b/backend/users/users.go index 91dcea68..cfdcb2fa 100644 --- a/backend/users/users.go +++ b/backend/users/users.go @@ -11,12 +11,9 @@ import ( "github.com/gtsteffaniak/filebrowser/rules" ) -// ViewMode describes a view mode. -type ViewMode string - -const ( - ListViewMode ViewMode = "list" - MosaicViewMode ViewMode = "mosaic" +var ( + ListViewMode = "list" + MosaicViewMode = "mosaic" ) // User describes a user. @@ -27,7 +24,7 @@ type User struct { Scope string `json:"scope"` Locale string `json:"locale"` LockPassword bool `json:"lockPassword"` - ViewMode ViewMode `json:"viewMode"` + ViewMode string `json:"viewMode"` SingleClick bool `json:"singleClick"` Perm Permissions `json:"perm"` Commands []string `json:"commands"` From 805381a017bb67a5ec4f725b9a4d7d7a122e07ec Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 11:05:40 -0500 Subject: [PATCH 02/11] removed all settings --- backend/cmd/config.go | 17 ----- backend/cmd/config_cat.go | 25 ------- backend/cmd/config_export.go | 37 ---------- backend/cmd/config_import.go | 94 ----------------------- backend/cmd/config_init.go | 1 - backend/cmd/config_set.go | 74 ------------------- backend/cmd/docs.go | 139 ----------------------------------- backend/cmd/hash.go | 25 ------- backend/cmd/root.go | 6 ++ backend/cmd/rule_rm.go | 66 ----------------- backend/cmd/rules.go | 92 ----------------------- backend/cmd/rules_add.go | 58 --------------- backend/cmd/rules_ls.go | 19 ----- backend/cmd/users_add.go | 51 ------------- backend/cmd/users_export.go | 24 ------ backend/cmd/users_find.go | 51 ------------- backend/cmd/users_import.go | 89 ---------------------- backend/cmd/users_rm.go | 31 -------- backend/cmd/users_update.go | 75 ------------------- backend/cmd/version.go | 21 ------ backend/http/commands.go | 111 ---------------------------- backend/http/http.go | 14 ---- backend/main.go | 2 +- 23 files changed, 7 insertions(+), 1115 deletions(-) delete mode 100644 backend/cmd/config_cat.go delete mode 100644 backend/cmd/config_export.go delete mode 100644 backend/cmd/config_import.go delete mode 100644 backend/cmd/config_set.go delete mode 100644 backend/cmd/docs.go delete mode 100644 backend/cmd/hash.go delete mode 100644 backend/cmd/rule_rm.go delete mode 100644 backend/cmd/rules.go delete mode 100644 backend/cmd/rules_add.go delete mode 100644 backend/cmd/rules_ls.go delete mode 100644 backend/cmd/users_add.go delete mode 100644 backend/cmd/users_export.go delete mode 100644 backend/cmd/users_find.go delete mode 100644 backend/cmd/users_import.go delete mode 100644 backend/cmd/users_rm.go delete mode 100644 backend/cmd/users_update.go delete mode 100644 backend/cmd/version.go delete mode 100644 backend/http/commands.go diff --git a/backend/cmd/config.go b/backend/cmd/config.go index 9ee88b85..0d132d8b 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -9,7 +9,6 @@ import ( "text/tabwriter" "github.com/spf13/cobra" - "github.com/spf13/pflag" "github.com/gtsteffaniak/filebrowser/auth" "github.com/gtsteffaniak/filebrowser/errors" @@ -27,22 +26,6 @@ var configCmd = &cobra.Command{ Args: cobra.NoArgs, } -func addConfigFlags(flags *pflag.FlagSet) { - addUserFlags(flags) - flags.BoolP("signup", "s", false, "allow users to signup") - flags.String("shell", "", "shell command to which other commands should be appended") - - flags.String("recaptcha.host", "https://www.google.com", "use another host for ReCAPTCHA. recaptcha.net might be useful in China") - flags.String("recaptcha.key", "", "ReCaptcha site key") - flags.String("recaptcha.secret", "", "ReCaptcha secret") - - flags.String("frontend.name", "", "replace 'File Browser' by this name") - flags.String("frontend.color", "", "set the theme color") - flags.String("frontend.files", "", "path to directory with images and custom styles") - flags.Bool("frontend.disableExternal", false, "disable external links such as GitHub links") - flags.Bool("frontend.disableUsedPercentage", false, "disable used disk percentage graph") -} - //nolint:gocyclo func getAuthentication() (string, auth.Auther) { method := settings.GlobalConfiguration.Auth.Method diff --git a/backend/cmd/config_cat.go b/backend/cmd/config_cat.go deleted file mode 100644 index 3f06eb9f..00000000 --- a/backend/cmd/config_cat.go +++ /dev/null @@ -1,25 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - configCmd.AddCommand(configCatCmd) -} - -var configCatCmd = &cobra.Command{ - Use: "cat", - Short: "Prints the configuration", - Long: `Prints the configuration.`, - Args: cobra.NoArgs, - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - set, err := d.store.Settings.Get() - checkErr(err) - ser, err := d.store.Settings.GetServer() - checkErr(err) - auther, err := d.store.Auth.Get(set.Auth.Method) - checkErr(err) - printSettings(ser, set, auther) - }, pythonConfig{}), -} diff --git a/backend/cmd/config_export.go b/backend/cmd/config_export.go deleted file mode 100644 index a4d8ecff..00000000 --- a/backend/cmd/config_export.go +++ /dev/null @@ -1,37 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - configCmd.AddCommand(configExportCmd) -} - -var configExportCmd = &cobra.Command{ - 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) - - server, err := d.store.Settings.GetServer() - checkErr(err) - - auther, err := d.store.Auth.Get(settings.Auth.Method) - checkErr(err) - - data := &settingsFile{ - Settings: settings, - Auther: auther, - Server: server, - } - - err = marshal(args[0], data) - checkErr(err) - }, pythonConfig{}), -} diff --git a/backend/cmd/config_import.go b/backend/cmd/config_import.go deleted file mode 100644 index 08ff806d..00000000 --- a/backend/cmd/config_import.go +++ /dev/null @@ -1,94 +0,0 @@ -package cmd - -import ( - "encoding/json" - "errors" - "path/filepath" - "reflect" - "log" - - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/auth" - "github.com/gtsteffaniak/filebrowser/settings" -) - -func init() { - configCmd.AddCommand(configImportCmd) -} - -type settingsFile struct { - Settings *settings.Settings `json:"settings"` - Server *settings.Server `json:"server"` - Auther interface{} `json:"auther"` -} - -var configImportCmd = &cobra.Command{ - 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. - -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 - if d.hadDB { - settings, err := d.store.Settings.Get() - checkErr(err) - key = settings.Key - } else { - key = generateKey() - } - file := settingsFile{} - err := unmarshal(args[0], &file) - checkErr(err) - log.Println(file.Settings) - file.Settings.Key = key - err = d.store.Settings.Save(file.Settings) - checkErr(err) - - err = d.store.Settings.SaveServer(file.Server) - checkErr(err) - - var rawAuther interface{} - if filepath.Ext(args[0]) != ".json" { //nolint:goconst - rawAuther = cleanUpInterfaceMap(file.Auther.(map[interface{}]interface{})) - } else { - rawAuther = file.Auther - } - log.Println("config_import",file.Settings.Auth) - var auther auth.Auther - switch file.Settings.Auth.Method { - case "password": - auther = getAuther(auth.JSONAuth{}, rawAuther).(*auth.JSONAuth) - case "noauth": - auther = getAuther(auth.NoAuth{}, rawAuther).(*auth.NoAuth) - case "proxy": - auther = getAuther(auth.ProxyAuth{}, rawAuther).(*auth.ProxyAuth) - case "hook": - auther = getAuther(&auth.HookAuth{}, rawAuther).(*auth.HookAuth) - default: - checkErr(errors.New("invalid auth method")) - } - - err = d.store.Auth.Save(auther) - checkErr(err) - - printSettings(file.Server, file.Settings, auther) - }, pythonConfig{allowNoDB: true}), -} - -func getAuther(sample auth.Auther, data interface{}) interface{} { - authType := reflect.TypeOf(sample) - auther := reflect.New(authType).Interface() - bytes, err := json.Marshal(data) - checkErr(err) - err = json.Unmarshal(bytes, &auther) - checkErr(err) - return auther -} diff --git a/backend/cmd/config_init.go b/backend/cmd/config_init.go index 47bf8df7..b627762f 100644 --- a/backend/cmd/config_init.go +++ b/backend/cmd/config_init.go @@ -10,7 +10,6 @@ import ( func init() { configCmd.AddCommand(configInitCmd) - addConfigFlags(configInitCmd.Flags()) } var configInitCmd = &cobra.Command{ diff --git a/backend/cmd/config_set.go b/backend/cmd/config_set.go deleted file mode 100644 index f30dd088..00000000 --- a/backend/cmd/config_set.go +++ /dev/null @@ -1,74 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func init() { - configCmd.AddCommand(configSetCmd) - addConfigFlags(configSetCmd.Flags()) -} - -var configSetCmd = &cobra.Command{ - Use: "set", - Short: "Updates the configuration", - Long: `Updates the configuration. Set the flags for the options -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() - set, err := d.store.Settings.Get() - checkErr(err) - - ser, err := d.store.Settings.GetServer() - checkErr(err) - - flags.Visit(func(flag *pflag.Flag) { - switch flag.Name { - case "baseurl": - ser.BaseURL = mustGetString(flags, flag.Name) - case "root": - ser.Root = mustGetString(flags, flag.Name) - case "socket": - ser.Socket = mustGetString(flags, flag.Name) - case "cert": - ser.TLSCert = mustGetString(flags, flag.Name) - case "key": - ser.TLSKey = mustGetString(flags, flag.Name) - case "address": - ser.Address = mustGetString(flags, flag.Name) - case "port": - ser.Port = 8080 - case "log": - ser.Log = mustGetString(flags, flag.Name) - case "signup": - set.Signup = mustGetBool(flags, flag.Name) - case "shell": - set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name)) - case "frontend.name": - set.Frontend.Name = mustGetString(flags, flag.Name) - case "frontend.color": - set.Frontend.Color = mustGetString(flags, flag.Name) - case "frontend.disableExternal": - set.Frontend.DisableExternal = mustGetBool(flags, flag.Name) - case "frontend.disableUsedPercentage": - set.Frontend.DisableUsedPercentage = mustGetBool(flags, flag.Name) - case "frontend.files": - set.Frontend.Files = mustGetString(flags, flag.Name) - } - }) - - getUserDefaults(flags, &set.UserDefaults, false) - - // read the defaults - _, auther := getAuthentication() - err = d.store.Auth.Save(auther) - checkErr(err) - err = d.store.Settings.Save(set) - checkErr(err) - err = d.store.Settings.SaveServer(ser) - checkErr(err) - printSettings(ser, set, auther) - }, pythonConfig{}), -} diff --git a/backend/cmd/docs.go b/backend/cmd/docs.go deleted file mode 100644 index 9ebb9573..00000000 --- a/backend/cmd/docs.go +++ /dev/null @@ -1,139 +0,0 @@ -package cmd - -import ( - "bytes" - "fmt" - "io" - "os" - "path/filepath" - "sort" - "strings" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func init() { - rootCmd.AddCommand(docsCmd) - docsCmd.Flags().StringP("path", "p", "./docs", "path to save the docs") -} - -func printToc(names []string) { - for i, name := range names { - name = strings.TrimSuffix(name, filepath.Ext(name)) - name = strings.Replace(name, "-", " ", -1) - names[i] = name - } - - sort.Strings(names) - - toc := "" - for _, name := range names { - toc += "* [" + name + "](cli/" + strings.Replace(name, " ", "-", -1) + ".md)\n" - } - - fmt.Println(toc) -} - -var docsCmd = &cobra.Command{ - Use: "docs", - Hidden: true, - Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, args []string) { - dir := mustGetString(cmd.Flags(), "path") - generateDocs(rootCmd, dir) - names := []string{} - - err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if err != nil || info.IsDir() { - return err - } - - if !strings.HasPrefix(info.Name(), "filebrowser") { - return nil - } - - names = append(names, info.Name()) - return nil - }) - - checkErr(err) - printToc(names) - }, -} - -func generateDocs(cmd *cobra.Command, dir string) { - for _, c := range cmd.Commands() { - if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { - continue - } - - generateDocs(c, dir) - } - - basename := strings.Replace(cmd.CommandPath(), " ", "-", -1) + ".md" - filename := filepath.Join(dir, basename) - f, err := os.Create(filename) - checkErr(err) - defer f.Close() - generateMarkdown(cmd, f) -} - -func generateMarkdown(cmd *cobra.Command, w io.Writer) { - cmd.InitDefaultHelpCmd() - cmd.InitDefaultHelpFlag() - - buf := new(bytes.Buffer) - name := cmd.CommandPath() - - short := cmd.Short - long := cmd.Long - if long == "" { - long = short - } - - buf.WriteString("---\ndescription: " + short + "\n---\n\n") - buf.WriteString("# " + name + "\n\n") - buf.WriteString("## Synopsis\n\n") - buf.WriteString(long + "\n\n") - - if cmd.Runnable() { - buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) - } - - if len(cmd.Example) > 0 { - buf.WriteString("## Examples\n\n") - buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example)) - } - - printOptions(buf, cmd) - _, err := buf.WriteTo(w) - checkErr(err) -} - -func generateFlagsTable(fs *pflag.FlagSet, buf io.StringWriter) { - _, _ = buf.WriteString("| Name | Shorthand | Usage |\n") - _, _ = buf.WriteString("|------|-----------|-------|\n") - - fs.VisitAll(func(f *pflag.Flag) { - _, _ = buf.WriteString("|" + f.Name + "|" + f.Shorthand + "|" + f.Usage + "|\n") - }) -} - -func printOptions(buf *bytes.Buffer, cmd *cobra.Command) { - flags := cmd.NonInheritedFlags() - flags.SetOutput(buf) - if flags.HasAvailableFlags() { - buf.WriteString("## Options\n\n") - generateFlagsTable(flags, buf) - buf.WriteString("\n") - } - - parentFlags := cmd.InheritedFlags() - parentFlags.SetOutput(buf) - if parentFlags.HasAvailableFlags() { - buf.WriteString("### Inherited\n\n") - generateFlagsTable(parentFlags, buf) - buf.WriteString("\n") - } -} diff --git a/backend/cmd/hash.go b/backend/cmd/hash.go deleted file mode 100644 index 41718afa..00000000 --- a/backend/cmd/hash.go +++ /dev/null @@ -1,25 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - rootCmd.AddCommand(hashCmd) -} - -var hashCmd = &cobra.Command{ - Use: "hash ", - 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) - fmt.Println(pwd) - }, -} diff --git a/backend/cmd/root.go b/backend/cmd/root.go index e5b10c08..970fde83 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -142,6 +142,12 @@ user created with the credentials from options "username" and "password".`, }, pythonConfig{allowNoDB: true}), } +func StartFilebrowser() { + if err := rootCmd.Execute(); err != nil { + log.Fatal(err) + } +} + func cleanupHandler(listener net.Listener, c chan os.Signal) { //nolint:interfacer sig := <-c log.Printf("Caught signal %s: shutting down.", sig) diff --git a/backend/cmd/rule_rm.go b/backend/cmd/rule_rm.go deleted file mode 100644 index 0aea796c..00000000 --- a/backend/cmd/rule_rm.go +++ /dev/null @@ -1,66 +0,0 @@ -package cmd - -import ( - "strconv" - - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/settings" - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - rulesCmd.AddCommand(rulesRmCommand) - rulesRmCommand.Flags().Uint("index", 0, "index of rule to remove") - _ = rulesRmCommand.MarkFlagRequired("index") -} - -var rulesRmCommand = &cobra.Command{ - Use: "rm [index_end]", - Short: "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 { //nolint:gomnd - return err - } - - for _, arg := range args { - if _, err := strconv.Atoi(arg); err != nil { - return err - } - } - - return nil - }, - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - i, err := strconv.Atoi(args[0]) - checkErr(err) - f := i - if len(args) == 2 { //nolint:gomnd - f, err = strconv.Atoi(args[1]) - checkErr(err) - } - - user := func(u *users.User) { - u.Rules = append(u.Rules[:i], u.Rules[f+1:]...) - err := d.store.Users.Save(u) - checkErr(err) - } - - global := func(s *settings.Settings) { - s.Rules = append(s.Rules[:i], s.Rules[f+1:]...) - err := d.store.Settings.Save(s) - checkErr(err) - } - - runRules(d.store, cmd, user, global) - }, pythonConfig{}), -} diff --git a/backend/cmd/rules.go b/backend/cmd/rules.go deleted file mode 100644 index 69df0d33..00000000 --- a/backend/cmd/rules.go +++ /dev/null @@ -1,92 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - "github.com/gtsteffaniak/filebrowser/rules" - "github.com/gtsteffaniak/filebrowser/settings" - "github.com/gtsteffaniak/filebrowser/storage" - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - rootCmd.AddCommand(rulesCmd) - rulesCmd.PersistentFlags().StringP("username", "u", "", "username of user to which the rules apply") - rulesCmd.PersistentFlags().UintP("id", "i", 0, "id of user to which the rules apply") -} - -var rulesCmd = &cobra.Command{ - Use: "rules", - 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 -an user, otherwise it will be applied to the global set or -rules.`, - Args: cobra.NoArgs, -} - -func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User), globalFn func(*settings.Settings)) { - id := getUserIdentifier(cmd.Flags()) - if id != nil { - user, err := st.Users.Get("", id) - checkErr(err) - - if usersFn != nil { - usersFn(user) - } - - printRules(user.Rules, id) - return - } - - s, err := st.Settings.Get() - checkErr(err) - - if globalFn != nil { - globalFn(s) - } - - printRules(s.Rules, id) -} - -func getUserIdentifier(flags *pflag.FlagSet) interface{} { - id := mustGetUint(flags, "id") - username := mustGetString(flags, "username") - - if id != 0 { - return id - } else if username != "" { - return username - } - - return nil -} - -func printRules(rulez []rules.Rule, id interface{}) { - if id == nil { - fmt.Printf("Global Rules:\n\n") - } else { - fmt.Printf("Rules for user %v:\n\n", id) - } - - for id, rule := range rulez { - fmt.Printf("(%d) ", id) - if rule.Regex { - if rule.Allow { - fmt.Printf("Allow Regex: \t%s\n", rule.Regexp.Raw) - } else { - fmt.Printf("Disallow Regex: \t%s\n", rule.Regexp.Raw) - } - } else { - if rule.Allow { - fmt.Printf("Allow Path: \t%s\n", rule.Path) - } else { - fmt.Printf("Disallow Path: \t%s\n", rule.Path) - } - } - } -} diff --git a/backend/cmd/rules_add.go b/backend/cmd/rules_add.go deleted file mode 100644 index 768717bd..00000000 --- a/backend/cmd/rules_add.go +++ /dev/null @@ -1,58 +0,0 @@ -package cmd - -import ( - "regexp" - - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/rules" - "github.com/gtsteffaniak/filebrowser/settings" - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - rulesCmd.AddCommand(rulesAddCmd) - rulesAddCmd.Flags().BoolP("allow", "a", false, "indicates this is an allow rule") - rulesAddCmd.Flags().BoolP("regex", "r", false, "indicates this is a regex rule") -} - -var rulesAddCmd = &cobra.Command{ - Use: "add ", - Short: "Add a global rule or user rule", - Long: `Add a global rule or user rule.`, - Args: cobra.ExactArgs(1), - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - allow := mustGetBool(cmd.Flags(), "allow") - regex := mustGetBool(cmd.Flags(), "regex") - exp := args[0] - - if regex { - regexp.MustCompile(exp) - } - - rule := rules.Rule{ - Allow: allow, - Regex: regex, - } - - if regex { - rule.Regexp = &rules.Regexp{Raw: exp} - } else { - rule.Path = exp - } - - user := func(u *users.User) { - u.Rules = append(u.Rules, rule) - err := d.store.Users.Save(u) - checkErr(err) - } - - global := func(s *settings.Settings) { - s.Rules = append(s.Rules, rule) - err := d.store.Settings.Save(s) - checkErr(err) - } - - runRules(d.store, cmd, user, global) - }, pythonConfig{}), -} diff --git a/backend/cmd/rules_ls.go b/backend/cmd/rules_ls.go deleted file mode 100644 index e0e5f8f8..00000000 --- a/backend/cmd/rules_ls.go +++ /dev/null @@ -1,19 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - rulesCmd.AddCommand(rulesLsCommand) -} - -var rulesLsCommand = &cobra.Command{ - Use: "ls", - Short: "List global rules or user specific rules", - Long: `List global rules or user specific rules.`, - Args: cobra.NoArgs, - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - runRules(d.store, cmd, nil, nil) - }, pythonConfig{}), -} diff --git a/backend/cmd/users_add.go b/backend/cmd/users_add.go deleted file mode 100644 index eac81240..00000000 --- a/backend/cmd/users_add.go +++ /dev/null @@ -1,51 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - usersCmd.AddCommand(usersAddCmd) - addUserFlags(usersAddCmd.Flags()) -} - -var usersAddCmd = &cobra.Command{ - Use: "add ", - Short: "Create a new user", - Long: `Create a new user and add it to the database.`, - Args: cobra.ExactArgs(2), //nolint:gomnd - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - s, err := d.store.Settings.Get() - checkErr(err) - getUserDefaults(cmd.Flags(), &s.UserDefaults, false) - - password, err := users.HashPwd(args[1]) - checkErr(err) - - user := &users.User{ - Username: args[0], - Password: password, - LockPassword: mustGetBool(cmd.Flags(), "lockPassword"), - } - - s.UserDefaults.Apply(user) - - servSettings, err := d.store.Settings.GetServer() - checkErr(err) - // since getUserDefaults() polluted s.Defaults.Scope - // which makes the Scope not the one saved in the db - // we need the right s.Defaults.Scope here - s2, err := d.store.Settings.Get() - checkErr(err) - - userHome, err := s2.MakeUserDir(user.Username, user.Scope, servSettings.Root) - checkErr(err) - user.Scope = userHome - - err = d.store.Users.Save(user) - checkErr(err) - printUsers([]*users.User{user}) - }, pythonConfig{}), -} diff --git a/backend/cmd/users_export.go b/backend/cmd/users_export.go deleted file mode 100644 index c0160f68..00000000 --- a/backend/cmd/users_export.go +++ /dev/null @@ -1,24 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - usersCmd.AddCommand(usersExportCmd) -} - -var usersExportCmd = &cobra.Command{ - 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) - - err = marshal(args[0], list) - checkErr(err) - }, pythonConfig{}), -} diff --git a/backend/cmd/users_find.go b/backend/cmd/users_find.go deleted file mode 100644 index b00959c4..00000000 --- a/backend/cmd/users_find.go +++ /dev/null @@ -1,51 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - usersCmd.AddCommand(usersFindCmd) - usersCmd.AddCommand(usersLsCmd) -} - -var usersFindCmd = &cobra.Command{ - Use: "find ", - Short: "Find a user by username or id", - Long: `Find a user by username or id. If no flag is set, all users will be printed.`, - Args: cobra.ExactArgs(1), - Run: findUsers, -} - -var usersLsCmd = &cobra.Command{ - Use: "ls", - Short: "List all users.", - Args: cobra.NoArgs, - Run: findUsers, -} - -var findUsers = python(func(cmd *cobra.Command, args []string, d pythonData) { - var ( - list []*users.User - user *users.User - err error - ) - - if len(args) == 1 { - username, id := parseUsernameOrID(args[0]) - if username != "" { - user, err = d.store.Users.Get("", username) - } else { - user, err = d.store.Users.Get("", id) - } - - list = []*users.User{user} - } else { - list, err = d.store.Users.Gets("") - } - - checkErr(err) - printUsers(list) -}, pythonConfig{}) diff --git a/backend/cmd/users_import.go b/backend/cmd/users_import.go deleted file mode 100644 index d5be6e9c..00000000 --- a/backend/cmd/users_import.go +++ /dev/null @@ -1,89 +0,0 @@ -package cmd - -import ( - "errors" - "fmt" - "os" - "strconv" - - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - usersCmd.AddCommand(usersImportCmd) - usersImportCmd.Flags().Bool("overwrite", false, "overwrite users with the same id/username combo") - usersImportCmd.Flags().Bool("replace", false, "replace the entire user base") -} - -var usersImportCmd = &cobra.Command{ - 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) - defer fd.Close() - - list := []*users.User{} - err = unmarshal(args[0], &list) - checkErr(err) - - for _, user := range list { - err = user.Clean("") - checkErr(err) - } - - 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 { - onDB, err := d.store.Users.Get("", user.ID) - - // User exists in DB. - if err == nil { - if !overwrite { - checkErr(errors.New("user " + strconv.Itoa(int(user.ID)) + " is already registred")) - } - - // If the usernames mismatch, check if there is another one in the DB - // with the new username. If there is, print an error and cancel the - // operation - if user.Username != onDB.Username { - if conflictuous, err := d.store.Users.Get("", user.Username); err == nil { //nolint:govet - checkErr(usernameConflictError(user.Username, conflictuous.ID, user.ID)) - } - } - } else { - // If it doesn't exist, set the ID to 0 to automatically get a new - // one that make sense in this DB. - user.ID = 0 - } - - err = d.store.Users.Save(user) - checkErr(err) - } - }, pythonConfig{}), -} - -func usernameConflictError(username string, originalID, newID uint) error { - return fmt.Errorf(`can't import user with ID %d and username "%s" because the username is already registred with the user %d`, - newID, username, originalID) -} diff --git a/backend/cmd/users_rm.go b/backend/cmd/users_rm.go deleted file mode 100644 index e3fef01b..00000000 --- a/backend/cmd/users_rm.go +++ /dev/null @@ -1,31 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -func init() { - usersCmd.AddCommand(usersRmCmd) -} - -var usersRmCmd = &cobra.Command{ - Use: "rm ", - Short: "Delete a user by username or id", - Long: `Delete a user by username or id`, - Args: cobra.ExactArgs(1), - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - username, id := parseUsernameOrID(args[0]) - var err error - - if username != "" { - err = d.store.Users.Delete(username) - } else { - err = d.store.Users.Delete(id) - } - - checkErr(err) - fmt.Println("user deleted successfully") - }, pythonConfig{}), -} diff --git a/backend/cmd/users_update.go b/backend/cmd/users_update.go deleted file mode 100644 index 09bb4b8d..00000000 --- a/backend/cmd/users_update.go +++ /dev/null @@ -1,75 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/settings" - "github.com/gtsteffaniak/filebrowser/users" -) - -func init() { - usersCmd.AddCommand(usersUpdateCmd) - - usersUpdateCmd.Flags().StringP("password", "p", "", "new password") - usersUpdateCmd.Flags().StringP("username", "u", "", "new username") - addUserFlags(usersUpdateCmd.Flags()) -} - -var usersUpdateCmd = &cobra.Command{ - Use: "update ", - Short: "Updates an existing user", - Long: `Updates an existing user. Set the flags for the -options you want to change.`, - Args: cobra.ExactArgs(1), - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - username, id := parseUsernameOrID(args[0]) - flags := cmd.Flags() - password := mustGetString(flags, "password") - newUsername := mustGetString(flags, "username") - - var ( - err error - user *users.User - ) - - if id != 0 { - user, err = d.store.Users.Get("", id) - } else { - user, err = d.store.Users.Get("", username) - } - - checkErr(err) - - defaults := settings.UserDefaults{ - Scope: user.Scope, - Locale: user.Locale, - ViewMode: user.ViewMode, - SingleClick: user.SingleClick, - Perm: user.Perm, - Sorting: user.Sorting, - Commands: user.Commands, - } - getUserDefaults(flags, &defaults, false) - user.Scope = defaults.Scope - user.Locale = defaults.Locale - user.ViewMode = defaults.ViewMode - user.SingleClick = defaults.SingleClick - user.Perm = defaults.Perm - user.Commands = defaults.Commands - user.Sorting = defaults.Sorting - user.LockPassword = mustGetBool(flags, "lockPassword") - - if newUsername != "" { - user.Username = newUsername - } - - if password != "" { - user.Password, err = users.HashPwd(password) - checkErr(err) - } - - err = d.store.Users.Update(user) - checkErr(err) - printUsers([]*users.User{user}) - }, pythonConfig{}), -} diff --git a/backend/cmd/version.go b/backend/cmd/version.go deleted file mode 100644 index 2e085103..00000000 --- a/backend/cmd/version.go +++ /dev/null @@ -1,21 +0,0 @@ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/gtsteffaniak/filebrowser/version" -) - -func init() { - rootCmd.AddCommand(versionCmd) -} - -var versionCmd = &cobra.Command{ - Use: "version", - Short: "Print the version number", - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("File Browser v" + version.Version + "/" + version.CommitSHA) - }, -} diff --git a/backend/http/commands.go b/backend/http/commands.go deleted file mode 100644 index cf886541..00000000 --- a/backend/http/commands.go +++ /dev/null @@ -1,111 +0,0 @@ -package http - -import ( - "bufio" - "io" - "log" - "net/http" - "os/exec" - "strings" - "time" - - "github.com/gorilla/websocket" - - "github.com/gtsteffaniak/filebrowser/runner" -) - -const ( - WSWriteDeadline = 10 * time.Second -) - -var upgrader = websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, -} - -var ( - cmdNotAllowed = []byte("Command not allowed.") -) - -//nolint:unparam -func wsErr(ws *websocket.Conn, r *http.Request, status int, err error) { - txt := http.StatusText(status) - if err != nil || status >= 400 { - log.Printf("%s: %v %s %v", r.URL.Path, status, r.RemoteAddr, err) - } - if err := ws.WriteControl(websocket.CloseInternalServerErr, []byte(txt), time.Now().Add(WSWriteDeadline)); err != nil { - log.Print(err) - } -} - -var commandsHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) { - conn, err := upgrader.Upgrade(w, r, nil) - if err != nil { - return http.StatusInternalServerError, err - } - defer conn.Close() - - var raw string - - for { - _, msg, err := conn.ReadMessage() //nolint:govet - if err != nil { - wsErr(conn, r, http.StatusInternalServerError, err) - return 0, nil - } - - raw = strings.TrimSpace(string(msg)) - if raw != "" { - break - } - } - - command, err := runner.ParseCommand(d.settings, raw) - if err != nil { - if err := conn.WriteMessage(websocket.TextMessage, []byte(err.Error())); err != nil { //nolint:govet - wsErr(conn, r, http.StatusInternalServerError, err) - } - return 0, nil - } - - if !d.server.EnableExec || !d.user.CanExecute(command[0]) { - if err := conn.WriteMessage(websocket.TextMessage, cmdNotAllowed); err != nil { //nolint:govet - wsErr(conn, r, http.StatusInternalServerError, err) - } - - return 0, nil - } - - cmd := exec.Command(command[0], command[1:]...) //nolint:gosec - cmd.Dir = d.user.FullPath(r.URL.Path) - - stdout, err := cmd.StdoutPipe() - if err != nil { - wsErr(conn, r, http.StatusInternalServerError, err) - return 0, nil - } - - stderr, err := cmd.StderrPipe() - if err != nil { - wsErr(conn, r, http.StatusInternalServerError, err) - return 0, nil - } - - if err := cmd.Start(); err != nil { - wsErr(conn, r, http.StatusInternalServerError, err) - return 0, nil - } - - s := bufio.NewScanner(io.MultiReader(stdout, stderr)) - for s.Scan() { - if err := conn.WriteMessage(websocket.TextMessage, s.Bytes()); err != nil { - log.Print(err) - } - } - - if err := cmd.Wait(); err != nil { - wsErr(conn, r, http.StatusInternalServerError, err) - } - - return 0, nil -}) diff --git a/backend/http/http.go b/backend/http/http.go index 2ef52c10..f12470fd 100644 --- a/backend/http/http.go +++ b/backend/http/http.go @@ -32,58 +32,44 @@ func NewHandler( }) }) index, static := getStaticHandlers(store, server, assetsFs) - // NOTE: This fixes the issue where it would redirect if people did not put a // trailing slash in the end. I hate this decision since this allows some awful // URLs https://www.gorillatoolkit.org/pkg/mux#Router.SkipClean r = r.SkipClean(true) - monkey := func(fn handleFunc, prefix string) http.Handler { return handle(fn, prefix, store, server) } - r.HandleFunc("/health", healthHandler) r.PathPrefix("/static").Handler(static) r.NotFoundHandler = index - api := r.PathPrefix("/api").Subrouter() - api.Handle("/login", monkey(loginHandler, "")) api.Handle("/signup", monkey(signupHandler, "")) api.Handle("/renew", monkey(renewHandler, "")) - users := api.PathPrefix("/users").Subrouter() users.Handle("", monkey(usersGetHandler, "")).Methods("GET") users.Handle("", monkey(userPostHandler, "")).Methods("POST") users.Handle("/{id:[0-9]+}", monkey(userPutHandler, "")).Methods("PUT") users.Handle("/{id:[0-9]+}", monkey(userGetHandler, "")).Methods("GET") users.Handle("/{id:[0-9]+}", monkey(userDeleteHandler, "")).Methods("DELETE") - api.PathPrefix("/resources").Handler(monkey(resourceGetHandler, "/api/resources")).Methods("GET") api.PathPrefix("/resources").Handler(monkey(resourceDeleteHandler(fileCache), "/api/resources")).Methods("DELETE") api.PathPrefix("/resources").Handler(monkey(resourcePostHandler(fileCache), "/api/resources")).Methods("POST") api.PathPrefix("/resources").Handler(monkey(resourcePutHandler, "/api/resources")).Methods("PUT") api.PathPrefix("/resources").Handler(monkey(resourcePatchHandler(fileCache), "/api/resources")).Methods("PATCH") - api.PathPrefix("/usage").Handler(monkey(diskUsage, "/api/usage")).Methods("GET") - api.Path("/shares").Handler(monkey(shareListHandler, "/api/shares")).Methods("GET") api.PathPrefix("/share").Handler(monkey(shareGetsHandler, "/api/share")).Methods("GET") api.PathPrefix("/share").Handler(monkey(sharePostHandler, "/api/share")).Methods("POST") api.PathPrefix("/share").Handler(monkey(shareDeleteHandler, "/api/share")).Methods("DELETE") - api.Handle("/settings", monkey(settingsGetHandler, "")).Methods("GET") api.Handle("/settings", monkey(settingsPutHandler, "")).Methods("PUT") - api.PathPrefix("/raw").Handler(monkey(rawHandler, "/api/raw")).Methods("GET") api.PathPrefix("/preview/{size}/{path:.*}"). Handler(monkey(previewHandler(imgSvc, fileCache, server.EnableThumbnails, server.ResizePreview), "/api/preview")).Methods("GET") - api.PathPrefix("/command").Handler(monkey(commandsHandler, "/api/command")).Methods("GET") api.PathPrefix("/search").Handler(monkey(searchHandler, "/api/search")).Methods("GET") - public := api.PathPrefix("/public").Subrouter() public.PathPrefix("/dl").Handler(monkey(publicDlHandler, "/api/public/dl/")).Methods("GET") public.PathPrefix("/share").Handler(monkey(publicShareHandler, "/api/public/share/")).Methods("GET") - return stripPrefix(server.BaseURL, r), nil } diff --git a/backend/main.go b/backend/main.go index 0859625e..9f606708 100644 --- a/backend/main.go +++ b/backend/main.go @@ -5,5 +5,5 @@ import ( ) func main() { - cmd.Execute() + cmd.StartFilebrowser() } From a4fd7dc7bbe9b0dbddbcaddc9c3b30bdec3b6218 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 11:24:49 -0500 Subject: [PATCH 03/11] updated --- backend/cmd/config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/cmd/config.go b/backend/cmd/config.go index 0d132d8b..cb2b98b0 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -112,7 +112,6 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintf(w, "\tColor:\t%s\n", set.Frontend.Color) fmt.Fprintln(w, "\nServer:") fmt.Fprintf(w, "\tLog:\t%s\n", ser.Log) - fmt.Fprintf(w, "\tPort:\t%s\n", ser.Port) fmt.Fprintf(w, "\tBase URL:\t%s\n", ser.BaseURL) fmt.Fprintf(w, "\tRoot:\t%s\n", ser.Root) fmt.Fprintf(w, "\tSocket:\t%s\n", ser.Socket) From 59decc06119dd71228d6c04cdb59b0667dcff8dd Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 11:26:01 -0500 Subject: [PATCH 04/11] updated results --- backend/benchmark_results.txt | 40 +++++++++++++++++------------------ backend/run_benchmark.sh | 1 - 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/backend/benchmark_results.txt b/backend/benchmark_results.txt index 973bc2e5..7eed7250 100644 --- a/backend/benchmark_results.txt +++ b/backend/benchmark_results.txt @@ -1,40 +1,38 @@ == Running benchmark == +/usr/local/go/bin/go ? github.com/gtsteffaniak/filebrowser [no test files] ? github.com/gtsteffaniak/filebrowser/auth [no test files] ? github.com/gtsteffaniak/filebrowser/cmd [no test files] PASS -ok github.com/gtsteffaniak/filebrowser/diskcache 0.588s +ok github.com/gtsteffaniak/filebrowser/diskcache 0.004s ? github.com/gtsteffaniak/filebrowser/errors [no test files] ? github.com/gtsteffaniak/filebrowser/files [no test files] PASS -ok github.com/gtsteffaniak/filebrowser/fileutils 0.212s -2023/08/18 17:10:41 h: 401 -2023/08/18 17:10:41 h: 401 -2023/08/18 17:10:41 h: 401 -2023/08/18 17:10:41 h: 401 -2023/08/18 17:10:41 h: 401 -2023/08/18 17:10:41 h: 401 +ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s +2023/09/02 11:25:34 Error opening YAML file: open filebrowser.yml: no such file or directory +exit status 1 +FAIL github.com/gtsteffaniak/filebrowser/http 0.002s PASS -ok github.com/gtsteffaniak/filebrowser/http 0.753s +ok github.com/gtsteffaniak/filebrowser/img 0.121s PASS -ok github.com/gtsteffaniak/filebrowser/img 0.362s -PASS -ok github.com/gtsteffaniak/filebrowser/rules 0.182s -PASS -ok github.com/gtsteffaniak/filebrowser/runner 0.198s -goos: darwin -goarch: arm64 +ok github.com/gtsteffaniak/filebrowser/rules 0.002s +2023/09/02 11:25:34 Error opening YAML file: open filebrowser.yml: no such file or directory +exit status 1 +FAIL github.com/gtsteffaniak/filebrowser/runner 0.002s +goos: linux +goarch: amd64 pkg: github.com/gtsteffaniak/filebrowser/search -BenchmarkSearchAllIndexes-10 10 5802738 ns/op 2756774 B/op 42606 allocs/op -BenchmarkFillIndex-10 10 4769329 ns/op 18512 B/op 453 allocs/op +cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz +BenchmarkSearchAllIndexes-8 10 5943468 ns/op 2980324 B/op 45985 allocs/op +BenchmarkFillIndex-8 10 3353868 ns/op 18476 B/op 451 allocs/op PASS -ok github.com/gtsteffaniak/filebrowser/search 0.356s +ok github.com/gtsteffaniak/filebrowser/search 0.119s ? github.com/gtsteffaniak/filebrowser/settings [no test files] ? github.com/gtsteffaniak/filebrowser/share [no test files] ? github.com/gtsteffaniak/filebrowser/storage [no test files] ? github.com/gtsteffaniak/filebrowser/storage/bolt [no test files] -? github.com/gtsteffaniak/filebrowser/storage/bolt/importer [no test files] PASS -ok github.com/gtsteffaniak/filebrowser/users 0.201s +ok github.com/gtsteffaniak/filebrowser/users 0.003s ? github.com/gtsteffaniak/filebrowser/version [no test files] +FAIL diff --git a/backend/run_benchmark.sh b/backend/run_benchmark.sh index 5e8e34cd..b9e2a2f0 100755 --- a/backend/run_benchmark.sh +++ b/backend/run_benchmark.sh @@ -1,6 +1,5 @@ #!/bin/sh ## TEST file used by docker testing containers -touch render.yml checkExit() { if [ "$?" -ne 0 ];then exit 1 From 0338a7b9475426093f565703890eb70c71697f1f Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 12:24:55 -0500 Subject: [PATCH 05/11] updated --- backend/cmd/cmd.go | 12 +++ backend/cmd/cmds.go | 26 +++++++ backend/cmd/cmds_add.go | 27 +++++++ backend/cmd/cmds_ls.go | 31 ++++++++ backend/cmd/cmds_rm.go | 56 ++++++++++++++ backend/cmd/config.go | 18 +++++ backend/cmd/config_cat.go | 25 +++++++ backend/cmd/config_export.go | 37 ++++++++++ backend/cmd/config_import.go | 94 +++++++++++++++++++++++ backend/cmd/config_init.go | 1 + backend/cmd/config_set.go | 74 +++++++++++++++++++ backend/cmd/docs.go | 139 +++++++++++++++++++++++++++++++++++ backend/cmd/hash.go | 25 +++++++ backend/cmd/rule_rm.go | 66 +++++++++++++++++ backend/cmd/rules.go | 92 +++++++++++++++++++++++ backend/cmd/rules_add.go | 58 +++++++++++++++ backend/cmd/rules_ls.go | 19 +++++ backend/cmd/users_add.go | 51 +++++++++++++ backend/cmd/users_export.go | 24 ++++++ backend/cmd/users_find.go | 51 +++++++++++++ backend/cmd/users_import.go | 89 ++++++++++++++++++++++ backend/cmd/users_rm.go | 31 ++++++++ backend/cmd/users_update.go | 75 +++++++++++++++++++ backend/cmd/utils.go | 4 +- backend/cmd/version.go | 21 ++++++ backend/filebrowser.yml | 28 +++---- 26 files changed, 1158 insertions(+), 16 deletions(-) create mode 100644 backend/cmd/cmd.go create mode 100644 backend/cmd/cmds.go create mode 100644 backend/cmd/cmds_add.go create mode 100644 backend/cmd/cmds_ls.go create mode 100644 backend/cmd/cmds_rm.go create mode 100644 backend/cmd/config_cat.go create mode 100644 backend/cmd/config_export.go create mode 100644 backend/cmd/config_import.go create mode 100644 backend/cmd/config_set.go create mode 100644 backend/cmd/docs.go create mode 100644 backend/cmd/hash.go create mode 100644 backend/cmd/rule_rm.go create mode 100644 backend/cmd/rules.go create mode 100644 backend/cmd/rules_add.go create mode 100644 backend/cmd/rules_ls.go create mode 100644 backend/cmd/users_add.go create mode 100644 backend/cmd/users_export.go create mode 100644 backend/cmd/users_find.go create mode 100644 backend/cmd/users_import.go create mode 100644 backend/cmd/users_rm.go create mode 100644 backend/cmd/users_update.go create mode 100644 backend/cmd/version.go diff --git a/backend/cmd/cmd.go b/backend/cmd/cmd.go new file mode 100644 index 00000000..18f52337 --- /dev/null +++ b/backend/cmd/cmd.go @@ -0,0 +1,12 @@ +package cmd + +import ( + "log" +) + +// Execute executes the commands. +func Execute() { + if err := rootCmd.Execute(); err != nil { + log.Fatal(err) + } +} diff --git a/backend/cmd/cmds.go b/backend/cmd/cmds.go new file mode 100644 index 00000000..cf951995 --- /dev/null +++ b/backend/cmd/cmds.go @@ -0,0 +1,26 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(cmdsCmd) +} + +var cmdsCmd = &cobra.Command{ + Use: "cmds", + Short: "Command runner management utility", + Long: `Command runner management utility.`, + Args: cobra.NoArgs, +} + +func printEvents(m map[string][]string) { + for evt, cmds := range m { + for i, cmd := range cmds { + fmt.Printf("%s(%d): %s\n", evt, i, cmd) + } + } +} diff --git a/backend/cmd/cmds_add.go b/backend/cmd/cmds_add.go new file mode 100644 index 00000000..fd2c0dc5 --- /dev/null +++ b/backend/cmd/cmds_add.go @@ -0,0 +1,27 @@ +package cmd + +import ( + "strings" + + "github.com/spf13/cobra" +) + +func init() { + cmdsCmd.AddCommand(cmdsAddCmd) +} + +var cmdsAddCmd = &cobra.Command{ + Use: "add ", + Short: "Add a command to run on a specific event", + Long: `Add a command to run on a specific event.`, + Args: cobra.MinimumNArgs(2), //nolint:gomnd + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + s, err := d.store.Settings.Get() + checkErr(err) + command := strings.Join(args[1:], " ") + s.Commands[args[0]] = append(s.Commands[args[0]], command) + err = d.store.Settings.Save(s) + checkErr(err) + printEvents(s.Commands) + }, pythonConfig{}), +} diff --git a/backend/cmd/cmds_ls.go b/backend/cmd/cmds_ls.go new file mode 100644 index 00000000..71f36382 --- /dev/null +++ b/backend/cmd/cmds_ls.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +func init() { + cmdsCmd.AddCommand(cmdsLsCmd) + cmdsLsCmd.Flags().StringP("event", "e", "", "event name, without 'before' or 'after'") +} + +var cmdsLsCmd = &cobra.Command{ + Use: "ls", + Short: "List all commands for each event", + Long: `List all commands for each event.`, + Args: cobra.NoArgs, + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + s, err := d.store.Settings.Get() + checkErr(err) + evt := mustGetString(cmd.Flags(), "event") + + if evt == "" { + printEvents(s.Commands) + } else { + show := map[string][]string{} + show["before_"+evt] = s.Commands["before_"+evt] + show["after_"+evt] = s.Commands["after_"+evt] + printEvents(show) + } + }, pythonConfig{}), +} diff --git a/backend/cmd/cmds_rm.go b/backend/cmd/cmds_rm.go new file mode 100644 index 00000000..e1f78863 --- /dev/null +++ b/backend/cmd/cmds_rm.go @@ -0,0 +1,56 @@ +package cmd + +import ( + "strconv" + + "github.com/spf13/cobra" +) + +func init() { + cmdsCmd.AddCommand(cmdsRmCmd) +} + +var cmdsRmCmd = &cobra.Command{ + Use: "rm [index_end]", + Short: "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 { //nolint:gomnd + return err + } + + for _, arg := range args[1:] { + if _, err := strconv.Atoi(arg); err != nil { + return err + } + } + + return nil + }, + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + s, err := d.store.Settings.Get() + checkErr(err) + evt := args[0] + + i, err := strconv.Atoi(args[1]) + checkErr(err) + f := i + if len(args) == 3 { //nolint:gomnd + f, err = strconv.Atoi(args[2]) + checkErr(err) + } + + s.Commands[evt] = append(s.Commands[evt][:i], s.Commands[evt][f+1:]...) + err = d.store.Settings.Save(s) + checkErr(err) + printEvents(s.Commands) + }, pythonConfig{}), +} diff --git a/backend/cmd/config.go b/backend/cmd/config.go index cb2b98b0..9ee88b85 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -9,6 +9,7 @@ import ( "text/tabwriter" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/gtsteffaniak/filebrowser/auth" "github.com/gtsteffaniak/filebrowser/errors" @@ -26,6 +27,22 @@ var configCmd = &cobra.Command{ Args: cobra.NoArgs, } +func addConfigFlags(flags *pflag.FlagSet) { + addUserFlags(flags) + flags.BoolP("signup", "s", false, "allow users to signup") + flags.String("shell", "", "shell command to which other commands should be appended") + + flags.String("recaptcha.host", "https://www.google.com", "use another host for ReCAPTCHA. recaptcha.net might be useful in China") + flags.String("recaptcha.key", "", "ReCaptcha site key") + flags.String("recaptcha.secret", "", "ReCaptcha secret") + + flags.String("frontend.name", "", "replace 'File Browser' by this name") + flags.String("frontend.color", "", "set the theme color") + flags.String("frontend.files", "", "path to directory with images and custom styles") + flags.Bool("frontend.disableExternal", false, "disable external links such as GitHub links") + flags.Bool("frontend.disableUsedPercentage", false, "disable used disk percentage graph") +} + //nolint:gocyclo func getAuthentication() (string, auth.Auther) { method := settings.GlobalConfiguration.Auth.Method @@ -112,6 +129,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintf(w, "\tColor:\t%s\n", set.Frontend.Color) fmt.Fprintln(w, "\nServer:") fmt.Fprintf(w, "\tLog:\t%s\n", ser.Log) + fmt.Fprintf(w, "\tPort:\t%s\n", ser.Port) fmt.Fprintf(w, "\tBase URL:\t%s\n", ser.BaseURL) fmt.Fprintf(w, "\tRoot:\t%s\n", ser.Root) fmt.Fprintf(w, "\tSocket:\t%s\n", ser.Socket) diff --git a/backend/cmd/config_cat.go b/backend/cmd/config_cat.go new file mode 100644 index 00000000..3f06eb9f --- /dev/null +++ b/backend/cmd/config_cat.go @@ -0,0 +1,25 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +func init() { + configCmd.AddCommand(configCatCmd) +} + +var configCatCmd = &cobra.Command{ + Use: "cat", + Short: "Prints the configuration", + Long: `Prints the configuration.`, + Args: cobra.NoArgs, + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + set, err := d.store.Settings.Get() + checkErr(err) + ser, err := d.store.Settings.GetServer() + checkErr(err) + auther, err := d.store.Auth.Get(set.Auth.Method) + checkErr(err) + printSettings(ser, set, auther) + }, pythonConfig{}), +} diff --git a/backend/cmd/config_export.go b/backend/cmd/config_export.go new file mode 100644 index 00000000..a4d8ecff --- /dev/null +++ b/backend/cmd/config_export.go @@ -0,0 +1,37 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +func init() { + configCmd.AddCommand(configExportCmd) +} + +var configExportCmd = &cobra.Command{ + 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) + + server, err := d.store.Settings.GetServer() + checkErr(err) + + auther, err := d.store.Auth.Get(settings.Auth.Method) + checkErr(err) + + data := &settingsFile{ + Settings: settings, + Auther: auther, + Server: server, + } + + err = marshal(args[0], data) + checkErr(err) + }, pythonConfig{}), +} diff --git a/backend/cmd/config_import.go b/backend/cmd/config_import.go new file mode 100644 index 00000000..08ff806d --- /dev/null +++ b/backend/cmd/config_import.go @@ -0,0 +1,94 @@ +package cmd + +import ( + "encoding/json" + "errors" + "path/filepath" + "reflect" + "log" + + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/auth" + "github.com/gtsteffaniak/filebrowser/settings" +) + +func init() { + configCmd.AddCommand(configImportCmd) +} + +type settingsFile struct { + Settings *settings.Settings `json:"settings"` + Server *settings.Server `json:"server"` + Auther interface{} `json:"auther"` +} + +var configImportCmd = &cobra.Command{ + 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. + +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 + if d.hadDB { + settings, err := d.store.Settings.Get() + checkErr(err) + key = settings.Key + } else { + key = generateKey() + } + file := settingsFile{} + err := unmarshal(args[0], &file) + checkErr(err) + log.Println(file.Settings) + file.Settings.Key = key + err = d.store.Settings.Save(file.Settings) + checkErr(err) + + err = d.store.Settings.SaveServer(file.Server) + checkErr(err) + + var rawAuther interface{} + if filepath.Ext(args[0]) != ".json" { //nolint:goconst + rawAuther = cleanUpInterfaceMap(file.Auther.(map[interface{}]interface{})) + } else { + rawAuther = file.Auther + } + log.Println("config_import",file.Settings.Auth) + var auther auth.Auther + switch file.Settings.Auth.Method { + case "password": + auther = getAuther(auth.JSONAuth{}, rawAuther).(*auth.JSONAuth) + case "noauth": + auther = getAuther(auth.NoAuth{}, rawAuther).(*auth.NoAuth) + case "proxy": + auther = getAuther(auth.ProxyAuth{}, rawAuther).(*auth.ProxyAuth) + case "hook": + auther = getAuther(&auth.HookAuth{}, rawAuther).(*auth.HookAuth) + default: + checkErr(errors.New("invalid auth method")) + } + + err = d.store.Auth.Save(auther) + checkErr(err) + + printSettings(file.Server, file.Settings, auther) + }, pythonConfig{allowNoDB: true}), +} + +func getAuther(sample auth.Auther, data interface{}) interface{} { + authType := reflect.TypeOf(sample) + auther := reflect.New(authType).Interface() + bytes, err := json.Marshal(data) + checkErr(err) + err = json.Unmarshal(bytes, &auther) + checkErr(err) + return auther +} diff --git a/backend/cmd/config_init.go b/backend/cmd/config_init.go index b627762f..47bf8df7 100644 --- a/backend/cmd/config_init.go +++ b/backend/cmd/config_init.go @@ -10,6 +10,7 @@ import ( func init() { configCmd.AddCommand(configInitCmd) + addConfigFlags(configInitCmd.Flags()) } var configInitCmd = &cobra.Command{ diff --git a/backend/cmd/config_set.go b/backend/cmd/config_set.go new file mode 100644 index 00000000..f30dd088 --- /dev/null +++ b/backend/cmd/config_set.go @@ -0,0 +1,74 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +func init() { + configCmd.AddCommand(configSetCmd) + addConfigFlags(configSetCmd.Flags()) +} + +var configSetCmd = &cobra.Command{ + Use: "set", + Short: "Updates the configuration", + Long: `Updates the configuration. Set the flags for the options +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() + set, err := d.store.Settings.Get() + checkErr(err) + + ser, err := d.store.Settings.GetServer() + checkErr(err) + + flags.Visit(func(flag *pflag.Flag) { + switch flag.Name { + case "baseurl": + ser.BaseURL = mustGetString(flags, flag.Name) + case "root": + ser.Root = mustGetString(flags, flag.Name) + case "socket": + ser.Socket = mustGetString(flags, flag.Name) + case "cert": + ser.TLSCert = mustGetString(flags, flag.Name) + case "key": + ser.TLSKey = mustGetString(flags, flag.Name) + case "address": + ser.Address = mustGetString(flags, flag.Name) + case "port": + ser.Port = 8080 + case "log": + ser.Log = mustGetString(flags, flag.Name) + case "signup": + set.Signup = mustGetBool(flags, flag.Name) + case "shell": + set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name)) + case "frontend.name": + set.Frontend.Name = mustGetString(flags, flag.Name) + case "frontend.color": + set.Frontend.Color = mustGetString(flags, flag.Name) + case "frontend.disableExternal": + set.Frontend.DisableExternal = mustGetBool(flags, flag.Name) + case "frontend.disableUsedPercentage": + set.Frontend.DisableUsedPercentage = mustGetBool(flags, flag.Name) + case "frontend.files": + set.Frontend.Files = mustGetString(flags, flag.Name) + } + }) + + getUserDefaults(flags, &set.UserDefaults, false) + + // read the defaults + _, auther := getAuthentication() + err = d.store.Auth.Save(auther) + checkErr(err) + err = d.store.Settings.Save(set) + checkErr(err) + err = d.store.Settings.SaveServer(ser) + checkErr(err) + printSettings(ser, set, auther) + }, pythonConfig{}), +} diff --git a/backend/cmd/docs.go b/backend/cmd/docs.go new file mode 100644 index 00000000..9ebb9573 --- /dev/null +++ b/backend/cmd/docs.go @@ -0,0 +1,139 @@ +package cmd + +import ( + "bytes" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" +) + +func init() { + rootCmd.AddCommand(docsCmd) + docsCmd.Flags().StringP("path", "p", "./docs", "path to save the docs") +} + +func printToc(names []string) { + for i, name := range names { + name = strings.TrimSuffix(name, filepath.Ext(name)) + name = strings.Replace(name, "-", " ", -1) + names[i] = name + } + + sort.Strings(names) + + toc := "" + for _, name := range names { + toc += "* [" + name + "](cli/" + strings.Replace(name, " ", "-", -1) + ".md)\n" + } + + fmt.Println(toc) +} + +var docsCmd = &cobra.Command{ + Use: "docs", + Hidden: true, + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + dir := mustGetString(cmd.Flags(), "path") + generateDocs(rootCmd, dir) + names := []string{} + + err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil || info.IsDir() { + return err + } + + if !strings.HasPrefix(info.Name(), "filebrowser") { + return nil + } + + names = append(names, info.Name()) + return nil + }) + + checkErr(err) + printToc(names) + }, +} + +func generateDocs(cmd *cobra.Command, dir string) { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { + continue + } + + generateDocs(c, dir) + } + + basename := strings.Replace(cmd.CommandPath(), " ", "-", -1) + ".md" + filename := filepath.Join(dir, basename) + f, err := os.Create(filename) + checkErr(err) + defer f.Close() + generateMarkdown(cmd, f) +} + +func generateMarkdown(cmd *cobra.Command, w io.Writer) { + cmd.InitDefaultHelpCmd() + cmd.InitDefaultHelpFlag() + + buf := new(bytes.Buffer) + name := cmd.CommandPath() + + short := cmd.Short + long := cmd.Long + if long == "" { + long = short + } + + buf.WriteString("---\ndescription: " + short + "\n---\n\n") + buf.WriteString("# " + name + "\n\n") + buf.WriteString("## Synopsis\n\n") + buf.WriteString(long + "\n\n") + + if cmd.Runnable() { + buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.UseLine())) + } + + if len(cmd.Example) > 0 { + buf.WriteString("## Examples\n\n") + buf.WriteString(fmt.Sprintf("```\n%s\n```\n\n", cmd.Example)) + } + + printOptions(buf, cmd) + _, err := buf.WriteTo(w) + checkErr(err) +} + +func generateFlagsTable(fs *pflag.FlagSet, buf io.StringWriter) { + _, _ = buf.WriteString("| Name | Shorthand | Usage |\n") + _, _ = buf.WriteString("|------|-----------|-------|\n") + + fs.VisitAll(func(f *pflag.Flag) { + _, _ = buf.WriteString("|" + f.Name + "|" + f.Shorthand + "|" + f.Usage + "|\n") + }) +} + +func printOptions(buf *bytes.Buffer, cmd *cobra.Command) { + flags := cmd.NonInheritedFlags() + flags.SetOutput(buf) + if flags.HasAvailableFlags() { + buf.WriteString("## Options\n\n") + generateFlagsTable(flags, buf) + buf.WriteString("\n") + } + + parentFlags := cmd.InheritedFlags() + parentFlags.SetOutput(buf) + if parentFlags.HasAvailableFlags() { + buf.WriteString("### Inherited\n\n") + generateFlagsTable(parentFlags, buf) + buf.WriteString("\n") + } +} diff --git a/backend/cmd/hash.go b/backend/cmd/hash.go new file mode 100644 index 00000000..41718afa --- /dev/null +++ b/backend/cmd/hash.go @@ -0,0 +1,25 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + rootCmd.AddCommand(hashCmd) +} + +var hashCmd = &cobra.Command{ + Use: "hash ", + 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) + fmt.Println(pwd) + }, +} diff --git a/backend/cmd/rule_rm.go b/backend/cmd/rule_rm.go new file mode 100644 index 00000000..0aea796c --- /dev/null +++ b/backend/cmd/rule_rm.go @@ -0,0 +1,66 @@ +package cmd + +import ( + "strconv" + + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/settings" + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + rulesCmd.AddCommand(rulesRmCommand) + rulesRmCommand.Flags().Uint("index", 0, "index of rule to remove") + _ = rulesRmCommand.MarkFlagRequired("index") +} + +var rulesRmCommand = &cobra.Command{ + Use: "rm [index_end]", + Short: "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 { //nolint:gomnd + return err + } + + for _, arg := range args { + if _, err := strconv.Atoi(arg); err != nil { + return err + } + } + + return nil + }, + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + i, err := strconv.Atoi(args[0]) + checkErr(err) + f := i + if len(args) == 2 { //nolint:gomnd + f, err = strconv.Atoi(args[1]) + checkErr(err) + } + + user := func(u *users.User) { + u.Rules = append(u.Rules[:i], u.Rules[f+1:]...) + err := d.store.Users.Save(u) + checkErr(err) + } + + global := func(s *settings.Settings) { + s.Rules = append(s.Rules[:i], s.Rules[f+1:]...) + err := d.store.Settings.Save(s) + checkErr(err) + } + + runRules(d.store, cmd, user, global) + }, pythonConfig{}), +} diff --git a/backend/cmd/rules.go b/backend/cmd/rules.go new file mode 100644 index 00000000..69df0d33 --- /dev/null +++ b/backend/cmd/rules.go @@ -0,0 +1,92 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/gtsteffaniak/filebrowser/rules" + "github.com/gtsteffaniak/filebrowser/settings" + "github.com/gtsteffaniak/filebrowser/storage" + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + rootCmd.AddCommand(rulesCmd) + rulesCmd.PersistentFlags().StringP("username", "u", "", "username of user to which the rules apply") + rulesCmd.PersistentFlags().UintP("id", "i", 0, "id of user to which the rules apply") +} + +var rulesCmd = &cobra.Command{ + Use: "rules", + 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 +an user, otherwise it will be applied to the global set or +rules.`, + Args: cobra.NoArgs, +} + +func runRules(st *storage.Storage, cmd *cobra.Command, usersFn func(*users.User), globalFn func(*settings.Settings)) { + id := getUserIdentifier(cmd.Flags()) + if id != nil { + user, err := st.Users.Get("", id) + checkErr(err) + + if usersFn != nil { + usersFn(user) + } + + printRules(user.Rules, id) + return + } + + s, err := st.Settings.Get() + checkErr(err) + + if globalFn != nil { + globalFn(s) + } + + printRules(s.Rules, id) +} + +func getUserIdentifier(flags *pflag.FlagSet) interface{} { + id := mustGetUint(flags, "id") + username := mustGetString(flags, "username") + + if id != 0 { + return id + } else if username != "" { + return username + } + + return nil +} + +func printRules(rulez []rules.Rule, id interface{}) { + if id == nil { + fmt.Printf("Global Rules:\n\n") + } else { + fmt.Printf("Rules for user %v:\n\n", id) + } + + for id, rule := range rulez { + fmt.Printf("(%d) ", id) + if rule.Regex { + if rule.Allow { + fmt.Printf("Allow Regex: \t%s\n", rule.Regexp.Raw) + } else { + fmt.Printf("Disallow Regex: \t%s\n", rule.Regexp.Raw) + } + } else { + if rule.Allow { + fmt.Printf("Allow Path: \t%s\n", rule.Path) + } else { + fmt.Printf("Disallow Path: \t%s\n", rule.Path) + } + } + } +} diff --git a/backend/cmd/rules_add.go b/backend/cmd/rules_add.go new file mode 100644 index 00000000..768717bd --- /dev/null +++ b/backend/cmd/rules_add.go @@ -0,0 +1,58 @@ +package cmd + +import ( + "regexp" + + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/rules" + "github.com/gtsteffaniak/filebrowser/settings" + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + rulesCmd.AddCommand(rulesAddCmd) + rulesAddCmd.Flags().BoolP("allow", "a", false, "indicates this is an allow rule") + rulesAddCmd.Flags().BoolP("regex", "r", false, "indicates this is a regex rule") +} + +var rulesAddCmd = &cobra.Command{ + Use: "add ", + Short: "Add a global rule or user rule", + Long: `Add a global rule or user rule.`, + Args: cobra.ExactArgs(1), + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + allow := mustGetBool(cmd.Flags(), "allow") + regex := mustGetBool(cmd.Flags(), "regex") + exp := args[0] + + if regex { + regexp.MustCompile(exp) + } + + rule := rules.Rule{ + Allow: allow, + Regex: regex, + } + + if regex { + rule.Regexp = &rules.Regexp{Raw: exp} + } else { + rule.Path = exp + } + + user := func(u *users.User) { + u.Rules = append(u.Rules, rule) + err := d.store.Users.Save(u) + checkErr(err) + } + + global := func(s *settings.Settings) { + s.Rules = append(s.Rules, rule) + err := d.store.Settings.Save(s) + checkErr(err) + } + + runRules(d.store, cmd, user, global) + }, pythonConfig{}), +} diff --git a/backend/cmd/rules_ls.go b/backend/cmd/rules_ls.go new file mode 100644 index 00000000..e0e5f8f8 --- /dev/null +++ b/backend/cmd/rules_ls.go @@ -0,0 +1,19 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +func init() { + rulesCmd.AddCommand(rulesLsCommand) +} + +var rulesLsCommand = &cobra.Command{ + Use: "ls", + Short: "List global rules or user specific rules", + Long: `List global rules or user specific rules.`, + Args: cobra.NoArgs, + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + runRules(d.store, cmd, nil, nil) + }, pythonConfig{}), +} diff --git a/backend/cmd/users_add.go b/backend/cmd/users_add.go new file mode 100644 index 00000000..eac81240 --- /dev/null +++ b/backend/cmd/users_add.go @@ -0,0 +1,51 @@ +package cmd + +import ( + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + usersCmd.AddCommand(usersAddCmd) + addUserFlags(usersAddCmd.Flags()) +} + +var usersAddCmd = &cobra.Command{ + Use: "add ", + Short: "Create a new user", + Long: `Create a new user and add it to the database.`, + Args: cobra.ExactArgs(2), //nolint:gomnd + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + s, err := d.store.Settings.Get() + checkErr(err) + getUserDefaults(cmd.Flags(), &s.UserDefaults, false) + + password, err := users.HashPwd(args[1]) + checkErr(err) + + user := &users.User{ + Username: args[0], + Password: password, + LockPassword: mustGetBool(cmd.Flags(), "lockPassword"), + } + + s.UserDefaults.Apply(user) + + servSettings, err := d.store.Settings.GetServer() + checkErr(err) + // since getUserDefaults() polluted s.Defaults.Scope + // which makes the Scope not the one saved in the db + // we need the right s.Defaults.Scope here + s2, err := d.store.Settings.Get() + checkErr(err) + + userHome, err := s2.MakeUserDir(user.Username, user.Scope, servSettings.Root) + checkErr(err) + user.Scope = userHome + + err = d.store.Users.Save(user) + checkErr(err) + printUsers([]*users.User{user}) + }, pythonConfig{}), +} diff --git a/backend/cmd/users_export.go b/backend/cmd/users_export.go new file mode 100644 index 00000000..c0160f68 --- /dev/null +++ b/backend/cmd/users_export.go @@ -0,0 +1,24 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +func init() { + usersCmd.AddCommand(usersExportCmd) +} + +var usersExportCmd = &cobra.Command{ + 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) + + err = marshal(args[0], list) + checkErr(err) + }, pythonConfig{}), +} diff --git a/backend/cmd/users_find.go b/backend/cmd/users_find.go new file mode 100644 index 00000000..b00959c4 --- /dev/null +++ b/backend/cmd/users_find.go @@ -0,0 +1,51 @@ +package cmd + +import ( + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + usersCmd.AddCommand(usersFindCmd) + usersCmd.AddCommand(usersLsCmd) +} + +var usersFindCmd = &cobra.Command{ + Use: "find ", + Short: "Find a user by username or id", + Long: `Find a user by username or id. If no flag is set, all users will be printed.`, + Args: cobra.ExactArgs(1), + Run: findUsers, +} + +var usersLsCmd = &cobra.Command{ + Use: "ls", + Short: "List all users.", + Args: cobra.NoArgs, + Run: findUsers, +} + +var findUsers = python(func(cmd *cobra.Command, args []string, d pythonData) { + var ( + list []*users.User + user *users.User + err error + ) + + if len(args) == 1 { + username, id := parseUsernameOrID(args[0]) + if username != "" { + user, err = d.store.Users.Get("", username) + } else { + user, err = d.store.Users.Get("", id) + } + + list = []*users.User{user} + } else { + list, err = d.store.Users.Gets("") + } + + checkErr(err) + printUsers(list) +}, pythonConfig{}) diff --git a/backend/cmd/users_import.go b/backend/cmd/users_import.go new file mode 100644 index 00000000..d5be6e9c --- /dev/null +++ b/backend/cmd/users_import.go @@ -0,0 +1,89 @@ +package cmd + +import ( + "errors" + "fmt" + "os" + "strconv" + + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + usersCmd.AddCommand(usersImportCmd) + usersImportCmd.Flags().Bool("overwrite", false, "overwrite users with the same id/username combo") + usersImportCmd.Flags().Bool("replace", false, "replace the entire user base") +} + +var usersImportCmd = &cobra.Command{ + 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) + defer fd.Close() + + list := []*users.User{} + err = unmarshal(args[0], &list) + checkErr(err) + + for _, user := range list { + err = user.Clean("") + checkErr(err) + } + + 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 { + onDB, err := d.store.Users.Get("", user.ID) + + // User exists in DB. + if err == nil { + if !overwrite { + checkErr(errors.New("user " + strconv.Itoa(int(user.ID)) + " is already registred")) + } + + // If the usernames mismatch, check if there is another one in the DB + // with the new username. If there is, print an error and cancel the + // operation + if user.Username != onDB.Username { + if conflictuous, err := d.store.Users.Get("", user.Username); err == nil { //nolint:govet + checkErr(usernameConflictError(user.Username, conflictuous.ID, user.ID)) + } + } + } else { + // If it doesn't exist, set the ID to 0 to automatically get a new + // one that make sense in this DB. + user.ID = 0 + } + + err = d.store.Users.Save(user) + checkErr(err) + } + }, pythonConfig{}), +} + +func usernameConflictError(username string, originalID, newID uint) error { + return fmt.Errorf(`can't import user with ID %d and username "%s" because the username is already registred with the user %d`, + newID, username, originalID) +} diff --git a/backend/cmd/users_rm.go b/backend/cmd/users_rm.go new file mode 100644 index 00000000..e3fef01b --- /dev/null +++ b/backend/cmd/users_rm.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +func init() { + usersCmd.AddCommand(usersRmCmd) +} + +var usersRmCmd = &cobra.Command{ + Use: "rm ", + Short: "Delete a user by username or id", + Long: `Delete a user by username or id`, + Args: cobra.ExactArgs(1), + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + username, id := parseUsernameOrID(args[0]) + var err error + + if username != "" { + err = d.store.Users.Delete(username) + } else { + err = d.store.Users.Delete(id) + } + + checkErr(err) + fmt.Println("user deleted successfully") + }, pythonConfig{}), +} diff --git a/backend/cmd/users_update.go b/backend/cmd/users_update.go new file mode 100644 index 00000000..09bb4b8d --- /dev/null +++ b/backend/cmd/users_update.go @@ -0,0 +1,75 @@ +package cmd + +import ( + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/settings" + "github.com/gtsteffaniak/filebrowser/users" +) + +func init() { + usersCmd.AddCommand(usersUpdateCmd) + + usersUpdateCmd.Flags().StringP("password", "p", "", "new password") + usersUpdateCmd.Flags().StringP("username", "u", "", "new username") + addUserFlags(usersUpdateCmd.Flags()) +} + +var usersUpdateCmd = &cobra.Command{ + Use: "update ", + Short: "Updates an existing user", + Long: `Updates an existing user. Set the flags for the +options you want to change.`, + Args: cobra.ExactArgs(1), + Run: python(func(cmd *cobra.Command, args []string, d pythonData) { + username, id := parseUsernameOrID(args[0]) + flags := cmd.Flags() + password := mustGetString(flags, "password") + newUsername := mustGetString(flags, "username") + + var ( + err error + user *users.User + ) + + if id != 0 { + user, err = d.store.Users.Get("", id) + } else { + user, err = d.store.Users.Get("", username) + } + + checkErr(err) + + defaults := settings.UserDefaults{ + Scope: user.Scope, + Locale: user.Locale, + ViewMode: user.ViewMode, + SingleClick: user.SingleClick, + Perm: user.Perm, + Sorting: user.Sorting, + Commands: user.Commands, + } + getUserDefaults(flags, &defaults, false) + user.Scope = defaults.Scope + user.Locale = defaults.Locale + user.ViewMode = defaults.ViewMode + user.SingleClick = defaults.SingleClick + user.Perm = defaults.Perm + user.Commands = defaults.Commands + user.Sorting = defaults.Sorting + user.LockPassword = mustGetBool(flags, "lockPassword") + + if newUsername != "" { + user.Username = newUsername + } + + if password != "" { + user.Password, err = users.HashPwd(password) + checkErr(err) + } + + err = d.store.Users.Update(user) + checkErr(err) + printUsers([]*users.User{user}) + }, pythonConfig{}), +} diff --git a/backend/cmd/utils.go b/backend/cmd/utils.go index ef0b9a7c..0ae50265 100644 --- a/backend/cmd/utils.go +++ b/backend/cmd/utils.go @@ -85,8 +85,7 @@ func dbExists(path string) (bool, error) { func python(fn pythonFunc, cfg pythonConfig) cobraFunc { return func(cmd *cobra.Command, args []string) { data := pythonData{hadDB: true} - - path := getParam(cmd.Flags(), "database") + path := settings.GlobalConfiguration.Server.Database exists, err := dbExists(path) if err != nil { @@ -100,6 +99,7 @@ func python(fn pythonFunc, cfg pythonConfig) cobraFunc { data.hadDB = exists db, err := storm.Open(path) checkErr(err) + defer db.Close() data.store, err = bolt.NewStorage(db) checkErr(err) diff --git a/backend/cmd/version.go b/backend/cmd/version.go new file mode 100644 index 00000000..2e085103 --- /dev/null +++ b/backend/cmd/version.go @@ -0,0 +1,21 @@ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/gtsteffaniak/filebrowser/version" +) + +func init() { + rootCmd.AddCommand(versionCmd) +} + +var versionCmd = &cobra.Command{ + Use: "version", + Short: "Print the version number", + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("File Browser v" + version.Version + "/" + version.CommitSHA) + }, +} diff --git a/backend/filebrowser.yml b/backend/filebrowser.yml index f68917f4..8a5d8ddf 100644 --- a/backend/filebrowser.yml +++ b/backend/filebrowser.yml @@ -4,8 +4,8 @@ server: socket: "" tlsKey: "" tlsCert: "" - enableThumbnails: true - resizePreview: false + enableThumbnails: false + resizePreview: true typeDetectionByHeader: true port: 8080 baseURL: "/" @@ -26,7 +26,7 @@ auth: frontend: name: "" disableExternal: false - disableUsedPercentage: false + disableUsedPercentage: true files: "" theme: "" color: "" @@ -34,19 +34,19 @@ userDefaults: scope: "" locale: "" viewMode: "" - singleClick: false + singleClick: true sorting: by: "" - asc: false + asc: true perm: - admin: false - execute: false - create: false - rename: false - modify: false - delete: false - share: false - download: false + admin: true + execute: true + create: true + rename: true + modify: true + delete: true + share: true + download: true commands: [] - hideDotfiles: false + hideDotfiles: true dateFormat: false From f1e05c583a4938e2b75ee13409c71ff5a73adabd Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 13:02:50 -0500 Subject: [PATCH 06/11] updated readme --- CHANGELOG.md | 8 +++++--- backend/cmd/config.go | 4 ++-- backend/cmd/config_init.go | 14 ++++++-------- backend/cmd/config_set.go | 2 +- backend/{filebrowser.yml => filebrowser.yaml} | 0 backend/settings/config.go | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) rename backend/{filebrowser.yml => filebrowser.yaml} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f40eb49e..ff9a43be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,14 @@ All notable changes to this project will be documented in this file. See [standa # v0.2.0 - - Works with new more advanced filebrowser.json - improved GUI - more unified coehisive look + - Adjusted header bar look and icon behavior - The shell is dead. - - If you need to use the shell, exec into the docker container. - - All configuration is done via filebrowser.yml + - If you need to use custom commands, exec into the docker container. + - All configuration is done via `filebrowser.yaml` + - Removed old code to migrate database veresions + - Removed all unused cmd code # v0.1.4 - various UI fixes diff --git a/backend/cmd/config.go b/backend/cmd/config.go index 9ee88b85..cfc7afe8 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -44,7 +44,7 @@ func addConfigFlags(flags *pflag.FlagSet) { } //nolint:gocyclo -func getAuthentication() (string, auth.Auther) { +func getAuthentication() auth.Auther { method := settings.GlobalConfiguration.Auth.Method var defaultAuther map[string]interface{} var auther auth.Auther @@ -111,7 +111,7 @@ func getAuthentication() (string, auth.Auther) { panic(errors.ErrInvalidAuthMethod) } - return method, auther + return auther } func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Auther) { diff --git a/backend/cmd/config_init.go b/backend/cmd/config_init.go index 47bf8df7..b3eaa3f7 100644 --- a/backend/cmd/config_init.go +++ b/backend/cmd/config_init.go @@ -23,14 +23,12 @@ to the defaults when creating new users and you don't override the options.`, Args: cobra.NoArgs, Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - defaults := settings.UserDefaults{} - flags := cmd.Flags() - getUserDefaults(flags, &defaults, true) - _, auther := getAuthentication() - ser := &settings.GlobalConfiguration.Server - err := d.store.Settings.Save(&settings.GlobalConfiguration) + auther := getAuthentication() + s := settings.GlobalConfiguration + s.Key = generateKey() + err := d.store.Settings.Save(&s) checkErr(err) - err = d.store.Settings.SaveServer(ser) + err = d.store.Settings.SaveServer(&s.Server) checkErr(err) err = d.store.Auth.Save(auther) checkErr(err) @@ -40,6 +38,6 @@ Congratulations! You've set up your database to use with File Browser. Now add your first user via 'filebrowser users add' and then you just need to call the main command to boot up the server. `) - printSettings(ser, &settings.GlobalConfiguration, auther) + printSettings(&s.Server, &s, auther) }, pythonConfig{noDB: true}), } diff --git a/backend/cmd/config_set.go b/backend/cmd/config_set.go index f30dd088..cb1b6917 100644 --- a/backend/cmd/config_set.go +++ b/backend/cmd/config_set.go @@ -62,7 +62,7 @@ you want to change. Other options will remain unchanged.`, getUserDefaults(flags, &set.UserDefaults, false) // read the defaults - _, auther := getAuthentication() + auther := getAuthentication() err = d.store.Auth.Save(auther) checkErr(err) err = d.store.Settings.Save(set) diff --git a/backend/filebrowser.yml b/backend/filebrowser.yaml similarity index 100% rename from backend/filebrowser.yml rename to backend/filebrowser.yaml diff --git a/backend/settings/config.go b/backend/settings/config.go index c0c427dd..153dd31b 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -11,7 +11,7 @@ var GlobalConfiguration Settings func init() { // Open and read the YAML file - yamlFile, err := os.Open("filebrowser.yml") + yamlFile, err := os.Open("filebrowser.yaml") if err != nil { log.Fatalf("Error opening YAML file: %v", err) } From a85b23018767dc499dacd666ef4028785f346cf1 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 13:07:51 -0500 Subject: [PATCH 07/11] updated tests helper = cache --- backend/cmd/config.go | 1 - backend/run_tests.sh | 1 - backend/test_output.txt | 113 ++++++++++++++++++++++++++++++++++++++++ test_output.txt | 0 4 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 backend/test_output.txt create mode 100644 test_output.txt diff --git a/backend/cmd/config.go b/backend/cmd/config.go index cfc7afe8..0555cc9b 100644 --- a/backend/cmd/config.go +++ b/backend/cmd/config.go @@ -129,7 +129,6 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut fmt.Fprintf(w, "\tColor:\t%s\n", set.Frontend.Color) fmt.Fprintln(w, "\nServer:") fmt.Fprintf(w, "\tLog:\t%s\n", ser.Log) - fmt.Fprintf(w, "\tPort:\t%s\n", ser.Port) fmt.Fprintf(w, "\tBase URL:\t%s\n", ser.BaseURL) fmt.Fprintf(w, "\tRoot:\t%s\n", ser.Root) fmt.Fprintf(w, "\tSocket:\t%s\n", ser.Socket) diff --git a/backend/run_tests.sh b/backend/run_tests.sh index f20b80b0..fc278bb2 100755 --- a/backend/run_tests.sh +++ b/backend/run_tests.sh @@ -1,6 +1,5 @@ #!/bin/sh ## TEST file used by docker testing containers -touch render.yml checkExit() { if [ "$?" -ne 0 ];then exit 1 diff --git a/backend/test_output.txt b/backend/test_output.txt new file mode 100644 index 00000000..42fde92b --- /dev/null +++ b/backend/test_output.txt @@ -0,0 +1,113 @@ + + == Running tests == +/usr/local/go/bin/go +? github.com/gtsteffaniak/filebrowser [no test files] +? github.com/gtsteffaniak/filebrowser/auth [no test files] +? github.com/gtsteffaniak/filebrowser/cmd [no test files] +? github.com/gtsteffaniak/filebrowser/errors [no test files] +? github.com/gtsteffaniak/filebrowser/files [no test files] +=== RUN TestFileCache +--- PASS: TestFileCache (0.00s) +PASS +ok github.com/gtsteffaniak/filebrowser/diskcache (cached) +=== RUN TestCommonPrefix +=== RUN TestCommonPrefix/sub_folder +=== RUN TestCommonPrefix/relative_path +=== RUN TestCommonPrefix/no_common_path +=== RUN TestCommonPrefix/same_lvl +--- PASS: TestCommonPrefix (0.00s) + --- PASS: TestCommonPrefix/sub_folder (0.00s) + --- PASS: TestCommonPrefix/relative_path (0.00s) + --- PASS: TestCommonPrefix/no_common_path (0.00s) + --- PASS: TestCommonPrefix/same_lvl (0.00s) +PASS +ok github.com/gtsteffaniak/filebrowser/fileutils (cached) +? github.com/gtsteffaniak/filebrowser/settings [no test files] +? github.com/gtsteffaniak/filebrowser/share [no test files] +? github.com/gtsteffaniak/filebrowser/storage [no test files] +? github.com/gtsteffaniak/filebrowser/storage/bolt [no test files] +2023/09/02 13:07:17 Error opening YAML file: open filebrowser.yaml: no such file or directory +FAIL github.com/gtsteffaniak/filebrowser/http 0.008s +=== RUN TestService_Resize +=== RUN TestService_Resize/convert_to_png +=== RUN TestService_Resize/convert_to_tiff +=== RUN TestService_Resize/resize_bmp +=== RUN TestService_Resize/resize_with_medium_quality +=== RUN TestService_Resize/resize_with_low_quality +=== RUN TestService_Resize/get_thumbnail_from_file_with_APP0_JFIF +=== RUN TestService_Resize/fill_upscale +=== RUN TestService_Resize/fit_upscale +=== RUN TestService_Resize/convert_to_gif +=== RUN TestService_Resize/convert_to_bmp +=== RUN TestService_Resize/resize_tiff +=== RUN TestService_Resize/resize_with_high_quality +=== RUN TestService_Resize/fill_downscale +=== RUN TestService_Resize/keep_original_format +=== RUN TestService_Resize/convert_to_unknown +=== RUN TestService_Resize/get_thumbnail_from_file_without_APP0_JFIF +=== RUN TestService_Resize/resize_for_higher_quality_levels +=== RUN TestService_Resize/broken_file +=== RUN TestService_Resize/fit_downscale +=== RUN TestService_Resize/convert_to_jpeg +=== RUN TestService_Resize/resize_png +=== RUN TestService_Resize/resize_gif +=== RUN TestService_Resize/resize_with_unknown_quality +=== RUN TestService_Resize/resize_from_file_without_IFD1_thumbnail +--- PASS: TestService_Resize (1.36s) + --- PASS: TestService_Resize/convert_to_png (0.01s) + --- PASS: TestService_Resize/convert_to_tiff (0.01s) + --- PASS: TestService_Resize/resize_bmp (0.01s) + --- PASS: TestService_Resize/resize_with_medium_quality (0.01s) + --- PASS: TestService_Resize/resize_with_low_quality (0.01s) + --- PASS: TestService_Resize/get_thumbnail_from_file_with_APP0_JFIF (0.02s) + --- PASS: TestService_Resize/fill_upscale (0.01s) + --- PASS: TestService_Resize/fit_upscale (0.00s) + --- PASS: TestService_Resize/convert_to_gif (0.01s) + --- PASS: TestService_Resize/convert_to_bmp (0.01s) + --- PASS: TestService_Resize/resize_tiff (0.01s) + --- PASS: TestService_Resize/resize_with_high_quality (0.01s) + --- PASS: TestService_Resize/fill_downscale (0.01s) + --- PASS: TestService_Resize/keep_original_format (0.01s) + --- PASS: TestService_Resize/convert_to_unknown (0.01s) + --- PASS: TestService_Resize/get_thumbnail_from_file_without_APP0_JFIF (0.03s) + --- PASS: TestService_Resize/resize_for_higher_quality_levels (0.03s) + --- PASS: TestService_Resize/broken_file (0.00s) + --- PASS: TestService_Resize/fit_downscale (0.01s) + --- PASS: TestService_Resize/convert_to_jpeg (0.01s) + --- PASS: TestService_Resize/resize_png (0.02s) + --- PASS: TestService_Resize/resize_gif (0.02s) + --- PASS: TestService_Resize/resize_with_unknown_quality (0.01s) + --- PASS: TestService_Resize/resize_from_file_without_IFD1_thumbnail (1.09s) +=== RUN TestService_FormatFromExtension +=== RUN TestService_FormatFromExtension/gif +=== RUN TestService_FormatFromExtension/tiff +=== RUN TestService_FormatFromExtension/bmp +=== RUN TestService_FormatFromExtension/unknown +=== RUN TestService_FormatFromExtension/jpg +=== RUN TestService_FormatFromExtension/jpeg +=== RUN TestService_FormatFromExtension/png +--- PASS: TestService_FormatFromExtension (0.00s) + --- PASS: TestService_FormatFromExtension/gif (0.00s) + --- PASS: TestService_FormatFromExtension/tiff (0.00s) + --- PASS: TestService_FormatFromExtension/bmp (0.00s) + --- PASS: TestService_FormatFromExtension/unknown (0.00s) + --- PASS: TestService_FormatFromExtension/jpg (0.00s) + --- PASS: TestService_FormatFromExtension/jpeg (0.00s) + --- PASS: TestService_FormatFromExtension/png (0.00s) +PASS +ok github.com/gtsteffaniak/filebrowser/img (cached) +=== RUN TestMatchHidden +--- PASS: TestMatchHidden (0.00s) +PASS +ok github.com/gtsteffaniak/filebrowser/rules (cached) +2023/09/02 13:07:17 Error opening YAML file: open filebrowser.yaml: no such file or directory +FAIL github.com/gtsteffaniak/filebrowser/runner 0.007s +=== RUN TestParseSearch +--- PASS: TestParseSearch (0.00s) +PASS +ok github.com/gtsteffaniak/filebrowser/search (cached) +? github.com/gtsteffaniak/filebrowser/version [no test files] +testing: warning: no tests to run +PASS +ok github.com/gtsteffaniak/filebrowser/users (cached) [no tests to run] +FAIL diff --git a/test_output.txt b/test_output.txt new file mode 100644 index 00000000..e69de29b From 33863f05c4d177b2a1703b2b9a2d7367678fc0bb Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 13:08:20 -0500 Subject: [PATCH 08/11] updated benchmark results helper = cache --- backend/benchmark_results.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/benchmark_results.txt b/backend/benchmark_results.txt index 7eed7250..20a445a4 100644 --- a/backend/benchmark_results.txt +++ b/backend/benchmark_results.txt @@ -10,24 +10,24 @@ ok github.com/gtsteffaniak/filebrowser/diskcache 0.004s ? github.com/gtsteffaniak/filebrowser/files [no test files] PASS ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s -2023/09/02 11:25:34 Error opening YAML file: open filebrowser.yml: no such file or directory +2023/09/02 13:08:16 Error opening YAML file: open filebrowser.yaml: no such file or directory exit status 1 -FAIL github.com/gtsteffaniak/filebrowser/http 0.002s +FAIL github.com/gtsteffaniak/filebrowser/http 0.003s PASS -ok github.com/gtsteffaniak/filebrowser/img 0.121s +ok github.com/gtsteffaniak/filebrowser/img 0.123s PASS -ok github.com/gtsteffaniak/filebrowser/rules 0.002s -2023/09/02 11:25:34 Error opening YAML file: open filebrowser.yml: no such file or directory +ok github.com/gtsteffaniak/filebrowser/rules 0.003s +2023/09/02 13:08:16 Error opening YAML file: open filebrowser.yaml: no such file or directory exit status 1 FAIL github.com/gtsteffaniak/filebrowser/runner 0.002s goos: linux goarch: amd64 pkg: github.com/gtsteffaniak/filebrowser/search cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz -BenchmarkSearchAllIndexes-8 10 5943468 ns/op 2980324 B/op 45985 allocs/op -BenchmarkFillIndex-8 10 3353868 ns/op 18476 B/op 451 allocs/op +BenchmarkSearchAllIndexes-8 10 5705789 ns/op 3017139 B/op 44605 allocs/op +BenchmarkFillIndex-8 10 3205461 ns/op 18498 B/op 454 allocs/op PASS -ok github.com/gtsteffaniak/filebrowser/search 0.119s +ok github.com/gtsteffaniak/filebrowser/search 0.117s ? github.com/gtsteffaniak/filebrowser/settings [no test files] ? github.com/gtsteffaniak/filebrowser/share [no test files] ? github.com/gtsteffaniak/filebrowser/storage [no test files] From 99c8bf80366ed061c06582a924a2d12a542afd6c Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 19:16:19 -0500 Subject: [PATCH 09/11] updated --- CHANGELOG.md | 8 +++--- backend/benchmark_results.txt | 34 ++++++++++++++----------- backend/main.go | 2 ++ backend/settings/config.go | 31 +++++++++++++++++++--- backend/{ => settings}/filebrowser.yaml | 0 backend/settings/settings_test.go | 10 ++++++++ 6 files changed, 63 insertions(+), 22 deletions(-) rename backend/{ => settings}/filebrowser.yaml (100%) create mode 100644 backend/settings/settings_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index ff9a43be..5eb36e2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,13 +5,15 @@ All notable changes to this project will be documented in this file. See [standa # v0.2.0 - - improved GUI + - improved UI - more unified coehisive look - Adjusted header bar look and icon behavior - The shell is dead. - If you need to use custom commands, exec into the docker container. - - All configuration is done via `filebrowser.yaml` - - Removed old code to migrate database veresions + - The json config file is dead. + - All configuration is done via advanced `filebrowser.yaml` + - The only flag that is allowed is flag to specify config file. + - Removed old code to migrate database versions - Removed all unused cmd code # v0.1.4 diff --git a/backend/benchmark_results.txt b/backend/benchmark_results.txt index 20a445a4..655b1f9c 100644 --- a/backend/benchmark_results.txt +++ b/backend/benchmark_results.txt @@ -9,30 +9,34 @@ ok github.com/gtsteffaniak/filebrowser/diskcache 0.004s ? github.com/gtsteffaniak/filebrowser/errors [no test files] ? github.com/gtsteffaniak/filebrowser/files [no test files] PASS -ok github.com/gtsteffaniak/filebrowser/fileutils 0.003s -2023/09/02 13:08:16 Error opening YAML file: open filebrowser.yaml: no such file or directory -exit status 1 -FAIL github.com/gtsteffaniak/filebrowser/http 0.003s +ok github.com/gtsteffaniak/filebrowser/fileutils 0.004s +2023/09/02 19:15:20 h: 401 +2023/09/02 19:15:20 h: 401 +2023/09/02 19:15:20 h: 401 +2023/09/02 19:15:20 h: 401 +2023/09/02 19:15:20 h: 401 +2023/09/02 19:15:20 h: 401 PASS -ok github.com/gtsteffaniak/filebrowser/img 0.123s +ok github.com/gtsteffaniak/filebrowser/http 0.094s PASS -ok github.com/gtsteffaniak/filebrowser/rules 0.003s -2023/09/02 13:08:16 Error opening YAML file: open filebrowser.yaml: no such file or directory -exit status 1 -FAIL github.com/gtsteffaniak/filebrowser/runner 0.002s +ok github.com/gtsteffaniak/filebrowser/img 0.122s +PASS +ok github.com/gtsteffaniak/filebrowser/rules 0.002s +PASS +ok github.com/gtsteffaniak/filebrowser/runner 0.004s goos: linux goarch: amd64 pkg: github.com/gtsteffaniak/filebrowser/search cpu: 11th Gen Intel(R) Core(TM) i5-11320H @ 3.20GHz -BenchmarkSearchAllIndexes-8 10 5705789 ns/op 3017139 B/op 44605 allocs/op -BenchmarkFillIndex-8 10 3205461 ns/op 18498 B/op 454 allocs/op +BenchmarkSearchAllIndexes-8 10 5176084 ns/op 2743632 B/op 42785 allocs/op +BenchmarkFillIndex-8 10 3263308 ns/op 18485 B/op 453 allocs/op PASS -ok github.com/gtsteffaniak/filebrowser/search 0.117s -? github.com/gtsteffaniak/filebrowser/settings [no test files] +ok github.com/gtsteffaniak/filebrowser/search 0.109s +PASS +ok github.com/gtsteffaniak/filebrowser/settings 0.004s ? github.com/gtsteffaniak/filebrowser/share [no test files] ? github.com/gtsteffaniak/filebrowser/storage [no test files] ? github.com/gtsteffaniak/filebrowser/storage/bolt [no test files] PASS -ok github.com/gtsteffaniak/filebrowser/users 0.003s +ok github.com/gtsteffaniak/filebrowser/users 0.004s ? github.com/gtsteffaniak/filebrowser/version [no test files] -FAIL diff --git a/backend/main.go b/backend/main.go index 9f606708..3b127cff 100644 --- a/backend/main.go +++ b/backend/main.go @@ -2,8 +2,10 @@ package main import ( "github.com/gtsteffaniak/filebrowser/cmd" + "github.com/gtsteffaniak/filebrowser/settings" ) func main() { + settings.Initialize() cmd.StartFilebrowser() } diff --git a/backend/settings/config.go b/backend/settings/config.go index 153dd31b..b2d2cd47 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -1,25 +1,49 @@ package settings import ( + "fmt" "log" "os" + "path/filepath" "github.com/goccy/go-yaml" ) var GlobalConfiguration Settings -func init() { +func Initialize() { // Open and read the YAML file yamlFile, err := os.Open("filebrowser.yaml") if err != nil { - log.Fatalf("Error opening YAML file: %v", err) + log.Println("Error opening config file: ", err) + log.Println("Using default config only") + // Get the current directory + dir, err := os.Getwd() + if err != nil { + fmt.Println("Error:", err) + return + } + + // Use the filepath package to join the directory and file names + err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { + if err != nil { + fmt.Println("Error:", err) + return err + } + // Check if it's a regular file (not a directory) + if !info.IsDir() { + fmt.Println(path) + } + return nil + }) + setDefaults() + return } defer yamlFile.Close() stat, err := yamlFile.Stat() if err != nil { - log.Fatalf("Error getting file information: %v", err) + log.Fatalf("Error getting file information: %s", err.Error()) } yamlData := make([]byte, stat.Size()) @@ -27,7 +51,6 @@ func init() { if err != nil { log.Fatalf("Error reading YAML data: %v", err) } - setDefaults() // Unmarshal the YAML data into the Settings struct err = yaml.Unmarshal(yamlData, &GlobalConfiguration) if err != nil { diff --git a/backend/filebrowser.yaml b/backend/settings/filebrowser.yaml similarity index 100% rename from backend/filebrowser.yaml rename to backend/settings/filebrowser.yaml diff --git a/backend/settings/settings_test.go b/backend/settings/settings_test.go new file mode 100644 index 00000000..5b9285d7 --- /dev/null +++ b/backend/settings/settings_test.go @@ -0,0 +1,10 @@ +package settings + +import ( + "testing" +) + +func TestConfigLoad(t *testing.T) { + Initialize() + t.Log("Say bye") +} From ea77a1962a243712bc74b77536af0888bc7e9c14 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sat, 2 Sep 2023 19:17:31 -0500 Subject: [PATCH 10/11] updated --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a0f628a7..4411460b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ RUN apk --no-cache add \ VOLUME /srv EXPOSE 8080 WORKDIR / -COPY --from=base /app/.filebrowser.json /.filebrowser.json +COPY --from=base /app/settings/filebrowser.yaml /filebrowser.yaml COPY --from=base /app/filebrowser /filebrowser COPY --from=nbuild /app/dist/ /frontend/dist/ ENTRYPOINT [ "./filebrowser" ] \ No newline at end of file From 50958430f7aefae68dfe07da9288634cc9650869 Mon Sep 17 00:00:00 2001 From: Graham Steffaniak Date: Sun, 3 Sep 2023 12:28:00 -0500 Subject: [PATCH 11/11] updated settings to work :) --- backend/auth/auth.go | 3 +- backend/auth/hook.go | 7 +- backend/auth/json.go | 5 +- backend/auth/none.go | 4 +- backend/auth/proxy.go | 7 +- backend/cmd/config.go | 162 ------------------------ backend/cmd/config_cat.go | 25 ---- backend/cmd/config_export.go | 37 ------ backend/cmd/config_import.go | 9 +- backend/cmd/config_init.go | 48 ++++++- backend/cmd/config_set.go | 74 ----------- backend/cmd/root.go | 44 +------ backend/cmd/users_add.go | 1 - backend/cmd/users_update.go | 1 - backend/{settings => }/filebrowser.yaml | 12 +- backend/go.mod | 6 +- backend/go.sum | 2 - backend/http/auth.go | 3 +- backend/settings/config.go | 55 +++----- backend/settings/settings_test.go | 42 +++++- backend/settings/structs.go | 1 - backend/settings/testingConfig.yaml | 52 ++++++++ backend/storage/bolt/utils.go | 4 + frontend/src/views/settings/Global.vue | 10 +- 24 files changed, 194 insertions(+), 420 deletions(-) delete mode 100644 backend/cmd/config.go delete mode 100644 backend/cmd/config_cat.go delete mode 100644 backend/cmd/config_export.go delete mode 100644 backend/cmd/config_set.go rename backend/{settings => }/filebrowser.yaml (84%) create mode 100644 backend/settings/testingConfig.yaml diff --git a/backend/auth/auth.go b/backend/auth/auth.go index c3b143a8..a1121c6f 100644 --- a/backend/auth/auth.go +++ b/backend/auth/auth.go @@ -3,14 +3,13 @@ package auth import ( "net/http" - "github.com/gtsteffaniak/filebrowser/settings" "github.com/gtsteffaniak/filebrowser/users" ) // Auther is the authentication interface. type Auther interface { // Auth is called to authenticate a request. - Auth(r *http.Request, usr users.Store, stg *settings.Settings, srv *settings.Server) (*users.User, error) + Auth(r *http.Request, usr users.Store) (*users.User, error) // LoginPage indicates if this auther needs a login page. LoginPage() bool } diff --git a/backend/auth/hook.go b/backend/auth/hook.go index def9d3bc..0ae5d143 100644 --- a/backend/auth/hook.go +++ b/backend/auth/hook.go @@ -31,7 +31,7 @@ type HookAuth struct { } // Auth authenticates the user via a json in content body. -func (a *HookAuth) Auth(r *http.Request, usr users.Store, stg *settings.Settings, srv *settings.Server) (*users.User, error) { +func (a *HookAuth) Auth(r *http.Request, usr users.Store) (*users.User, error) { var cred hookCred if r.Body == nil { @@ -44,8 +44,8 @@ func (a *HookAuth) Auth(r *http.Request, usr users.Store, stg *settings.Settings } a.Users = usr - a.Settings = stg - a.Server = srv + a.Settings = &settings.GlobalConfiguration + a.Server = &settings.GlobalConfiguration.Server a.Cred = cred action, err := a.RunCommand() @@ -150,7 +150,6 @@ func (a *HookAuth) SaveUser() (*users.User, error) { if err != nil { return nil, err } - // create user with the provided credentials d := &users.User{ Username: a.Cred.Username, diff --git a/backend/auth/json.go b/backend/auth/json.go index ce7143de..d3734789 100644 --- a/backend/auth/json.go +++ b/backend/auth/json.go @@ -23,7 +23,8 @@ type JSONAuth struct { } // Auth authenticates the user via a json in content body. -func (a JSONAuth) Auth(r *http.Request, usr users.Store, stg *settings.Settings, srv *settings.Server) (*users.User, error) { +func (a JSONAuth) Auth(r *http.Request, usr users.Store) (*users.User, error) { + config := &settings.GlobalConfiguration var cred jsonCred if r.Body == nil { @@ -48,7 +49,7 @@ func (a JSONAuth) Auth(r *http.Request, usr users.Store, stg *settings.Settings, } } - u, err := usr.Get(srv.Root, cred.Username) + u, err := usr.Get(config.Server.Root, cred.Username) if err != nil || !users.CheckPwd(cred.Password, u.Password) { return nil, os.ErrPermission } diff --git a/backend/auth/none.go b/backend/auth/none.go index 6549780f..43688a26 100644 --- a/backend/auth/none.go +++ b/backend/auth/none.go @@ -14,8 +14,8 @@ const MethodNoAuth = "noauth" type NoAuth struct{} // Auth uses authenticates user 1. -func (a NoAuth) Auth(r *http.Request, usr users.Store, stg *settings.Settings, srv *settings.Server) (*users.User, error) { - return usr.Get(srv.Root, uint(1)) +func (a NoAuth) Auth(r *http.Request, usr users.Store) (*users.User, error) { + return usr.Get(settings.GlobalConfiguration.Server.Root, uint(1)) } // LoginPage tells that no auth doesn't require a login page. diff --git a/backend/auth/proxy.go b/backend/auth/proxy.go index a14e92a6..cf3e5936 100644 --- a/backend/auth/proxy.go +++ b/backend/auth/proxy.go @@ -4,8 +4,9 @@ import ( "net/http" "os" - "github.com/gtsteffaniak/filebrowser/errors" "github.com/gtsteffaniak/filebrowser/settings" + + "github.com/gtsteffaniak/filebrowser/errors" "github.com/gtsteffaniak/filebrowser/users" ) @@ -18,9 +19,9 @@ type ProxyAuth struct { } // Auth authenticates the user via an HTTP header. -func (a ProxyAuth) Auth(r *http.Request, usr users.Store, stg *settings.Settings, srv *settings.Server) (*users.User, error) { +func (a ProxyAuth) Auth(r *http.Request, usr users.Store) (*users.User, error) { username := r.Header.Get(a.Header) - user, err := usr.Get(srv.Root, username) + user, err := usr.Get(settings.GlobalConfiguration.Server.Root, username) if err == errors.ErrNotExist { return nil, os.ErrPermission } diff --git a/backend/cmd/config.go b/backend/cmd/config.go deleted file mode 100644 index 0555cc9b..00000000 --- a/backend/cmd/config.go +++ /dev/null @@ -1,162 +0,0 @@ -package cmd - -import ( - "encoding/json" - nerrors "errors" - "fmt" - "os" - "strings" - "text/tabwriter" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - "github.com/gtsteffaniak/filebrowser/auth" - "github.com/gtsteffaniak/filebrowser/errors" - "github.com/gtsteffaniak/filebrowser/settings" -) - -func init() { - rootCmd.AddCommand(configCmd) -} - -var configCmd = &cobra.Command{ - Use: "config", - Short: "Configuration management utility", - Long: `Configuration management utility.`, - Args: cobra.NoArgs, -} - -func addConfigFlags(flags *pflag.FlagSet) { - addUserFlags(flags) - flags.BoolP("signup", "s", false, "allow users to signup") - flags.String("shell", "", "shell command to which other commands should be appended") - - flags.String("recaptcha.host", "https://www.google.com", "use another host for ReCAPTCHA. recaptcha.net might be useful in China") - flags.String("recaptcha.key", "", "ReCaptcha site key") - flags.String("recaptcha.secret", "", "ReCaptcha secret") - - flags.String("frontend.name", "", "replace 'File Browser' by this name") - flags.String("frontend.color", "", "set the theme color") - flags.String("frontend.files", "", "path to directory with images and custom styles") - flags.Bool("frontend.disableExternal", false, "disable external links such as GitHub links") - flags.Bool("frontend.disableUsedPercentage", false, "disable used disk percentage graph") -} - -//nolint:gocyclo -func getAuthentication() auth.Auther { - method := settings.GlobalConfiguration.Auth.Method - var defaultAuther map[string]interface{} - var auther auth.Auther - if method == "proxy" { - header := settings.GlobalConfiguration.Auth.Header - if header == "" { - header = defaultAuther["header"].(string) - } - - if header == "" { - checkErr(nerrors.New("you must set the flag 'auth.header' for method 'proxy'")) - } - - auther = &auth.ProxyAuth{Header: header} - } - - if method == "noauth" { - auther = &auth.NoAuth{} - } - - if method == "password" { - jsonAuth := &auth.JSONAuth{} - host := settings.GlobalConfiguration.Auth.Recaptcha.Host - key := settings.GlobalConfiguration.Auth.Recaptcha.Key - secret := settings.GlobalConfiguration.Auth.Recaptcha.Secret - - if key == "" { - if kmap, ok := defaultAuther["recaptcha"].(map[string]interface{}); ok { - key = kmap["key"].(string) - } - } - - if secret == "" { - if smap, ok := defaultAuther["recaptcha"].(map[string]interface{}); ok { - secret = smap["secret"].(string) - } - } - - if key != "" && secret != "" { - jsonAuth.ReCaptcha = &auth.ReCaptcha{ - Host: host, - Key: key, - Secret: secret, - } - } - auther = jsonAuth - } - - if method == "hook" { - command := settings.GlobalConfiguration.Auth.Command - - if command == "" { - command = defaultAuther["command"].(string) - } - - if command == "" { - checkErr(nerrors.New("you must set the flag 'auth.command' for method 'hook'")) - } - - auther = &auth.HookAuth{Command: command} - } - - if auther == nil { - panic(errors.ErrInvalidAuthMethod) - } - - return auther -} - -func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Auther) { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) //nolint:gomnd - - fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup) - fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir) - fmt.Fprintf(w, "Auth method:\t%s\n", set.Auth.Method) - fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " ")) - fmt.Fprintln(w, "\nFrontend:") - fmt.Fprintf(w, "\tName:\t%s\n", set.Frontend.Name) - fmt.Fprintf(w, "\tFiles override:\t%s\n", set.Frontend.Files) - fmt.Fprintf(w, "\tDisable external links:\t%t\n", set.Frontend.DisableExternal) - fmt.Fprintf(w, "\tDisable used disk percentage graph:\t%t\n", set.Frontend.DisableUsedPercentage) - fmt.Fprintf(w, "\tColor:\t%s\n", set.Frontend.Color) - fmt.Fprintln(w, "\nServer:") - fmt.Fprintf(w, "\tLog:\t%s\n", ser.Log) - fmt.Fprintf(w, "\tBase URL:\t%s\n", ser.BaseURL) - fmt.Fprintf(w, "\tRoot:\t%s\n", ser.Root) - fmt.Fprintf(w, "\tSocket:\t%s\n", ser.Socket) - fmt.Fprintf(w, "\tAddress:\t%s\n", ser.Address) - fmt.Fprintf(w, "\tTLS Cert:\t%s\n", ser.TLSCert) - fmt.Fprintf(w, "\tTLS Key:\t%s\n", ser.TLSKey) - fmt.Fprintf(w, "\tExec Enabled:\t%t\n", ser.EnableExec) - fmt.Fprintln(w, "\nDefaults:") - fmt.Fprintf(w, "\tScope:\t%s\n", set.UserDefaults.Scope) - fmt.Fprintf(w, "\tLocale:\t%s\n", set.UserDefaults.Locale) - fmt.Fprintf(w, "\tView mode:\t%s\n", set.UserDefaults.ViewMode) - fmt.Fprintf(w, "\tSingle Click:\t%t\n", set.UserDefaults.SingleClick) - fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.UserDefaults.Commands, " ")) - fmt.Fprintf(w, "\tSorting:\n") - fmt.Fprintf(w, "\t\tBy:\t%s\n", set.UserDefaults.Sorting.By) - fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.UserDefaults.Sorting.Asc) - fmt.Fprintf(w, "\tPermissions:\n") - fmt.Fprintf(w, "\t\tAdmin:\t%t\n", set.UserDefaults.Perm.Admin) - fmt.Fprintf(w, "\t\tExecute:\t%t\n", set.UserDefaults.Perm.Execute) - fmt.Fprintf(w, "\t\tCreate:\t%t\n", set.UserDefaults.Perm.Create) - fmt.Fprintf(w, "\t\tRename:\t%t\n", set.UserDefaults.Perm.Rename) - fmt.Fprintf(w, "\t\tModify:\t%t\n", set.UserDefaults.Perm.Modify) - fmt.Fprintf(w, "\t\tDelete:\t%t\n", set.UserDefaults.Perm.Delete) - fmt.Fprintf(w, "\t\tShare:\t%t\n", set.UserDefaults.Perm.Share) - fmt.Fprintf(w, "\t\tDownload:\t%t\n", set.UserDefaults.Perm.Download) - w.Flush() - - b, err := json.MarshalIndent(auther, "", " ") - checkErr(err) - fmt.Printf("\nAuther configuration (raw):\n\n%s\n\n", string(b)) -} diff --git a/backend/cmd/config_cat.go b/backend/cmd/config_cat.go deleted file mode 100644 index 3f06eb9f..00000000 --- a/backend/cmd/config_cat.go +++ /dev/null @@ -1,25 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - configCmd.AddCommand(configCatCmd) -} - -var configCatCmd = &cobra.Command{ - Use: "cat", - Short: "Prints the configuration", - Long: `Prints the configuration.`, - Args: cobra.NoArgs, - Run: python(func(cmd *cobra.Command, args []string, d pythonData) { - set, err := d.store.Settings.Get() - checkErr(err) - ser, err := d.store.Settings.GetServer() - checkErr(err) - auther, err := d.store.Auth.Get(set.Auth.Method) - checkErr(err) - printSettings(ser, set, auther) - }, pythonConfig{}), -} diff --git a/backend/cmd/config_export.go b/backend/cmd/config_export.go deleted file mode 100644 index a4d8ecff..00000000 --- a/backend/cmd/config_export.go +++ /dev/null @@ -1,37 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" -) - -func init() { - configCmd.AddCommand(configExportCmd) -} - -var configExportCmd = &cobra.Command{ - 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) - - server, err := d.store.Settings.GetServer() - checkErr(err) - - auther, err := d.store.Auth.Get(settings.Auth.Method) - checkErr(err) - - data := &settingsFile{ - Settings: settings, - Auther: auther, - Server: server, - } - - err = marshal(args[0], data) - checkErr(err) - }, pythonConfig{}), -} diff --git a/backend/cmd/config_import.go b/backend/cmd/config_import.go index 08ff806d..ed6702fc 100644 --- a/backend/cmd/config_import.go +++ b/backend/cmd/config_import.go @@ -3,9 +3,9 @@ package cmd import ( "encoding/json" "errors" + "log" "path/filepath" "reflect" - "log" "github.com/spf13/cobra" @@ -13,10 +13,6 @@ import ( "github.com/gtsteffaniak/filebrowser/settings" ) -func init() { - configCmd.AddCommand(configImportCmd) -} - type settingsFile struct { Settings *settings.Settings `json:"settings"` Server *settings.Server `json:"server"` @@ -61,7 +57,7 @@ The path must be for a json or yaml file.`, } else { rawAuther = file.Auther } - log.Println("config_import",file.Settings.Auth) + log.Println("config_import", file.Settings.Auth) var auther auth.Auther switch file.Settings.Auth.Method { case "password": @@ -79,7 +75,6 @@ The path must be for a json or yaml file.`, err = d.store.Auth.Save(auther) checkErr(err) - printSettings(file.Server, file.Settings, auther) }, pythonConfig{allowNoDB: true}), } diff --git a/backend/cmd/config_init.go b/backend/cmd/config_init.go index b3eaa3f7..758f3da5 100644 --- a/backend/cmd/config_init.go +++ b/backend/cmd/config_init.go @@ -5,14 +5,11 @@ import ( "github.com/spf13/cobra" + "github.com/gtsteffaniak/filebrowser/auth" + "github.com/gtsteffaniak/filebrowser/errors" "github.com/gtsteffaniak/filebrowser/settings" ) -func init() { - configCmd.AddCommand(configInitCmd) - addConfigFlags(configInitCmd.Flags()) -} - var configInitCmd = &cobra.Command{ Use: "init", Short: "Initialize a new database", @@ -38,6 +35,45 @@ Congratulations! You've set up your database to use with File Browser. Now add your first user via 'filebrowser users add' and then you just need to call the main command to boot up the server. `) - printSettings(&s.Server, &s, auther) }, pythonConfig{noDB: true}), } + +//nolint:gocyclo +func getAuthentication() auth.Auther { + method := settings.GlobalConfiguration.Auth.Method + var auther auth.Auther + if method == "proxy" { + header := settings.GlobalConfiguration.Auth.Header + auther = &auth.ProxyAuth{Header: header} + } + + if method == "noauth" { + auther = &auth.NoAuth{} + } + + if method == "password" { + jsonAuth := &auth.JSONAuth{} + host := settings.GlobalConfiguration.Auth.Recaptcha.Host + key := settings.GlobalConfiguration.Auth.Recaptcha.Key + secret := settings.GlobalConfiguration.Auth.Recaptcha.Secret + if key != "" && secret != "" { + jsonAuth.ReCaptcha = &auth.ReCaptcha{ + Host: host, + Key: key, + Secret: secret, + } + } + auther = jsonAuth + } + + if method == "hook" { + command := settings.GlobalConfiguration.Auth.Command + auther = &auth.HookAuth{Command: command} + } + + if auther == nil { + panic(errors.ErrInvalidAuthMethod) + } + + return auther +} diff --git a/backend/cmd/config_set.go b/backend/cmd/config_set.go deleted file mode 100644 index cb1b6917..00000000 --- a/backend/cmd/config_set.go +++ /dev/null @@ -1,74 +0,0 @@ -package cmd - -import ( - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -func init() { - configCmd.AddCommand(configSetCmd) - addConfigFlags(configSetCmd.Flags()) -} - -var configSetCmd = &cobra.Command{ - Use: "set", - Short: "Updates the configuration", - Long: `Updates the configuration. Set the flags for the options -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() - set, err := d.store.Settings.Get() - checkErr(err) - - ser, err := d.store.Settings.GetServer() - checkErr(err) - - flags.Visit(func(flag *pflag.Flag) { - switch flag.Name { - case "baseurl": - ser.BaseURL = mustGetString(flags, flag.Name) - case "root": - ser.Root = mustGetString(flags, flag.Name) - case "socket": - ser.Socket = mustGetString(flags, flag.Name) - case "cert": - ser.TLSCert = mustGetString(flags, flag.Name) - case "key": - ser.TLSKey = mustGetString(flags, flag.Name) - case "address": - ser.Address = mustGetString(flags, flag.Name) - case "port": - ser.Port = 8080 - case "log": - ser.Log = mustGetString(flags, flag.Name) - case "signup": - set.Signup = mustGetBool(flags, flag.Name) - case "shell": - set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name)) - case "frontend.name": - set.Frontend.Name = mustGetString(flags, flag.Name) - case "frontend.color": - set.Frontend.Color = mustGetString(flags, flag.Name) - case "frontend.disableExternal": - set.Frontend.DisableExternal = mustGetBool(flags, flag.Name) - case "frontend.disableUsedPercentage": - set.Frontend.DisableUsedPercentage = mustGetBool(flags, flag.Name) - case "frontend.files": - set.Frontend.Files = mustGetString(flags, flag.Name) - } - }) - - getUserDefaults(flags, &set.UserDefaults, false) - - // read the defaults - auther := getAuthentication() - err = d.store.Auth.Save(auther) - checkErr(err) - err = d.store.Settings.Save(set) - checkErr(err) - err = d.store.Settings.SaveServer(ser) - checkErr(err) - printSettings(ser, set, auther) - }, pythonConfig{}), -} diff --git a/backend/cmd/root.go b/backend/cmd/root.go index 970fde83..2e823472 100644 --- a/backend/cmd/root.go +++ b/backend/cmd/root.go @@ -210,50 +210,18 @@ func setupLog(logMethod string) { } func quickSetup(flags *pflag.FlagSet, d pythonData) { - set := &settings.Settings{ - Key: generateKey(), - Signup: false, - CreateUserDir: false, - UserHomeBasePath: settings.DefaultUsersHomeBasePath, - UserDefaults: settings.UserDefaults{ - Scope: ".", - Locale: "en", - SingleClick: false, - Perm: users.Permissions{ - Admin: false, - Execute: true, - Create: true, - Rename: true, - Modify: true, - Delete: true, - Share: true, - Download: true, - }, - }, - Frontend: settings.Frontend{}, - Commands: nil, - Shell: nil, - Rules: nil, - } + settings.GlobalConfiguration.Key = generateKey() var err error if settings.GlobalConfiguration.Auth.Method == "noauth" { - set.Auth.Method = "noauth" + settings.GlobalConfiguration.Auth.Method = "noauth" err = d.store.Auth.Save(&auth.NoAuth{}) } else { - set.Auth.Method = "password" + settings.GlobalConfiguration.Auth.Method = "password" err = d.store.Auth.Save(&auth.JSONAuth{}) } - err = d.store.Settings.Save(set) + err = d.store.Settings.Save(&settings.GlobalConfiguration) checkErr(err) - - ser := &settings.Server{ - BaseURL: getParam(flags, "baseurl"), - Log: getParam(flags, "log"), - TLSKey: getParam(flags, "key"), - TLSCert: getParam(flags, "cert"), - Root: getParam(flags, "root"), - } - err = d.store.Settings.SaveServer(ser) + err = d.store.Settings.SaveServer(&settings.GlobalConfiguration.Server) checkErr(err) username := getParam(flags, "username") @@ -274,7 +242,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) { LockPassword: false, } - set.UserDefaults.Apply(user) + settings.GlobalConfiguration.UserDefaults.Apply(user) user.Perm.Admin = true err = d.store.Users.Save(user) diff --git a/backend/cmd/users_add.go b/backend/cmd/users_add.go index eac81240..0ba430eb 100644 --- a/backend/cmd/users_add.go +++ b/backend/cmd/users_add.go @@ -19,7 +19,6 @@ var usersAddCmd = &cobra.Command{ Run: python(func(cmd *cobra.Command, args []string, d pythonData) { s, err := d.store.Settings.Get() checkErr(err) - getUserDefaults(cmd.Flags(), &s.UserDefaults, false) password, err := users.HashPwd(args[1]) checkErr(err) diff --git a/backend/cmd/users_update.go b/backend/cmd/users_update.go index 09bb4b8d..04dd7ce5 100644 --- a/backend/cmd/users_update.go +++ b/backend/cmd/users_update.go @@ -49,7 +49,6 @@ options you want to change.`, Sorting: user.Sorting, Commands: user.Commands, } - getUserDefaults(flags, &defaults, false) user.Scope = defaults.Scope user.Locale = defaults.Locale user.ViewMode = defaults.ViewMode diff --git a/backend/settings/filebrowser.yaml b/backend/filebrowser.yaml similarity index 84% rename from backend/settings/filebrowser.yaml rename to backend/filebrowser.yaml index 8a5d8ddf..6a202701 100644 --- a/backend/settings/filebrowser.yaml +++ b/backend/filebrowser.yaml @@ -1,11 +1,11 @@ server: - indexingInterval: 5 - numImageProcessors: 2 + indexingInterval: 60 + numImageProcessors: 8 socket: "" tlsKey: "" tlsCert: "" - enableThumbnails: false - resizePreview: true + enableThumbnails: true + resizePreview: false typeDetectionByHeader: true port: 8080 baseURL: "/" @@ -21,7 +21,7 @@ auth: header: "" method: noauth command: "" - signup: false + signup: true shell: "" frontend: name: "" @@ -34,7 +34,7 @@ userDefaults: scope: "" locale: "" viewMode: "" - singleClick: true + singleClick: false sorting: by: "" asc: true diff --git a/backend/go.mod b/backend/go.mod index f2ab4898..63bde874 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -9,12 +9,11 @@ require ( github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 github.com/goccy/go-yaml v1.11.0 github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/google/go-cmp v0.5.9 github.com/gorilla/mux v1.8.0 - github.com/gorilla/websocket v1.5.0 github.com/maruel/natural v1.1.0 github.com/marusama/semaphore/v2 v2.5.0 github.com/mholt/archiver/v3 v3.5.1 - github.com/pelletier/go-toml/v2 v2.0.9 github.com/shirou/gopsutil/v3 v3.23.7 github.com/spf13/afero v1.9.5 github.com/spf13/cobra v1.7.0 @@ -22,7 +21,6 @@ require ( github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce - go.etcd.io/bbolt v1.3.7 golang.org/x/crypto v0.12.0 golang.org/x/image v0.11.0 golang.org/x/text v0.12.0 @@ -51,6 +49,7 @@ require ( github.com/mattn/go-isatty v0.0.14 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/nwaples/rardecode v1.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/pierrec/lz4/v4 v4.1.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect @@ -60,6 +59,7 @@ require ( github.com/ulikunitz/xz v0.5.9 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect + go.etcd.io/bbolt v1.3.7 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/backend/go.sum b/backend/go.sum index ebb50138..5aa94277 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -178,8 +178,6 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= diff --git a/backend/http/auth.go b/backend/http/auth.go index 5ff0f656..53dda241 100644 --- a/backend/http/auth.go +++ b/backend/http/auth.go @@ -107,7 +107,7 @@ var loginHandler = func(w http.ResponseWriter, r *http.Request, d *data) (int, e return http.StatusInternalServerError, err } - user, err := auther.Auth(r, d.store.Users, d.settings, d.server) + user, err := auther.Auth(r, d.store.Users) if err == os.ErrPermission { return http.StatusForbidden, nil } else if err != nil { @@ -177,6 +177,7 @@ var renewHandler = withUser(func(w http.ResponseWriter, r *http.Request, d *data }) func printToken(w http.ResponseWriter, _ *http.Request, d *data, user *users.User) (int, error) { + log.Printf("%#v", user) claims := &authToken{ User: userInfo{ ID: user.ID, diff --git a/backend/settings/config.go b/backend/settings/config.go index b2d2cd47..751b0406 100644 --- a/backend/settings/config.go +++ b/backend/settings/config.go @@ -1,43 +1,31 @@ package settings import ( - "fmt" "log" "os" - "path/filepath" "github.com/goccy/go-yaml" ) var GlobalConfiguration Settings +var configYml = "filebrowser.yaml" func Initialize() { - // Open and read the YAML file - yamlFile, err := os.Open("filebrowser.yaml") + yamlData := loadConfigFile() + GlobalConfiguration = setDefaults() + err := yaml.Unmarshal(yamlData, &GlobalConfiguration) if err != nil { - log.Println("Error opening config file: ", err) - log.Println("Using default config only") - // Get the current directory - dir, err := os.Getwd() - if err != nil { - fmt.Println("Error:", err) - return - } + log.Fatalf("Error unmarshaling YAML data: %v", err) + } +} - // Use the filepath package to join the directory and file names - err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if err != nil { - fmt.Println("Error:", err) - return err - } - // Check if it's a regular file (not a directory) - if !info.IsDir() { - fmt.Println(path) - } - return nil - }) +func loadConfigFile() []byte { + // Open and read the YAML file + yamlFile, err := os.Open(configYml) + if err != nil { + log.Printf("Error opening config file: %v\nUsing default config only", err) setDefaults() - return + return []byte{} } defer yamlFile.Close() @@ -51,22 +39,16 @@ func Initialize() { if err != nil { log.Fatalf("Error reading YAML data: %v", err) } - // Unmarshal the YAML data into the Settings struct - err = yaml.Unmarshal(yamlData, &GlobalConfiguration) - if err != nil { - log.Fatalf("Error unmarshaling YAML data: %v", err) - } - // Now you have the Settings struct with values from the YAML file - // You can access the values like: defaultSettings.Key, defaultSettings.Server.Port, etc. + return yamlData } -func setDefaults() { - GlobalConfiguration = Settings{ +func setDefaults() Settings { + return Settings{ Signup: true, Server: Server{ IndexingInterval: 5, Port: 8080, - NumImageProcessors: 1, + NumImageProcessors: 4, BaseURL: "", }, Auth: Auth{ @@ -75,5 +57,8 @@ func setDefaults() { Host: "", }, }, + UserDefaults: UserDefaults{ + HideDotfiles: true, + }, } } diff --git a/backend/settings/settings_test.go b/backend/settings/settings_test.go index 5b9285d7..7eefacd7 100644 --- a/backend/settings/settings_test.go +++ b/backend/settings/settings_test.go @@ -1,10 +1,46 @@ package settings import ( + "log" "testing" + + "github.com/goccy/go-yaml" + "github.com/google/go-cmp/cmp" ) -func TestConfigLoad(t *testing.T) { - Initialize() - t.Log("Say bye") +func TestConfigLoadChanged(t *testing.T) { + configYml = "./testingConfig.yaml" + yamlData := loadConfigFile() + // Marshal the YAML data to a more human-readable format + newConfig := setDefaults() + GlobalConfiguration := setDefaults() + + err := yaml.Unmarshal(yamlData, &newConfig) + if err != nil { + log.Fatalf("Error unmarshaling YAML data: %v", err) + } + // Use go-cmp to compare the two structs + if diff := cmp.Diff(newConfig, GlobalConfiguration); diff == "" { + t.Errorf("No change when there should have been (-want +got):\n%s", diff) + } +} + +func TestConfigLoadSpecificValues(t *testing.T) { + configYml = "./testingConfig.yaml" + yamlData := loadConfigFile() + // Marshal the YAML data to a more human-readable format + newConfig := setDefaults() + GlobalConfiguration := setDefaults() + + err := yaml.Unmarshal(yamlData, &newConfig) + if err != nil { + log.Fatalf("Error unmarshaling YAML data: %v", err) + } + + if GlobalConfiguration.Auth.Method == newConfig.Auth.Method { + log.Fatalf("Differences should have been found, but were not on Auth method") + } + if GlobalConfiguration.UserDefaults.HideDotfiles == newConfig.UserDefaults.HideDotfiles { + log.Fatalf("Differences should have been found, but were not on Auth method") + } } diff --git a/backend/settings/structs.go b/backend/settings/structs.go index 7b05b531..84401379 100644 --- a/backend/settings/structs.go +++ b/backend/settings/structs.go @@ -64,7 +64,6 @@ type Server struct { Log string `json:"log"` Database string `json:"database"` Root string `json:"root"` - EnablePreviewResize bool `json:"enablePreviewResize"` } type Frontend struct { diff --git a/backend/settings/testingConfig.yaml b/backend/settings/testingConfig.yaml new file mode 100644 index 00000000..f2dd121d --- /dev/null +++ b/backend/settings/testingConfig.yaml @@ -0,0 +1,52 @@ +server: + indexingInterval: 5 + numImageProcessors: 4 + socket: "" + tlsKey: "" + tlsCert: "" + enableThumbnails: false + resizePreview: true + typeDetectionByHeader: true + port: 8080 + baseURL: "/" + address: "" + log: "stdout" + database: "database.db" + root: "/srv" +auth: + recaptcha: + host: "" + key: "" + secret: "" + header: "" + method: json + command: "" + signup: false + shell: "" +frontend: + name: "" + disableExternal: false + disableUsedPercentage: true + files: "" + theme: "" + color: "" +userDefaults: + scope: "" + locale: "" + viewMode: "" + singleClick: true + sorting: + by: "" + asc: true + perm: + admin: true + execute: true + create: true + rename: true + modify: true + delete: true + share: true + download: true + commands: [] + hideDotfiles: false + dateFormat: false diff --git a/backend/storage/bolt/utils.go b/backend/storage/bolt/utils.go index fa84e3c3..f0cc6253 100644 --- a/backend/storage/bolt/utils.go +++ b/backend/storage/bolt/utils.go @@ -1,12 +1,15 @@ package bolt import ( + "log" + "github.com/asdine/storm/v3" "github.com/gtsteffaniak/filebrowser/errors" ) func get(db *storm.DB, name string, to interface{}) error { + log.Printf("name, %v , to %#v", name, to) err := db.Get("config", name, to) if err == storm.ErrNotFound { return errors.ErrNotExist @@ -16,5 +19,6 @@ func get(db *storm.DB, name string, to interface{}) error { } func save(db *storm.DB, name string, from interface{}) error { + log.Printf("name, %v , from %#v", name, from) return db.Set("config", name, from) } diff --git a/frontend/src/views/settings/Global.vue b/frontend/src/views/settings/Global.vue index 3807dab6..ff1618f7 100644 --- a/frontend/src/views/settings/Global.vue +++ b/frontend/src/views/settings/Global.vue @@ -56,7 +56,7 @@

{{ $t("settings.disableExternalLinks") }} @@ -65,7 +65,7 @@

{{ $t("settings.disableUsedDiskPercentage") }} @@ -75,7 +75,7 @@

@@ -85,7 +85,7 @@

@@ -97,7 +97,7 @@