github.com/adacta-ru/mattermost-server/v6@v6.0.0/app/team.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"errors"
    10  	"fmt"
    11  	"image"
    12  	"image/png"
    13  	"io"
    14  	"mime/multipart"
    15  	"net/http"
    16  	"net/url"
    17  	"strings"
    18  
    19  	"github.com/disintegration/imaging"
    20  	"github.com/adacta-ru/mattermost-server/v6/mlog"
    21  	"github.com/adacta-ru/mattermost-server/v6/model"
    22  	"github.com/adacta-ru/mattermost-server/v6/plugin"
    23  	"github.com/adacta-ru/mattermost-server/v6/store"
    24  	"github.com/adacta-ru/mattermost-server/v6/utils"
    25  )
    26  
    27  func (a *App) CreateTeam(team *model.Team) (*model.Team, *model.AppError) {
    28  	team.InviteId = ""
    29  	rteam, err := a.Srv().Store.Team().Save(team)
    30  	if err != nil {
    31  		var invErr *store.ErrInvalidInput
    32  		var appErr *model.AppError
    33  		switch {
    34  		case errors.As(err, &invErr):
    35  			return nil, model.NewAppError("CreateTeam", "app.team.save.existing.app_error", nil, invErr.Error(), http.StatusBadRequest)
    36  		case errors.As(err, &appErr):
    37  			return nil, appErr
    38  		default:
    39  			return nil, model.NewAppError("CreateTeam", "app.team.save.app_error", nil, err.Error(), http.StatusInternalServerError)
    40  		}
    41  	}
    42  
    43  	if _, err := a.CreateDefaultChannels(rteam.Id); err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	return rteam, nil
    48  }
    49  
    50  func (a *App) CreateTeamWithUser(team *model.Team, userId string) (*model.Team, *model.AppError) {
    51  	user, err := a.GetUser(userId)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	team.Email = user.Email
    56  
    57  	if !a.isTeamEmailAllowed(user, team) {
    58  		return nil, model.NewAppError("isTeamEmailAllowed", "api.team.is_team_creation_allowed.domain.app_error", nil, "", http.StatusBadRequest)
    59  	}
    60  
    61  	rteam, err := a.CreateTeam(team)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	if err = a.JoinUserToTeam(rteam, user, ""); err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	return rteam, nil
    71  }
    72  
    73  func (a *App) normalizeDomains(domains string) []string {
    74  	// commas and @ signs are optional
    75  	// can be in the form of "@corp.mattermost.com, mattermost.com mattermost.org" -> corp.mattermost.com mattermost.com mattermost.org
    76  	return strings.Fields(strings.TrimSpace(strings.ToLower(strings.Replace(strings.Replace(domains, "@", " ", -1), ",", " ", -1))))
    77  }
    78  
    79  func (a *App) isEmailAddressAllowed(email string, allowedDomains []string) bool {
    80  	for _, restriction := range allowedDomains {
    81  		domains := a.normalizeDomains(restriction)
    82  		if len(domains) <= 0 {
    83  			continue
    84  		}
    85  		matched := false
    86  		for _, d := range domains {
    87  			if strings.HasSuffix(email, "@"+d) {
    88  				matched = true
    89  				break
    90  			}
    91  		}
    92  		if !matched {
    93  			return false
    94  		}
    95  	}
    96  
    97  	return true
    98  }
    99  
   100  func (a *App) isTeamEmailAllowed(user *model.User, team *model.Team) bool {
   101  	if user.IsBot {
   102  		return true
   103  	}
   104  	email := strings.ToLower(user.Email)
   105  	allowedDomains := a.getAllowedDomains(user, team)
   106  	return a.isEmailAddressAllowed(email, allowedDomains)
   107  }
   108  
   109  func (a *App) getAllowedDomains(user *model.User, team *model.Team) []string {
   110  	if user.IsGuest() {
   111  		return []string{*a.Config().GuestAccountsSettings.RestrictCreationToDomains}
   112  	}
   113  	// First check per team allowedDomains, then app wide restrictions
   114  	return []string{team.AllowedDomains, *a.Config().TeamSettings.RestrictCreationToDomains}
   115  }
   116  
   117  func (a *App) CheckValidDomains(team *model.Team) *model.AppError {
   118  	validDomains := a.normalizeDomains(*a.Config().TeamSettings.RestrictCreationToDomains)
   119  	if len(validDomains) > 0 {
   120  		for _, domain := range a.normalizeDomains(team.AllowedDomains) {
   121  			matched := false
   122  			for _, d := range validDomains {
   123  				if domain == d {
   124  					matched = true
   125  					break
   126  				}
   127  			}
   128  			if !matched {
   129  				err := model.NewAppError("UpdateTeam", "api.team.update_restricted_domains.mismatch.app_error", map[string]interface{}{"Domain": domain}, "", http.StatusBadRequest)
   130  				return err
   131  			}
   132  		}
   133  	}
   134  
   135  	return nil
   136  }
   137  
   138  func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
   139  	oldTeam, err := a.GetTeam(team.Id)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  
   144  	if err = a.CheckValidDomains(team); err != nil {
   145  		return nil, err
   146  	}
   147  
   148  	oldTeam.DisplayName = team.DisplayName
   149  	oldTeam.Description = team.Description
   150  	oldTeam.AllowOpenInvite = team.AllowOpenInvite
   151  	oldTeam.CompanyName = team.CompanyName
   152  	oldTeam.AllowedDomains = team.AllowedDomains
   153  	oldTeam.LastTeamIconUpdate = team.LastTeamIconUpdate
   154  	oldTeam.GroupConstrained = team.GroupConstrained
   155  
   156  	oldTeam, err = a.updateTeamUnsanitized(oldTeam)
   157  	if err != nil {
   158  		return team, err
   159  	}
   160  
   161  	a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   162  
   163  	return oldTeam, nil
   164  }
   165  
   166  func (a *App) updateTeamUnsanitized(team *model.Team) (*model.Team, *model.AppError) {
   167  	team, err := a.Srv().Store.Team().Update(team)
   168  	if err != nil {
   169  		var invErr *store.ErrInvalidInput
   170  		var appErr *model.AppError
   171  		switch {
   172  		case errors.As(err, &invErr):
   173  			return nil, model.NewAppError("updateTeamUnsanitized", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
   174  		case errors.As(err, &appErr):
   175  			return nil, appErr
   176  		default:
   177  			return nil, model.NewAppError("updateTeamUnsanitized", "app.team.update.updating.app_error", nil, err.Error(), http.StatusInternalServerError)
   178  		}
   179  	}
   180  
   181  	return team, nil
   182  }
   183  
   184  // RenameTeam is used to rename the team Name and the DisplayName fields
   185  func (a *App) RenameTeam(team *model.Team, newTeamName string, newDisplayName string) (*model.Team, *model.AppError) {
   186  
   187  	// check if name is occupied
   188  	_, errnf := a.GetTeamByName(newTeamName)
   189  
   190  	// "-" can be used as a newTeamName if only DisplayName change is wanted
   191  	if errnf == nil && newTeamName != "-" {
   192  		errbody := fmt.Sprintf("team with name %s already exists", newTeamName)
   193  		return nil, model.NewAppError("RenameTeam", "app.team.rename_team.name_occupied", nil, errbody, http.StatusBadRequest)
   194  	}
   195  
   196  	if newTeamName != "-" {
   197  		team.Name = newTeamName
   198  	}
   199  
   200  	if newDisplayName != "" {
   201  		team.DisplayName = newDisplayName
   202  	}
   203  
   204  	newTeam, err := a.updateTeamUnsanitized(team)
   205  	if err != nil {
   206  		return nil, err
   207  	}
   208  
   209  	return newTeam, nil
   210  }
   211  
   212  func (a *App) UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError) {
   213  	oldTeam, err := a.GetTeam(team.Id)
   214  	if err != nil {
   215  		return nil, err
   216  	}
   217  
   218  	oldTeam.SchemeId = team.SchemeId
   219  
   220  	oldTeam, nErr := a.Srv().Store.Team().Update(oldTeam)
   221  	if nErr != nil {
   222  		var invErr *store.ErrInvalidInput
   223  		var appErr *model.AppError
   224  		switch {
   225  		case errors.As(nErr, &invErr):
   226  			return nil, model.NewAppError("UpdateTeamScheme", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
   227  		case errors.As(nErr, &appErr):
   228  			return nil, appErr
   229  		default:
   230  			return nil, model.NewAppError("UpdateTeamScheme", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   231  		}
   232  	}
   233  
   234  	a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM_SCHEME)
   235  
   236  	return oldTeam, nil
   237  }
   238  
   239  func (a *App) UpdateTeamPrivacy(teamId string, teamType string, allowOpenInvite bool) *model.AppError {
   240  	oldTeam, err := a.GetTeam(teamId)
   241  	if err != nil {
   242  		return err
   243  	}
   244  
   245  	// Force a regeneration of the invite token if changing a team to restricted.
   246  	if (allowOpenInvite != oldTeam.AllowOpenInvite || teamType != oldTeam.Type) && (!allowOpenInvite || teamType == model.TEAM_INVITE) {
   247  		oldTeam.InviteId = model.NewId()
   248  	}
   249  
   250  	oldTeam.Type = teamType
   251  	oldTeam.AllowOpenInvite = allowOpenInvite
   252  
   253  	oldTeam, nErr := a.Srv().Store.Team().Update(oldTeam)
   254  	if nErr != nil {
   255  		var invErr *store.ErrInvalidInput
   256  		var appErr *model.AppError
   257  		switch {
   258  		case errors.As(nErr, &invErr):
   259  			return model.NewAppError("UpdateTeamPrivacy", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
   260  		case errors.As(nErr, &appErr):
   261  			return appErr
   262  		default:
   263  			return model.NewAppError("UpdateTeamPrivacy", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   264  		}
   265  	}
   266  
   267  	a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   268  
   269  	return nil
   270  }
   271  
   272  func (a *App) PatchTeam(teamId string, patch *model.TeamPatch) (*model.Team, *model.AppError) {
   273  	team, err := a.GetTeam(teamId)
   274  	if err != nil {
   275  		return nil, err
   276  	}
   277  
   278  	team.Patch(patch)
   279  	if patch.AllowOpenInvite != nil && !*patch.AllowOpenInvite {
   280  		team.InviteId = model.NewId()
   281  	}
   282  
   283  	if err = a.CheckValidDomains(team); err != nil {
   284  		return nil, err
   285  	}
   286  
   287  	team, err = a.updateTeamUnsanitized(team)
   288  	if err != nil {
   289  		return team, err
   290  	}
   291  
   292  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   293  
   294  	return team, nil
   295  }
   296  
   297  func (a *App) RegenerateTeamInviteId(teamId string) (*model.Team, *model.AppError) {
   298  	team, err := a.GetTeam(teamId)
   299  	if err != nil {
   300  		return nil, err
   301  	}
   302  
   303  	team.InviteId = model.NewId()
   304  
   305  	updatedTeam, nErr := a.Srv().Store.Team().Update(team)
   306  	if nErr != nil {
   307  		var invErr *store.ErrInvalidInput
   308  		var appErr *model.AppError
   309  		switch {
   310  		case errors.As(nErr, &invErr):
   311  			return nil, model.NewAppError("RegenerateTeamInviteId", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
   312  		case errors.As(nErr, &appErr):
   313  			return nil, appErr
   314  		default:
   315  			return nil, model.NewAppError("RegenerateTeamInviteId", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   316  		}
   317  	}
   318  
   319  	a.sendTeamEvent(updatedTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   320  
   321  	return updatedTeam, nil
   322  }
   323  
   324  func (a *App) sendTeamEvent(team *model.Team, event string) {
   325  	sanitizedTeam := &model.Team{}
   326  	*sanitizedTeam = *team
   327  	sanitizedTeam.Sanitize()
   328  
   329  	teamId := "" // no filtering by teamId by default
   330  	if event == model.WEBSOCKET_EVENT_UPDATE_TEAM {
   331  		// in case of update_team event - we send the message only to members of that team
   332  		teamId = team.Id
   333  	}
   334  	message := model.NewWebSocketEvent(event, teamId, "", "", nil)
   335  	message.Add("team", sanitizedTeam.ToJson())
   336  	a.Publish(message)
   337  }
   338  
   339  func (a *App) GetSchemeRolesForTeam(teamId string) (string, string, string, *model.AppError) {
   340  	team, err := a.GetTeam(teamId)
   341  	if err != nil {
   342  		return "", "", "", err
   343  	}
   344  
   345  	if team.SchemeId != nil && *team.SchemeId != "" {
   346  		scheme, err := a.GetScheme(*team.SchemeId)
   347  		if err != nil {
   348  			return "", "", "", err
   349  		}
   350  		return scheme.DefaultTeamGuestRole, scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole, nil
   351  	}
   352  
   353  	return model.TEAM_GUEST_ROLE_ID, model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID, nil
   354  }
   355  
   356  func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) {
   357  	member, nErr := a.Srv().Store.Team().GetMember(teamId, userId)
   358  	if nErr != nil {
   359  		var nfErr *store.ErrNotFound
   360  		switch {
   361  		case errors.As(nErr, &nfErr):
   362  			return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.get_member.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
   363  		default:
   364  			return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.get_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   365  		}
   366  	}
   367  
   368  	if member == nil {
   369  		return nil, model.NewAppError("UpdateTeamMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userId+" teamId="+teamId, http.StatusBadRequest)
   370  	}
   371  
   372  	schemeGuestRole, schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForTeam(teamId)
   373  	if err != nil {
   374  		return nil, err
   375  	}
   376  
   377  	prevSchemeGuestValue := member.SchemeGuest
   378  
   379  	var newExplicitRoles []string
   380  	member.SchemeGuest = false
   381  	member.SchemeUser = false
   382  	member.SchemeAdmin = false
   383  
   384  	for _, roleName := range strings.Fields(newRoles) {
   385  		var role *model.Role
   386  		role, err = a.GetRoleByName(roleName)
   387  		if err != nil {
   388  			err.StatusCode = http.StatusBadRequest
   389  			return nil, err
   390  		}
   391  		if !role.SchemeManaged {
   392  			// The role is not scheme-managed, so it's OK to apply it to the explicit roles field.
   393  			newExplicitRoles = append(newExplicitRoles, roleName)
   394  		} else {
   395  			// The role is scheme-managed, so need to check if it is part of the scheme for this channel or not.
   396  			switch roleName {
   397  			case schemeAdminRole:
   398  				member.SchemeAdmin = true
   399  			case schemeUserRole:
   400  				member.SchemeUser = true
   401  			case schemeGuestRole:
   402  				member.SchemeGuest = true
   403  			default:
   404  				// If not part of the scheme for this team, then it is not allowed to apply it as an explicit role.
   405  				return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest)
   406  			}
   407  		}
   408  	}
   409  
   410  	if member.SchemeGuest && member.SchemeUser {
   411  		return nil, model.NewAppError("UpdateTeamMemberRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest)
   412  	}
   413  
   414  	if prevSchemeGuestValue != member.SchemeGuest {
   415  		return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.changing_guest_role.app_error", nil, "", http.StatusBadRequest)
   416  	}
   417  
   418  	member.ExplicitRoles = strings.Join(newExplicitRoles, " ")
   419  
   420  	member, nErr = a.Srv().Store.Team().UpdateMember(member)
   421  	if nErr != nil {
   422  		var appErr *model.AppError
   423  		switch {
   424  		case errors.As(nErr, &appErr):
   425  			return nil, appErr
   426  		default:
   427  			return nil, model.NewAppError("UpdateTeamMemberRoles", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   428  		}
   429  	}
   430  
   431  	a.ClearSessionCacheForUser(userId)
   432  
   433  	a.sendUpdatedMemberRoleEvent(userId, member)
   434  
   435  	return member, nil
   436  }
   437  
   438  func (a *App) UpdateTeamMemberSchemeRoles(teamId string, userId string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.TeamMember, *model.AppError) {
   439  	member, err := a.GetTeamMember(teamId, userId)
   440  	if err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	member.SchemeAdmin = isSchemeAdmin
   445  	member.SchemeUser = isSchemeUser
   446  	member.SchemeGuest = isSchemeGuest
   447  
   448  	if member.SchemeUser && member.SchemeGuest {
   449  		return nil, model.NewAppError("UpdateTeamMemberSchemeRoles", "api.team.update_team_member_roles.guest_and_user.app_error", nil, "", http.StatusBadRequest)
   450  	}
   451  
   452  	// If the migration is not completed, we also need to check the default team_admin/team_user roles are not present in the roles field.
   453  	if err = a.IsPhase2MigrationCompleted(); err != nil {
   454  		member.ExplicitRoles = RemoveRoles([]string{model.TEAM_GUEST_ROLE_ID, model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID}, member.ExplicitRoles)
   455  	}
   456  
   457  	member, nErr := a.Srv().Store.Team().UpdateMember(member)
   458  	if nErr != nil {
   459  		var appErr *model.AppError
   460  		switch {
   461  		case errors.As(nErr, &appErr):
   462  			return nil, appErr
   463  		default:
   464  			return nil, model.NewAppError("UpdateTeamMemberSchemeRoles", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   465  		}
   466  	}
   467  
   468  	a.ClearSessionCacheForUser(userId)
   469  
   470  	a.sendUpdatedMemberRoleEvent(userId, member)
   471  
   472  	return member, nil
   473  }
   474  
   475  func (a *App) sendUpdatedMemberRoleEvent(userId string, member *model.TeamMember) {
   476  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", userId, nil)
   477  	message.Add("member", member.ToJson())
   478  	a.Publish(message)
   479  }
   480  
   481  func (a *App) AddUserToTeam(teamId string, userId string, userRequestorId string) (*model.Team, *model.AppError) {
   482  	tchan := make(chan store.StoreResult, 1)
   483  	go func() {
   484  		team, err := a.Srv().Store.Team().Get(teamId)
   485  		tchan <- store.StoreResult{Data: team, NErr: err}
   486  		close(tchan)
   487  	}()
   488  
   489  	uchan := make(chan store.StoreResult, 1)
   490  	go func() {
   491  		user, err := a.Srv().Store.User().Get(userId)
   492  		uchan <- store.StoreResult{Data: user, NErr: err}
   493  		close(uchan)
   494  	}()
   495  
   496  	result := <-tchan
   497  	if result.NErr != nil {
   498  		var nfErr *store.ErrNotFound
   499  		switch {
   500  		case errors.As(result.NErr, &nfErr):
   501  			return nil, model.NewAppError("AddUserToTeam", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
   502  		default:
   503  			return nil, model.NewAppError("AddUserToTeam", "app.team.get.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
   504  		}
   505  	}
   506  	team := result.Data.(*model.Team)
   507  
   508  	result = <-uchan
   509  	if result.NErr != nil {
   510  		var nfErr *store.ErrNotFound
   511  		switch {
   512  		case errors.As(result.NErr, &nfErr):
   513  			return nil, model.NewAppError("AddUserToTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound)
   514  		default:
   515  			return nil, model.NewAppError("AddUserToTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
   516  		}
   517  	}
   518  	user := result.Data.(*model.User)
   519  
   520  	if err := a.JoinUserToTeam(team, user, userRequestorId); err != nil {
   521  		return nil, err
   522  	}
   523  
   524  	return team, nil
   525  }
   526  
   527  func (a *App) AddUserToTeamByTeamId(teamId string, user *model.User) *model.AppError {
   528  	team, err := a.Srv().Store.Team().Get(teamId)
   529  	if err != nil {
   530  		var nfErr *store.ErrNotFound
   531  		switch {
   532  		case errors.As(err, &nfErr):
   533  			return model.NewAppError("AddUserToTeamByTeamId", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
   534  		default:
   535  			return model.NewAppError("AddUserToTeamByTeamId", "app.team.get.finding.app_error", nil, err.Error(), http.StatusInternalServerError)
   536  		}
   537  	}
   538  
   539  	return a.JoinUserToTeam(team, user, "")
   540  }
   541  
   542  func (a *App) AddUserToTeamByToken(userId string, tokenId string) (*model.Team, *model.AppError) {
   543  	token, err := a.Srv().Store.Token().GetByToken(tokenId)
   544  	if err != nil {
   545  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, err.Error(), http.StatusBadRequest)
   546  	}
   547  
   548  	if token.Type != TOKEN_TYPE_TEAM_INVITATION && token.Type != TOKEN_TYPE_GUEST_INVITATION {
   549  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest)
   550  	}
   551  
   552  	if model.GetMillis()-token.CreateAt >= INVITATION_EXPIRY_TIME {
   553  		a.DeleteToken(token)
   554  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest)
   555  	}
   556  
   557  	tokenData := model.MapFromJson(strings.NewReader(token.Extra))
   558  
   559  	tchan := make(chan store.StoreResult, 1)
   560  	go func() {
   561  		team, err := a.Srv().Store.Team().Get(tokenData["teamId"])
   562  		tchan <- store.StoreResult{Data: team, NErr: err}
   563  		close(tchan)
   564  	}()
   565  
   566  	uchan := make(chan store.StoreResult, 1)
   567  	go func() {
   568  		user, err := a.Srv().Store.User().Get(userId)
   569  		uchan <- store.StoreResult{Data: user, NErr: err}
   570  		close(uchan)
   571  	}()
   572  
   573  	result := <-tchan
   574  	if result.NErr != nil {
   575  		var nfErr *store.ErrNotFound
   576  		switch {
   577  		case errors.As(result.NErr, &nfErr):
   578  			return nil, model.NewAppError("AddUserToTeamByToken", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
   579  		default:
   580  			return nil, model.NewAppError("AddUserToTeamByToken", "app.team.get.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
   581  		}
   582  	}
   583  	team := result.Data.(*model.Team)
   584  
   585  	if team.IsGroupConstrained() {
   586  		return nil, model.NewAppError("AddUserToTeamByToken", "app.team.invite_token.group_constrained.error", nil, "", http.StatusForbidden)
   587  	}
   588  
   589  	result = <-uchan
   590  	if result.NErr != nil {
   591  		var nfErr *store.ErrNotFound
   592  		switch {
   593  		case errors.As(result.NErr, &nfErr):
   594  			return nil, model.NewAppError("AddUserToTeamByToken", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound)
   595  		default:
   596  			return nil, model.NewAppError("AddUserToTeamByToken", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
   597  		}
   598  	}
   599  	user := result.Data.(*model.User)
   600  
   601  	if user.IsGuest() && token.Type == TOKEN_TYPE_TEAM_INVITATION {
   602  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.invalid_invitation_type.app_error", nil, "", http.StatusBadRequest)
   603  	}
   604  	if !user.IsGuest() && token.Type == TOKEN_TYPE_GUEST_INVITATION {
   605  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.invalid_invitation_type.app_error", nil, "", http.StatusBadRequest)
   606  	}
   607  
   608  	if err := a.JoinUserToTeam(team, user, ""); err != nil {
   609  		return nil, err
   610  	}
   611  
   612  	if token.Type == TOKEN_TYPE_GUEST_INVITATION {
   613  		channels, err := a.Srv().Store.Channel().GetChannelsByIds(strings.Split(tokenData["channels"], " "), false)
   614  		if err != nil {
   615  			return nil, model.NewAppError("AddUserToTeamByToken", "app.channel.get_channels_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError)
   616  		}
   617  
   618  		for _, channel := range channels {
   619  			_, err := a.AddUserToChannel(user, channel)
   620  			if err != nil {
   621  				mlog.Error("error adding user to channel", mlog.Err(err))
   622  			}
   623  		}
   624  	}
   625  
   626  	if err := a.DeleteToken(token); err != nil {
   627  		return nil, err
   628  	}
   629  
   630  	return team, nil
   631  }
   632  
   633  func (a *App) AddUserToTeamByInviteId(inviteId string, userId string) (*model.Team, *model.AppError) {
   634  	tchan := make(chan store.StoreResult, 1)
   635  	go func() {
   636  		team, err := a.Srv().Store.Team().GetByInviteId(inviteId)
   637  		tchan <- store.StoreResult{Data: team, NErr: err}
   638  		close(tchan)
   639  	}()
   640  
   641  	uchan := make(chan store.StoreResult, 1)
   642  	go func() {
   643  		user, err := a.Srv().Store.User().Get(userId)
   644  		uchan <- store.StoreResult{Data: user, NErr: err}
   645  		close(uchan)
   646  	}()
   647  
   648  	result := <-tchan
   649  	if result.NErr != nil {
   650  		var nfErr *store.ErrNotFound
   651  		switch {
   652  		case errors.As(result.NErr, &nfErr):
   653  			return nil, model.NewAppError("AddUserToTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
   654  		default:
   655  			return nil, model.NewAppError("AddUserToTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
   656  		}
   657  	}
   658  	team := result.Data.(*model.Team)
   659  
   660  	result = <-uchan
   661  	if result.NErr != nil {
   662  		var nfErr *store.ErrNotFound
   663  		switch {
   664  		case errors.As(result.NErr, &nfErr):
   665  			return nil, model.NewAppError("AddUserToTeamByInviteId", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound)
   666  		default:
   667  			return nil, model.NewAppError("AddUserToTeamByInviteId", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
   668  		}
   669  	}
   670  	user := result.Data.(*model.User)
   671  
   672  	if err := a.JoinUserToTeam(team, user, ""); err != nil {
   673  		return nil, err
   674  	}
   675  
   676  	return team, nil
   677  }
   678  
   679  // Returns three values:
   680  // 1. a pointer to the team member, if successful
   681  // 2. a boolean: true if the user has a non-deleted team member for that team already, otherwise false.
   682  // 3. a pointer to an AppError if something went wrong.
   683  func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMember, bool, *model.AppError) {
   684  	tm := &model.TeamMember{
   685  		TeamId:      team.Id,
   686  		UserId:      user.Id,
   687  		SchemeGuest: user.IsGuest(),
   688  		SchemeUser:  !user.IsGuest(),
   689  	}
   690  
   691  	if !user.IsGuest() {
   692  		userShouldBeAdmin, err := a.UserIsInAdminRoleGroup(user.Id, team.Id, model.GroupSyncableTypeTeam)
   693  		if err != nil {
   694  			return nil, false, err
   695  		}
   696  		tm.SchemeAdmin = userShouldBeAdmin
   697  	}
   698  
   699  	if team.Email == user.Email {
   700  		tm.SchemeAdmin = true
   701  	}
   702  
   703  	rtm, err := a.Srv().Store.Team().GetMember(team.Id, user.Id)
   704  	if err != nil {
   705  		// Membership appears to be missing. Lets try to add.
   706  		tmr, nErr := a.Srv().Store.Team().SaveMember(tm, *a.Config().TeamSettings.MaxUsersPerTeam)
   707  		if nErr != nil {
   708  			var appErr *model.AppError
   709  			var conflictErr *store.ErrConflict
   710  			var limitExeededErr *store.ErrLimitExceeded
   711  			switch {
   712  			case errors.As(nErr, &appErr): // in case we haven't converted to plain error.
   713  				return nil, false, appErr
   714  			case errors.As(nErr, &conflictErr):
   715  				return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.conflict.app_error", nil, nErr.Error(), http.StatusBadRequest)
   716  			case errors.As(nErr, &limitExeededErr):
   717  				return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.max_accounts.app_error", nil, nErr.Error(), http.StatusBadRequest)
   718  			default: // last fallback in case it doesn't map to an existing app error.
   719  				return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.save_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   720  			}
   721  		}
   722  		return tmr, false, nil
   723  	}
   724  
   725  	// Membership already exists.  Check if deleted and update, otherwise do nothing
   726  	// Do nothing if already added
   727  	if rtm.DeleteAt == 0 {
   728  		return rtm, true, nil
   729  	}
   730  
   731  	membersCount, err := a.Srv().Store.Team().GetActiveMemberCount(tm.TeamId, nil)
   732  	if err != nil {
   733  		return nil, false, model.NewAppError("joinUserToTeam", "app.team.get_active_member_count.app_error", nil, err.Error(), http.StatusInternalServerError)
   734  	}
   735  
   736  	if membersCount >= int64(*a.Config().TeamSettings.MaxUsersPerTeam) {
   737  		return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.max_accounts.app_error", nil, "teamId="+tm.TeamId, http.StatusBadRequest)
   738  	}
   739  
   740  	member, nErr := a.Srv().Store.Team().UpdateMember(tm)
   741  	if nErr != nil {
   742  		var appErr *model.AppError
   743  		switch {
   744  		case errors.As(nErr, &appErr):
   745  			return nil, false, appErr
   746  		default:
   747  			return nil, false, model.NewAppError("joinUserToTeam", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
   748  		}
   749  	}
   750  
   751  	return member, false, nil
   752  }
   753  
   754  func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId string) *model.AppError {
   755  	if !a.isTeamEmailAllowed(user, team) {
   756  		return model.NewAppError("JoinUserToTeam", "api.team.join_user_to_team.allowed_domains.app_error", nil, "", http.StatusBadRequest)
   757  	}
   758  	tm, alreadyAdded, err := a.joinUserToTeam(team, user)
   759  	if err != nil {
   760  		return err
   761  	}
   762  	if alreadyAdded {
   763  		return nil
   764  	}
   765  
   766  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
   767  		var actor *model.User
   768  		if userRequestorId != "" {
   769  			actor, _ = a.GetUser(userRequestorId)
   770  		}
   771  
   772  		a.Srv().Go(func() {
   773  			pluginContext := a.PluginContext()
   774  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
   775  				hooks.UserHasJoinedTeam(pluginContext, tm, actor)
   776  				return true
   777  			}, plugin.UserHasJoinedTeamId)
   778  		})
   779  	}
   780  
   781  	if _, err := a.Srv().Store.User().UpdateUpdateAt(user.Id); err != nil {
   782  		return model.NewAppError("JoinUserToTeam", "app.user.update_update.app_error", nil, err.Error(), http.StatusInternalServerError)
   783  	}
   784  
   785  	if err := a.createInitialSidebarCategories(user.Id, team.Id); err != nil {
   786  		mlog.Error(
   787  			"Encountered an issue creating default sidebar categories.",
   788  			mlog.String("user_id", user.Id),
   789  			mlog.String("team_id", team.Id),
   790  			mlog.Err(err),
   791  		)
   792  	}
   793  
   794  	shouldBeAdmin := team.Email == user.Email
   795  
   796  	if !user.IsGuest() {
   797  		// Soft error if there is an issue joining the default channels
   798  		if err := a.JoinDefaultChannels(team.Id, user, shouldBeAdmin, userRequestorId); err != nil {
   799  			mlog.Error(
   800  				"Encountered an issue joining default channels.",
   801  				mlog.String("user_id", user.Id),
   802  				mlog.String("team_id", team.Id),
   803  				mlog.Err(err),
   804  			)
   805  		}
   806  	}
   807  
   808  	a.ClearSessionCacheForUser(user.Id)
   809  	a.InvalidateCacheForUser(user.Id)
   810  	a.invalidateCacheForUserTeams(user.Id)
   811  
   812  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil)
   813  	message.Add("team_id", team.Id)
   814  	message.Add("user_id", user.Id)
   815  	a.Publish(message)
   816  
   817  	return nil
   818  }
   819  
   820  func (a *App) GetTeam(teamId string) (*model.Team, *model.AppError) {
   821  	team, err := a.Srv().Store.Team().Get(teamId)
   822  	if err != nil {
   823  		var nfErr *store.ErrNotFound
   824  		switch {
   825  		case errors.As(err, &nfErr):
   826  			return nil, model.NewAppError("GetTeam", "app.team.get.find.app_error", nil, nfErr.Error(), http.StatusNotFound)
   827  		default:
   828  			return nil, model.NewAppError("GetTeam", "app.team.get.finding.app_error", nil, err.Error(), http.StatusInternalServerError)
   829  		}
   830  	}
   831  
   832  	return team, nil
   833  }
   834  
   835  func (a *App) GetTeamByName(name string) (*model.Team, *model.AppError) {
   836  	team, err := a.Srv().Store.Team().GetByName(name)
   837  	if err != nil {
   838  		var nfErr *store.ErrNotFound
   839  		switch {
   840  		case errors.As(err, &nfErr):
   841  			return nil, model.NewAppError("GetTeamByName", "app.team.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
   842  		default:
   843  			return nil, model.NewAppError("GetTeamByName", "app.team.get_by_name.app_error", nil, err.Error(), http.StatusNotFound)
   844  		}
   845  	}
   846  
   847  	return team, nil
   848  }
   849  
   850  func (a *App) GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) {
   851  	team, err := a.Srv().Store.Team().GetByInviteId(inviteId)
   852  	if err != nil {
   853  		var nfErr *store.ErrNotFound
   854  		switch {
   855  		case errors.As(err, &nfErr):
   856  			return nil, model.NewAppError("GetTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
   857  		default:
   858  			return nil, model.NewAppError("GetTeamByInviteId", "app.team.get_by_invite_id.finding.app_error", nil, err.Error(), http.StatusInternalServerError)
   859  		}
   860  	}
   861  
   862  	return team, nil
   863  }
   864  
   865  func (a *App) GetAllTeams() ([]*model.Team, *model.AppError) {
   866  	teams, err := a.Srv().Store.Team().GetAll()
   867  	if err != nil {
   868  		return nil, model.NewAppError("GetAllTeams", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   869  	}
   870  
   871  	return teams, nil
   872  }
   873  
   874  func (a *App) GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   875  	teams, err := a.Srv().Store.Team().GetAllPage(offset, limit)
   876  	if err != nil {
   877  		return nil, model.NewAppError("GetAllTeamsPage", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   878  	}
   879  
   880  	return teams, nil
   881  }
   882  
   883  func (a *App) GetAllTeamsPageWithCount(offset int, limit int) (*model.TeamsWithCount, *model.AppError) {
   884  	totalCount, err := a.Srv().Store.Team().AnalyticsTeamCount(true)
   885  	if err != nil {
   886  		return nil, model.NewAppError("GetAllTeamsPageWithCount", "app.team.analytics_team_count.app_error", nil, err.Error(), http.StatusInternalServerError)
   887  	}
   888  	teams, err := a.Srv().Store.Team().GetAllPage(offset, limit)
   889  	if err != nil {
   890  		return nil, model.NewAppError("GetAllTeamsPageWithCount", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   891  	}
   892  	return &model.TeamsWithCount{Teams: teams, TotalCount: totalCount}, nil
   893  }
   894  
   895  func (a *App) GetAllPrivateTeams() ([]*model.Team, *model.AppError) {
   896  	teams, err := a.Srv().Store.Team().GetAllPrivateTeamListing()
   897  	if err != nil {
   898  		return nil, model.NewAppError("GetAllPrivateTeams", "app.team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   899  	}
   900  
   901  	return teams, nil
   902  }
   903  
   904  func (a *App) GetAllPrivateTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   905  	teams, err := a.Srv().Store.Team().GetAllPrivateTeamPageListing(offset, limit)
   906  	if err != nil {
   907  		return nil, model.NewAppError("GetAllPrivateTeamsPage", "app.team.get_all_private_team_page_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   908  	}
   909  
   910  	return teams, nil
   911  }
   912  
   913  func (a *App) GetAllPrivateTeamsPageWithCount(offset int, limit int) (*model.TeamsWithCount, *model.AppError) {
   914  	totalCount, err := a.Srv().Store.Team().AnalyticsPrivateTeamCount()
   915  	if err != nil {
   916  		return nil, model.NewAppError("GetAllPrivateTeamsPageWithCount", "app.team.analytics_private_team_count.app_error", nil, err.Error(), http.StatusInternalServerError)
   917  	}
   918  	teams, err := a.Srv().Store.Team().GetAllPrivateTeamPageListing(offset, limit)
   919  	if err != nil {
   920  		return nil, model.NewAppError("GetAllPrivateTeamsPageWithCount", "app.team.get_all_private_team_page_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   921  	}
   922  	return &model.TeamsWithCount{Teams: teams, TotalCount: totalCount}, nil
   923  }
   924  
   925  func (a *App) GetAllPublicTeams() ([]*model.Team, *model.AppError) {
   926  	teams, err := a.Srv().Store.Team().GetAllTeamListing()
   927  	if err != nil {
   928  		return nil, model.NewAppError("GetAllPublicTeams", "app.team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   929  	}
   930  
   931  	return teams, nil
   932  }
   933  
   934  func (a *App) GetAllPublicTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   935  	teams, err := a.Srv().Store.Team().GetAllTeamPageListing(offset, limit)
   936  	if err != nil {
   937  		return nil, model.NewAppError("GetAllPublicTeamsPage", "app.team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   938  	}
   939  
   940  	return teams, nil
   941  }
   942  
   943  func (a *App) GetAllPublicTeamsPageWithCount(offset int, limit int) (*model.TeamsWithCount, *model.AppError) {
   944  	totalCount, err := a.Srv().Store.Team().AnalyticsPublicTeamCount()
   945  	if err != nil {
   946  		return nil, model.NewAppError("GetAllPublicTeamsPageWithCount", "app.team.analytics_public_team_count.app_error", nil, err.Error(), http.StatusInternalServerError)
   947  	}
   948  	teams, err := a.Srv().Store.Team().GetAllPublicTeamPageListing(offset, limit)
   949  	if err != nil {
   950  		return nil, model.NewAppError("GetAllPublicTeamsPageWithCount", "app.team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   951  	}
   952  	return &model.TeamsWithCount{Teams: teams, TotalCount: totalCount}, nil
   953  }
   954  
   955  // SearchAllTeams returns a team list and the total count of the results
   956  func (a *App) SearchAllTeams(searchOpts *model.TeamSearch) ([]*model.Team, int64, *model.AppError) {
   957  	if searchOpts.IsPaginated() {
   958  		teams, count, err := a.Srv().Store.Team().SearchAllPaged(searchOpts.Term, searchOpts)
   959  		if err != nil {
   960  			return nil, 0, model.NewAppError("SearchAllTeams", "app.team.search_all_team.app_error", nil, err.Error(), http.StatusInternalServerError)
   961  		}
   962  
   963  		return teams, count, nil
   964  	}
   965  	results, err := a.Srv().Store.Team().SearchAll(searchOpts.Term, searchOpts)
   966  	if err != nil {
   967  		return nil, 0, model.NewAppError("SearchAllTeams", "app.team.search_all_team.app_error", nil, err.Error(), http.StatusInternalServerError)
   968  	}
   969  	return results, int64(len(results)), nil
   970  }
   971  
   972  func (a *App) SearchPublicTeams(term string) ([]*model.Team, *model.AppError) {
   973  	teams, err := a.Srv().Store.Team().SearchOpen(term)
   974  	if err != nil {
   975  		return nil, model.NewAppError("SearchPublicTeams", "app.team.search_open_team.app_error", nil, err.Error(), http.StatusInternalServerError)
   976  	}
   977  
   978  	return teams, nil
   979  }
   980  
   981  func (a *App) SearchPrivateTeams(term string) ([]*model.Team, *model.AppError) {
   982  	teams, err := a.Srv().Store.Team().SearchPrivate(term)
   983  	if err != nil {
   984  		return nil, model.NewAppError("SearchPrivateTeams", "app.team.search_private_team.app_error", nil, err.Error(), http.StatusInternalServerError)
   985  	}
   986  
   987  	return teams, nil
   988  }
   989  
   990  func (a *App) GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) {
   991  	teams, err := a.Srv().Store.Team().GetTeamsByUserId(userId)
   992  	if err != nil {
   993  		return nil, model.NewAppError("GetTeamsForUser", "app.team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   994  	}
   995  
   996  	return teams, nil
   997  }
   998  
   999  func (a *App) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
  1000  	teamMember, err := a.Srv().Store.Team().GetMember(teamId, userId)
  1001  	if err != nil {
  1002  		var nfErr *store.ErrNotFound
  1003  		switch {
  1004  		case errors.As(err, &nfErr):
  1005  			return nil, model.NewAppError("GetTeamMember", "app.team.get_member.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1006  		default:
  1007  			return nil, model.NewAppError("GetTeamMember", "app.team.get_member.app_error", nil, err.Error(), http.StatusInternalServerError)
  1008  		}
  1009  	}
  1010  
  1011  	return teamMember, nil
  1012  }
  1013  
  1014  func (a *App) GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError) {
  1015  	teamMembers, err := a.Srv().Store.Team().GetTeamsForUser(context.Background(), userId)
  1016  	if err != nil {
  1017  		return nil, model.NewAppError("GetTeamMembersForUser", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  1018  	}
  1019  
  1020  	return teamMembers, nil
  1021  }
  1022  
  1023  func (a *App) GetTeamMembersForUserWithPagination(userId string, page, perPage int) ([]*model.TeamMember, *model.AppError) {
  1024  	teamMembers, err := a.Srv().Store.Team().GetTeamsForUserWithPagination(userId, page, perPage)
  1025  	if err != nil {
  1026  		return nil, model.NewAppError("GetTeamMembersForUserWithPagination", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  1027  	}
  1028  
  1029  	return teamMembers, nil
  1030  }
  1031  
  1032  func (a *App) GetTeamMembers(teamId string, offset int, limit int, teamMembersGetOptions *model.TeamMembersGetOptions) ([]*model.TeamMember, *model.AppError) {
  1033  	teamMembers, err := a.Srv().Store.Team().GetMembers(teamId, offset, limit, teamMembersGetOptions)
  1034  	if err != nil {
  1035  		return nil, model.NewAppError("GetTeamMembers", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError)
  1036  	}
  1037  
  1038  	return teamMembers, nil
  1039  }
  1040  
  1041  func (a *App) GetTeamMembersByIds(teamId string, userIds []string, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, *model.AppError) {
  1042  	teamMembers, err := a.Srv().Store.Team().GetMembersByIds(teamId, userIds, restrictions)
  1043  	if err != nil {
  1044  		return nil, model.NewAppError("GetTeamMembersByIds", "app.team.get_members_by_ids.app_error", nil, err.Error(), http.StatusInternalServerError)
  1045  	}
  1046  
  1047  	return teamMembers, nil
  1048  }
  1049  
  1050  func (a *App) AddTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
  1051  	if _, err := a.AddUserToTeam(teamId, userId, ""); err != nil {
  1052  		return nil, err
  1053  	}
  1054  
  1055  	teamMember, err := a.GetTeamMember(teamId, userId)
  1056  	if err != nil {
  1057  		return nil, err
  1058  	}
  1059  
  1060  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
  1061  	message.Add("team_id", teamId)
  1062  	message.Add("user_id", userId)
  1063  	a.Publish(message)
  1064  
  1065  	return teamMember, nil
  1066  }
  1067  
  1068  func (a *App) AddTeamMembers(teamId string, userIds []string, userRequestorId string, graceful bool) ([]*model.TeamMemberWithError, *model.AppError) {
  1069  	var membersWithErrors []*model.TeamMemberWithError
  1070  
  1071  	for _, userId := range userIds {
  1072  		if _, err := a.AddUserToTeam(teamId, userId, userRequestorId); err != nil {
  1073  			if graceful {
  1074  				membersWithErrors = append(membersWithErrors, &model.TeamMemberWithError{
  1075  					UserId: userId,
  1076  					Error:  err,
  1077  				})
  1078  				continue
  1079  			}
  1080  			return nil, err
  1081  		}
  1082  
  1083  		teamMember, err := a.GetTeamMember(teamId, userId)
  1084  		if err != nil {
  1085  			return nil, err
  1086  		}
  1087  		membersWithErrors = append(membersWithErrors, &model.TeamMemberWithError{
  1088  			UserId: userId,
  1089  			Member: teamMember,
  1090  		})
  1091  
  1092  		message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
  1093  		message.Add("team_id", teamId)
  1094  		message.Add("user_id", userId)
  1095  		a.Publish(message)
  1096  	}
  1097  
  1098  	return membersWithErrors, nil
  1099  }
  1100  
  1101  func (a *App) AddTeamMemberByToken(userId, tokenId string) (*model.TeamMember, *model.AppError) {
  1102  	team, err := a.AddUserToTeamByToken(userId, tokenId)
  1103  	if err != nil {
  1104  		return nil, err
  1105  	}
  1106  
  1107  	teamMember, err := a.GetTeamMember(team.Id, userId)
  1108  	if err != nil {
  1109  		return nil, err
  1110  	}
  1111  
  1112  	return teamMember, nil
  1113  }
  1114  
  1115  func (a *App) AddTeamMemberByInviteId(inviteId, userId string) (*model.TeamMember, *model.AppError) {
  1116  	team, err := a.AddUserToTeamByInviteId(inviteId, userId)
  1117  	if err != nil {
  1118  		return nil, err
  1119  	}
  1120  
  1121  	if team.IsGroupConstrained() {
  1122  		return nil, model.NewAppError("AddTeamMemberByInviteId", "app.team.invite_id.group_constrained.error", nil, "", http.StatusForbidden)
  1123  	}
  1124  
  1125  	teamMember, err := a.GetTeamMember(team.Id, userId)
  1126  	if err != nil {
  1127  		return nil, err
  1128  	}
  1129  	return teamMember, nil
  1130  }
  1131  
  1132  func (a *App) GetTeamUnread(teamId, userId string) (*model.TeamUnread, *model.AppError) {
  1133  	channelUnreads, err := a.Srv().Store.Team().GetChannelUnreadsForTeam(teamId, userId)
  1134  	if err != nil {
  1135  		return nil, model.NewAppError("GetTeamUnread", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
  1136  	}
  1137  
  1138  	var teamUnread = &model.TeamUnread{
  1139  		MsgCount:     0,
  1140  		MentionCount: 0,
  1141  		TeamId:       teamId,
  1142  	}
  1143  
  1144  	for _, cu := range channelUnreads {
  1145  		teamUnread.MentionCount += cu.MentionCount
  1146  
  1147  		if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
  1148  			teamUnread.MsgCount += cu.MsgCount
  1149  		}
  1150  	}
  1151  
  1152  	return teamUnread, nil
  1153  }
  1154  
  1155  func (a *App) RemoveUserFromTeam(teamId string, userId string, requestorId string) *model.AppError {
  1156  	tchan := make(chan store.StoreResult, 1)
  1157  	go func() {
  1158  		team, err := a.Srv().Store.Team().Get(teamId)
  1159  		tchan <- store.StoreResult{Data: team, NErr: err}
  1160  		close(tchan)
  1161  	}()
  1162  
  1163  	uchan := make(chan store.StoreResult, 1)
  1164  	go func() {
  1165  		user, err := a.Srv().Store.User().Get(userId)
  1166  		uchan <- store.StoreResult{Data: user, NErr: err}
  1167  		close(uchan)
  1168  	}()
  1169  
  1170  	result := <-tchan
  1171  	if result.NErr != nil {
  1172  		var nfErr *store.ErrNotFound
  1173  		switch {
  1174  		case errors.As(result.NErr, &nfErr):
  1175  			return model.NewAppError("RemoveUserFromTeam", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1176  		default:
  1177  			return model.NewAppError("RemoveUserFromTeam", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1178  		}
  1179  	}
  1180  	team := result.Data.(*model.Team)
  1181  
  1182  	result = <-uchan
  1183  	if result.NErr != nil {
  1184  		var nfErr *store.ErrNotFound
  1185  		switch {
  1186  		case errors.As(result.NErr, &nfErr):
  1187  			return model.NewAppError("RemoveUserFromTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound)
  1188  		default:
  1189  			return model.NewAppError("RemoveUserFromTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1190  		}
  1191  	}
  1192  	user := result.Data.(*model.User)
  1193  
  1194  	if err := a.LeaveTeam(team, user, requestorId); err != nil {
  1195  		return err
  1196  	}
  1197  
  1198  	return nil
  1199  }
  1200  
  1201  func (a *App) RemoveTeamMemberFromTeam(teamMember *model.TeamMember, requestorId string) *model.AppError {
  1202  	// Send the websocket message before we actually do the remove so the user being removed gets it.
  1203  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, teamMember.TeamId, "", "", nil)
  1204  	message.Add("user_id", teamMember.UserId)
  1205  	message.Add("team_id", teamMember.TeamId)
  1206  	a.Publish(message)
  1207  
  1208  	user, nErr := a.Srv().Store.User().Get(teamMember.UserId)
  1209  	if nErr != nil {
  1210  		var nfErr *store.ErrNotFound
  1211  		switch {
  1212  		case errors.As(nErr, &nfErr):
  1213  			return model.NewAppError("RemoveTeamMemberFromTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound)
  1214  		default:
  1215  			return model.NewAppError("RemoveTeamMemberFromTeam", "app.user.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1216  		}
  1217  	}
  1218  
  1219  	teamMember.Roles = ""
  1220  	teamMember.DeleteAt = model.GetMillis()
  1221  
  1222  	if _, nErr := a.Srv().Store.Team().UpdateMember(teamMember); nErr != nil {
  1223  		var appErr *model.AppError
  1224  		switch {
  1225  		case errors.As(nErr, &appErr):
  1226  			return appErr
  1227  		default:
  1228  			return model.NewAppError("RemoveTeamMemberFromTeam", "app.team.save_member.save.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1229  		}
  1230  	}
  1231  
  1232  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
  1233  		var actor *model.User
  1234  		if requestorId != "" {
  1235  			actor, _ = a.GetUser(requestorId)
  1236  		}
  1237  
  1238  		a.Srv().Go(func() {
  1239  			pluginContext := a.PluginContext()
  1240  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
  1241  				hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
  1242  				return true
  1243  			}, plugin.UserHasLeftTeamId)
  1244  		})
  1245  	}
  1246  
  1247  	if _, err := a.Srv().Store.User().UpdateUpdateAt(user.Id); err != nil {
  1248  		return model.NewAppError("RemoveTeamMemberFromTeam", "app.user.update_update.app_error", nil, err.Error(), http.StatusInternalServerError)
  1249  	}
  1250  
  1251  	if err := a.Srv().Store.Channel().ClearSidebarOnTeamLeave(user.Id, teamMember.TeamId); err != nil {
  1252  		return model.NewAppError("RemoveTeamMemberFromTeam", "app.channel.sidebar_categories.app_error", nil, err.Error(), http.StatusInternalServerError)
  1253  	}
  1254  
  1255  	// delete the preferences that set the last channel used in the team and other team specific preferences
  1256  	if err := a.Srv().Store.Preference().DeleteCategory(user.Id, teamMember.TeamId); err != nil {
  1257  		return model.NewAppError("RemoveTeamMemberFromTeam", "app.preference.delete.app_error", nil, err.Error(), http.StatusInternalServerError)
  1258  	}
  1259  
  1260  	a.ClearSessionCacheForUser(user.Id)
  1261  	a.InvalidateCacheForUser(user.Id)
  1262  	a.invalidateCacheForUserTeams(user.Id)
  1263  
  1264  	return nil
  1265  }
  1266  
  1267  func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string) *model.AppError {
  1268  	teamMember, err := a.GetTeamMember(team.Id, user.Id)
  1269  	if err != nil {
  1270  		return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest)
  1271  	}
  1272  
  1273  	var channelList *model.ChannelList
  1274  
  1275  	var nErr error
  1276  	if channelList, nErr = a.Srv().Store.Channel().GetChannels(team.Id, user.Id, true, 0); nErr != nil {
  1277  		var nfErr *store.ErrNotFound
  1278  		if errors.As(nErr, &nfErr) {
  1279  			channelList = &model.ChannelList{}
  1280  		} else {
  1281  			return model.NewAppError("LeaveTeam", "app.channel.get_channels.get.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1282  		}
  1283  	}
  1284  
  1285  	for _, channel := range *channelList {
  1286  		if !channel.IsGroupOrDirect() {
  1287  			a.invalidateCacheForChannelMembers(channel.Id)
  1288  			if nErr = a.Srv().Store.Channel().RemoveMember(channel.Id, user.Id); nErr != nil {
  1289  				return model.NewAppError("LeaveTeam", "app.channel.remove_member.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1290  			}
  1291  		}
  1292  	}
  1293  
  1294  	channel, nErr := a.Srv().Store.Channel().GetByName(team.Id, model.DEFAULT_CHANNEL, false)
  1295  	if nErr != nil {
  1296  		var nfErr *store.ErrNotFound
  1297  		switch {
  1298  		case errors.As(nErr, &nfErr):
  1299  			return model.NewAppError("LeaveTeam", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1300  		default:
  1301  			return model.NewAppError("LeaveTeam", "app.channel.get_by_name.existing.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1302  		}
  1303  	}
  1304  
  1305  	if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
  1306  		if requestorId == user.Id {
  1307  			if err = a.postLeaveTeamMessage(user, channel); err != nil {
  1308  				mlog.Error("Failed to post join/leave message", mlog.Err(err))
  1309  			}
  1310  		} else {
  1311  			if err = a.postRemoveFromTeamMessage(user, channel); err != nil {
  1312  				mlog.Error("Failed to post join/leave message", mlog.Err(err))
  1313  			}
  1314  		}
  1315  	}
  1316  
  1317  	if err := a.RemoveTeamMemberFromTeam(teamMember, requestorId); err != nil {
  1318  		return err
  1319  	}
  1320  
  1321  	return nil
  1322  }
  1323  
  1324  func (a *App) postLeaveTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
  1325  	post := &model.Post{
  1326  		ChannelId: channel.Id,
  1327  		Message:   fmt.Sprintf(utils.T("api.team.leave.left"), user.Username),
  1328  		Type:      model.POST_LEAVE_TEAM,
  1329  		UserId:    user.Id,
  1330  		Props: model.StringInterface{
  1331  			"username": user.Username,
  1332  		},
  1333  	}
  1334  
  1335  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  1336  		return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  1337  	}
  1338  
  1339  	return nil
  1340  }
  1341  
  1342  func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
  1343  	post := &model.Post{
  1344  		ChannelId: channel.Id,
  1345  		Message:   fmt.Sprintf(utils.T("api.team.remove_user_from_team.removed"), user.Username),
  1346  		Type:      model.POST_REMOVE_FROM_TEAM,
  1347  		UserId:    user.Id,
  1348  		Props: model.StringInterface{
  1349  			"username": user.Username,
  1350  		},
  1351  	}
  1352  
  1353  	if _, err := a.CreatePost(post, channel, false, true); err != nil {
  1354  		return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
  1355  	}
  1356  
  1357  	return nil
  1358  }
  1359  
  1360  func (a *App) prepareInviteNewUsersToTeam(teamId, senderId string) (*model.User, *model.Team, *model.AppError) {
  1361  	tchan := make(chan store.StoreResult, 1)
  1362  	go func() {
  1363  		team, err := a.Srv().Store.Team().Get(teamId)
  1364  		tchan <- store.StoreResult{Data: team, NErr: err}
  1365  		close(tchan)
  1366  	}()
  1367  
  1368  	uchan := make(chan store.StoreResult, 1)
  1369  	go func() {
  1370  		user, err := a.Srv().Store.User().Get(senderId)
  1371  		uchan <- store.StoreResult{Data: user, NErr: err}
  1372  		close(uchan)
  1373  	}()
  1374  
  1375  	result := <-tchan
  1376  	if result.NErr != nil {
  1377  		var nfErr *store.ErrNotFound
  1378  		switch {
  1379  		case errors.As(result.NErr, &nfErr):
  1380  			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1381  		default:
  1382  			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1383  		}
  1384  	}
  1385  	team := result.Data.(*model.Team)
  1386  
  1387  	result = <-uchan
  1388  	if result.NErr != nil {
  1389  		var nfErr *store.ErrNotFound
  1390  		switch {
  1391  		case errors.As(result.NErr, &nfErr):
  1392  			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound)
  1393  		default:
  1394  			return nil, nil, model.NewAppError("prepareInviteNewUsersToTeam", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1395  		}
  1396  	}
  1397  	user := result.Data.(*model.User)
  1398  	return user, team, nil
  1399  }
  1400  
  1401  func genEmailInviteWithErrorList(emailList []string) []*model.EmailInviteWithError {
  1402  	invitesNotSent := make([]*model.EmailInviteWithError, len(emailList))
  1403  	for i := range emailList {
  1404  		invite := &model.EmailInviteWithError{
  1405  			Email: emailList[i],
  1406  			Error: model.NewAppError("inviteUsersToTeam", "api.team.invite_members.limit_reached.app_error", map[string]interface{}{"Addresses": emailList[i]}, "", http.StatusBadRequest),
  1407  		}
  1408  		invitesNotSent[i] = invite
  1409  	}
  1410  	return invitesNotSent
  1411  }
  1412  
  1413  func (a *App) GetErrorListForEmailsOverLimit(emailList []string, cloudUserLimit int64) ([]string, []*model.EmailInviteWithError, *model.AppError) {
  1414  	var invitesNotSent []*model.EmailInviteWithError
  1415  	if cloudUserLimit <= 0 {
  1416  		return emailList, invitesNotSent, nil
  1417  	}
  1418  	systemUserCount, _ := a.Srv().Store.User().Count(model.UserCountOptions{})
  1419  	remainingUsers := cloudUserLimit - systemUserCount
  1420  	if remainingUsers <= 0 {
  1421  		// No remaining users so all fail
  1422  		invitesNotSent = genEmailInviteWithErrorList(emailList)
  1423  		emailList = nil
  1424  	} else if remainingUsers < int64(len(emailList)) {
  1425  		// Trim the email list to only invite as many users as are remaining in subscription
  1426  		// Set graceful errors for the remaining email addresses
  1427  		emailsAboveLimit := emailList[remainingUsers:]
  1428  		invitesNotSent = genEmailInviteWithErrorList(emailsAboveLimit)
  1429  		// If 1 user remaining we have to prevent 0:0 reslicing
  1430  		if remainingUsers == 1 {
  1431  			email := emailList[0]
  1432  			emailList = nil
  1433  			emailList = append(emailList, email)
  1434  		} else {
  1435  			emailList = emailList[:(remainingUsers - 1)]
  1436  		}
  1437  	}
  1438  
  1439  	return emailList, invitesNotSent, nil
  1440  }
  1441  
  1442  func (a *App) InviteNewUsersToTeamGracefully(emailList []string, teamId, senderId string) ([]*model.EmailInviteWithError, *model.AppError) {
  1443  	if !*a.Config().ServiceSettings.EnableEmailInvitations {
  1444  		return nil, model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
  1445  	}
  1446  
  1447  	if len(emailList) == 0 {
  1448  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
  1449  		return nil, err
  1450  	}
  1451  	user, team, err := a.prepareInviteNewUsersToTeam(teamId, senderId)
  1452  	if err != nil {
  1453  		return nil, err
  1454  	}
  1455  	allowedDomains := a.getAllowedDomains(user, team)
  1456  	var inviteListWithErrors []*model.EmailInviteWithError
  1457  	var goodEmails []string
  1458  	for _, email := range emailList {
  1459  		invite := &model.EmailInviteWithError{
  1460  			Email: email,
  1461  			Error: nil,
  1462  		}
  1463  		if !a.isEmailAddressAllowed(email, allowedDomains) {
  1464  			invite.Error = model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": email}, "", http.StatusBadRequest)
  1465  		} else {
  1466  			goodEmails = append(goodEmails, email)
  1467  		}
  1468  		inviteListWithErrors = append(inviteListWithErrors, invite)
  1469  	}
  1470  
  1471  	if len(goodEmails) > 0 {
  1472  		nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
  1473  		err = a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, goodEmails, a.GetSiteURL())
  1474  		if err != nil {
  1475  			return nil, err
  1476  		}
  1477  	}
  1478  
  1479  	return inviteListWithErrors, nil
  1480  }
  1481  
  1482  func (a *App) prepareInviteGuestsToChannels(teamId string, guestsInvite *model.GuestsInvite, senderId string) (*model.User, *model.Team, []*model.Channel, *model.AppError) {
  1483  	if err := guestsInvite.IsValid(); err != nil {
  1484  		return nil, nil, nil, err
  1485  	}
  1486  
  1487  	tchan := make(chan store.StoreResult, 1)
  1488  	go func() {
  1489  		team, err := a.Srv().Store.Team().Get(teamId)
  1490  		tchan <- store.StoreResult{Data: team, NErr: err}
  1491  		close(tchan)
  1492  	}()
  1493  	cchan := make(chan store.StoreResult, 1)
  1494  	go func() {
  1495  		channels, err := a.Srv().Store.Channel().GetChannelsByIds(guestsInvite.Channels, false)
  1496  		cchan <- store.StoreResult{Data: channels, NErr: err}
  1497  		close(cchan)
  1498  	}()
  1499  	uchan := make(chan store.StoreResult, 1)
  1500  	go func() {
  1501  		user, err := a.Srv().Store.User().Get(senderId)
  1502  		uchan <- store.StoreResult{Data: user, NErr: err}
  1503  		close(uchan)
  1504  	}()
  1505  
  1506  	result := <-cchan
  1507  	if result.NErr != nil {
  1508  		return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.channel.get_channels_by_ids.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1509  	}
  1510  	channels := result.Data.([]*model.Channel)
  1511  
  1512  	result = <-uchan
  1513  	if result.NErr != nil {
  1514  		var nfErr *store.ErrNotFound
  1515  		switch {
  1516  		case errors.As(result.NErr, &nfErr):
  1517  			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", MISSING_ACCOUNT_ERROR, nil, nfErr.Error(), http.StatusNotFound)
  1518  		default:
  1519  			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.user.get.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1520  		}
  1521  	}
  1522  	user := result.Data.(*model.User)
  1523  
  1524  	result = <-tchan
  1525  	if result.NErr != nil {
  1526  		var nfErr *store.ErrNotFound
  1527  		switch {
  1528  		case errors.As(result.NErr, &nfErr):
  1529  			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.team.get_by_invite_id.finding.app_error", nil, nfErr.Error(), http.StatusNotFound)
  1530  		default:
  1531  			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "app.team.get_by_invite_id.finding.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1532  		}
  1533  	}
  1534  	team := result.Data.(*model.Team)
  1535  
  1536  	for _, channel := range channels {
  1537  		if channel.TeamId != teamId {
  1538  			return nil, nil, nil, model.NewAppError("prepareInviteGuestsToChannels", "api.team.invite_guests.channel_in_invalid_team.app_error", nil, "", http.StatusBadRequest)
  1539  		}
  1540  	}
  1541  	return user, team, channels, nil
  1542  }
  1543  
  1544  func (a *App) InviteGuestsToChannelsGracefully(teamId string, guestsInvite *model.GuestsInvite, senderId string) ([]*model.EmailInviteWithError, *model.AppError) {
  1545  	if !*a.Config().ServiceSettings.EnableEmailInvitations {
  1546  		return nil, model.NewAppError("InviteGuestsToChannelsGracefully", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
  1547  	}
  1548  
  1549  	user, team, channels, err := a.prepareInviteGuestsToChannels(teamId, guestsInvite, senderId)
  1550  	if err != nil {
  1551  		return nil, err
  1552  	}
  1553  
  1554  	var inviteListWithErrors []*model.EmailInviteWithError
  1555  	var goodEmails []string
  1556  	for _, email := range guestsInvite.Emails {
  1557  		invite := &model.EmailInviteWithError{
  1558  			Email: email,
  1559  			Error: nil,
  1560  		}
  1561  		if !CheckEmailDomain(email, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) {
  1562  			invite.Error = model.NewAppError("InviteGuestsToChannelsGracefully", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": email}, "", http.StatusBadRequest)
  1563  		} else {
  1564  			goodEmails = append(goodEmails, email)
  1565  		}
  1566  		inviteListWithErrors = append(inviteListWithErrors, invite)
  1567  	}
  1568  
  1569  	if len(goodEmails) > 0 {
  1570  		nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
  1571  		senderProfileImage, _, err := a.GetProfileImage(user)
  1572  		if err != nil {
  1573  			a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
  1574  		}
  1575  		err = a.Srv().EmailService.sendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, goodEmails, a.GetSiteURL(), guestsInvite.Message)
  1576  		if err != nil {
  1577  			return nil, err
  1578  		}
  1579  	}
  1580  
  1581  	return inviteListWithErrors, nil
  1582  }
  1583  
  1584  func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string) *model.AppError {
  1585  	if !*a.Config().ServiceSettings.EnableEmailInvitations {
  1586  		return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
  1587  	}
  1588  
  1589  	if len(emailList) == 0 {
  1590  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
  1591  		return err
  1592  	}
  1593  
  1594  	user, team, err := a.prepareInviteNewUsersToTeam(teamId, senderId)
  1595  	if err != nil {
  1596  		return err
  1597  	}
  1598  
  1599  	allowedDomains := a.getAllowedDomains(user, team)
  1600  	var invalidEmailList []string
  1601  
  1602  	for _, email := range emailList {
  1603  		if !a.isEmailAddressAllowed(email, allowedDomains) {
  1604  			invalidEmailList = append(invalidEmailList, email)
  1605  		}
  1606  	}
  1607  
  1608  	if len(invalidEmailList) > 0 {
  1609  		s := strings.Join(invalidEmailList, ", ")
  1610  		return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest)
  1611  	}
  1612  
  1613  	nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
  1614  	err = a.Srv().EmailService.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, emailList, a.GetSiteURL())
  1615  	if err != nil {
  1616  		return err
  1617  	}
  1618  
  1619  	return nil
  1620  }
  1621  
  1622  func (a *App) InviteGuestsToChannels(teamId string, guestsInvite *model.GuestsInvite, senderId string) *model.AppError {
  1623  	if !*a.Config().ServiceSettings.EnableEmailInvitations {
  1624  		return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
  1625  	}
  1626  
  1627  	user, team, channels, err := a.prepareInviteGuestsToChannels(teamId, guestsInvite, senderId)
  1628  	if err != nil {
  1629  		return err
  1630  	}
  1631  
  1632  	var invalidEmailList []string
  1633  	for _, email := range guestsInvite.Emails {
  1634  		if !CheckEmailDomain(email, *a.Config().GuestAccountsSettings.RestrictCreationToDomains) {
  1635  			invalidEmailList = append(invalidEmailList, email)
  1636  		}
  1637  	}
  1638  
  1639  	if len(invalidEmailList) > 0 {
  1640  		s := strings.Join(invalidEmailList, ", ")
  1641  		return model.NewAppError("InviteGuestsToChannels", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest)
  1642  	}
  1643  
  1644  	nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
  1645  	senderProfileImage, _, err := a.GetProfileImage(user)
  1646  	if err != nil {
  1647  		a.Log().Warn("Unable to get the sender user profile image.", mlog.String("user_id", user.Id), mlog.String("team_id", team.Id), mlog.Err(err))
  1648  	}
  1649  	err = a.Srv().EmailService.sendGuestInviteEmails(team, channels, user.GetDisplayName(nameFormat), user.Id, senderProfileImage, guestsInvite.Emails, a.GetSiteURL(), guestsInvite.Message)
  1650  	if err != nil {
  1651  		return err
  1652  	}
  1653  
  1654  	return nil
  1655  }
  1656  
  1657  func (a *App) FindTeamByName(name string) bool {
  1658  	if _, err := a.Srv().Store.Team().GetByName(name); err != nil {
  1659  		return false
  1660  	}
  1661  	return true
  1662  }
  1663  
  1664  func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError) {
  1665  	data, err := a.Srv().Store.Team().GetChannelUnreadsForAllTeams(excludeTeamId, userId)
  1666  	if err != nil {
  1667  		return nil, model.NewAppError("GetTeamsUnreadForUser", "app.team.get_unread.app_error", nil, err.Error(), http.StatusInternalServerError)
  1668  	}
  1669  
  1670  	members := []*model.TeamUnread{}
  1671  	membersMap := make(map[string]*model.TeamUnread)
  1672  
  1673  	unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
  1674  		tu.MentionCount += cu.MentionCount
  1675  
  1676  		if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
  1677  			tu.MsgCount += cu.MsgCount
  1678  		}
  1679  
  1680  		return tu
  1681  	}
  1682  
  1683  	for i := range data {
  1684  		id := data[i].TeamId
  1685  		if mu, ok := membersMap[id]; ok {
  1686  			membersMap[id] = unreads(data[i], mu)
  1687  		} else {
  1688  			membersMap[id] = unreads(data[i], &model.TeamUnread{
  1689  				MsgCount:     0,
  1690  				MentionCount: 0,
  1691  				TeamId:       id,
  1692  			})
  1693  		}
  1694  	}
  1695  
  1696  	for _, val := range membersMap {
  1697  		members = append(members, val)
  1698  	}
  1699  
  1700  	return members, nil
  1701  }
  1702  
  1703  func (a *App) PermanentDeleteTeamId(teamId string) *model.AppError {
  1704  	team, err := a.GetTeam(teamId)
  1705  	if err != nil {
  1706  		return err
  1707  	}
  1708  
  1709  	return a.PermanentDeleteTeam(team)
  1710  }
  1711  
  1712  func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError {
  1713  	team.DeleteAt = model.GetMillis()
  1714  	if _, err := a.Srv().Store.Team().Update(team); err != nil {
  1715  		var invErr *store.ErrInvalidInput
  1716  		var appErr *model.AppError
  1717  		switch {
  1718  		case errors.As(err, &invErr):
  1719  			return model.NewAppError("PermanentDeleteTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
  1720  		case errors.As(err, &appErr):
  1721  			return appErr
  1722  		default:
  1723  			return model.NewAppError("PermanentDeleteTeam", "app.team.update.updating.app_error", nil, err.Error(), http.StatusInternalServerError)
  1724  		}
  1725  	}
  1726  
  1727  	if channels, err := a.Srv().Store.Channel().GetTeamChannels(team.Id); err != nil {
  1728  		var nfErr *store.ErrNotFound
  1729  		if !errors.As(err, &nfErr) {
  1730  			return model.NewAppError("PermanentDeleteTeam", "app.channel.get_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1731  		}
  1732  	} else {
  1733  		for _, c := range *channels {
  1734  			a.PermanentDeleteChannel(c)
  1735  		}
  1736  	}
  1737  
  1738  	if err := a.Srv().Store.Team().RemoveAllMembersByTeam(team.Id); err != nil {
  1739  		return model.NewAppError("PermanentDeleteTeam", "app.team.remove_member.app_error", nil, err.Error(), http.StatusInternalServerError)
  1740  	}
  1741  
  1742  	if err := a.Srv().Store.Command().PermanentDeleteByTeam(team.Id); err != nil {
  1743  		return model.NewAppError("PermanentDeleteTeam", "app.team.permanentdeleteteam.internal_error", nil, err.Error(), http.StatusInternalServerError)
  1744  	}
  1745  
  1746  	if err := a.Srv().Store.Team().PermanentDelete(team.Id); err != nil {
  1747  		return model.NewAppError("PermanentDeleteTeam", "app.team.permanent_delete.app_error", nil, err.Error(), http.StatusInternalServerError)
  1748  	}
  1749  
  1750  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
  1751  
  1752  	return nil
  1753  }
  1754  
  1755  func (a *App) SoftDeleteTeam(teamId string) *model.AppError {
  1756  	team, err := a.GetTeam(teamId)
  1757  	if err != nil {
  1758  		return err
  1759  	}
  1760  
  1761  	team.DeleteAt = model.GetMillis()
  1762  	team, nErr := a.Srv().Store.Team().Update(team)
  1763  	if nErr != nil {
  1764  		var invErr *store.ErrInvalidInput
  1765  		var appErr *model.AppError
  1766  		switch {
  1767  		case errors.As(nErr, &invErr):
  1768  			return model.NewAppError("SoftDeleteTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
  1769  		case errors.As(nErr, &appErr):
  1770  			return appErr
  1771  		default:
  1772  			return model.NewAppError("SoftDeleteTeam", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1773  		}
  1774  	}
  1775  
  1776  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
  1777  
  1778  	return nil
  1779  }
  1780  
  1781  func (a *App) RestoreTeam(teamId string) *model.AppError {
  1782  	team, err := a.GetTeam(teamId)
  1783  	if err != nil {
  1784  		return err
  1785  	}
  1786  
  1787  	team.DeleteAt = 0
  1788  	team, nErr := a.Srv().Store.Team().Update(team)
  1789  	if nErr != nil {
  1790  		var invErr *store.ErrInvalidInput
  1791  		var appErr *model.AppError
  1792  		switch {
  1793  		case errors.As(nErr, &invErr):
  1794  			return model.NewAppError("RestoreTeam", "app.team.update.find.app_error", nil, invErr.Error(), http.StatusBadRequest)
  1795  		case errors.As(nErr, &appErr):
  1796  			return appErr
  1797  		default:
  1798  			return model.NewAppError("RestoreTeam", "app.team.update.updating.app_error", nil, nErr.Error(), http.StatusInternalServerError)
  1799  		}
  1800  	}
  1801  
  1802  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_RESTORE_TEAM)
  1803  	return nil
  1804  }
  1805  
  1806  func (a *App) GetTeamStats(teamId string, restrictions *model.ViewUsersRestrictions) (*model.TeamStats, *model.AppError) {
  1807  	tchan := make(chan store.StoreResult, 1)
  1808  	go func() {
  1809  		totalMemberCount, err := a.Srv().Store.Team().GetTotalMemberCount(teamId, restrictions)
  1810  		tchan <- store.StoreResult{Data: totalMemberCount, NErr: err}
  1811  		close(tchan)
  1812  	}()
  1813  	achan := make(chan store.StoreResult, 1)
  1814  	go func() {
  1815  		memberCount, err := a.Srv().Store.Team().GetActiveMemberCount(teamId, restrictions)
  1816  		achan <- store.StoreResult{Data: memberCount, NErr: err}
  1817  		close(achan)
  1818  	}()
  1819  
  1820  	stats := &model.TeamStats{}
  1821  	stats.TeamId = teamId
  1822  
  1823  	result := <-tchan
  1824  	if result.NErr != nil {
  1825  		return nil, model.NewAppError("GetTeamStats", "app.team.get_member_count.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1826  	}
  1827  	stats.TotalMemberCount = result.Data.(int64)
  1828  
  1829  	result = <-achan
  1830  	if result.NErr != nil {
  1831  		return nil, model.NewAppError("GetTeamStats", "app.team.get_active_member_count.app_error", nil, result.NErr.Error(), http.StatusInternalServerError)
  1832  	}
  1833  	stats.ActiveMemberCount = result.Data.(int64)
  1834  
  1835  	return stats, nil
  1836  }
  1837  
  1838  func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
  1839  	tokenId := query.Get("t")
  1840  	inviteId := query.Get("id")
  1841  
  1842  	if len(tokenId) > 0 {
  1843  		token, err := a.Srv().Store.Token().GetByToken(tokenId)
  1844  		if err != nil {
  1845  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
  1846  		}
  1847  
  1848  		if token.Type != TOKEN_TYPE_TEAM_INVITATION && token.Type != TOKEN_TYPE_GUEST_INVITATION {
  1849  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
  1850  		}
  1851  
  1852  		if model.GetMillis()-token.CreateAt >= INVITATION_EXPIRY_TIME {
  1853  			a.DeleteToken(token)
  1854  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest)
  1855  		}
  1856  
  1857  		tokenData := model.MapFromJson(strings.NewReader(token.Extra))
  1858  
  1859  		return tokenData["teamId"], nil
  1860  	}
  1861  	if len(inviteId) > 0 {
  1862  		team, err := a.Srv().Store.Team().GetByInviteId(inviteId)
  1863  		if err == nil {
  1864  			return team.Id, nil
  1865  		}
  1866  		// soft fail, so we still create user but don't auto-join team
  1867  		mlog.Error("error getting team by inviteId.", mlog.String("invite_id", inviteId), mlog.Err(err))
  1868  	}
  1869  
  1870  	return "", nil
  1871  }
  1872  
  1873  func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
  1874  	if a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_MANAGE_TEAM) {
  1875  		return team
  1876  	}
  1877  
  1878  	if a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_INVITE_USER) {
  1879  		inviteId := team.InviteId
  1880  		team.Sanitize()
  1881  		team.InviteId = inviteId
  1882  		return team
  1883  	}
  1884  
  1885  	team.Sanitize()
  1886  
  1887  	return team
  1888  }
  1889  
  1890  func (a *App) SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team {
  1891  	for _, team := range teams {
  1892  		a.SanitizeTeam(session, team)
  1893  	}
  1894  
  1895  	return teams
  1896  }
  1897  
  1898  func (a *App) GetTeamIcon(team *model.Team) ([]byte, *model.AppError) {
  1899  	if len(*a.Config().FileSettings.DriverName) == 0 {
  1900  		return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.filesettings_no_driver.app_error", nil, "", http.StatusNotImplemented)
  1901  	}
  1902  
  1903  	path := "teams/" + team.Id + "/teamIcon.png"
  1904  	data, err := a.ReadFile(path)
  1905  	if err != nil {
  1906  		return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.read_file.app_error", nil, err.Error(), http.StatusNotFound)
  1907  	}
  1908  
  1909  	return data, nil
  1910  }
  1911  
  1912  func (a *App) SetTeamIcon(teamId string, imageData *multipart.FileHeader) *model.AppError {
  1913  	file, err := imageData.Open()
  1914  	if err != nil {
  1915  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.open.app_error", nil, err.Error(), http.StatusBadRequest)
  1916  	}
  1917  	defer file.Close()
  1918  	return a.SetTeamIconFromMultiPartFile(teamId, file)
  1919  }
  1920  
  1921  func (a *App) SetTeamIconFromMultiPartFile(teamId string, file multipart.File) *model.AppError {
  1922  	team, getTeamErr := a.GetTeam(teamId)
  1923  
  1924  	if getTeamErr != nil {
  1925  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.get_team.app_error", nil, getTeamErr.Error(), http.StatusBadRequest)
  1926  	}
  1927  
  1928  	if len(*a.Config().FileSettings.DriverName) == 0 {
  1929  		return model.NewAppError("setTeamIcon", "api.team.set_team_icon.storage.app_error", nil, "", http.StatusNotImplemented)
  1930  	}
  1931  
  1932  	// Decode image config first to check dimensions before loading the whole thing into memory later on
  1933  	config, _, err := image.DecodeConfig(file)
  1934  	if err != nil {
  1935  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode_config.app_error", nil, err.Error(), http.StatusBadRequest)
  1936  	}
  1937  
  1938  	// This casting is done to prevent overflow on 32 bit systems (not needed
  1939  	// in 64 bits systems because images can't have more than 32 bits height or
  1940  	// width)
  1941  	if int64(config.Width)*int64(config.Height) > model.MaxImageSize {
  1942  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.too_large.app_error", nil, "", http.StatusBadRequest)
  1943  	}
  1944  
  1945  	file.Seek(0, 0)
  1946  
  1947  	return a.SetTeamIconFromFile(team, file)
  1948  }
  1949  
  1950  func (a *App) SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppError {
  1951  	// Decode image into Image object
  1952  	img, _, err := image.Decode(file)
  1953  	if err != nil {
  1954  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode.app_error", nil, err.Error(), http.StatusBadRequest)
  1955  	}
  1956  
  1957  	orientation, _ := getImageOrientation(file)
  1958  	img = makeImageUpright(img, orientation)
  1959  
  1960  	// Scale team icon
  1961  	teamIconWidthAndHeight := 128
  1962  	img = imaging.Fill(img, teamIconWidthAndHeight, teamIconWidthAndHeight, imaging.Center, imaging.Lanczos)
  1963  
  1964  	buf := new(bytes.Buffer)
  1965  	err = png.Encode(buf, img)
  1966  	if err != nil {
  1967  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.encode.app_error", nil, err.Error(), http.StatusInternalServerError)
  1968  	}
  1969  
  1970  	path := "teams/" + team.Id + "/teamIcon.png"
  1971  
  1972  	if _, err := a.WriteFile(buf, path); err != nil {
  1973  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.write_file.app_error", nil, "", http.StatusInternalServerError)
  1974  	}
  1975  
  1976  	curTime := model.GetMillis()
  1977  
  1978  	if err := a.Srv().Store.Team().UpdateLastTeamIconUpdate(team.Id, curTime); err != nil {
  1979  		return model.NewAppError("SetTeamIcon", "api.team.team_icon.update.app_error", nil, err.Error(), http.StatusBadRequest)
  1980  	}
  1981  
  1982  	// manually set time to avoid possible cluster inconsistencies
  1983  	team.LastTeamIconUpdate = curTime
  1984  
  1985  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM)
  1986  
  1987  	return nil
  1988  }
  1989  
  1990  func (a *App) RemoveTeamIcon(teamId string) *model.AppError {
  1991  	team, err := a.GetTeam(teamId)
  1992  	if err != nil {
  1993  		return model.NewAppError("RemoveTeamIcon", "api.team.remove_team_icon.get_team.app_error", nil, err.Error(), http.StatusBadRequest)
  1994  	}
  1995  
  1996  	if err := a.Srv().Store.Team().UpdateLastTeamIconUpdate(teamId, 0); err != nil {
  1997  		return model.NewAppError("RemoveTeamIcon", "api.team.team_icon.update.app_error", nil, err.Error(), http.StatusBadRequest)
  1998  	}
  1999  
  2000  	team.LastTeamIconUpdate = 0
  2001  
  2002  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM)
  2003  
  2004  	return nil
  2005  }
  2006  
  2007  func (a *App) InvalidateAllEmailInvites() *model.AppError {
  2008  	if err := a.Srv().Store.Token().RemoveAllTokensByType(TOKEN_TYPE_TEAM_INVITATION); err != nil {
  2009  		return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, err.Error(), http.StatusBadRequest)
  2010  	}
  2011  	if err := a.Srv().Store.Token().RemoveAllTokensByType(TOKEN_TYPE_GUEST_INVITATION); err != nil {
  2012  		return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, err.Error(), http.StatusBadRequest)
  2013  	}
  2014  	return nil
  2015  }
  2016  
  2017  func (a *App) ClearTeamMembersCache(teamID string) {
  2018  	perPage := 100
  2019  	page := 0
  2020  
  2021  	for {
  2022  		teamMembers, err := a.Srv().Store.Team().GetMembers(teamID, page*perPage, perPage, nil)
  2023  		if err != nil {
  2024  			a.Log().Warn("error clearing cache for team members", mlog.String("team_id", teamID), mlog.String("err", err.Error()))
  2025  			break
  2026  		}
  2027  
  2028  		for _, teamMember := range teamMembers {
  2029  			a.ClearSessionCacheForUser(teamMember.UserId)
  2030  
  2031  			message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", teamMember.UserId, nil)
  2032  			message.Add("member", teamMember.ToJson())
  2033  			a.Publish(message)
  2034  		}
  2035  
  2036  		length := len(teamMembers)
  2037  		if length < perPage {
  2038  			break
  2039  		}
  2040  
  2041  		page++
  2042  	}
  2043  }