diff options
-rw-r--r-- | api4/command.go | 64 | ||||
-rw-r--r-- | api4/command_test.go | 86 | ||||
-rw-r--r-- | model/client4.go | 11 |
3 files changed, 161 insertions, 0 deletions
diff --git a/api4/command.go b/api4/command.go index f44363522..47c37fe34 100644 --- a/api4/command.go +++ b/api4/command.go @@ -4,8 +4,10 @@ package api4 import ( + "io/ioutil" "net/http" "strconv" + "strings" l4g "github.com/alecthomas/log4go" "github.com/mattermost/platform/app" @@ -18,12 +20,16 @@ func InitCommand() { BaseRoutes.Commands.Handle("", ApiSessionRequired(createCommand)).Methods("POST") BaseRoutes.Commands.Handle("", ApiSessionRequired(listCommands)).Methods("GET") + BaseRoutes.Commands.Handle("/execute", ApiSessionRequired(executeCommand)).Methods("POST") BaseRoutes.Command.Handle("", ApiSessionRequired(updateCommand)).Methods("PUT") BaseRoutes.Command.Handle("", ApiSessionRequired(deleteCommand)).Methods("DELETE") BaseRoutes.Team.Handle("/commands/autocomplete", ApiSessionRequired(listAutocompleteCommands)).Methods("GET") BaseRoutes.Command.Handle("/regen_token", ApiSessionRequired(regenCommandToken)).Methods("PUT") + + BaseRoutes.Teams.Handle("/command_test", ApiHandler(testCommand)).Methods("POST") + BaseRoutes.Teams.Handle("/command_test", ApiHandler(testCommand)).Methods("GET") } func createCommand(c *Context, w http.ResponseWriter, r *http.Request) { @@ -183,6 +189,44 @@ func listCommands(c *Context, w http.ResponseWriter, r *http.Request) { w.Write([]byte(model.CommandListToJson(commands))) } +func executeCommand(c *Context, w http.ResponseWriter, r *http.Request) { + commandArgs := model.CommandArgsFromJson(r.Body) + if commandArgs == nil { + c.SetInvalidParam("command_args") + return + } + + if len(commandArgs.Command) <= 1 || strings.Index(commandArgs.Command, "/") != 0 || len(commandArgs.ChannelId) != 26 { + c.Err = model.NewAppError("executeCommand", "api.command.execute_command.start.app_error", nil, "", http.StatusBadRequest) + return + } + + if !app.SessionHasPermissionToChannel(c.Session, commandArgs.ChannelId, model.PERMISSION_USE_SLASH_COMMANDS) { + c.SetPermissionError(model.PERMISSION_USE_SLASH_COMMANDS) + return + } + + channel, err := app.GetChannel(commandArgs.ChannelId) + if err != nil { + c.Err = err + return + } + + commandArgs.TeamId = channel.TeamId + commandArgs.UserId = c.Session.UserId + commandArgs.T = c.T + commandArgs.Session = c.Session + commandArgs.SiteURL = c.GetSiteURLHeader() + + response, err := app.ExecuteCommand(commandArgs) + if err != nil { + c.Err = err + return + } + + w.Write([]byte(response.ToJson())) +} + func listAutocompleteCommands(c *Context, w http.ResponseWriter, r *http.Request) { c.RequireTeamId() if c.Err != nil { @@ -239,3 +283,23 @@ func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) { w.Write([]byte(model.MapToJson(resp))) } + +func testCommand(c *Context, w http.ResponseWriter, r *http.Request) { + r.ParseForm() + + msg := "" + if r.Method == "POST" { + msg = msg + "\ntoken=" + r.FormValue("token") + msg = msg + "\nteam_domain=" + r.FormValue("team_domain") + } else { + body, _ := ioutil.ReadAll(r.Body) + msg = string(body) + } + + rc := &model.CommandResponse{ + Text: "test command response " + msg, + ResponseType: model.COMMAND_RESPONSE_TYPE_IN_CHANNEL, + } + + w.Write([]byte(rc.ToJson())) +} diff --git a/api4/command_test.go b/api4/command_test.go index 0aaca3c0f..4bbf20084 100644 --- a/api4/command_test.go +++ b/api4/command_test.go @@ -379,5 +379,91 @@ func TestRegenToken(t *testing.T) { if token != "" { t.Fatal("should not return the token") } +} + +func TestExecuteCommand(t *testing.T) { + th := Setup().InitBasic().InitSystemAdmin() + defer TearDown() + Client := th.Client + channel := th.BasicChannel + + enableCommands := *utils.Cfg.ServiceSettings.EnableCommands + defer func() { + utils.Cfg.ServiceSettings.EnableCommands = &enableCommands + }() + *utils.Cfg.ServiceSettings.EnableCommands = true + postCmd := &model.Command{ + CreatorId: th.BasicUser.Id, + TeamId: th.BasicTeam.Id, + URL: "http://localhost" + utils.Cfg.ServiceSettings.ListenAddress + model.API_URL_SUFFIX_V4 + "/teams/command_test", + Method: model.COMMAND_METHOD_POST, + Trigger: "postcommand", + } + + if _, err := app.CreateCommand(postCmd); err != nil { + t.Fatal("failed to create post command") + } + + commandResponse, resp := Client.ExecuteCommand(channel.Id, "/postcommand") + CheckNoError(t, resp) + + if commandResponse == nil { + t.Fatal("command response should have returned") + } + + posts, err := app.GetPostsPage(channel.Id, 0, 10) + if err != nil || posts == nil || len(posts.Order) != 2 { + t.Fatal("Test command failed to send") + } + + getCmd := &model.Command{ + CreatorId: th.BasicUser.Id, + TeamId: th.BasicTeam.Id, + URL: "http://localhost" + utils.Cfg.ServiceSettings.ListenAddress + model.API_URL_SUFFIX_V4 + "/teams/command_test", + Method: model.COMMAND_METHOD_GET, + Trigger: "getcommand", + } + + if _, err := app.CreateCommand(getCmd); err != nil { + t.Fatal("failed to create get command") + } + + commandResponse, resp = Client.ExecuteCommand(channel.Id, "/getcommand") + CheckNoError(t, resp) + + if commandResponse == nil { + t.Fatal("command response should have returned") + } + + posts, err = app.GetPostsPage(channel.Id, 0, 10) + if err != nil || posts == nil || len(posts.Order) != 3 { + t.Fatal("Test command failed to send") + } + + _, resp = Client.ExecuteCommand(channel.Id, "") + CheckBadRequestStatus(t, resp) + + _, resp = Client.ExecuteCommand(channel.Id, "/") + CheckBadRequestStatus(t, resp) + + _, resp = Client.ExecuteCommand(channel.Id, "getcommand") + CheckBadRequestStatus(t, resp) + + _, resp = Client.ExecuteCommand(channel.Id, "/junk") + CheckNotFoundStatus(t, resp) + + otherUser := th.CreateUser() + Client.Login(otherUser.Email, otherUser.Password) + + _, resp = Client.ExecuteCommand(channel.Id, "/getcommand") + CheckForbiddenStatus(t, resp) + + Client.Logout() + + _, resp = Client.ExecuteCommand(channel.Id, "/getcommand") + CheckUnauthorizedStatus(t, resp) + + _, resp = th.SystemAdminClient.ExecuteCommand(channel.Id, "/getcommand") + CheckNoError(t, resp) } diff --git a/model/client4.go b/model/client4.go index 2a7338809..a33e62846 100644 --- a/model/client4.go +++ b/model/client4.go @@ -2389,6 +2389,17 @@ func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Res } } +// ExecuteCommand executes a given command. +func (c *Client4) ExecuteCommand(channelId, command string) (*CommandResponse, *Response) { + commandArgs := &CommandArgs{ChannelId: channelId, Command: command} + if r, err := c.DoApiPost(c.GetCommandsRoute()+"/execute", commandArgs.ToJson()); err != nil { + return nil, &Response{StatusCode: r.StatusCode, Error: err} + } else { + defer closeBody(r) + return CommandResponseFromJson(r.Body), BuildResponse(r) + } +} + // ListCommands will retrieve a list of commands available in the team. func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response) { if r, err := c.DoApiGet(c.GetTeamAutoCompleteCommandsRoute(teamId), ""); err != nil { |