github.com/demisto/mattermost-server@v4.9.0-rc3+incompatible/cmd/commands/channel.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  	"errors"
     8  	"fmt"
     9  
    10  	"github.com/mattermost/mattermost-server/app"
    11  	"github.com/mattermost/mattermost-server/cmd"
    12  	"github.com/mattermost/mattermost-server/model"
    13  	"github.com/spf13/cobra"
    14  )
    15  
    16  var ChannelCmd = &cobra.Command{
    17  	Use:   "channel",
    18  	Short: "Management of channels",
    19  }
    20  
    21  var ChannelCreateCmd = &cobra.Command{
    22  	Use:   "create",
    23  	Short: "Create a channel",
    24  	Long:  `Create a channel.`,
    25  	Example: `  channel create --team myteam --name mynewchannel --display_name "My New Channel"
    26    channel create --team myteam --name mynewprivatechannel --display_name "My New Private Channel" --private`,
    27  	RunE: createChannelCmdF,
    28  }
    29  
    30  var RemoveChannelUsersCmd = &cobra.Command{
    31  	Use:     "remove [channel] [users]",
    32  	Short:   "Remove users from channel",
    33  	Long:    "Remove some users from channel",
    34  	Example: "  channel remove mychannel user@example.com username",
    35  	RunE:    removeChannelUsersCmdF,
    36  }
    37  
    38  var AddChannelUsersCmd = &cobra.Command{
    39  	Use:     "add [channel] [users]",
    40  	Short:   "Add users to channel",
    41  	Long:    "Add some users to channel",
    42  	Example: "  channel add mychannel user@example.com username",
    43  	RunE:    addChannelUsersCmdF,
    44  }
    45  
    46  var ArchiveChannelsCmd = &cobra.Command{
    47  	Use:   "archive [channels]",
    48  	Short: "Archive channels",
    49  	Long: `Archive some channels.
    50  Archive a channel along with all related information including posts from the database.
    51  Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
    52  	Example: "  channel archive myteam:mychannel",
    53  	RunE:    archiveChannelsCmdF,
    54  }
    55  
    56  var DeleteChannelsCmd = &cobra.Command{
    57  	Use:   "delete [channels]",
    58  	Short: "Delete channels",
    59  	Long: `Permanently delete some channels.
    60  Permanently deletes a channel along with all related information including posts from the database.
    61  Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
    62  	Example: "  channel delete myteam:mychannel",
    63  	RunE:    deleteChannelsCmdF,
    64  }
    65  
    66  var ListChannelsCmd = &cobra.Command{
    67  	Use:   "list [teams]",
    68  	Short: "List all channels on specified teams.",
    69  	Long: `List all channels on specified teams.
    70  Archived channels are appended with ' (archived)'.`,
    71  	Example: "  channel list myteam",
    72  	RunE:    listChannelsCmdF,
    73  }
    74  
    75  var MoveChannelsCmd = &cobra.Command{
    76  	Use:   "move [team] [channels]",
    77  	Short: "Moves channels to the specified team",
    78  	Long: `Moves the provided channels to the specified team.
    79  Validates that all users in the channel belong to the target team. Incoming/Outgoing webhooks are moved along with the channel.
    80  Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
    81  	Example: "  channel move newteam oldteam:mychannel",
    82  	RunE:    moveChannelsCmdF,
    83  }
    84  
    85  var RestoreChannelsCmd = &cobra.Command{
    86  	Use:   "restore [channels]",
    87  	Short: "Restore some channels",
    88  	Long: `Restore a previously deleted channel
    89  Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
    90  	Example: "  channel restore myteam:mychannel",
    91  	RunE:    restoreChannelsCmdF,
    92  }
    93  
    94  var ModifyChannelCmd = &cobra.Command{
    95  	Use:   "modify [channel]",
    96  	Short: "Modify a channel's public/private type",
    97  	Long: `Change the public/private type of a channel.
    98  Channel can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
    99  	Example: "  channel modify myteam:mychannel --private",
   100  	RunE:    modifyChannelCmdF,
   101  }
   102  
   103  func init() {
   104  	ChannelCreateCmd.Flags().String("name", "", "Channel Name")
   105  	ChannelCreateCmd.Flags().String("display_name", "", "Channel Display Name")
   106  	ChannelCreateCmd.Flags().String("team", "", "Team name or ID")
   107  	ChannelCreateCmd.Flags().String("header", "", "Channel header")
   108  	ChannelCreateCmd.Flags().String("purpose", "", "Channel purpose")
   109  	ChannelCreateCmd.Flags().Bool("private", false, "Create a private channel.")
   110  
   111  	MoveChannelsCmd.Flags().String("username", "", "Required. Username who is moving the channel.")
   112  
   113  	DeleteChannelsCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the channels.")
   114  
   115  	ModifyChannelCmd.Flags().Bool("private", false, "Convert the channel to a private channel")
   116  	ModifyChannelCmd.Flags().Bool("public", false, "Convert the channel to a public channel")
   117  	ModifyChannelCmd.Flags().String("username", "", "Required. Username who changes the channel privacy.")
   118  
   119  	ChannelCmd.AddCommand(
   120  		ChannelCreateCmd,
   121  		RemoveChannelUsersCmd,
   122  		AddChannelUsersCmd,
   123  		ArchiveChannelsCmd,
   124  		DeleteChannelsCmd,
   125  		ListChannelsCmd,
   126  		MoveChannelsCmd,
   127  		RestoreChannelsCmd,
   128  		ModifyChannelCmd,
   129  	)
   130  
   131  	cmd.RootCmd.AddCommand(ChannelCmd)
   132  }
   133  
   134  func createChannelCmdF(command *cobra.Command, args []string) error {
   135  	a, err := cmd.InitDBCommandContextCobra(command)
   136  	if err != nil {
   137  		return err
   138  	}
   139  
   140  	name, errn := command.Flags().GetString("name")
   141  	if errn != nil || name == "" {
   142  		return errors.New("Name is required")
   143  	}
   144  	displayname, errdn := command.Flags().GetString("display_name")
   145  	if errdn != nil || displayname == "" {
   146  		return errors.New("Display Name is required")
   147  	}
   148  	teamArg, errteam := command.Flags().GetString("team")
   149  	if errteam != nil || teamArg == "" {
   150  		return errors.New("Team is required")
   151  	}
   152  	header, _ := command.Flags().GetString("header")
   153  	purpose, _ := command.Flags().GetString("purpose")
   154  	useprivate, _ := command.Flags().GetBool("private")
   155  
   156  	channelType := model.CHANNEL_OPEN
   157  	if useprivate {
   158  		channelType = model.CHANNEL_PRIVATE
   159  	}
   160  
   161  	team := getTeamFromTeamArg(a, teamArg)
   162  	if team == nil {
   163  		return errors.New("Unable to find team: " + teamArg)
   164  	}
   165  
   166  	channel := &model.Channel{
   167  		TeamId:      team.Id,
   168  		Name:        name,
   169  		DisplayName: displayname,
   170  		Header:      header,
   171  		Purpose:     purpose,
   172  		Type:        channelType,
   173  		CreatorId:   "",
   174  	}
   175  
   176  	if _, err := a.CreateChannel(channel, false); err != nil {
   177  		return err
   178  	}
   179  
   180  	return nil
   181  }
   182  
   183  func removeChannelUsersCmdF(command *cobra.Command, args []string) error {
   184  	a, err := cmd.InitDBCommandContextCobra(command)
   185  	if err != nil {
   186  		return err
   187  	}
   188  
   189  	if len(args) < 2 {
   190  		return errors.New("Not enough arguments.")
   191  	}
   192  
   193  	channel := getChannelFromChannelArg(a, args[0])
   194  	if channel == nil {
   195  		return errors.New("Unable to find channel '" + args[0] + "'")
   196  	}
   197  
   198  	users := getUsersFromUserArgs(a, args[1:])
   199  	for i, user := range users {
   200  		removeUserFromChannel(a, channel, user, args[i+1])
   201  	}
   202  
   203  	return nil
   204  }
   205  
   206  func removeUserFromChannel(a *app.App, channel *model.Channel, user *model.User, userArg string) {
   207  	if user == nil {
   208  		cmd.CommandPrintErrorln("Can't find user '" + userArg + "'")
   209  		return
   210  	}
   211  	if err := a.RemoveUserFromChannel(user.Id, "", channel); err != nil {
   212  		cmd.CommandPrintErrorln("Unable to remove '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
   213  	}
   214  }
   215  
   216  func addChannelUsersCmdF(command *cobra.Command, args []string) error {
   217  	a, err := cmd.InitDBCommandContextCobra(command)
   218  	if err != nil {
   219  		return err
   220  	}
   221  
   222  	if len(args) < 2 {
   223  		return errors.New("Not enough arguments.")
   224  	}
   225  
   226  	channel := getChannelFromChannelArg(a, args[0])
   227  	if channel == nil {
   228  		return errors.New("Unable to find channel '" + args[0] + "'")
   229  	}
   230  
   231  	users := getUsersFromUserArgs(a, args[1:])
   232  	for i, user := range users {
   233  		addUserToChannel(a, channel, user, args[i+1])
   234  	}
   235  
   236  	return nil
   237  }
   238  
   239  func addUserToChannel(a *app.App, channel *model.Channel, user *model.User, userArg string) {
   240  	if user == nil {
   241  		cmd.CommandPrintErrorln("Can't find user '" + userArg + "'")
   242  		return
   243  	}
   244  	if _, err := a.AddUserToChannel(user, channel); err != nil {
   245  		cmd.CommandPrintErrorln("Unable to add '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
   246  	}
   247  }
   248  
   249  func archiveChannelsCmdF(command *cobra.Command, args []string) error {
   250  	a, err := cmd.InitDBCommandContextCobra(command)
   251  	if err != nil {
   252  		return err
   253  	}
   254  
   255  	if len(args) < 1 {
   256  		return errors.New("Enter at least one channel to archive.")
   257  	}
   258  
   259  	channels := getChannelsFromChannelArgs(a, args)
   260  	for i, channel := range channels {
   261  		if channel == nil {
   262  			cmd.CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   263  			continue
   264  		}
   265  		if result := <-a.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); result.Err != nil {
   266  			cmd.CommandPrintErrorln("Unable to archive channel '" + channel.Name + "' error: " + result.Err.Error())
   267  		}
   268  	}
   269  
   270  	return nil
   271  }
   272  
   273  func deleteChannelsCmdF(command *cobra.Command, args []string) error {
   274  	a, err := cmd.InitDBCommandContextCobra(command)
   275  	if err != nil {
   276  		return err
   277  	}
   278  
   279  	if len(args) < 1 {
   280  		return errors.New("Enter at least one channel to delete.")
   281  	}
   282  
   283  	confirmFlag, _ := command.Flags().GetBool("confirm")
   284  	if !confirmFlag {
   285  		var confirm string
   286  		cmd.CommandPrettyPrintln("Are you sure you want to delete the channels specified?  All data will be permanently deleted? (YES/NO): ")
   287  		fmt.Scanln(&confirm)
   288  		if confirm != "YES" {
   289  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   290  		}
   291  	}
   292  
   293  	channels := getChannelsFromChannelArgs(a, args)
   294  	for i, channel := range channels {
   295  		if channel == nil {
   296  			cmd.CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   297  			continue
   298  		}
   299  		if err := deleteChannel(a, channel); err != nil {
   300  			cmd.CommandPrintErrorln("Unable to delete channel '" + channel.Name + "' error: " + err.Error())
   301  		} else {
   302  			cmd.CommandPrettyPrintln("Deleted channel '" + channel.Name + "'")
   303  		}
   304  	}
   305  
   306  	return nil
   307  }
   308  
   309  func deleteChannel(a *app.App, channel *model.Channel) *model.AppError {
   310  	return a.PermanentDeleteChannel(channel)
   311  }
   312  
   313  func moveChannelsCmdF(command *cobra.Command, args []string) error {
   314  	a, err := cmd.InitDBCommandContextCobra(command)
   315  	if err != nil {
   316  		return err
   317  	}
   318  
   319  	if len(args) < 2 {
   320  		return errors.New("Enter the destination team and at least one channel to move.")
   321  	}
   322  
   323  	team := getTeamFromTeamArg(a, args[0])
   324  	if team == nil {
   325  		return errors.New("Unable to find destination team '" + args[0] + "'")
   326  	}
   327  
   328  	username, erru := command.Flags().GetString("username")
   329  	if erru != nil || username == "" {
   330  		return errors.New("Username is required")
   331  	}
   332  	user := getUserFromUserArg(a, username)
   333  
   334  	channels := getChannelsFromChannelArgs(a, args[1:])
   335  	for i, channel := range channels {
   336  		if channel == nil {
   337  			cmd.CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   338  			continue
   339  		}
   340  		originTeamID := channel.TeamId
   341  		if err := moveChannel(a, team, channel, user); err != nil {
   342  			cmd.CommandPrintErrorln("Unable to move channel '" + channel.Name + "' error: " + err.Error())
   343  		} else {
   344  			cmd.CommandPrettyPrintln("Moved channel '" + channel.Name + "' to " + team.Name + "(" + team.Id + ") from " + originTeamID + ".")
   345  		}
   346  	}
   347  
   348  	return nil
   349  }
   350  
   351  func moveChannel(a *app.App, team *model.Team, channel *model.Channel, user *model.User) *model.AppError {
   352  	oldTeamId := channel.TeamId
   353  
   354  	if err := a.MoveChannel(team, channel, user); err != nil {
   355  		return err
   356  	}
   357  
   358  	if incomingWebhooks, err := a.GetIncomingWebhooksForTeamPage(oldTeamId, 0, 10000000); err != nil {
   359  		return err
   360  	} else {
   361  		for _, webhook := range incomingWebhooks {
   362  			if webhook.ChannelId == channel.Id {
   363  				webhook.TeamId = team.Id
   364  				if result := <-a.Srv.Store.Webhook().UpdateIncoming(webhook); result.Err != nil {
   365  					cmd.CommandPrintErrorln("Failed to move incoming webhook '" + webhook.Id + "' to new team.")
   366  				}
   367  			}
   368  		}
   369  	}
   370  
   371  	if outgoingWebhooks, err := a.GetOutgoingWebhooksForTeamPage(oldTeamId, 0, 10000000); err != nil {
   372  		return err
   373  	} else {
   374  		for _, webhook := range outgoingWebhooks {
   375  			if webhook.ChannelId == channel.Id {
   376  				webhook.TeamId = team.Id
   377  				if result := <-a.Srv.Store.Webhook().UpdateOutgoing(webhook); result.Err != nil {
   378  					cmd.CommandPrintErrorln("Failed to move outgoing webhook '" + webhook.Id + "' to new team.")
   379  				}
   380  			}
   381  		}
   382  	}
   383  
   384  	return nil
   385  }
   386  
   387  func listChannelsCmdF(command *cobra.Command, args []string) error {
   388  	a, err := cmd.InitDBCommandContextCobra(command)
   389  	if err != nil {
   390  		return err
   391  	}
   392  
   393  	if len(args) < 1 {
   394  		return errors.New("Enter at least one team.")
   395  	}
   396  
   397  	teams := getTeamsFromTeamArgs(a, args)
   398  	for i, team := range teams {
   399  		if team == nil {
   400  			cmd.CommandPrintErrorln("Unable to find team '" + args[i] + "'")
   401  			continue
   402  		}
   403  		if result := <-a.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
   404  			cmd.CommandPrintErrorln("Unable to list channels for '" + args[i] + "'")
   405  		} else {
   406  			channels := result.Data.([]*model.Channel)
   407  
   408  			for _, channel := range channels {
   409  				if channel.DeleteAt > 0 {
   410  					cmd.CommandPrettyPrintln(channel.Name + " (archived)")
   411  				} else {
   412  					cmd.CommandPrettyPrintln(channel.Name)
   413  				}
   414  			}
   415  		}
   416  	}
   417  
   418  	return nil
   419  }
   420  
   421  func restoreChannelsCmdF(command *cobra.Command, args []string) error {
   422  	a, err := cmd.InitDBCommandContextCobra(command)
   423  	if err != nil {
   424  		return err
   425  	}
   426  
   427  	if len(args) < 1 {
   428  		return errors.New("Enter at least one channel.")
   429  	}
   430  
   431  	channels := getChannelsFromChannelArgs(a, args)
   432  	for i, channel := range channels {
   433  		if channel == nil {
   434  			cmd.CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   435  			continue
   436  		}
   437  		if result := <-a.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
   438  			cmd.CommandPrintErrorln("Unable to restore channel '" + args[i] + "'")
   439  		}
   440  	}
   441  
   442  	return nil
   443  }
   444  
   445  func modifyChannelCmdF(command *cobra.Command, args []string) error {
   446  	a, err := cmd.InitDBCommandContextCobra(command)
   447  	if err != nil {
   448  		return err
   449  	}
   450  
   451  	if len(args) != 1 {
   452  		return errors.New("Enter at one channel to modify.")
   453  	}
   454  
   455  	username, erru := command.Flags().GetString("username")
   456  	if erru != nil || username == "" {
   457  		return errors.New("Username is required")
   458  	}
   459  
   460  	public, _ := command.Flags().GetBool("public")
   461  	private, _ := command.Flags().GetBool("private")
   462  
   463  	if public == private {
   464  		return errors.New("You must specify only one of --public or --private")
   465  	}
   466  
   467  	channel := getChannelFromChannelArg(a, args[0])
   468  	if channel == nil {
   469  		return errors.New("Unable to find channel '" + args[0] + "'")
   470  	}
   471  
   472  	if !(channel.Type == model.CHANNEL_OPEN || channel.Type == model.CHANNEL_PRIVATE) {
   473  		return errors.New("You can only change the type of public/private channels.")
   474  	}
   475  
   476  	channel.Type = model.CHANNEL_OPEN
   477  	if private {
   478  		channel.Type = model.CHANNEL_PRIVATE
   479  	}
   480  
   481  	user := getUserFromUserArg(a, username)
   482  	if _, err := a.UpdateChannelPrivacy(channel, user); err != nil {
   483  		return errors.New("Failed to update channel ('" + args[0] + "') privacy - " + err.Error())
   484  	}
   485  
   486  	return nil
   487  }