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