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