APIv4 POST /commands/execute (#6205)

This commit is contained in:
Saturnino Abril
2017-04-27 09:41:52 -04:00
committed by Joram Wilander
parent bd66587183
commit 0e007e344b
3 changed files with 162 additions and 1 deletions
+64
View File
@@ -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()))
}
+87 -1
View File
@@ -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)
}
+11
View File
@@ -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 {