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