github.com/wgh-/mattermost-server@v4.8.0-rc2+incompatible/cmd/platform/channel.go (about)

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