github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/cmd/mattermost/commands/team.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 "errors" 8 "fmt" 9 "sort" 10 "strings" 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 "github.com/spf13/cobra" 16 ) 17 18 var TeamCmd = &cobra.Command{ 19 Use: "team", 20 Short: "Management of teams", 21 } 22 23 var TeamCreateCmd = &cobra.Command{ 24 Use: "create", 25 Short: "Create a team", 26 Long: `Create a team.`, 27 Example: ` team create --name mynewteam --display_name "My New Team" 28 team create --name private --display_name "My New Private Team" --private`, 29 RunE: createTeamCmdF, 30 } 31 32 var RemoveUsersCmd = &cobra.Command{ 33 Use: "remove [team] [users]", 34 Short: "Remove users from team", 35 Long: "Remove some users from team", 36 Example: " team remove myteam user@example.com username", 37 Args: cobra.MinimumNArgs(2), 38 RunE: removeUsersCmdF, 39 } 40 41 var AddUsersCmd = &cobra.Command{ 42 Use: "add [team] [users]", 43 Short: "Add users to team", 44 Long: "Add some users to team", 45 Example: " team add myteam user@example.com username", 46 Args: cobra.MinimumNArgs(2), 47 RunE: addUsersCmdF, 48 } 49 50 var DeleteTeamsCmd = &cobra.Command{ 51 Use: "delete [teams]", 52 Short: "Delete teams", 53 Long: `Permanently delete some teams. 54 Permanently deletes a team along with all related information including posts from the database.`, 55 Example: " team delete myteam", 56 Args: cobra.MinimumNArgs(1), 57 RunE: deleteTeamsCmdF, 58 } 59 60 var ListTeamsCmd = &cobra.Command{ 61 Use: "list", 62 Short: "List all teams.", 63 Long: `List all teams on the server.`, 64 Example: " team list", 65 RunE: listTeamsCmdF, 66 } 67 68 var SearchTeamCmd = &cobra.Command{ 69 Use: "search [teams]", 70 Short: "Search for teams", 71 Long: "Search for teams based on name", 72 Example: " team search team1", 73 Args: cobra.MinimumNArgs(1), 74 RunE: searchTeamCmdF, 75 } 76 77 var ArchiveTeamCmd = &cobra.Command{ 78 Use: "archive [teams]", 79 Short: "Archive teams", 80 Long: "Archive teams based on name", 81 Example: " team archive team1", 82 Args: cobra.MinimumNArgs(1), 83 RunE: archiveTeamCmdF, 84 } 85 86 var RestoreTeamsCmd = &cobra.Command{ 87 Use: "restore [teams]", 88 Short: "Restore some teams", 89 Long: `Restore a previously deleted team`, 90 Example: " team restore myteam", 91 Args: cobra.MinimumNArgs(1), 92 RunE: restoreTeamsCmdF, 93 } 94 95 var TeamRenameCmd = &cobra.Command{ 96 Use: "rename", 97 Short: "Rename a team", 98 Long: `Rename a team.`, 99 Example: ` team rename myteam newteamname --display_name "My New Team Name" 100 team rename myteam - --display_name "My New Team Name"`, 101 Args: cobra.MinimumNArgs(2), 102 RunE: renameTeamCmdF, 103 } 104 105 var ModifyTeamCmd = &cobra.Command{ 106 Use: "modify [team] [flag]", 107 Short: "Modify a team's privacy setting to public or private", 108 Long: `Modify a team's privacy setting to public or private.`, 109 Example: " team modify myteam --private", 110 Args: cobra.ExactArgs(1), 111 RunE: modifyTeamCmdF, 112 } 113 114 func init() { 115 TeamCreateCmd.Flags().String("name", "", "Team Name") 116 TeamCreateCmd.Flags().String("display_name", "", "Team Display Name") 117 TeamCreateCmd.Flags().Bool("private", false, "Create a private team.") 118 TeamCreateCmd.Flags().String("email", "", "Administrator Email (anyone with this email is automatically a team admin)") 119 120 DeleteTeamsCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the team and a DB backup has been performed.") 121 122 TeamRenameCmd.Flags().String("display_name", "", "Team Display Name") 123 124 ModifyTeamCmd.Flags().Bool("private", false, "Convert the team to a private team") 125 ModifyTeamCmd.Flags().Bool("public", false, "Convert the team to a public team") 126 127 TeamCmd.AddCommand( 128 TeamCreateCmd, 129 RemoveUsersCmd, 130 AddUsersCmd, 131 DeleteTeamsCmd, 132 ListTeamsCmd, 133 SearchTeamCmd, 134 ArchiveTeamCmd, 135 RestoreTeamsCmd, 136 TeamRenameCmd, 137 ModifyTeamCmd, 138 ) 139 RootCmd.AddCommand(TeamCmd) 140 } 141 142 func createTeamCmdF(command *cobra.Command, args []string) error { 143 a, err := InitDBCommandContextCobra(command) 144 if err != nil { 145 return err 146 } 147 defer a.Srv().Shutdown() 148 149 name, errn := command.Flags().GetString("name") 150 if errn != nil || name == "" { 151 return errors.New("Name is required") 152 } 153 displayname, errdn := command.Flags().GetString("display_name") 154 if errdn != nil || displayname == "" { 155 return errors.New("Display Name is required") 156 } 157 email, _ := command.Flags().GetString("email") 158 email = strings.ToLower(email) 159 useprivate, _ := command.Flags().GetBool("private") 160 161 teamType := model.TEAM_OPEN 162 if useprivate { 163 teamType = model.TEAM_INVITE 164 } 165 166 team := &model.Team{ 167 Name: name, 168 DisplayName: displayname, 169 Email: email, 170 Type: teamType, 171 } 172 173 createdTeam, errCreate := a.CreateTeam(team) 174 if errCreate != nil { 175 return errors.New("Team creation failed: " + errCreate.Error()) 176 } 177 178 auditRec := a.MakeAuditRecord("createTeam", audit.Success) 179 auditRec.AddMeta("team", createdTeam) 180 a.LogAuditRec(auditRec, nil) 181 182 return nil 183 } 184 185 func removeUsersCmdF(command *cobra.Command, args []string) error { 186 a, err := InitDBCommandContextCobra(command) 187 if err != nil { 188 return err 189 } 190 defer a.Srv().Shutdown() 191 192 team := getTeamFromTeamArg(a, args[0]) 193 if team == nil { 194 return errors.New("Unable to find team '" + args[0] + "'") 195 } 196 197 users := getUsersFromUserArgs(a, args[1:]) 198 for i, user := range users { 199 removeUserFromTeam(a, team, user, args[i+1]) 200 } 201 202 return nil 203 } 204 205 func removeUserFromTeam(a *app.App, team *model.Team, user *model.User, userArg string) { 206 if user == nil { 207 CommandPrintErrorln("Can't find user '" + userArg + "'") 208 return 209 } 210 if err := a.LeaveTeam(team, user, ""); err != nil { 211 CommandPrintErrorln("Unable to remove '" + userArg + "' from " + team.Name + ". Error: " + err.Error()) 212 return 213 } 214 215 auditRec := a.MakeAuditRecord("removeUserFromTeam", audit.Success) 216 auditRec.AddMeta("user", user) 217 auditRec.AddMeta("team", team) 218 a.LogAuditRec(auditRec, nil) 219 } 220 221 func addUsersCmdF(command *cobra.Command, args []string) error { 222 a, err := InitDBCommandContextCobra(command) 223 if err != nil { 224 return err 225 } 226 defer a.Srv().Shutdown() 227 228 team := getTeamFromTeamArg(a, args[0]) 229 if team == nil { 230 return errors.New("Unable to find team '" + args[0] + "'") 231 } 232 233 users := getUsersFromUserArgs(a, args[1:]) 234 for i, user := range users { 235 addUserToTeam(a, team, user, args[i+1]) 236 } 237 return nil 238 } 239 240 func addUserToTeam(a *app.App, team *model.Team, user *model.User, userArg string) { 241 if user == nil { 242 CommandPrintErrorln("Can't find user '" + userArg + "'") 243 return 244 } 245 if err := a.JoinUserToTeam(team, user, ""); err != nil { 246 CommandPrintErrorln("Unable to add '" + userArg + "' to " + team.Name) 247 return 248 } 249 250 auditRec := a.MakeAuditRecord("addUserToTeam", audit.Success) 251 auditRec.AddMeta("user", user) 252 auditRec.AddMeta("team", team) 253 a.LogAuditRec(auditRec, nil) 254 } 255 256 func deleteTeamsCmdF(command *cobra.Command, args []string) error { 257 a, err := InitDBCommandContextCobra(command) 258 if err != nil { 259 return err 260 } 261 defer a.Srv().Shutdown() 262 263 confirmFlag, _ := command.Flags().GetBool("confirm") 264 if !confirmFlag { 265 var confirm string 266 CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ") 267 fmt.Scanln(&confirm) 268 269 if confirm != "YES" { 270 return errors.New("ABORTED: You did not answer YES exactly, in all capitals.") 271 } 272 CommandPrettyPrintln("Are you sure you want to delete the teams specified? All data will be permanently deleted? (YES/NO): ") 273 fmt.Scanln(&confirm) 274 if confirm != "YES" { 275 return errors.New("ABORTED: You did not answer YES exactly, in all capitals.") 276 } 277 } 278 279 teams := getTeamsFromTeamArgs(a, args) 280 for i, team := range teams { 281 if team == nil { 282 CommandPrintErrorln("Unable to find team '" + args[i] + "'") 283 continue 284 } 285 if err := deleteTeam(a, team); err != nil { 286 CommandPrintErrorln("Unable to delete team '" + team.Name + "' error: " + err.Error()) 287 } else { 288 CommandPrettyPrintln("Deleted team '" + team.Name + "'") 289 290 auditRec := a.MakeAuditRecord("deleteTeams", audit.Success) 291 auditRec.AddMeta("team", team) 292 a.LogAuditRec(auditRec, nil) 293 } 294 } 295 return nil 296 } 297 298 func deleteTeam(a *app.App, team *model.Team) *model.AppError { 299 return a.PermanentDeleteTeam(team) 300 } 301 302 func listTeamsCmdF(command *cobra.Command, args []string) error { 303 a, err := InitDBCommandContextCobra(command) 304 if err != nil { 305 return err 306 } 307 defer a.Srv().Shutdown() 308 309 teams, err2 := a.GetAllTeams() 310 if err2 != nil { 311 return err2 312 } 313 314 for _, team := range teams { 315 if team.DeleteAt > 0 { 316 CommandPrettyPrintln(team.Name + " (archived)") 317 } else { 318 CommandPrettyPrintln(team.Name) 319 } 320 } 321 322 return nil 323 } 324 325 func searchTeamCmdF(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 var teams []*model.Team 333 334 for _, searchTerm := range args { 335 foundTeams, _, err := a.SearchAllTeams(&model.TeamSearch{Term: searchTerm}) 336 if err != nil { 337 return err 338 } 339 teams = append(teams, foundTeams...) 340 } 341 342 sortedTeams := removeDuplicatesAndSortTeams(teams) 343 344 for _, team := range sortedTeams { 345 if team.DeleteAt > 0 { 346 CommandPrettyPrintln(team.Name + ": " + team.DisplayName + " (" + team.Id + ")" + " (archived)") 347 } else { 348 CommandPrettyPrintln(team.Name + ": " + team.DisplayName + " (" + team.Id + ")") 349 } 350 } 351 352 return nil 353 } 354 355 // Restores archived teams by name 356 func restoreTeamsCmdF(command *cobra.Command, args []string) error { 357 a, err := InitDBCommandContextCobra(command) 358 if err != nil { 359 return err 360 } 361 defer a.Srv().Shutdown() 362 363 teams := getTeamsFromTeamArgs(a, args) 364 for i, team := range teams { 365 if team == nil { 366 CommandPrintErrorln("Unable to find team '" + args[i] + "'") 367 continue 368 } 369 err := a.RestoreTeam(team.Id) 370 if err != nil { 371 CommandPrintErrorln("Unable to restore team '" + team.Name + "' error: " + err.Error()) 372 } else { 373 auditRec := a.MakeAuditRecord("restoreTeams", audit.Success) 374 auditRec.AddMeta("team", team) 375 a.LogAuditRec(auditRec, nil) 376 } 377 } 378 return nil 379 } 380 381 // Removes duplicates and sorts teams by name 382 func removeDuplicatesAndSortTeams(teams []*model.Team) []*model.Team { 383 keys := make(map[string]bool) 384 result := []*model.Team{} 385 for _, team := range teams { 386 if _, value := keys[team.Name]; !value { 387 keys[team.Name] = true 388 result = append(result, team) 389 } 390 } 391 sort.Slice(result, func(i, j int) bool { 392 return result[i].Name < result[j].Name 393 }) 394 return result 395 } 396 397 func archiveTeamCmdF(command *cobra.Command, args []string) error { 398 a, err := InitDBCommandContextCobra(command) 399 if err != nil { 400 return err 401 } 402 defer a.Srv().Shutdown() 403 404 foundTeams := getTeamsFromTeamArgs(a, args) 405 for i, team := range foundTeams { 406 if team == nil { 407 CommandPrintErrorln("Unable to find team '" + args[i] + "'") 408 continue 409 } 410 if err := a.SoftDeleteTeam(team.Id); err != nil { 411 CommandPrintErrorln("Unable to archive team '"+team.Name+"' error: ", err) 412 } else { 413 auditRec := a.MakeAuditRecord("archiveTeam", audit.Success) 414 auditRec.AddMeta("team", team) 415 a.LogAuditRec(auditRec, nil) 416 } 417 } 418 return nil 419 } 420 421 func renameTeamCmdF(command *cobra.Command, args []string) error { 422 423 a, err := InitDBCommandContextCobra(command) 424 if err != nil { 425 return err 426 } 427 defer a.Srv().Shutdown() 428 429 team := getTeamFromTeamArg(a, args[0]) 430 if team == nil { 431 return errors.New("Unable to find team '" + args[0] + "'") 432 } 433 434 var newDisplayName, newTeamName string 435 436 newTeamName = args[1] 437 438 // let user use old team Name when only Display Name change is wanted 439 if newTeamName == team.Name { 440 newTeamName = "-" 441 } 442 443 newDisplayName, errdn := command.Flags().GetString("display_name") 444 if errdn != nil { 445 return errdn 446 } 447 448 updatedTeam, errrt := a.RenameTeam(team, newTeamName, newDisplayName) 449 if errrt != nil { 450 CommandPrintErrorln("Unable to rename team to '"+newTeamName+"' error: ", errrt) 451 } 452 453 auditRec := a.MakeAuditRecord("renameTeam", audit.Success) 454 auditRec.AddMeta("team", team) 455 auditRec.AddMeta("update", updatedTeam) 456 a.LogAuditRec(auditRec, nil) 457 458 return nil 459 } 460 461 func modifyTeamCmdF(command *cobra.Command, args []string) error { 462 a, err := InitDBCommandContextCobra(command) 463 if err != nil { 464 return err 465 } 466 defer a.Srv().Shutdown() 467 468 team := getTeamFromTeamArg(a, args[0]) 469 if team == nil { 470 return errors.New("Unable to find team '" + args[0] + "'") 471 } 472 473 public, _ := command.Flags().GetBool("public") 474 private, _ := command.Flags().GetBool("private") 475 476 if public == private { 477 return errors.New("You must specify only one of --public or --private") 478 } 479 480 if public { 481 team.Type = model.TEAM_OPEN 482 team.AllowOpenInvite = true 483 } else if private { 484 team.Type = model.TEAM_INVITE 485 team.AllowOpenInvite = false 486 } 487 488 if err := a.UpdateTeamPrivacy(team.Id, team.Type, team.AllowOpenInvite); err != nil { 489 return errors.New("Failed to update privacy for team" + args[0]) 490 } 491 492 auditRec := a.MakeAuditRecord("modifyTeam", audit.Success) 493 auditRec.AddMeta("team", team) 494 auditRec.AddMeta("type", team.Type) 495 auditRec.AddMeta("allow_open_invite", team.AllowOpenInvite) 496 a.LogAuditRec(auditRec, nil) 497 498 return nil 499 }