[MM 12373] Create CLI command "webhook modify-outgoing" (#10028)

* Add test for modifying outgoing webhook

* Add command to modify an outgoing webhook

* Use updated test helper

* Use errors.Wrap

* Lower case error strings and use fmt.Errorf

* Clone webhook into updatedHook

* Rename error variables
This commit is contained in:
Miguel Alatzar
2019-01-08 11:10:19 -08:00
committed by Jesse Hallam
parent ca4dcf4404
commit 6b59ab4ee8
2 changed files with 202 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ package commands
import (
"fmt"
"strings"
"github.com/mattermost/mattermost-server/model"
"github.com/pkg/errors"
@@ -49,6 +50,14 @@ var WebhookCreateOutgoingCmd = &cobra.Command{
RunE: createOutgoingWebhookCmdF,
}
var WebhookModifyOutgoingCmd = &cobra.Command{
Use: "modify-outgoing",
Short: "Modify outgoing webhook",
Long: "Modify existing outgoing webhook by changing its title, description, channel, icon, url, content-type, and triggers",
Example: ` webhook modify-outgoing [webhookId] --channel [channelId] --display-name [displayName] --description "New webhook description" --icon http://localhost:8000/my-slash-handler-bot-icon.png --url http://localhost:8000/my-webhook-handler --content-type "application/json" --trigger-word test --trigger-when start`,
RunE: modifyOutgoingWebhookCmdF,
}
var WebhookDeleteCmd = &cobra.Command{
Use: "delete",
Short: "Delete webhooks",
@@ -285,6 +294,90 @@ func createOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
return nil
}
func modifyOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
app, err := InitDBCommandContextCobra(command)
if err != nil {
return err
}
defer app.Shutdown()
if len(args) < 1 {
return errors.New("WebhookID is not specified")
}
webhookArg := args[0]
oldHook, appErr := app.GetOutgoingWebhook(webhookArg)
if appErr != nil {
return fmt.Errorf("unable to find webhook '%s'", webhookArg)
}
updatedHook := model.OutgoingWebhookFromJson(strings.NewReader(oldHook.ToJson()))
channelArg, _ := command.Flags().GetString("channel")
if channelArg != "" {
channel := getChannelFromChannelArg(app, channelArg)
if channel == nil {
return fmt.Errorf("unable to find channel '%s'", channelArg)
}
updatedHook.ChannelId = channel.Id
}
displayName, _ := command.Flags().GetString("display-name")
if displayName != "" {
updatedHook.DisplayName = displayName
}
description, _ := command.Flags().GetString("description")
if description != "" {
updatedHook.Description = description
}
triggerWords, err := command.Flags().GetStringArray("trigger-word")
if err != nil {
return errors.Wrap(err, "invalid trigger-word parameter")
}
if len(triggerWords) > 0 {
updatedHook.TriggerWords = triggerWords
}
triggerWhenString, _ := command.Flags().GetString("trigger-when")
if triggerWhenString != "" {
var triggerWhen int
if triggerWhenString == "exact" {
triggerWhen = 0
} else if triggerWhenString == "start" {
triggerWhen = 1
} else {
return errors.New("invalid trigger-when parameter")
}
updatedHook.TriggerWhen = triggerWhen
}
iconURL, _ := command.Flags().GetString("icon")
if iconURL != "" {
updatedHook.IconURL = iconURL
}
contentType, _ := command.Flags().GetString("content-type")
if contentType != "" {
updatedHook.ContentType = contentType
}
callbackURLs, err := command.Flags().GetStringArray("url")
if err != nil {
return errors.Wrap(err, "invalid URL parameter")
}
if len(callbackURLs) > 0 {
updatedHook.CallbackURLs = callbackURLs
}
if _, appErr := app.UpdateOutgoingWebhook(oldHook, updatedHook); appErr != nil {
return appErr
}
return nil
}
func deleteWebhookCmdF(command *cobra.Command, args []string) error {
app, err := InitDBCommandContextCobra(command)
if err != nil {
@@ -332,11 +425,21 @@ func init() {
WebhookCreateOutgoingCmd.Flags().StringArray("url", []string{}, "Callback URL (required)")
WebhookCreateOutgoingCmd.Flags().String("content-type", "", "Content-type")
WebhookModifyOutgoingCmd.Flags().String("channel", "", "Channel name or ID")
WebhookModifyOutgoingCmd.Flags().String("display-name", "", "Outgoing webhook display name")
WebhookModifyOutgoingCmd.Flags().String("description", "", "Outgoing webhook description")
WebhookModifyOutgoingCmd.Flags().StringArray("trigger-word", []string{}, "Word to trigger webhook")
WebhookModifyOutgoingCmd.Flags().String("trigger-when", "", "When to trigger webhook (exact: for first word matches a trigger word exactly, start: for first word starts with a trigger word)")
WebhookModifyOutgoingCmd.Flags().String("icon", "", "Icon URL")
WebhookModifyOutgoingCmd.Flags().StringArray("url", []string{}, "Callback URL")
WebhookModifyOutgoingCmd.Flags().String("content-type", "", "Content-type")
WebhookCmd.AddCommand(
WebhookListCmd,
WebhookCreateIncomingCmd,
WebhookModifyIncomingCmd,
WebhookCreateOutgoingCmd,
WebhookModifyOutgoingCmd,
WebhookDeleteCmd,
)

View File

@@ -245,6 +245,105 @@ func TestCreateOutgoingWebhook(t *testing.T) {
}
}
func TestModifyOutgoingWebhook(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
config := th.Config()
config.ServiceSettings.EnableOutgoingWebhooks = true
th.SetConfig(config)
defaultRolePermissions := th.SaveDefaultRolePermissions()
defer func() {
th.RestoreDefaultRolePermissions(defaultRolePermissions)
}()
th.AddPermissionToRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_ADMIN_ROLE_ID)
th.RemovePermissionFromRole(model.PERMISSION_MANAGE_WEBHOOKS.Id, model.TEAM_USER_ROLE_ID)
description := "myhookoutdesc"
displayName := "myhookoutname"
triggerWords := model.StringArray{"myhookoutword1"}
triggerWhen := 0
callbackURLs := model.StringArray{"http://myhookouturl1"}
iconURL := "myhookicon1"
contentType := "myhookcontent1"
outgoingWebhook := &model.OutgoingWebhook{
CreatorId: th.BasicUser.Id,
Username: th.BasicUser.Username,
TeamId: th.BasicTeam.Id,
ChannelId: th.BasicChannel.Id,
DisplayName: displayName,
Description: description,
TriggerWords: triggerWords,
TriggerWhen: triggerWhen,
CallbackURLs: callbackURLs,
IconURL: iconURL,
ContentType: contentType,
}
oldHook, err := th.App.CreateOutgoingWebhook(outgoingWebhook)
if err != nil {
t.Fatal("unable to create outgoing webhooks: " + err.Error())
}
defer func() {
th.App.DeleteOutgoingWebhook(oldHook.Id)
}()
// should fail because you need to specify valid outgoing webhook
require.Error(t, th.RunCommand(t, "webhook", "modify-outgoing", "doesnotexist"))
// should fail because you need to specify valid channel
require.Error(t, th.RunCommand(t, "webhook", "modify-outgoing", oldHook.Id, "--channel", th.BasicTeam.Name+":doesnotexist"))
// should fail because you need to specify valid trigger when
require.Error(t, th.RunCommand(t, "webhook", "modify-outgoing", oldHook.Id, "--channel", th.BasicTeam.Name+th.BasicChannel.Id, "--trigger-when", "invalid"))
// should fail because you need to specify a valid callback URL
require.Error(t, th.RunCommand(t, "webhook", "modify-outgoing", oldHook.Id, "--channel", th.BasicTeam.Name+th.BasicChannel.Id, "--callback-url", "invalid"))
modifiedChannelID := th.BasicChannel2.Id
modifiedDisplayName := "myhookoutname2"
modifiedDescription := "myhookoutdesc2"
modifiedTriggerWords := model.StringArray{"myhookoutword2A", "myhookoutword2B"}
modifiedTriggerWhen := "start"
modifiedIconURL := "myhookouticon2"
modifiedContentType := "myhookcontent2"
modifiedCallbackURLs := model.StringArray{"http://myhookouturl2A", "http://myhookouturl2B"}
th.CheckCommand(t, "webhook", "modify-outgoing", oldHook.Id,
"--channel", modifiedChannelID,
"--display-name", modifiedDisplayName,
"--description", modifiedDescription,
"--trigger-word", modifiedTriggerWords[0],
"--trigger-word", modifiedTriggerWords[1],
"--trigger-when", modifiedTriggerWhen,
"--icon", modifiedIconURL,
"--content-type", modifiedContentType,
"--url", modifiedCallbackURLs[0],
"--url", modifiedCallbackURLs[1],
)
modifiedHook, err := th.App.GetOutgoingWebhook(oldHook.Id)
if err != nil {
t.Fatal("unable to retrieve modified outgoing webhook")
}
updateFailed := modifiedHook.ChannelId != modifiedChannelID ||
modifiedHook.DisplayName != modifiedDisplayName ||
modifiedHook.Description != modifiedDescription ||
len(modifiedHook.TriggerWords) != len(modifiedTriggerWords) ||
modifiedHook.TriggerWords[0] != modifiedTriggerWords[0] ||
modifiedHook.TriggerWords[1] != modifiedTriggerWords[1] ||
modifiedHook.TriggerWhen != 1 ||
modifiedHook.IconURL != modifiedIconURL ||
modifiedHook.ContentType != modifiedContentType ||
len(modifiedHook.CallbackURLs) != len(modifiedCallbackURLs) ||
modifiedHook.CallbackURLs[0] != modifiedCallbackURLs[0] ||
modifiedHook.CallbackURLs[1] != modifiedCallbackURLs[1]
if updateFailed {
t.Fatal("Failed to update outgoing webhook")
}
}
func TestDeleteWebhooks(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()