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