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