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