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