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