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