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