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