github.com/space0122/mattermost-server@v5.11.1+incompatible/cmd/mattermost/commands/webhook.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package commands
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/mattermost/mattermost-server/model"
    11  	"github.com/pkg/errors"
    12  	"github.com/spf13/cobra"
    13  )
    14  
    15  var WebhookCmd = &cobra.Command{
    16  	Use:   "webhook",
    17  	Short: "Management of webhooks",
    18  }
    19  
    20  var WebhookListCmd = &cobra.Command{
    21  	Use:     "list",
    22  	Short:   "List webhooks",
    23  	Long:    "list all webhooks",
    24  	Example: "  webhook list myteam",
    25  	RunE:    listWebhookCmdF,
    26  }
    27  
    28  var WebhookShowCmd = &cobra.Command{
    29  	Use:     "show [webhookId]",
    30  	Short:   "Show a webhook",
    31  	Long:    "Show the webhook specified by [webhookId]",
    32  	Args:    cobra.ExactArgs(1),
    33  	Example: "  webhook show w16zb5tu3n1zkqo18goqry1je",
    34  	RunE:    showWebhookCmdF,
    35  }
    36  
    37  var WebhookCreateIncomingCmd = &cobra.Command{
    38  	Use:     "create-incoming",
    39  	Short:   "Create incoming webhook",
    40  	Long:    "create incoming webhook which allows external posting of messages to specific channel",
    41  	Example: "  webhook create-incoming --channel [channelID] --user [userID] --display-name [displayName] --description [webhookDescription] --lock-to-channel --icon [iconURL]",
    42  	RunE:    createIncomingWebhookCmdF,
    43  }
    44  
    45  var WebhookModifyIncomingCmd = &cobra.Command{
    46  	Use:     "modify-incoming",
    47  	Short:   "Modify incoming webhook",
    48  	Long:    "Modify existing incoming webhook by changing its title, description, channel or icon url",
    49  	Example: "  webhook modify-incoming [webhookID] --channel [channelID] --display-name [displayName] --description [webhookDescription] --lock-to-channel --icon [iconURL]",
    50  	RunE:    modifyIncomingWebhookCmdF,
    51  }
    52  
    53  var WebhookCreateOutgoingCmd = &cobra.Command{
    54  	Use:   "create-outgoing",
    55  	Short: "Create outgoing webhook",
    56  	Long:  "create outgoing webhook which allows external posting of messages from a specific channel",
    57  	Example: `  webhook create-outgoing --team myteam --user myusername --display-name mywebhook --trigger-word "build" --trigger-word "test" --url http://localhost:8000/my-webhook-handler
    58  	webhook create-outgoing --team myteam --channel mychannel --user myusername --display-name mywebhook --description "My cool webhook" --trigger-when start --trigger-word build --trigger-word test --icon http://localhost:8000/my-slash-handler-bot-icon.png --url http://localhost:8000/my-webhook-handler --content-type "application/json"`,
    59  	RunE: createOutgoingWebhookCmdF,
    60  }
    61  
    62  var WebhookModifyOutgoingCmd = &cobra.Command{
    63  	Use:     "modify-outgoing",
    64  	Short:   "Modify outgoing webhook",
    65  	Long:    "Modify existing outgoing webhook by changing its title, description, channel, icon, url, content-type, and triggers",
    66  	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`,
    67  	RunE:    modifyOutgoingWebhookCmdF,
    68  }
    69  
    70  var WebhookDeleteCmd = &cobra.Command{
    71  	Use:     "delete",
    72  	Short:   "Delete webhooks",
    73  	Long:    "Delete webhook with given id",
    74  	Example: "  webhook delete [webhookID]",
    75  	RunE:    deleteWebhookCmdF,
    76  }
    77  
    78  func listWebhookCmdF(command *cobra.Command, args []string) error {
    79  	app, err := InitDBCommandContextCobra(command)
    80  	if err != nil {
    81  		return err
    82  	}
    83  	defer app.Shutdown()
    84  
    85  	var teams []*model.Team
    86  	if len(args) < 1 {
    87  		var getErr *model.AppError
    88  		// If no team is specified, list all teams
    89  		teams, getErr = app.GetAllTeams()
    90  		if getErr != nil {
    91  			return getErr
    92  		}
    93  	} else {
    94  		teams = getTeamsFromTeamArgs(app, args)
    95  	}
    96  
    97  	for i, team := range teams {
    98  		if team == nil {
    99  			CommandPrintErrorln("Unable to find team '" + args[i] + "'")
   100  			continue
   101  		}
   102  
   103  		// Fetch all hooks with a very large limit so we get them all.
   104  		incomingResult := app.Srv.Store.Webhook().GetIncomingByTeam(team.Id, 0, 100000000)
   105  		outgoingResult := app.Srv.Store.Webhook().GetOutgoingByTeam(team.Id, 0, 100000000)
   106  
   107  		if result := <-incomingResult; result.Err == nil {
   108  			CommandPrettyPrintln(fmt.Sprintf("Incoming webhooks for %s (%s):", team.DisplayName, team.Name))
   109  			hooks := result.Data.([]*model.IncomingWebhook)
   110  			for _, hook := range hooks {
   111  				CommandPrettyPrintln("\t" + hook.DisplayName + " (" + hook.Id + ")")
   112  			}
   113  		} else {
   114  			CommandPrintErrorln("Unable to list incoming webhooks for '" + args[i] + "'")
   115  		}
   116  
   117  		if result := <-outgoingResult; result.Err == nil {
   118  			hooks := result.Data.([]*model.OutgoingWebhook)
   119  			CommandPrettyPrintln(fmt.Sprintf("Outgoing webhooks for %s (%s):", team.DisplayName, team.Name))
   120  			for _, hook := range hooks {
   121  				CommandPrettyPrintln("\t" + hook.DisplayName + " (" + hook.Id + ")")
   122  			}
   123  		} else {
   124  			CommandPrintErrorln("Unable to list outgoing webhooks for '" + args[i] + "'")
   125  		}
   126  	}
   127  	return nil
   128  }
   129  
   130  func createIncomingWebhookCmdF(command *cobra.Command, args []string) error {
   131  	app, err := InitDBCommandContextCobra(command)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	defer app.Shutdown()
   136  
   137  	channelArg, errChannel := command.Flags().GetString("channel")
   138  	if errChannel != nil || channelArg == "" {
   139  		return errors.New("Channel is required")
   140  	}
   141  	channel := getChannelFromChannelArg(app, channelArg)
   142  	if channel == nil {
   143  		return errors.New("Unable to find channel '" + channelArg + "'")
   144  	}
   145  
   146  	userArg, errUser := command.Flags().GetString("user")
   147  	if errUser != nil || userArg == "" {
   148  		return errors.New("User is required")
   149  	}
   150  	user := getUserFromUserArg(app, userArg)
   151  	if user == nil {
   152  		return errors.New("Unable to find user '" + userArg + "'")
   153  	}
   154  
   155  	displayName, _ := command.Flags().GetString("display-name")
   156  	description, _ := command.Flags().GetString("description")
   157  	iconURL, _ := command.Flags().GetString("icon")
   158  	channelLocked, _ := command.Flags().GetBool("lock-to-channel")
   159  
   160  	incomingWebhook := &model.IncomingWebhook{
   161  		ChannelId:     channel.Id,
   162  		DisplayName:   displayName,
   163  		Description:   description,
   164  		IconURL:       iconURL,
   165  		ChannelLocked: channelLocked,
   166  	}
   167  
   168  	createdIncoming, errIncomingWebhook := app.CreateIncomingWebhookForChannel(user.Id, channel, incomingWebhook)
   169  	if errIncomingWebhook != nil {
   170  		return errIncomingWebhook
   171  	}
   172  
   173  	CommandPrettyPrintln("Id: " + createdIncoming.Id)
   174  	CommandPrettyPrintln("Display Name: " + createdIncoming.DisplayName)
   175  
   176  	return nil
   177  }
   178  
   179  func modifyIncomingWebhookCmdF(command *cobra.Command, args []string) error {
   180  	app, err := InitDBCommandContextCobra(command)
   181  	if err != nil {
   182  		return err
   183  	}
   184  	defer app.Shutdown()
   185  
   186  	if len(args) < 1 {
   187  		return errors.New("WebhookID is not specified")
   188  	}
   189  
   190  	webhookArg := args[0]
   191  	oldHook, getErr := app.GetIncomingWebhook(webhookArg)
   192  	if getErr != nil {
   193  		return errors.New("Unable to find webhook '" + webhookArg + "'")
   194  	}
   195  
   196  	updatedHook := oldHook
   197  
   198  	channelArg, _ := command.Flags().GetString("channel")
   199  	if channelArg != "" {
   200  		channel := getChannelFromChannelArg(app, channelArg)
   201  		if channel == nil {
   202  			return errors.New("Unable to find channel '" + channelArg + "'")
   203  		}
   204  		updatedHook.ChannelId = channel.Id
   205  	}
   206  
   207  	displayName, _ := command.Flags().GetString("display-name")
   208  	if displayName != "" {
   209  		updatedHook.DisplayName = displayName
   210  	}
   211  	description, _ := command.Flags().GetString("description")
   212  	if description != "" {
   213  		updatedHook.Description = description
   214  	}
   215  	iconUrl, _ := command.Flags().GetString("icon")
   216  	if iconUrl != "" {
   217  		updatedHook.IconURL = iconUrl
   218  	}
   219  	channelLocked, _ := command.Flags().GetBool("lock-to-channel")
   220  	updatedHook.ChannelLocked = channelLocked
   221  
   222  	if _, err := app.UpdateIncomingWebhook(oldHook, updatedHook); err != nil {
   223  		return err
   224  	}
   225  
   226  	return nil
   227  }
   228  
   229  func createOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
   230  	app, err := InitDBCommandContextCobra(command)
   231  	if err != nil {
   232  		return err
   233  	}
   234  	defer app.Shutdown()
   235  
   236  	teamArg, errTeam := command.Flags().GetString("team")
   237  	if errTeam != nil || teamArg == "" {
   238  		return errors.New("Team is required")
   239  	}
   240  	team := getTeamFromTeamArg(app, teamArg)
   241  	if team == nil {
   242  		return errors.New("Unable to find team: " + teamArg)
   243  	}
   244  
   245  	userArg, errUser := command.Flags().GetString("user")
   246  	if errUser != nil || userArg == "" {
   247  		return errors.New("User is required")
   248  	}
   249  	user := getUserFromUserArg(app, userArg)
   250  	if user == nil {
   251  		return errors.New("Unable to find user: " + userArg)
   252  	}
   253  
   254  	displayName, errName := command.Flags().GetString("display-name")
   255  	if errName != nil || displayName == "" {
   256  		return errors.New("Display name is required")
   257  	}
   258  
   259  	triggerWords, errWords := command.Flags().GetStringArray("trigger-word")
   260  	if errWords != nil || len(triggerWords) == 0 {
   261  		return errors.New("Trigger word or words required")
   262  	}
   263  
   264  	callbackURLs, errURL := command.Flags().GetStringArray("url")
   265  	if errURL != nil || len(callbackURLs) == 0 {
   266  		return errors.New("Callback URL or URLs required")
   267  	}
   268  
   269  	triggerWhenString, _ := command.Flags().GetString("trigger-when")
   270  	var triggerWhen int
   271  	if triggerWhenString == "exact" {
   272  		triggerWhen = 0
   273  	} else if triggerWhenString == "start" {
   274  		triggerWhen = 1
   275  	} else {
   276  		return errors.New("Invalid trigger when parameter")
   277  	}
   278  	description, _ := command.Flags().GetString("description")
   279  	contentType, _ := command.Flags().GetString("content-type")
   280  	iconURL, _ := command.Flags().GetString("icon")
   281  
   282  	outgoingWebhook := &model.OutgoingWebhook{
   283  		CreatorId:    user.Id,
   284  		Username:     user.Username,
   285  		TeamId:       team.Id,
   286  		TriggerWords: triggerWords,
   287  		TriggerWhen:  triggerWhen,
   288  		CallbackURLs: callbackURLs,
   289  		DisplayName:  displayName,
   290  		Description:  description,
   291  		ContentType:  contentType,
   292  		IconURL:      iconURL,
   293  	}
   294  
   295  	channelArg, _ := command.Flags().GetString("channel")
   296  	if channelArg != "" {
   297  		channel := getChannelFromChannelArg(app, channelArg)
   298  		if channel != nil {
   299  			outgoingWebhook.ChannelId = channel.Id
   300  		}
   301  	}
   302  
   303  	createdOutgoing, errOutgoing := app.CreateOutgoingWebhook(outgoingWebhook)
   304  	if errOutgoing != nil {
   305  		return errOutgoing
   306  	}
   307  
   308  	CommandPrettyPrintln("Id: " + createdOutgoing.Id)
   309  	CommandPrettyPrintln("Display Name: " + createdOutgoing.DisplayName)
   310  
   311  	return nil
   312  }
   313  
   314  func modifyOutgoingWebhookCmdF(command *cobra.Command, args []string) error {
   315  	app, err := InitDBCommandContextCobra(command)
   316  	if err != nil {
   317  		return err
   318  	}
   319  	defer app.Shutdown()
   320  
   321  	if len(args) < 1 {
   322  		return errors.New("WebhookID is not specified")
   323  	}
   324  
   325  	webhookArg := args[0]
   326  	oldHook, appErr := app.GetOutgoingWebhook(webhookArg)
   327  	if appErr != nil {
   328  		return fmt.Errorf("unable to find webhook '%s'", webhookArg)
   329  	}
   330  
   331  	updatedHook := model.OutgoingWebhookFromJson(strings.NewReader(oldHook.ToJson()))
   332  
   333  	channelArg, _ := command.Flags().GetString("channel")
   334  	if channelArg != "" {
   335  		channel := getChannelFromChannelArg(app, channelArg)
   336  		if channel == nil {
   337  			return fmt.Errorf("unable to find channel '%s'", channelArg)
   338  		}
   339  		updatedHook.ChannelId = channel.Id
   340  	}
   341  
   342  	displayName, _ := command.Flags().GetString("display-name")
   343  	if displayName != "" {
   344  		updatedHook.DisplayName = displayName
   345  	}
   346  
   347  	description, _ := command.Flags().GetString("description")
   348  	if description != "" {
   349  		updatedHook.Description = description
   350  	}
   351  
   352  	triggerWords, err := command.Flags().GetStringArray("trigger-word")
   353  	if err != nil {
   354  		return errors.Wrap(err, "invalid trigger-word parameter")
   355  	}
   356  	if len(triggerWords) > 0 {
   357  		updatedHook.TriggerWords = triggerWords
   358  	}
   359  
   360  	triggerWhenString, _ := command.Flags().GetString("trigger-when")
   361  	if triggerWhenString != "" {
   362  		var triggerWhen int
   363  		if triggerWhenString == "exact" {
   364  			triggerWhen = 0
   365  		} else if triggerWhenString == "start" {
   366  			triggerWhen = 1
   367  		} else {
   368  			return errors.New("invalid trigger-when parameter")
   369  		}
   370  		updatedHook.TriggerWhen = triggerWhen
   371  	}
   372  
   373  	iconURL, _ := command.Flags().GetString("icon")
   374  	if iconURL != "" {
   375  		updatedHook.IconURL = iconURL
   376  	}
   377  
   378  	contentType, _ := command.Flags().GetString("content-type")
   379  	if contentType != "" {
   380  		updatedHook.ContentType = contentType
   381  	}
   382  
   383  	callbackURLs, err := command.Flags().GetStringArray("url")
   384  	if err != nil {
   385  		return errors.Wrap(err, "invalid URL parameter")
   386  	}
   387  	if len(callbackURLs) > 0 {
   388  		updatedHook.CallbackURLs = callbackURLs
   389  	}
   390  
   391  	if _, appErr := app.UpdateOutgoingWebhook(oldHook, updatedHook); appErr != nil {
   392  		return appErr
   393  	}
   394  
   395  	return nil
   396  }
   397  
   398  func deleteWebhookCmdF(command *cobra.Command, args []string) error {
   399  	app, err := InitDBCommandContextCobra(command)
   400  	if err != nil {
   401  		return err
   402  	}
   403  	defer app.Shutdown()
   404  
   405  	if len(args) < 1 {
   406  		return errors.New("WebhookID is not specified")
   407  	}
   408  
   409  	webhookId := args[0]
   410  	errIncomingWebhook := app.DeleteIncomingWebhook(webhookId)
   411  	errOutgoingWebhook := app.DeleteOutgoingWebhook(webhookId)
   412  
   413  	if errIncomingWebhook != nil && errOutgoingWebhook != nil {
   414  		return errors.New("Unable to delete webhook '" + webhookId + "'")
   415  	}
   416  
   417  	return nil
   418  }
   419  
   420  func showWebhookCmdF(command *cobra.Command, args []string) error {
   421  	app, err := InitDBCommandContextCobra(command)
   422  	if err != nil {
   423  		return err
   424  	}
   425  	defer app.Shutdown()
   426  
   427  	webhookId := args[0]
   428  	if incomingWebhook, err := app.GetIncomingWebhook(webhookId); err == nil {
   429  		fmt.Printf("%s", prettyPrintStruct(*incomingWebhook))
   430  		return nil
   431  	}
   432  	if outgoingWebhook, err := app.GetOutgoingWebhook(webhookId); err == nil {
   433  		fmt.Printf("%s", prettyPrintStruct(*outgoingWebhook))
   434  		return nil
   435  	}
   436  
   437  	return errors.New("Webhook with id " + webhookId + " not found")
   438  }
   439  
   440  func init() {
   441  	WebhookCreateIncomingCmd.Flags().String("channel", "", "Channel ID (required)")
   442  	WebhookCreateIncomingCmd.Flags().String("user", "", "User ID (required)")
   443  	WebhookCreateIncomingCmd.Flags().String("display-name", "", "Incoming webhook display name")
   444  	WebhookCreateIncomingCmd.Flags().String("description", "", "Incoming webhook description")
   445  	WebhookCreateIncomingCmd.Flags().String("icon", "", "Icon URL")
   446  	WebhookCreateIncomingCmd.Flags().Bool("lock-to-channel", false, "Lock to channel")
   447  
   448  	WebhookModifyIncomingCmd.Flags().String("channel", "", "Channel ID")
   449  	WebhookModifyIncomingCmd.Flags().String("display-name", "", "Incoming webhook display name")
   450  	WebhookModifyIncomingCmd.Flags().String("description", "", "Incoming webhook description")
   451  	WebhookModifyIncomingCmd.Flags().String("icon", "", "Icon URL")
   452  	WebhookModifyIncomingCmd.Flags().Bool("lock-to-channel", false, "Lock to channel")
   453  
   454  	WebhookCreateOutgoingCmd.Flags().String("team", "", "Team name or ID (required)")
   455  	WebhookCreateOutgoingCmd.Flags().String("channel", "", "Channel name or ID")
   456  	WebhookCreateOutgoingCmd.Flags().String("user", "", "User username, email, or ID (required)")
   457  	WebhookCreateOutgoingCmd.Flags().String("display-name", "", "Outgoing webhook display name (required)")
   458  	WebhookCreateOutgoingCmd.Flags().String("description", "", "Outgoing webhook description")
   459  	WebhookCreateOutgoingCmd.Flags().StringArray("trigger-word", []string{}, "Word to trigger webhook (required)")
   460  	WebhookCreateOutgoingCmd.Flags().String("trigger-when", "exact", "When to trigger webhook (exact: for first word matches a trigger word exactly, start: for first word starts with a trigger word)")
   461  	WebhookCreateOutgoingCmd.Flags().String("icon", "", "Icon URL")
   462  	WebhookCreateOutgoingCmd.Flags().StringArray("url", []string{}, "Callback URL (required)")
   463  	WebhookCreateOutgoingCmd.Flags().String("content-type", "", "Content-type")
   464  
   465  	WebhookModifyOutgoingCmd.Flags().String("channel", "", "Channel name or ID")
   466  	WebhookModifyOutgoingCmd.Flags().String("display-name", "", "Outgoing webhook display name")
   467  	WebhookModifyOutgoingCmd.Flags().String("description", "", "Outgoing webhook description")
   468  	WebhookModifyOutgoingCmd.Flags().StringArray("trigger-word", []string{}, "Word to trigger webhook")
   469  	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)")
   470  	WebhookModifyOutgoingCmd.Flags().String("icon", "", "Icon URL")
   471  	WebhookModifyOutgoingCmd.Flags().StringArray("url", []string{}, "Callback URL")
   472  	WebhookModifyOutgoingCmd.Flags().String("content-type", "", "Content-type")
   473  
   474  	WebhookCmd.AddCommand(
   475  		WebhookListCmd,
   476  		WebhookCreateIncomingCmd,
   477  		WebhookModifyIncomingCmd,
   478  		WebhookCreateOutgoingCmd,
   479  		WebhookModifyOutgoingCmd,
   480  		WebhookDeleteCmd,
   481  		WebhookShowCmd,
   482  	)
   483  
   484  	RootCmd.AddCommand(WebhookCmd)
   485  }