github.com/psyb0t/mattermost-server@v4.6.1-0.20180125161845-5503a1351abf+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  	deleteChannelsCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the channels.")
   110  
   111  	modifyChannelCmd.Flags().Bool("private", false, "Convert the channel to a private channel")
   112  	modifyChannelCmd.Flags().Bool("public", false, "Convert the channel to a public channel")
   113  	modifyChannelCmd.Flags().String("username", "", "Required. Username who changes the channel privacy.")
   114  
   115  	channelCmd.AddCommand(
   116  		channelCreateCmd,
   117  		removeChannelUsersCmd,
   118  		addChannelUsersCmd,
   119  		archiveChannelsCmd,
   120  		deleteChannelsCmd,
   121  		listChannelsCmd,
   122  		moveChannelsCmd,
   123  		restoreChannelsCmd,
   124  		modifyChannelCmd,
   125  	)
   126  }
   127  
   128  func createChannelCmdF(cmd *cobra.Command, args []string) error {
   129  	a, err := initDBCommandContextCobra(cmd)
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	name, errn := cmd.Flags().GetString("name")
   135  	if errn != nil || name == "" {
   136  		return errors.New("Name is required")
   137  	}
   138  	displayname, errdn := cmd.Flags().GetString("display_name")
   139  	if errdn != nil || displayname == "" {
   140  		return errors.New("Display Name is required")
   141  	}
   142  	teamArg, errteam := cmd.Flags().GetString("team")
   143  	if errteam != nil || teamArg == "" {
   144  		return errors.New("Team is required")
   145  	}
   146  	header, _ := cmd.Flags().GetString("header")
   147  	purpose, _ := cmd.Flags().GetString("purpose")
   148  	useprivate, _ := cmd.Flags().GetBool("private")
   149  
   150  	channelType := model.CHANNEL_OPEN
   151  	if useprivate {
   152  		channelType = model.CHANNEL_PRIVATE
   153  	}
   154  
   155  	team := getTeamFromTeamArg(a, teamArg)
   156  	if team == nil {
   157  		return errors.New("Unable to find team: " + teamArg)
   158  	}
   159  
   160  	channel := &model.Channel{
   161  		TeamId:      team.Id,
   162  		Name:        name,
   163  		DisplayName: displayname,
   164  		Header:      header,
   165  		Purpose:     purpose,
   166  		Type:        channelType,
   167  		CreatorId:   "",
   168  	}
   169  
   170  	if _, err := a.CreateChannel(channel, false); err != nil {
   171  		return err
   172  	}
   173  
   174  	return nil
   175  }
   176  
   177  func removeChannelUsersCmdF(cmd *cobra.Command, args []string) error {
   178  	a, err := initDBCommandContextCobra(cmd)
   179  	if err != nil {
   180  		return err
   181  	}
   182  
   183  	if len(args) < 2 {
   184  		return errors.New("Not enough arguments.")
   185  	}
   186  
   187  	channel := getChannelFromChannelArg(a, args[0])
   188  	if channel == nil {
   189  		return errors.New("Unable to find channel '" + args[0] + "'")
   190  	}
   191  
   192  	users := getUsersFromUserArgs(a, args[1:])
   193  	for i, user := range users {
   194  		removeUserFromChannel(a, channel, user, args[i+1])
   195  	}
   196  
   197  	return nil
   198  }
   199  
   200  func removeUserFromChannel(a *app.App, channel *model.Channel, user *model.User, userArg string) {
   201  	if user == nil {
   202  		CommandPrintErrorln("Can't find user '" + userArg + "'")
   203  		return
   204  	}
   205  	if err := a.RemoveUserFromChannel(user.Id, "", channel); err != nil {
   206  		CommandPrintErrorln("Unable to remove '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
   207  	}
   208  }
   209  
   210  func addChannelUsersCmdF(cmd *cobra.Command, args []string) error {
   211  	a, err := initDBCommandContextCobra(cmd)
   212  	if err != nil {
   213  		return err
   214  	}
   215  
   216  	if len(args) < 2 {
   217  		return errors.New("Not enough arguments.")
   218  	}
   219  
   220  	channel := getChannelFromChannelArg(a, args[0])
   221  	if channel == nil {
   222  		return errors.New("Unable to find channel '" + args[0] + "'")
   223  	}
   224  
   225  	users := getUsersFromUserArgs(a, args[1:])
   226  	for i, user := range users {
   227  		addUserToChannel(a, channel, user, args[i+1])
   228  	}
   229  
   230  	return nil
   231  }
   232  
   233  func addUserToChannel(a *app.App, channel *model.Channel, user *model.User, userArg string) {
   234  	if user == nil {
   235  		CommandPrintErrorln("Can't find user '" + userArg + "'")
   236  		return
   237  	}
   238  	if _, err := a.AddUserToChannel(user, channel); err != nil {
   239  		CommandPrintErrorln("Unable to add '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
   240  	}
   241  }
   242  
   243  func archiveChannelsCmdF(cmd *cobra.Command, args []string) error {
   244  	a, err := initDBCommandContextCobra(cmd)
   245  	if err != nil {
   246  		return err
   247  	}
   248  
   249  	if len(args) < 1 {
   250  		return errors.New("Enter at least one channel to archive.")
   251  	}
   252  
   253  	channels := getChannelsFromChannelArgs(a, args)
   254  	for i, channel := range channels {
   255  		if channel == nil {
   256  			CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   257  			continue
   258  		}
   259  		if result := <-a.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); result.Err != nil {
   260  			CommandPrintErrorln("Unable to archive channel '" + channel.Name + "' error: " + result.Err.Error())
   261  		}
   262  	}
   263  
   264  	return nil
   265  }
   266  
   267  func deleteChannelsCmdF(cmd *cobra.Command, args []string) error {
   268  	a, err := initDBCommandContextCobra(cmd)
   269  	if err != nil {
   270  		return err
   271  	}
   272  
   273  	if len(args) < 1 {
   274  		return errors.New("Enter at least one channel to delete.")
   275  	}
   276  
   277  	confirmFlag, _ := cmd.Flags().GetBool("confirm")
   278  	if !confirmFlag {
   279  		var confirm string
   280  		CommandPrettyPrintln("Are you sure you want to delete the channels specified?  All data will be permanently deleted? (YES/NO): ")
   281  		fmt.Scanln(&confirm)
   282  		if confirm != "YES" {
   283  			return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
   284  		}
   285  	}
   286  
   287  	channels := getChannelsFromChannelArgs(a, args)
   288  	for i, channel := range channels {
   289  		if channel == nil {
   290  			CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   291  			continue
   292  		}
   293  		if err := deleteChannel(a, channel); err != nil {
   294  			CommandPrintErrorln("Unable to delete channel '" + channel.Name + "' error: " + err.Error())
   295  		} else {
   296  			CommandPrettyPrintln("Deleted channel '" + channel.Name + "'")
   297  		}
   298  	}
   299  
   300  	return nil
   301  }
   302  
   303  func deleteChannel(a *app.App, channel *model.Channel) *model.AppError {
   304  	return a.PermanentDeleteChannel(channel)
   305  }
   306  
   307  func moveChannelsCmdF(cmd *cobra.Command, args []string) error {
   308  	a, err := initDBCommandContextCobra(cmd)
   309  	if err != nil {
   310  		return err
   311  	}
   312  
   313  	if len(args) < 2 {
   314  		return errors.New("Enter the destination team and at least one channel to move.")
   315  	}
   316  
   317  	team := getTeamFromTeamArg(a, args[0])
   318  	if team == nil {
   319  		return errors.New("Unable to find destination team '" + args[0] + "'")
   320  	}
   321  
   322  	channels := getChannelsFromChannelArgs(a, args[1:])
   323  	for i, channel := range channels {
   324  		if channel == nil {
   325  			CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   326  			continue
   327  		}
   328  		if err := moveChannel(a, team, channel); err != nil {
   329  			CommandPrintErrorln("Unable to move channel '" + channel.Name + "' error: " + err.Error())
   330  		} else {
   331  			CommandPrettyPrintln("Moved channel '" + channel.Name + "'")
   332  		}
   333  	}
   334  
   335  	return nil
   336  }
   337  
   338  func moveChannel(a *app.App, team *model.Team, channel *model.Channel) *model.AppError {
   339  	oldTeamId := channel.TeamId
   340  
   341  	if err := a.MoveChannel(team, channel); err != nil {
   342  		return err
   343  	}
   344  
   345  	if incomingWebhooks, err := a.GetIncomingWebhooksForTeamPage(oldTeamId, 0, 10000000); err != nil {
   346  		return err
   347  	} else {
   348  		for _, webhook := range incomingWebhooks {
   349  			if webhook.ChannelId == channel.Id {
   350  				webhook.TeamId = team.Id
   351  				if result := <-a.Srv.Store.Webhook().UpdateIncoming(webhook); result.Err != nil {
   352  					CommandPrintErrorln("Failed to move incoming webhook '" + webhook.Id + "' to new team.")
   353  				}
   354  			}
   355  		}
   356  	}
   357  
   358  	if outgoingWebhooks, err := a.GetOutgoingWebhooksForTeamPage(oldTeamId, 0, 10000000); err != nil {
   359  		return err
   360  	} else {
   361  		for _, webhook := range outgoingWebhooks {
   362  			if webhook.ChannelId == channel.Id {
   363  				webhook.TeamId = team.Id
   364  				if result := <-a.Srv.Store.Webhook().UpdateOutgoing(webhook); result.Err != nil {
   365  					CommandPrintErrorln("Failed to move outgoing webhook '" + webhook.Id + "' to new team.")
   366  				}
   367  			}
   368  		}
   369  	}
   370  
   371  	return nil
   372  }
   373  
   374  func listChannelsCmdF(cmd *cobra.Command, args []string) error {
   375  	a, err := initDBCommandContextCobra(cmd)
   376  	if err != nil {
   377  		return err
   378  	}
   379  
   380  	if len(args) < 1 {
   381  		return errors.New("Enter at least one team.")
   382  	}
   383  
   384  	teams := getTeamsFromTeamArgs(a, args)
   385  	for i, team := range teams {
   386  		if team == nil {
   387  			CommandPrintErrorln("Unable to find team '" + args[i] + "'")
   388  			continue
   389  		}
   390  		if result := <-a.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
   391  			CommandPrintErrorln("Unable to list channels for '" + args[i] + "'")
   392  		} else {
   393  			channels := result.Data.([]*model.Channel)
   394  
   395  			for _, channel := range channels {
   396  				if channel.DeleteAt > 0 {
   397  					CommandPrettyPrintln(channel.Name + " (archived)")
   398  				} else {
   399  					CommandPrettyPrintln(channel.Name)
   400  				}
   401  			}
   402  		}
   403  	}
   404  
   405  	return nil
   406  }
   407  
   408  func restoreChannelsCmdF(cmd *cobra.Command, args []string) error {
   409  	a, err := initDBCommandContextCobra(cmd)
   410  	if err != nil {
   411  		return err
   412  	}
   413  
   414  	if len(args) < 1 {
   415  		return errors.New("Enter at least one channel.")
   416  	}
   417  
   418  	channels := getChannelsFromChannelArgs(a, args)
   419  	for i, channel := range channels {
   420  		if channel == nil {
   421  			CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
   422  			continue
   423  		}
   424  		if result := <-a.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
   425  			CommandPrintErrorln("Unable to restore channel '" + args[i] + "'")
   426  		}
   427  	}
   428  
   429  	return nil
   430  }
   431  
   432  func modifyChannelCmdF(cmd *cobra.Command, args []string) error {
   433  	a, err := initDBCommandContextCobra(cmd)
   434  	if err != nil {
   435  		return err
   436  	}
   437  
   438  	if len(args) != 1 {
   439  		return errors.New("Enter at one channel to modify.")
   440  	}
   441  
   442  	username, erru := cmd.Flags().GetString("username")
   443  	if erru != nil || username == "" {
   444  		return errors.New("Username is required")
   445  	}
   446  
   447  	public, _ := cmd.Flags().GetBool("public")
   448  	private, _ := cmd.Flags().GetBool("private")
   449  
   450  	if public == private {
   451  		return errors.New("You must specify only one of --public or --private")
   452  	}
   453  
   454  	channel := getChannelFromChannelArg(a, args[0])
   455  	if channel == nil {
   456  		return errors.New("Unable to find channel '" + args[0] + "'")
   457  	}
   458  
   459  	if !(channel.Type == model.CHANNEL_OPEN || channel.Type == model.CHANNEL_PRIVATE) {
   460  		return errors.New("You can only change the type of public/private channels.")
   461  	}
   462  
   463  	channel.Type = model.CHANNEL_OPEN
   464  	if private {
   465  		channel.Type = model.CHANNEL_PRIVATE
   466  	}
   467  
   468  	user := getUserFromUserArg(a, username)
   469  	if _, err := a.UpdateChannelPrivacy(channel, user); err != nil {
   470  		return errors.New("Failed to update channel ('" + args[0] + "') privacy - " + err.Error())
   471  	}
   472  
   473  	return nil
   474  }