From df393398490453df627e4f688b5c7bcd3510391d Mon Sep 17 00:00:00 2001 From: Adin Schmahmann Date: Tue, 4 Aug 2020 17:01:13 -0400 Subject: [PATCH] refactor: move external command checks into commands lib (#198) * refactor: move environment-based command restrictions to be stored with the command itself --- command.go | 34 ++++++++++++++++++++++++++++++++++ http/parse.go | 13 ++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/command.go b/command.go index 9acb8c96..f31b3de2 100644 --- a/command.go +++ b/command.go @@ -90,6 +90,39 @@ type Command struct { // simple typo in a sub command will invoke the parent command and may // end up returning a cryptic error to the user. Subcommands map[string]*Command + + // NoRemote denotes that a command cannot be executed in a remote environment + NoRemote bool + + // NoLocal denotes that a command cannot be executed in a local environment + NoLocal bool + + // Extra contains a set of other command-specific parameters + Extra *Extra +} + +// Extra is a set of tag information for a command +type Extra struct { + m map[interface{}]interface{} +} + +func (e *Extra) SetValue(key, value interface{}) *Extra { + if e == nil { + e = &Extra{} + } + if e.m == nil { + e.m = make(map[interface{}]interface{}) + } + e.m[key] = value + return e +} + +func (e *Extra) GetValue(key interface{}) (interface{}, bool) { + if e == nil || e.m == nil { + return nil, false + } + val, found := e.m[key] + return val, found } var ( @@ -141,6 +174,7 @@ func (c *Command) call(req *Request, re ResponseEmitter, env Environment) error } // Resolve returns the subcommands at the given path +// The returned set of subcommands starts with this command and therefore is always at least size 1 func (c *Command) Resolve(pth []string) ([]*Command, error) { cmds := make([]*Command, len(pth)+1) cmds[0] = c diff --git a/http/parse.go b/http/parse.go index d35c281d..a7bfa67b 100644 --- a/http/parse.go +++ b/http/parse.go @@ -28,12 +28,19 @@ func parseRequest(r *http.Request, root *cmds.Command) (*cmds.Request, error) { getPath = pth[:len(pth)-1] ) - cmd, err := root.Get(getPath) + cmdPath, err := root.Resolve(getPath) if err != nil { // 404 if there is no command at that path return nil, ErrNotFound } + for _, c := range cmdPath { + if c.NoRemote { + return nil, ErrNotFound + } + } + + cmd := cmdPath[len(cmdPath)-1] sub := cmd.Subcommands[pth[len(pth)-1]] if sub == nil { @@ -49,6 +56,10 @@ func parseRequest(r *http.Request, root *cmds.Command) (*cmds.Request, error) { cmd = sub } + if cmd.NoRemote { + return nil, ErrNotFound + } + opts, stringArgs2 := parseOptions(r) optDefs, err := root.GetOptions(pth) if err != nil {