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