From aae318028ba37f763b17c6f875b594fb7a22bb90 Mon Sep 17 00:00:00 2001 From: Henrique Dias Date: Sun, 18 Dec 2016 12:34:31 +0000 Subject: [PATCH] before and after save hooks --- config/commands.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++ config/config.go | 15 +++++++++++- filemanager.go | 8 ++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 config/commands.go diff --git a/config/commands.go b/config/commands.go new file mode 100644 index 00000000..d0720b95 --- /dev/null +++ b/config/commands.go @@ -0,0 +1,61 @@ +package config + +import ( + "log" + "net/http" + "os" + "os/exec" + "path/filepath" + "strings" + + "github.com/mholt/caddy" +) + +type commandRunner func(r *http.Request, c *Config, u *User) error + +// CommandRunner ... +func CommandRunner(c *caddy.Controller) (commandRunner, error) { + fn := func(r *http.Request, c *Config, u *User) error { return nil } + + args := c.RemainingArgs() + if len(args) == 0 { + return fn, c.ArgErr() + } + + nonblock := false + if len(args) > 1 && args[len(args)-1] == "&" { + // Run command in background; non-blocking + nonblock = true + args = args[:len(args)-1] + } + + command, args, err := caddy.SplitCommandAndArgs(strings.Join(args, " ")) + if err != nil { + return fn, c.Err(err.Error()) + } + + fn = func(r *http.Request, c *Config, u *User) error { + path := strings.Replace(r.URL.Path, c.BaseURL+c.WebDavURL, "", 1) + path = u.Scope + "/" + path + path = filepath.Clean(path) + + for i := range args { + args[i] = strings.Replace(args[i], "{path}", path, -1) + } + + cmd := exec.Command(command, args...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if nonblock { + log.Printf("[INFO] Nonblocking Command:\"%s %s\"", command, strings.Join(args, " ")) + return cmd.Start() + } + + log.Printf("[INFO] Blocking Command:\"%s %s\"", command, strings.Join(args, " ")) + return cmd.Run() + } + + return fn, nil +} diff --git a/config/config.go b/config/config.go index 3bcbbc12..6b1fa1d3 100644 --- a/config/config.go +++ b/config/config.go @@ -3,6 +3,7 @@ package config import ( "fmt" "io/ioutil" + "net/http" "regexp" "strconv" "strings" @@ -23,9 +24,11 @@ type Config struct { HugoEnabled bool // Enables the Hugo plugin for File Manager Users map[string]*User WebDavURL string - CurrentUser *User + BeforeSave commandRunner + AfterSave commandRunner } +// AbsoluteURL ... func (c Config) AbsoluteURL() string { return c.PrefixURL + c.BaseURL } @@ -70,6 +73,8 @@ func Parse(c *caddy.Controller) ([]Config, error) { cfg.AllowEdit = true cfg.AllowNew = true cfg.Commands = []string{"git", "svn", "hg"} + cfg.BeforeSave = func(r *http.Request, c *Config, u *User) error { return nil } + cfg.AfterSave = func(r *http.Request, c *Config, u *User) error { return nil } cfg.Rules = []*Rule{{ Regex: true, Allow: false, @@ -106,6 +111,14 @@ func Parse(c *caddy.Controller) ([]Config, error) { if user.FrontMatter != "yaml" && user.FrontMatter != "json" && user.FrontMatter != "toml" { return configs, c.Err("frontmatter type not supported") } + case "before_save": + if cfg.BeforeSave, err = CommandRunner(c); err != nil { + return configs, err + } + case "after_save": + if cfg.AfterSave, err = CommandRunner(c); err != nil { + return configs, err + } case "webdav": if !c.NextArg() { return configs, c.ArgErr() diff --git a/filemanager.go b/filemanager.go index 0ba46d6a..0f60ca86 100644 --- a/filemanager.go +++ b/filemanager.go @@ -83,12 +83,20 @@ func (f FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, err // Preprocess the PUT request if it's the case if r.Method == http.MethodPut { + if err = c.BeforeSave(r, c, user); err != nil { + return http.StatusInternalServerError, err + } + if handlers.PreProccessPUT(w, r, c, user) != nil { return http.StatusInternalServerError, err } } c.Handler.ServeHTTP(w, r) + if err = c.AfterSave(r, c, user); err != nil { + return http.StatusInternalServerError, err + } + return 0, nil }