From bf054c6379fc61b5a088762338f78898799f1eb1 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 30 Dec 2018 12:40:57 +0000 Subject: [PATCH] feat: settings working once more License: MIT Signed-off-by: Henrique Dias --- cmd/config.go | 2 ++ cmd/users.go | 8 ++--- cmd/users_update.go | 2 ++ frontend | 2 +- go.mod | 1 + go.sum | 2 ++ http/auth.go | 1 + http/http.go | 17 +++++++++++ http/resource.go | 2 +- http/settings.go | 74 +++++++++++++++++++++++++++++++++++++++++++++ http/static.go | 21 +++++++------ types/rule.go | 2 +- types/runner.go | 6 ++-- types/settings.go | 1 + types/user.go | 18 +++++------ 15 files changed, 132 insertions(+), 27 deletions(-) create mode 100644 http/settings.go diff --git a/cmd/config.go b/cmd/config.go index 54e06720..3cc46ea0 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "strings" "text/tabwriter" "github.com/filebrowser/filebrowser/auth" @@ -99,6 +100,7 @@ func printSettings(s *types.Settings, auther types.Auther) { fmt.Fprintf(w, "\tScope:\t%s\n", s.Defaults.Scope) fmt.Fprintf(w, "\tLocale:\t%s\n", s.Defaults.Locale) fmt.Fprintf(w, "\tView mode:\t%s\n", s.Defaults.ViewMode) + fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(s.Defaults.Commands, " ")) fmt.Fprintf(w, "\tSorting:\n") fmt.Fprintf(w, "\t\tBy:\t%s\n", s.Defaults.Sorting.By) fmt.Fprintf(w, "\t\tAsc:\t%t\n", s.Defaults.Sorting.Asc) diff --git a/cmd/users.go b/cmd/users.go index 577b9467..84aa5a4c 100644 --- a/cmd/users.go +++ b/cmd/users.go @@ -66,7 +66,6 @@ func usernameOrIDRequired(cmd *cobra.Command, args []string) error { func addUserFlags(cmd *cobra.Command) { cmd.Flags().Bool("perm.admin", false, "admin perm for users") cmd.Flags().Bool("perm.execute", true, "execute perm for users") - cmd.Flags().StringSlice("perm.commands", nil, "a list of the commands a user can execute") cmd.Flags().Bool("perm.create", true, "create perm for users") cmd.Flags().Bool("perm.rename", true, "rename perm for users") cmd.Flags().Bool("perm.modify", true, "modify perm for users") @@ -76,6 +75,7 @@ func addUserFlags(cmd *cobra.Command) { cmd.Flags().String("sorting.by", "name", "sorting mode (name, size or modified)") cmd.Flags().Bool("sorting.asc", false, "sorting by ascending order") cmd.Flags().Bool("lockPassword", false, "lock password") + cmd.Flags().StringSlice("commands", nil, "a list of the commands a user can execute") cmd.Flags().String("scope", "", "scope for users") cmd.Flags().String("locale", "en", "locale for users") cmd.Flags().String("viewMode", string(types.ListViewMode), "view mode for users") @@ -114,10 +114,10 @@ func getUserDefaults(cmd *cobra.Command, defaults *types.UserDefaults, all bool) defaults.Perm.Share = mustGetBool(cmd, "perm.share") case "perm.download": defaults.Perm.Download = mustGetBool(cmd, "perm.download") - case "perm.commands": - commands, err := cmd.Flags().GetStringSlice("perm.commands") + case "commands": + commands, err := cmd.Flags().GetStringSlice("commands") checkErr(err) - defaults.Perm.Commands = commands + defaults.Commands = commands case "sorting.by": defaults.Sorting.By = mustGetString(cmd, "sorting.by") case "sorting.asc": diff --git a/cmd/users_update.go b/cmd/users_update.go index dcf1f1ee..448dbb74 100644 --- a/cmd/users_update.go +++ b/cmd/users_update.go @@ -47,12 +47,14 @@ options you want to change.`, ViewMode: user.ViewMode, Perm: user.Perm, Sorting: user.Sorting, + Commands: user.Commands, } getUserDefaults(cmd, &defaults, false) user.Scope = defaults.Scope user.Locale = defaults.Locale user.ViewMode = defaults.ViewMode user.Perm = defaults.Perm + user.Commands = defaults.Commands user.Sorting = defaults.Sorting user.LockPassword = mustGetBool(cmd, "lockPassword") diff --git a/frontend b/frontend index 9977299d..daaf341b 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit 9977299d4e3dd201cd3bf648fb70b03e09d6e4e3 +Subproject commit daaf341bc3b6a973a9b32dbeb6b02331cedb6b05 diff --git a/go.mod b/go.mod index cf5c040c..4991000d 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/hacdias/fileutils v0.0.0-20171121222743-76b1c6ab9067 github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jessevdk/go-flags v1.4.0 // indirect + github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3 github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 // indirect github.com/kr/pretty v0.1.0 // indirect github.com/maruel/natural v0.0.0-20180416170133-dbcb3e2e8cf1 diff --git a/go.sum b/go.sum index ed6b8056..e32afbe3 100644 --- a/go.sum +++ b/go.sum @@ -42,6 +42,8 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3 h1:sHsPfNMAG70QAvKbddQ0uScZCHQoZsT5NykGRCeeeIs= +github.com/jinzhu/copier v0.0.0-20180308034124-7e38e58719c3/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1 h1:PJPDf8OUfOK1bb/NeTKd4f1QXZItOX389VN3B6qC8ro= github.com/kardianos/osext v0.0.0-20170510131534-ae77be60afb1/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= diff --git a/http/auth.go b/http/auth.go index 970bf872..7318660f 100644 --- a/http/auth.go +++ b/http/auth.go @@ -56,6 +56,7 @@ func (e *Env) signupHandler(w http.ResponseWriter, r *http.Request) { Locale: e.Settings.Defaults.Locale, Perm: e.Settings.Defaults.Perm, ViewMode: e.Settings.Defaults.ViewMode, + Commands: e.Settings.Defaults.Commands, Scope: e.Settings.Defaults.Scope, } diff --git a/http/http.go b/http/http.go index 768ada51..e8f95a70 100644 --- a/http/http.go +++ b/http/http.go @@ -59,6 +59,9 @@ func Handler(e *Env) http.Handler { api.PathPrefix("/share").HandlerFunc(e.auth(e.sharePostHandler)).Methods("POST") api.PathPrefix("/share").HandlerFunc(e.auth(e.shareDeleteHandler)).Methods("DELETE") + api.HandleFunc("/settings", e.auth(e.settingsGetHandler)).Methods("GET") + api.HandleFunc("/settings", e.auth(e.settingsPutHandler)).Methods("PUT") + api.PathPrefix("/raw").HandlerFunc(e.auth(e.rawHandler)).Methods("GET") return r @@ -100,3 +103,17 @@ func (e *Env) getUser(w http.ResponseWriter, r *http.Request) (*types.User, bool return user, true } + +func (e *Env) getAdminUser(w http.ResponseWriter, r *http.Request) (*types.User, bool) { + user, ok := e.getUser(w, r) + if !ok { + return nil, false + } + + if !user.Perm.Admin { + httpErr(w, r, http.StatusForbidden, nil) + return nil, false + } + + return user, true +} diff --git a/http/resource.go b/http/resource.go index 4440bdae..02684e27 100644 --- a/http/resource.go +++ b/http/resource.go @@ -228,7 +228,7 @@ func (e *Env) resourcePatchHandler(w http.ResponseWriter, r *http.Request) { } return user.Fs.Rename(src, dst) - }, "action", src, dst, user) + }, action, src, dst, user) httpErr(w, r, httpFsErr(err), err) } diff --git a/http/settings.go b/http/settings.go new file mode 100644 index 00000000..22c1da66 --- /dev/null +++ b/http/settings.go @@ -0,0 +1,74 @@ +package http + +import ( + "encoding/json" + "net/http" + + "github.com/filebrowser/filebrowser/types" + "github.com/jinzhu/copier" +) + +type settingsData struct { + Signup bool `json:"signup"` + Defaults types.UserDefaults `json:"defaults"` + Rules []types.Rule `json:"rules"` + Commands map[string][]string `json:"commands"` +} + +func (e *Env) settingsGetHandler(w http.ResponseWriter, r *http.Request) { + _, ok := e.getAdminUser(w, r) + if !ok { + return + } + + data := &settingsData{ + Signup: e.Settings.Signup, + Defaults: e.Settings.Defaults, + Rules: e.Settings.Rules, + Commands: e.Runner.Commands, + } + + renderJSON(w, r, data) +} + +func (e *Env) settingsPutHandler(w http.ResponseWriter, r *http.Request) { + _, ok := e.getAdminUser(w, r) + if !ok { + return + } + + req := &settingsData{} + err := json.NewDecoder(r.Body).Decode(req) + if err != nil { + httpErr(w, r, http.StatusBadRequest, err) + return + } + + runner := &types.Runner{Commands: req.Commands} + err = e.Store.Config.SaveRunner(runner) + if err != nil { + httpErr(w, r, http.StatusInternalServerError, err) + return + } + + settings := &types.Settings{} + err = copier.Copy(settings, e.Settings) + if err != nil { + httpErr(w, r, http.StatusInternalServerError, err) + return + } + + settings.Signup = req.Signup + settings.Defaults = req.Defaults + settings.Rules = req.Rules + + err = e.Store.Config.SaveSettings(settings) + if err != nil { + httpErr(w, r, http.StatusInternalServerError, err) + return + } + + // TODO: env locks + e.Runner = runner + e.Settings = settings +} diff --git a/http/static.go b/http/static.go index 69eda896..653e88d5 100644 --- a/http/static.go +++ b/http/static.go @@ -14,13 +14,9 @@ import ( "github.com/filebrowser/filebrowser/types" ) -func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { - box := rice.MustFindBox("../frontend/dist") - handler := http.FileServer(box.HTTPBox()) - +func (e *Env) getStaticData () map[string]interface{} { baseURL := strings.TrimSuffix(e.Settings.BaseURL, "/") staticURL := strings.TrimPrefix(baseURL+"/static", "/") - cssFile := "" // TODO: baseurl must always not have the trailing slash data := map[string]interface{}{ @@ -43,7 +39,6 @@ func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { } if err == nil { - cssFile = path data["CSS"] = true } } @@ -61,10 +56,18 @@ func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { b, _ := json.MarshalIndent(data, "", " ") data["Json"] = string(b) + return data +} + +func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { + box := rice.MustFindBox("../frontend/dist") + handler := http.FileServer(box.HTTPBox()) + + handleWithData := func(w http.ResponseWriter, r *http.Request, file string, contentType string) { w.Header().Set("Content-Type", contentType) index := template.Must(template.New("index").Delims("[{[", "]}]").Parse(box.MustString(file))) - err := index.Execute(w, data) + err := index.Execute(w, e.getStaticData()) if err != nil { httpErr(w, r, http.StatusInternalServerError, err) @@ -91,8 +94,8 @@ func (e *Env) getStaticHandlers() (http.Handler, http.Handler) { http.ServeFile(w, r, path) return } - } else if r.URL.Path == "custom.css" && cssFile != "" { - http.ServeFile(w, r, cssFile) + } else if r.URL.Path == "custom.css" && e.Settings.Branding.Files != "" { + http.ServeFile(w, r, filepath.Join(e.Settings.Branding.Files, "custom.css")) return } } diff --git a/types/rule.go b/types/rule.go index 9155e132..3de537ca 100644 --- a/types/rule.go +++ b/types/rule.go @@ -16,7 +16,7 @@ type Rule struct { // Regexp is a wrapper to the native regexp type where we // save the raw expression. type Regexp struct { - Raw string + Raw string `json:"raw"` regexp *regexp.Regexp } diff --git a/types/runner.go b/types/runner.go index c7cb2990..d3d0417e 100644 --- a/types/runner.go +++ b/types/runner.go @@ -15,8 +15,6 @@ import ( var DefaultEvents = []string{ "before_save", "after_save", - "before_publish", - "after_publish", "before_copy", "after_copy", "before_rename", @@ -55,6 +53,10 @@ func (r Runner) do(event string, path string, destination string, user *User) er } for _, command := range commands { + if command == "" { + continue + } + args := strings.Split(command, " ") nonblock := false diff --git a/types/settings.go b/types/settings.go index a1eb0854..21753048 100644 --- a/types/settings.go +++ b/types/settings.go @@ -40,4 +40,5 @@ type UserDefaults struct { ViewMode ViewMode `json:"viewMode"` Sorting Sorting `json:"sorting"` Perm Permissions `json:"perm"` + Commands []string `json:"commands"` } diff --git a/types/user.go b/types/user.go index 3505624b..6bc43698 100644 --- a/types/user.go +++ b/types/user.go @@ -15,15 +15,14 @@ const ( // Permissions describe a user's permissions. type Permissions struct { - Admin bool `json:"admin"` - Execute bool `json:"execute"` - Create bool `json:"create"` - Rename bool `json:"rename"` - Modify bool `json:"edit"` - Delete bool `json:"delete"` - Share bool `json:"share"` - Download bool `json:"download"` - Commands []string `json:"commands"` + Admin bool `json:"admin"` + Execute bool `json:"execute"` + Create bool `json:"create"` + Rename bool `json:"rename"` + Modify bool `json:"edit"` + Delete bool `json:"delete"` + Share bool `json:"share"` + Download bool `json:"download"` } // User describes a user. @@ -36,6 +35,7 @@ type User struct { LockPassword bool `json:"lockPassword"` ViewMode ViewMode `json:"viewMode"` Perm Permissions `json:"perm"` + Commands []string `json:"commands"` Sorting Sorting `json:"sorting"` Fs afero.Fs `json:"-"` Rules []Rule `json:"rules"`