github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/cmd/mattermost/commands/channel.go (about) 1 // Copyright (c) 2015-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/pkg/errors" 10 "github.com/spf13/cobra" 11 12 "github.com/mattermost/mattermost-server/v5/app" 13 "github.com/mattermost/mattermost-server/v5/audit" 14 "github.com/mattermost/mattermost-server/v5/model" 15 ) 16 17 var ChannelCmd = &cobra.Command{ 18 Use: "channel", 19 Short: "Management of channels", 20 } 21 22 var ChannelCreateCmd = &cobra.Command{ 23 Use: "create", 24 Short: "Create a channel", 25 Long: `Create a channel.`, 26 Example: ` channel create --team myteam --name mynewchannel --display_name "My New Channel" 27 channel create --team myteam --name mynewprivatechannel --display_name "My New Private Channel" --private`, 28 RunE: createChannelCmdF, 29 } 30 31 var ChannelRenameCmd = &cobra.Command{ 32 Use: "rename", 33 Short: "Rename a channel", 34 Long: `Rename a channel.`, 35 Example: `" channel rename myteam:mychannel newchannelname --display_name "New Display Name"`, 36 Args: cobra.MinimumNArgs(2), 37 RunE: renameChannelCmdF, 38 } 39 40 var RemoveChannelUsersCmd = &cobra.Command{ 41 Use: "remove [channel] [users]", 42 Short: "Remove users from channel", 43 Long: "Remove some users from channel", 44 Example: ` channel remove myteam:mychannel user@example.com username 45 channel remove myteam:mychannel --all-users`, 46 RunE: removeChannelUsersCmdF, 47 } 48 49 var AddChannelUsersCmd = &cobra.Command{ 50 Use: "add [channel] [users]", 51 Short: "Add users to channel", 52 Long: "Add some users to channel", 53 Example: " channel add myteam:mychannel user@example.com username", 54 Args: cobra.MinimumNArgs(2), 55 RunE: addChannelUsersCmdF, 56 } 57 58 var ArchiveChannelsCmd = &cobra.Command{ 59 Use: "archive [channels]", 60 Short: "Archive channels", 61 Long: `Archive some channels. 62 Archive a channel along with all related information including posts from the database. 63 Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`, 64 Example: " channel archive myteam:mychannel", 65 Args: cobra.MinimumNArgs(1), 66 RunE: archiveChannelsCmdF, 67 } 68 69 var DeleteChannelsCmd = &cobra.Command{ 70 Use: "delete [channels]", 71 Short: "Delete channels", 72 Long: `Permanently delete some channels. 73 Permanently deletes a channel along with all related information including posts from the database. 74 Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`, 75 Example: " channel delete myteam:mychannel", 76 Args: cobra.MinimumNArgs(1), 77 RunE: deleteChannelsCmdF, 78 } 79 80 var ListChannelsCmd = &cobra.Command{ 81 Use: "list [teams]", 82 Short: "List all channels on specified teams.", 83 Long: `List all channels on specified teams. 84 Archived channels are appended with ' (archived)'. 85 Private channels are appended with ' (private)'.`, 86 Example: " channel list myteam", 87 Args: cobra.MinimumNArgs(1), 88 RunE: listChannelsCmdF, 89 } 90 91 var MoveChannelsCmd = &cobra.Command{ 92 Use: "move [team] [channels] --username [user]", 93 Short: "Moves channels to the specified team", 94 Long: `Moves the provided channels to the specified team. 95 Validates that all users in the channel belong to the target team. Incoming/Outgoing webhooks are moved along with the channel. 96 Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`, 97 Example: " channel move newteam oldteam:mychannel --username myusername", 98 Args: cobra.MinimumNArgs(2), 99 RunE: moveChannelsCmdF, 100 } 101 102 var RestoreChannelsCmd = &cobra.Command{ 103 Use: "restore [channels]", 104 Short: "Restore some channels", 105 Long: `Restore a previously deleted channel 106 Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`, 107 Example: " channel restore myteam:mychannel", 108 Args: cobra.MinimumNArgs(1), 109 RunE: restoreChannelsCmdF, 110 } 111 112 var ModifyChannelCmd = &cobra.Command{ 113 Use: "modify [channel] [flags] --username [user]", 114 Short: "Modify a channel's public/private type", 115 Long: `Change the public/private type of a channel. 116 Channel can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`, 117 Example: " channel modify myteam:mychannel --private --username myusername", 118 Args: cobra.MinimumNArgs(1), 119 RunE: modifyChannelCmdF, 120 } 121 122 var SearchChannelCmd = &cobra.Command{ 123 Use: "search [channel]\n mattermost search --team [team] [channel]", 124 Short: "Search a channel", 125 Long: `Search a channel by channel name. 126 Channel can be specified by team. ie. --team myTeam myChannel or by team ID.`, 127 Example: ` channel search myChannel 128 channel search --team myTeam myChannel`, 129 Args: cobra.ExactArgs(1), 130 RunE: searchChannelCmdF, 131 } 132 133 func init() { 134 ChannelCreateCmd.Flags().String("name", "", "Channel Name") 135 ChannelCreateCmd.Flags().String("display_name", "", "Channel Display Name") 136 ChannelCreateCmd.Flags().String("team", "", "Team name or ID") 137 ChannelCreateCmd.Flags().String("header", "", "Channel header") 138 ChannelCreateCmd.Flags().String("purpose", "", "Channel purpose") 139 ChannelCreateCmd.Flags().Bool("private", false, "Create a private channel.") 140 141 MoveChannelsCmd.Flags().String("username", "", "Required. Username who is moving the channel.") 142 143 DeleteChannelsCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the channels.") 144 145 ModifyChannelCmd.Flags().Bool("private", false, "Convert the channel to a private channel") 146 ModifyChannelCmd.Flags().Bool("public", false, "Convert the channel to a public channel") 147 ModifyChannelCmd.Flags().String("username", "", "Required. Username who changes the channel privacy.") 148 149 ChannelRenameCmd.Flags().String("display_name", "", "Channel Display Name") 150 SearchChannelCmd.Flags().String("team", "", "Team name or ID") 151 152 RemoveChannelUsersCmd.Flags().Bool("all-users", false, "Remove all users from the indicated channel.") 153 154 ChannelCmd.AddCommand( 155 ChannelCreateCmd, 156 RemoveChannelUsersCmd, 157 AddChannelUsersCmd, 158 ArchiveChannelsCmd, 159 DeleteChannelsCmd, 160 ListChannelsCmd, 161 MoveChannelsCmd, 162 RestoreChannelsCmd, 163 ModifyChannelCmd, 164 ChannelRenameCmd, 165 SearchChannelCmd, 166 ) 167 168 RootCmd.AddCommand(ChannelCmd) 169 } 170 171 func createChannelCmdF(command *cobra.Command, args []string) error { 172 a, err := InitDBCommandContextCobra(command) 173 if err != nil { 174 return err 175 } 176 defer a.Srv().Shutdown() 177 178 name, errn := command.Flags().GetString("name") 179 if errn != nil || name == "" { 180 return errors.New("Name is required") 181 } 182 displayname, errdn := command.Flags().GetString("display_name") 183 if errdn != nil || displayname == "" { 184 return errors.New("Display Name is required") 185 } 186 teamArg, errteam := command.Flags().GetString("team") 187 if errteam != nil || teamArg == "" { 188 return errors.New("Team is required") 189 } 190 header, _ := command.Flags().GetString("header") 191 purpose, _ := command.Flags().GetString("purpose") 192 useprivate, _ := command.Flags().GetBool("private") 193 194 channelType := model.CHANNEL_OPEN 195 if useprivate { 196 channelType = model.CHANNEL_PRIVATE 197 } 198 199 team := getTeamFromTeamArg(a, teamArg) 200 if team == nil { 201 return errors.New("Unable to find team: " + teamArg) 202 } 203 204 channel := &model.Channel{ 205 TeamId: team.Id, 206 Name: name, 207 DisplayName: displayname, 208 Header: header, 209 Purpose: purpose, 210 Type: channelType, 211 CreatorId: "", 212 } 213 214 createdChannel, errCreatedChannel := a.CreateChannel(channel, false) 215 if errCreatedChannel != nil { 216 return errCreatedChannel 217 } 218 219 auditRec := a.MakeAuditRecord("createChannel", audit.Success) 220 auditRec.AddMeta("channel", createdChannel) 221 auditRec.AddMeta("team", team) 222 a.LogAuditRec(auditRec, nil) 223 224 CommandPrettyPrintln("Id: " + createdChannel.Id) 225 CommandPrettyPrintln("Name: " + createdChannel.Name) 226 CommandPrettyPrintln("Display Name: " + createdChannel.DisplayName) 227 return nil 228 } 229 230 func removeChannelUsersCmdF(command *cobra.Command, args []string) error { 231 a, err := InitDBCommandContextCobra(command) 232 if err != nil { 233 return err 234 } 235 defer a.Srv().Shutdown() 236 237 allUsers, _ := command.Flags().GetBool("all-users") 238 239 if allUsers && len(args) != 1 { 240 return errors.New("individual users must not be specified in conjunction with the --all-users flag") 241 } 242 243 if !allUsers && len(args) < 2 { 244 return errors.New("you must specify some users to remove from the channel, or use the --all-users flag to remove them all") 245 } 246 247 channel := getChannelFromChannelArg(a, args[0]) 248 if channel == nil { 249 return errors.New("Unable to find channel '" + args[0] + "'") 250 } 251 252 if allUsers { 253 removeAllUsersFromChannel(a, channel) 254 } else { 255 users := getUsersFromUserArgs(a, args[1:]) 256 for i, user := range users { 257 removeUserFromChannel(a, channel, user, args[i+1]) 258 } 259 } 260 return nil 261 } 262 263 func removeUserFromChannel(a *app.App, channel *model.Channel, user *model.User, userArg string) { 264 if user == nil { 265 CommandPrintErrorln("Can't find user '" + userArg + "'") 266 return 267 } 268 if err := a.RemoveUserFromChannel(user.Id, "", channel); err != nil { 269 CommandPrintErrorln("Unable to remove '" + userArg + "' from " + channel.Name + ". Error: " + err.Error()) 270 return 271 } 272 273 auditRec := a.MakeAuditRecord("removeUserFromChannel", audit.Success) 274 auditRec.AddMeta("channel", channel) 275 auditRec.AddMeta("user", user) 276 a.LogAuditRec(auditRec, nil) 277 } 278 279 func removeAllUsersFromChannel(a *app.App, channel *model.Channel) { 280 if err := a.Srv().Store.Channel().PermanentDeleteMembersByChannel(channel.Id); err != nil { 281 CommandPrintErrorln("Unable to remove all users from " + channel.Name + ". Error: " + err.Error()) 282 return 283 } 284 285 auditRec := a.MakeAuditRecord("removeAllUsersFromChannel", audit.Success) 286 auditRec.AddMeta("channel", channel) 287 a.LogAuditRec(auditRec, nil) 288 } 289 290 func addChannelUsersCmdF(command *cobra.Command, args []string) error { 291 a, err := InitDBCommandContextCobra(command) 292 if err != nil { 293 return err 294 } 295 defer a.Srv().Shutdown() 296 297 channel := getChannelFromChannelArg(a, args[0]) 298 if channel == nil { 299 return errors.New("Unable to find channel '" + args[0] + "'") 300 } 301 302 users := getUsersFromUserArgs(a, args[1:]) 303 for i, user := range users { 304 addUserToChannel(a, channel, user, args[i+1]) 305 } 306 return nil 307 } 308 309 func addUserToChannel(a *app.App, channel *model.Channel, user *model.User, userArg string) { 310 if user == nil { 311 CommandPrintErrorln("Can't find user '" + userArg + "'") 312 return 313 } 314 if _, err := a.AddUserToChannel(user, channel); err != nil { 315 CommandPrintErrorln("Unable to add '" + userArg + "' from " + channel.Name + ". Error: " + err.Error()) 316 return 317 } 318 319 auditRec := a.MakeAuditRecord("addUserToChannel", audit.Success) 320 auditRec.AddMeta("channel", channel) 321 auditRec.AddMeta("user", user) 322 a.LogAuditRec(auditRec, nil) 323 } 324 325 func archiveChannelsCmdF(command *cobra.Command, args []string) error { 326 a, err := InitDBCommandContextCobra(command) 327 if err != nil { 328 return err 329 } 330 defer a.Srv().Shutdown() 331 332 channels := getChannelsFromChannelArgs(a, args) 333 for i, channel := range channels { 334 if channel == nil { 335 CommandPrintErrorln("Unable to find channel '" + args[i] + "'") 336 continue 337 } 338 if err := a.Srv().Store.Channel().Delete(channel.Id, model.GetMillis()); err != nil { 339 CommandPrintErrorln("Unable to archive channel '" + channel.Name + "' error: " + err.Error()) 340 continue 341 } 342 auditRec := a.MakeAuditRecord("archiveChannel", audit.Success) 343 auditRec.AddMeta("channel", channel) 344 a.LogAuditRec(auditRec, nil) 345 } 346 return nil 347 } 348 349 func deleteChannelsCmdF(command *cobra.Command, args []string) error { 350 a, err := InitDBCommandContextCobra(command) 351 if err != nil { 352 return err 353 } 354 defer a.Srv().Shutdown() 355 356 confirmFlag, _ := command.Flags().GetBool("confirm") 357 if !confirmFlag { 358 var confirm string 359 CommandPrettyPrintln("Are you sure you want to delete the channels specified? All data will be permanently deleted? (YES/NO): ") 360 fmt.Scanln(&confirm) 361 if confirm != "YES" { 362 return errors.New("ABORTED: You did not answer YES exactly, in all capitals.") 363 } 364 } 365 366 channels := getChannelsFromChannelArgs(a, args) 367 for i, channel := range channels { 368 if channel == nil { 369 CommandPrintErrorln("Unable to find channel '" + args[i] + "'") 370 continue 371 } 372 if err := deleteChannel(a, channel); err != nil { 373 CommandPrintErrorln("Unable to delete channel '" + channel.Name + "' error: " + err.Error()) 374 } else { 375 CommandPrettyPrintln("Deleted channel '" + channel.Name + "'") 376 377 auditRec := a.MakeAuditRecord("deleteChannel", audit.Success) 378 auditRec.AddMeta("channel", channel) 379 a.LogAuditRec(auditRec, nil) 380 } 381 } 382 return nil 383 } 384 385 func deleteChannel(a *app.App, channel *model.Channel) *model.AppError { 386 return a.PermanentDeleteChannel(channel) 387 } 388 389 func moveChannelsCmdF(command *cobra.Command, args []string) error { 390 a, err := InitDBCommandContextCobra(command) 391 if err != nil { 392 return err 393 } 394 defer a.Srv().Shutdown() 395 396 team := getTeamFromTeamArg(a, args[0]) 397 if team == nil { 398 return errors.New("Unable to find destination team '" + args[0] + "'") 399 } 400 401 username, erru := command.Flags().GetString("username") 402 if erru != nil || username == "" { 403 return errors.New("Username is required.") 404 } 405 user := getUserFromUserArg(a, username) 406 407 channels := getChannelsFromChannelArgs(a, args[1:]) 408 for i, channel := range channels { 409 if channel == nil { 410 CommandPrintErrorln("Unable to find channel '" + args[i+1] + "'") 411 continue 412 } 413 originTeamID := channel.TeamId 414 if err := moveChannel(a, team, channel, user); err != nil { 415 CommandPrintErrorln("Unable to move channel '" + channel.Name + "' error: " + err.Error()) 416 } else { 417 CommandPrettyPrintln("Moved channel '" + channel.Name + "' to " + team.Name + "(" + team.Id + ") from " + originTeamID + ".") 418 } 419 } 420 return nil 421 } 422 423 func moveChannel(a *app.App, team *model.Team, channel *model.Channel, user *model.User) *model.AppError { 424 oldTeamId := channel.TeamId 425 426 if err := a.RemoveAllDeactivatedMembersFromChannel(channel); err != nil { 427 return err 428 } 429 430 if err := a.MoveChannel(team, channel, user); err != nil { 431 return err 432 } 433 434 auditRec := a.MakeAuditRecord("moveChannel", audit.Success) 435 auditRec.AddMeta("channel", channel) 436 auditRec.AddMeta("team", team) 437 a.LogAuditRec(auditRec, nil) 438 439 incomingWebhooks, err := a.GetIncomingWebhooksForTeamPage(oldTeamId, 0, 10000000) 440 if err != nil { 441 return err 442 } 443 for _, webhook := range incomingWebhooks { 444 if webhook.ChannelId == channel.Id { 445 webhook.TeamId = team.Id 446 if _, err := a.Srv().Store.Webhook().UpdateIncoming(webhook); err != nil { 447 CommandPrintErrorln("Failed to move incoming webhook '" + webhook.Id + "' to new team.") 448 } 449 } 450 } 451 452 outgoingWebhooks, err := a.GetOutgoingWebhooksForTeamPage(oldTeamId, 0, 10000000) 453 if err != nil { 454 return err 455 } 456 for _, webhook := range outgoingWebhooks { 457 if webhook.ChannelId == channel.Id { 458 webhook.TeamId = team.Id 459 if _, err := a.Srv().Store.Webhook().UpdateOutgoing(webhook); err != nil { 460 CommandPrintErrorln("Failed to move outgoing webhook '" + webhook.Id + "' to new team.") 461 } 462 } 463 } 464 465 return nil 466 } 467 468 func listChannelsCmdF(command *cobra.Command, args []string) error { 469 a, err := InitDBCommandContextCobra(command) 470 if err != nil { 471 return err 472 } 473 defer a.Srv().Shutdown() 474 475 teams := getTeamsFromTeamArgs(a, args) 476 for i, team := range teams { 477 if team == nil { 478 CommandPrintErrorln("Unable to find team '" + args[i] + "'") 479 continue 480 } 481 if channels, chanErr := a.Srv().Store.Channel().GetAll(team.Id); chanErr != nil { 482 CommandPrintErrorln("Unable to list channels for '" + args[i] + "'") 483 } else { 484 for _, channel := range channels { 485 output := channel.Name 486 if channel.DeleteAt > 0 { 487 output += " (archived)" 488 } 489 if channel.Type == model.CHANNEL_PRIVATE { 490 output += " (private)" 491 } 492 CommandPrettyPrintln(output) 493 } 494 } 495 } 496 497 return nil 498 } 499 500 func restoreChannelsCmdF(command *cobra.Command, args []string) error { 501 a, err := InitDBCommandContextCobra(command) 502 if err != nil { 503 return err 504 } 505 defer a.Srv().Shutdown() 506 507 channels := getChannelsFromChannelArgs(a, args) 508 for i, channel := range channels { 509 if channel == nil { 510 CommandPrintErrorln("Unable to find channel '" + args[i] + "'") 511 continue 512 } 513 if err := a.Srv().Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); err != nil { 514 CommandPrintErrorln("Unable to restore channel '" + args[i] + "'") 515 continue 516 } 517 auditRec := a.MakeAuditRecord("restoreChannel", audit.Success) 518 auditRec.AddMeta("channel", channel) 519 a.LogAuditRec(auditRec, nil) 520 } 521 522 suffix := "" 523 if len(channels) > 1 { 524 suffix = "s" 525 } 526 CommandPrintln("Successfully restored channel" + suffix) 527 return nil 528 } 529 530 func modifyChannelCmdF(command *cobra.Command, args []string) error { 531 a, err := InitDBCommandContextCobra(command) 532 if err != nil { 533 return err 534 } 535 defer a.Srv().Shutdown() 536 537 username, erru := command.Flags().GetString("username") 538 if erru != nil || username == "" { 539 return errors.New("Username is required.") 540 } 541 542 public, _ := command.Flags().GetBool("public") 543 private, _ := command.Flags().GetBool("private") 544 545 if public == private { 546 return errors.New("You must specify only one of --public or --private") 547 } 548 549 channel := getChannelFromChannelArg(a, args[0]) 550 if channel == nil { 551 return errors.New("Unable to find channel '" + args[0] + "'") 552 } 553 554 if !(channel.Type == model.CHANNEL_OPEN || channel.Type == model.CHANNEL_PRIVATE) { 555 return errors.New("You can only change the type of public/private channels.") 556 } 557 558 channel.Type = model.CHANNEL_OPEN 559 if private { 560 channel.Type = model.CHANNEL_PRIVATE 561 } 562 563 user := getUserFromUserArg(a, username) 564 if user == nil { 565 return fmt.Errorf("Unable to find user: '%v'", username) 566 } 567 568 updatedChannel, errUpdate := a.UpdateChannelPrivacy(channel, user) 569 if errUpdate != nil { 570 return errors.Wrapf(err, "Failed to update channel ('%s') privacy", args[0]) 571 } 572 573 auditRec := a.MakeAuditRecord("modifyChannel", audit.Success) 574 auditRec.AddMeta("channel", channel) 575 auditRec.AddMeta("user", user) 576 auditRec.AddMeta("update", updatedChannel) 577 a.LogAuditRec(auditRec, nil) 578 579 return nil 580 } 581 582 func renameChannelCmdF(command *cobra.Command, args []string) error { 583 a, err := InitDBCommandContextCobra(command) 584 var newDisplayName, newChannelName string 585 if err != nil { 586 return err 587 } 588 defer a.Srv().Shutdown() 589 590 channel := getChannelFromChannelArg(a, args[0]) 591 if channel == nil { 592 return errors.New("Unable to find channel '" + args[0] + "'") 593 } 594 595 newChannelName = args[1] 596 newDisplayName, errdn := command.Flags().GetString("display_name") 597 if errdn != nil { 598 return errdn 599 } 600 601 updatedChannel, errch := a.RenameChannel(channel, newChannelName, newDisplayName) 602 if errch != nil { 603 return errors.Wrapf(errch, "Error in updating channel from %s to %s", channel.Name, newChannelName) 604 } 605 606 auditRec := a.MakeAuditRecord("renameChannel", audit.Success) 607 auditRec.AddMeta("channel", channel) 608 auditRec.AddMeta("update", updatedChannel) 609 a.LogAuditRec(auditRec, nil) 610 611 return nil 612 } 613 614 func searchChannelCmdF(command *cobra.Command, args []string) error { 615 a, err := InitDBCommandContextCobra(command) 616 if err != nil { 617 return errors.Wrap(err, "failed to InitDBCommandContextCobra") 618 } 619 defer a.Srv().Shutdown() 620 621 var channel *model.Channel 622 623 if teamArg, _ := command.Flags().GetString("team"); teamArg != "" { 624 team := getTeamFromTeamArg(a, teamArg) 625 if team == nil { 626 CommandPrettyPrintln(fmt.Sprintf("Team %s is not found", teamArg)) 627 return nil 628 } 629 630 var aErr *model.AppError 631 channel, aErr = a.GetChannelByName(args[0], team.Id, true) 632 if aErr != nil || channel == nil { 633 CommandPrettyPrintln(fmt.Sprintf("Channel %s is not found in team %s", args[0], teamArg)) 634 return nil 635 } 636 } else { 637 teams, aErr := a.GetAllTeams() 638 if aErr != nil { 639 return errors.Wrap(err, "failed to GetAllTeams") 640 } 641 642 for _, team := range teams { 643 channel, _ = a.GetChannelByName(args[0], team.Id, true) 644 if channel != nil && channel.Name == args[0] { 645 break 646 } 647 } 648 649 if channel == nil { 650 CommandPrettyPrintln(fmt.Sprintf("Channel %s is not found in any team", args[0])) 651 return nil 652 } 653 } 654 655 output := fmt.Sprintf(`Channel Name: %s, Display Name: %s, Channel ID: %s`, channel.Name, channel.DisplayName, channel.Id) 656 if channel.DeleteAt > 0 { 657 output += " (archived)" 658 } 659 if channel.Type == model.CHANNEL_PRIVATE { 660 output += " (private)" 661 } 662 CommandPrettyPrintln(output) 663 664 return nil 665 }