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  }