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