github.com/nhannv/mattermost-server@v5.11.1+incompatible/app/team.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"image"
    10  	"image/png"
    11  	"io"
    12  	"mime/multipart"
    13  	"net/http"
    14  	"net/url"
    15  	"strings"
    16  
    17  	"github.com/disintegration/imaging"
    18  	"github.com/mattermost/mattermost-server/mlog"
    19  	"github.com/mattermost/mattermost-server/model"
    20  	"github.com/mattermost/mattermost-server/plugin"
    21  	"github.com/mattermost/mattermost-server/utils"
    22  )
    23  
    24  func (a *App) CreateTeam(team *model.Team) (*model.Team, *model.AppError) {
    25  	team.InviteId = ""
    26  	result := <-a.Srv.Store.Team().Save(team)
    27  	if result.Err != nil {
    28  		return nil, result.Err
    29  	}
    30  	rteam := result.Data.(*model.Team)
    31  
    32  	if _, err := a.CreateDefaultChannels(rteam.Id); err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	return rteam, nil
    37  }
    38  
    39  func (a *App) CreateTeamWithUser(team *model.Team, userId string) (*model.Team, *model.AppError) {
    40  	user, err := a.GetUser(userId)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  	team.Email = user.Email
    45  
    46  	if !a.isTeamEmailAllowed(user, team) {
    47  		return nil, model.NewAppError("isTeamEmailAllowed", "api.team.is_team_creation_allowed.domain.app_error", nil, "", http.StatusBadRequest)
    48  	}
    49  
    50  	rteam, err := a.CreateTeam(team)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	if err = a.JoinUserToTeam(rteam, user, ""); err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	return rteam, nil
    60  }
    61  
    62  func (a *App) normalizeDomains(domains string) []string {
    63  	// commas and @ signs are optional
    64  	// can be in the form of "@corp.mattermost.com, mattermost.com mattermost.org" -> corp.mattermost.com mattermost.com mattermost.org
    65  	return strings.Fields(strings.TrimSpace(strings.ToLower(strings.Replace(strings.Replace(domains, "@", " ", -1), ",", " ", -1))))
    66  }
    67  
    68  func (a *App) isTeamEmailAddressAllowed(email string, allowedDomains string) bool {
    69  	email = strings.ToLower(email)
    70  	// First check per team allowedDomains, then app wide restrictions
    71  	for _, restriction := range []string{allowedDomains, *a.Config().TeamSettings.RestrictCreationToDomains} {
    72  		domains := a.normalizeDomains(restriction)
    73  		if len(domains) <= 0 {
    74  			continue
    75  		}
    76  		matched := false
    77  		for _, d := range domains {
    78  			if strings.HasSuffix(email, "@"+d) {
    79  				matched = true
    80  				break
    81  			}
    82  		}
    83  		if !matched {
    84  			return false
    85  		}
    86  	}
    87  
    88  	return true
    89  }
    90  
    91  func (a *App) isTeamEmailAllowed(user *model.User, team *model.Team) bool {
    92  	email := strings.ToLower(user.Email)
    93  	return a.isTeamEmailAddressAllowed(email, team.AllowedDomains)
    94  }
    95  
    96  func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
    97  	oldTeam, err := a.GetTeam(team.Id)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  
   102  	validDomains := a.normalizeDomains(*a.Config().TeamSettings.RestrictCreationToDomains)
   103  	if len(validDomains) > 0 {
   104  		for _, domain := range a.normalizeDomains(team.AllowedDomains) {
   105  			matched := false
   106  			for _, d := range validDomains {
   107  				if domain == d {
   108  					matched = true
   109  					break
   110  				}
   111  			}
   112  			if !matched {
   113  				err = model.NewAppError("UpdateTeam", "api.team.update_restricted_domains.mismatch.app_error", map[string]interface{}{"Domain": domain}, "", http.StatusBadRequest)
   114  				return nil, err
   115  			}
   116  		}
   117  	}
   118  
   119  	oldTeam.DisplayName = team.DisplayName
   120  	oldTeam.Description = team.Description
   121  	oldTeam.AllowOpenInvite = team.AllowOpenInvite
   122  	oldTeam.CompanyName = team.CompanyName
   123  	oldTeam.AllowedDomains = team.AllowedDomains
   124  	oldTeam.LastTeamIconUpdate = team.LastTeamIconUpdate
   125  
   126  	oldTeam, err = a.updateTeamUnsanitized(oldTeam)
   127  	if err != nil {
   128  		return team, err
   129  	}
   130  
   131  	a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   132  
   133  	return oldTeam, nil
   134  }
   135  
   136  func (a *App) updateTeamUnsanitized(team *model.Team) (*model.Team, *model.AppError) {
   137  	result := <-a.Srv.Store.Team().Update(team)
   138  	if result.Err != nil {
   139  		return nil, result.Err
   140  	}
   141  
   142  	return result.Data.(*model.Team), nil
   143  }
   144  
   145  // RenameTeam is used to rename the team Name and the DisplayName fields
   146  func (a *App) RenameTeam(team *model.Team, newTeamName string, newDisplayName string) (*model.Team, *model.AppError) {
   147  
   148  	// check if name is occupied
   149  	_, errnf := a.GetTeamByName(newTeamName)
   150  
   151  	// "-" can be used as a newTeamName if only DisplayName change is wanted
   152  	if errnf == nil && newTeamName != "-" {
   153  		errbody := fmt.Sprintf("team with name %s already exists", newTeamName)
   154  		return nil, model.NewAppError("RenameTeam", "app.team.rename_team.name_occupied", nil, errbody, http.StatusBadRequest)
   155  	}
   156  
   157  	if newTeamName != "-" {
   158  		team.Name = newTeamName
   159  	}
   160  
   161  	if newDisplayName != "" {
   162  		team.DisplayName = newDisplayName
   163  	}
   164  
   165  	newTeam, err := a.updateTeamUnsanitized(team)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  
   170  	return newTeam, nil
   171  }
   172  
   173  func (a *App) UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError) {
   174  	oldTeam, err := a.GetTeam(team.Id)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  
   179  	oldTeam.SchemeId = team.SchemeId
   180  
   181  	if result := <-a.Srv.Store.Team().Update(oldTeam); result.Err != nil {
   182  		return nil, result.Err
   183  	}
   184  
   185  	a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   186  
   187  	return oldTeam, nil
   188  }
   189  
   190  func (a *App) PatchTeam(teamId string, patch *model.TeamPatch) (*model.Team, *model.AppError) {
   191  	team, err := a.GetTeam(teamId)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  
   196  	team.Patch(patch)
   197  
   198  	updatedTeam, err := a.UpdateTeam(team)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  
   203  	a.sendTeamEvent(updatedTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   204  
   205  	return updatedTeam, nil
   206  }
   207  
   208  func (a *App) RegenerateTeamInviteId(teamId string) (*model.Team, *model.AppError) {
   209  	team, err := a.GetTeam(teamId)
   210  	if err != nil {
   211  		return nil, err
   212  	}
   213  
   214  	team.InviteId = model.NewId()
   215  
   216  	res := <-a.Srv.Store.Team().Update(team)
   217  	if res.Err != nil {
   218  		return nil, res.Err
   219  	}
   220  	updatedTeam := res.Data.(*model.Team)
   221  
   222  	a.sendTeamEvent(updatedTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   223  
   224  	return updatedTeam, nil
   225  }
   226  
   227  func (a *App) sendTeamEvent(team *model.Team, event string) {
   228  	sanitizedTeam := &model.Team{}
   229  	*sanitizedTeam = *team
   230  	sanitizedTeam.Sanitize()
   231  
   232  	message := model.NewWebSocketEvent(event, "", "", "", nil)
   233  	message.Add("team", sanitizedTeam.ToJson())
   234  	a.Publish(message)
   235  }
   236  
   237  func (a *App) GetSchemeRolesForTeam(teamId string) (string, string, *model.AppError) {
   238  	team, err := a.GetTeam(teamId)
   239  	if err != nil {
   240  		return "", "", err
   241  	}
   242  
   243  	if team.SchemeId != nil && len(*team.SchemeId) != 0 {
   244  		scheme, err := a.GetScheme(*team.SchemeId)
   245  		if err != nil {
   246  			return "", "", err
   247  		}
   248  		return scheme.DefaultTeamUserRole, scheme.DefaultTeamAdminRole, nil
   249  	}
   250  
   251  	return model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID, nil
   252  }
   253  
   254  func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) {
   255  	result := <-a.Srv.Store.Team().GetMember(teamId, userId)
   256  	if result.Err != nil {
   257  		return nil, result.Err
   258  	}
   259  	member := result.Data.(*model.TeamMember)
   260  
   261  	if member == nil {
   262  		err := model.NewAppError("UpdateTeamMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userId+" teamId="+teamId, http.StatusBadRequest)
   263  		return nil, err
   264  	}
   265  
   266  	schemeUserRole, schemeAdminRole, err := a.GetSchemeRolesForTeam(teamId)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  
   271  	var newExplicitRoles []string
   272  	member.SchemeUser = false
   273  	member.SchemeAdmin = false
   274  
   275  	for _, roleName := range strings.Fields(newRoles) {
   276  		role, err := a.GetRoleByName(roleName)
   277  		if err != nil {
   278  			err.StatusCode = http.StatusBadRequest
   279  			return nil, err
   280  		}
   281  		if !role.SchemeManaged {
   282  			// The role is not scheme-managed, so it's OK to apply it to the explicit roles field.
   283  			newExplicitRoles = append(newExplicitRoles, roleName)
   284  		} else {
   285  			// The role is scheme-managed, so need to check if it is part of the scheme for this channel or not.
   286  			switch roleName {
   287  			case schemeAdminRole:
   288  				member.SchemeAdmin = true
   289  			case schemeUserRole:
   290  				member.SchemeUser = true
   291  			default:
   292  				// If not part of the scheme for this channel, then it is not allowed to apply it as an explicit role.
   293  				return nil, model.NewAppError("UpdateTeamMemberRoles", "api.channel.update_team_member_roles.scheme_role.app_error", nil, "role_name="+roleName, http.StatusBadRequest)
   294  			}
   295  		}
   296  	}
   297  
   298  	member.ExplicitRoles = strings.Join(newExplicitRoles, " ")
   299  
   300  	result = <-a.Srv.Store.Team().UpdateMember(member)
   301  	if result.Err != nil {
   302  		return nil, result.Err
   303  	}
   304  	member = result.Data.(*model.TeamMember)
   305  
   306  	a.ClearSessionCacheForUser(userId)
   307  
   308  	a.sendUpdatedMemberRoleEvent(userId, member)
   309  
   310  	return member, nil
   311  }
   312  
   313  func (a *App) UpdateTeamMemberSchemeRoles(teamId string, userId string, isSchemeUser bool, isSchemeAdmin bool) (*model.TeamMember, *model.AppError) {
   314  	member, err := a.GetTeamMember(teamId, userId)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  
   319  	member.SchemeAdmin = isSchemeAdmin
   320  	member.SchemeUser = isSchemeUser
   321  
   322  	// 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.
   323  	if err = a.IsPhase2MigrationCompleted(); err != nil {
   324  		member.ExplicitRoles = RemoveRoles([]string{model.TEAM_USER_ROLE_ID, model.TEAM_ADMIN_ROLE_ID}, member.ExplicitRoles)
   325  	}
   326  
   327  	result := <-a.Srv.Store.Team().UpdateMember(member)
   328  	if result.Err != nil {
   329  		return nil, result.Err
   330  	}
   331  	member = result.Data.(*model.TeamMember)
   332  
   333  	a.ClearSessionCacheForUser(userId)
   334  
   335  	a.sendUpdatedMemberRoleEvent(userId, member)
   336  
   337  	return member, nil
   338  }
   339  
   340  func (a *App) sendUpdatedMemberRoleEvent(userId string, member *model.TeamMember) {
   341  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", userId, nil)
   342  	message.Add("member", member.ToJson())
   343  	a.Publish(message)
   344  }
   345  
   346  func (a *App) AddUserToTeam(teamId string, userId string, userRequestorId string) (*model.Team, *model.AppError) {
   347  	tchan := a.Srv.Store.Team().Get(teamId)
   348  	uchan := a.Srv.Store.User().Get(userId)
   349  
   350  	result := <-tchan
   351  	if result.Err != nil {
   352  		return nil, result.Err
   353  	}
   354  	team := result.Data.(*model.Team)
   355  
   356  	result = <-uchan
   357  	if result.Err != nil {
   358  		return nil, result.Err
   359  	}
   360  	user := result.Data.(*model.User)
   361  
   362  	if err := a.JoinUserToTeam(team, user, userRequestorId); err != nil {
   363  		return nil, err
   364  	}
   365  
   366  	return team, nil
   367  }
   368  
   369  func (a *App) AddUserToTeamByTeamId(teamId string, user *model.User) *model.AppError {
   370  	result := <-a.Srv.Store.Team().Get(teamId)
   371  	if result.Err != nil {
   372  		return result.Err
   373  	}
   374  	return a.JoinUserToTeam(result.Data.(*model.Team), user, "")
   375  }
   376  
   377  func (a *App) AddUserToTeamByToken(userId string, tokenId string) (*model.Team, *model.AppError) {
   378  	result := <-a.Srv.Store.Token().GetByToken(tokenId)
   379  	if result.Err != nil {
   380  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, result.Err.Error(), http.StatusBadRequest)
   381  	}
   382  
   383  	token := result.Data.(*model.Token)
   384  	if token.Type != TOKEN_TYPE_TEAM_INVITATION {
   385  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest)
   386  	}
   387  
   388  	if model.GetMillis()-token.CreateAt >= TEAM_INVITATION_EXPIRY_TIME {
   389  		a.DeleteToken(token)
   390  		return nil, model.NewAppError("AddUserToTeamByToken", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest)
   391  	}
   392  
   393  	tokenData := model.MapFromJson(strings.NewReader(token.Extra))
   394  
   395  	tchan := a.Srv.Store.Team().Get(tokenData["teamId"])
   396  	uchan := a.Srv.Store.User().Get(userId)
   397  
   398  	result = <-tchan
   399  	if result.Err != nil {
   400  		return nil, result.Err
   401  	}
   402  	team := result.Data.(*model.Team)
   403  
   404  	result = <-uchan
   405  	if result.Err != nil {
   406  		return nil, result.Err
   407  	}
   408  	user := result.Data.(*model.User)
   409  
   410  	if err := a.JoinUserToTeam(team, user, ""); err != nil {
   411  		return nil, err
   412  	}
   413  
   414  	if err := a.DeleteToken(token); err != nil {
   415  		return nil, err
   416  	}
   417  
   418  	return team, nil
   419  }
   420  
   421  func (a *App) AddUserToTeamByInviteId(inviteId string, userId string) (*model.Team, *model.AppError) {
   422  	tchan := a.Srv.Store.Team().GetByInviteId(inviteId)
   423  	uchan := a.Srv.Store.User().Get(userId)
   424  
   425  	result := <-tchan
   426  	if result.Err != nil {
   427  		return nil, result.Err
   428  	}
   429  	team := result.Data.(*model.Team)
   430  
   431  	result = <-uchan
   432  	if result.Err != nil {
   433  		return nil, result.Err
   434  	}
   435  	user := result.Data.(*model.User)
   436  
   437  	if err := a.JoinUserToTeam(team, user, ""); err != nil {
   438  		return nil, err
   439  	}
   440  
   441  	return team, nil
   442  }
   443  
   444  // Returns three values:
   445  // 1. a pointer to the team member, if successful
   446  // 2. a boolean: true if the user has a non-deleted team member for that team already, otherwise false.
   447  // 3. a pointer to an AppError if something went wrong.
   448  func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMember, bool, *model.AppError) {
   449  	tm := &model.TeamMember{
   450  		TeamId:     team.Id,
   451  		UserId:     user.Id,
   452  		SchemeUser: true,
   453  	}
   454  
   455  	if team.Email == user.Email {
   456  		tm.SchemeAdmin = true
   457  	}
   458  
   459  	etmr := <-a.Srv.Store.Team().GetMember(team.Id, user.Id)
   460  	if etmr.Err != nil {
   461  		// Membership appears to be missing. Lets try to add.
   462  		tmr := <-a.Srv.Store.Team().SaveMember(tm, *a.Config().TeamSettings.MaxUsersPerTeam)
   463  		if tmr.Err != nil {
   464  			return nil, false, tmr.Err
   465  		}
   466  		return tmr.Data.(*model.TeamMember), false, nil
   467  	}
   468  
   469  	// Membership already exists.  Check if deleted and and update, otherwise do nothing
   470  	rtm := etmr.Data.(*model.TeamMember)
   471  
   472  	// Do nothing if already added
   473  	if rtm.DeleteAt == 0 {
   474  		return rtm, true, nil
   475  	}
   476  
   477  	membersCount := <-a.Srv.Store.Team().GetActiveMemberCount(tm.TeamId)
   478  	if membersCount.Err != nil {
   479  		return nil, false, membersCount.Err
   480  	}
   481  
   482  	if membersCount.Data.(int64) >= int64(*a.Config().TeamSettings.MaxUsersPerTeam) {
   483  		return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.max_accounts.app_error", nil, "teamId="+tm.TeamId, http.StatusBadRequest)
   484  	}
   485  
   486  	tmr := <-a.Srv.Store.Team().UpdateMember(tm)
   487  	if tmr.Err != nil {
   488  		return nil, false, tmr.Err
   489  	}
   490  
   491  	return tmr.Data.(*model.TeamMember), false, nil
   492  }
   493  
   494  func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId string) *model.AppError {
   495  	if !a.isTeamEmailAllowed(user, team) {
   496  		return model.NewAppError("JoinUserToTeam", "api.team.join_user_to_team.allowed_domains.app_error", nil, "", http.StatusBadRequest)
   497  	}
   498  	tm, alreadyAdded, err := a.joinUserToTeam(team, user)
   499  	if err != nil {
   500  		return err
   501  	}
   502  	if alreadyAdded {
   503  		return nil
   504  	}
   505  
   506  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
   507  		var actor *model.User
   508  		if userRequestorId != "" {
   509  			actor, _ = a.GetUser(userRequestorId)
   510  		}
   511  
   512  		a.Srv.Go(func() {
   513  			pluginContext := a.PluginContext()
   514  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
   515  				hooks.UserHasJoinedTeam(pluginContext, tm, actor)
   516  				return true
   517  			}, plugin.UserHasJoinedTeamId)
   518  		})
   519  	}
   520  
   521  	if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
   522  		return uua.Err
   523  	}
   524  
   525  	shouldBeAdmin := team.Email == user.Email
   526  
   527  	// Soft error if there is an issue joining the default channels
   528  	if err := a.JoinDefaultChannels(team.Id, user, shouldBeAdmin, userRequestorId); err != nil {
   529  		mlog.Error(fmt.Sprintf("Encountered an issue joining default channels err=%v", err), mlog.String("user_id", user.Id), mlog.String("team_id", team.Id))
   530  	}
   531  
   532  	a.ClearSessionCacheForUser(user.Id)
   533  	a.InvalidateCacheForUser(user.Id)
   534  
   535  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil)
   536  	message.Add("team_id", team.Id)
   537  	message.Add("user_id", user.Id)
   538  	a.Publish(message)
   539  
   540  	return nil
   541  }
   542  
   543  func (a *App) GetTeam(teamId string) (*model.Team, *model.AppError) {
   544  	result := <-a.Srv.Store.Team().Get(teamId)
   545  	if result.Err != nil {
   546  		return nil, result.Err
   547  	}
   548  	return result.Data.(*model.Team), nil
   549  }
   550  
   551  func (a *App) GetTeamByName(name string) (*model.Team, *model.AppError) {
   552  	result := <-a.Srv.Store.Team().GetByName(name)
   553  	if result.Err != nil {
   554  		result.Err.StatusCode = http.StatusNotFound
   555  		return nil, result.Err
   556  	}
   557  	return result.Data.(*model.Team), nil
   558  }
   559  
   560  func (a *App) GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) {
   561  	result := <-a.Srv.Store.Team().GetByInviteId(inviteId)
   562  	if result.Err != nil {
   563  		return nil, result.Err
   564  	}
   565  	return result.Data.(*model.Team), nil
   566  }
   567  
   568  func (a *App) GetAllTeams() ([]*model.Team, *model.AppError) {
   569  	result := <-a.Srv.Store.Team().GetAll()
   570  	if result.Err != nil {
   571  		return nil, result.Err
   572  	}
   573  	return result.Data.([]*model.Team), nil
   574  }
   575  
   576  func (a *App) GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   577  	result := <-a.Srv.Store.Team().GetAllPage(offset, limit)
   578  	if result.Err != nil {
   579  		return nil, result.Err
   580  	}
   581  	return result.Data.([]*model.Team), nil
   582  }
   583  
   584  func (a *App) GetAllPrivateTeams() ([]*model.Team, *model.AppError) {
   585  	result := <-a.Srv.Store.Team().GetAllPrivateTeamListing()
   586  	if result.Err != nil {
   587  		return nil, result.Err
   588  	}
   589  	return result.Data.([]*model.Team), nil
   590  }
   591  
   592  func (a *App) GetAllPrivateTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   593  	result := <-a.Srv.Store.Team().GetAllPrivateTeamPageListing(offset, limit)
   594  	if result.Err != nil {
   595  		return nil, result.Err
   596  	}
   597  	return result.Data.([]*model.Team), nil
   598  }
   599  
   600  func (a *App) GetAllPublicTeams() ([]*model.Team, *model.AppError) {
   601  	result := <-a.Srv.Store.Team().GetAllTeamListing()
   602  	if result.Err != nil {
   603  		return nil, result.Err
   604  	}
   605  	return result.Data.([]*model.Team), nil
   606  }
   607  
   608  func (a *App) GetAllPublicTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   609  	result := <-a.Srv.Store.Team().GetAllTeamPageListing(offset, limit)
   610  	if result.Err != nil {
   611  		return nil, result.Err
   612  	}
   613  	return result.Data.([]*model.Team), nil
   614  }
   615  
   616  func (a *App) SearchAllTeams(term string) ([]*model.Team, *model.AppError) {
   617  	result := <-a.Srv.Store.Team().SearchAll(term)
   618  	if result.Err != nil {
   619  		return nil, result.Err
   620  	}
   621  	return result.Data.([]*model.Team), nil
   622  }
   623  
   624  func (a *App) SearchPublicTeams(term string) ([]*model.Team, *model.AppError) {
   625  	result := <-a.Srv.Store.Team().SearchOpen(term)
   626  	if result.Err != nil {
   627  		return nil, result.Err
   628  	}
   629  	return result.Data.([]*model.Team), nil
   630  }
   631  
   632  func (a *App) SearchPrivateTeams(term string) ([]*model.Team, *model.AppError) {
   633  	result := <-a.Srv.Store.Team().SearchPrivate(term)
   634  	if result.Err != nil {
   635  		return nil, result.Err
   636  	}
   637  	return result.Data.([]*model.Team), nil
   638  }
   639  
   640  func (a *App) GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) {
   641  	result := <-a.Srv.Store.Team().GetTeamsByUserId(userId)
   642  	if result.Err != nil {
   643  		return nil, result.Err
   644  	}
   645  	return result.Data.([]*model.Team), nil
   646  }
   647  
   648  func (a *App) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
   649  	result := <-a.Srv.Store.Team().GetMember(teamId, userId)
   650  	if result.Err != nil {
   651  		return nil, result.Err
   652  	}
   653  	return result.Data.(*model.TeamMember), nil
   654  }
   655  
   656  func (a *App) GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError) {
   657  	result := <-a.Srv.Store.Team().GetTeamsForUser(userId)
   658  	if result.Err != nil {
   659  		return nil, result.Err
   660  	}
   661  	return result.Data.([]*model.TeamMember), nil
   662  }
   663  
   664  func (a *App) GetTeamMembersForUserWithPagination(userId string, page, perPage int) ([]*model.TeamMember, *model.AppError) {
   665  	result := <-a.Srv.Store.Team().GetTeamsForUserWithPagination(userId, page, perPage)
   666  	if result.Err != nil {
   667  		return nil, result.Err
   668  	}
   669  	return result.Data.([]*model.TeamMember), nil
   670  }
   671  
   672  func (a *App) GetTeamMembers(teamId string, offset int, limit int) ([]*model.TeamMember, *model.AppError) {
   673  	result := <-a.Srv.Store.Team().GetMembers(teamId, offset, limit)
   674  	if result.Err != nil {
   675  		return nil, result.Err
   676  	}
   677  	return result.Data.([]*model.TeamMember), nil
   678  }
   679  
   680  func (a *App) GetTeamMembersByIds(teamId string, userIds []string) ([]*model.TeamMember, *model.AppError) {
   681  	result := <-a.Srv.Store.Team().GetMembersByIds(teamId, userIds)
   682  	if result.Err != nil {
   683  		return nil, result.Err
   684  	}
   685  	return result.Data.([]*model.TeamMember), nil
   686  }
   687  
   688  func (a *App) AddTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
   689  	if _, err := a.AddUserToTeam(teamId, userId, ""); err != nil {
   690  		return nil, err
   691  	}
   692  
   693  	teamMember, err := a.GetTeamMember(teamId, userId)
   694  	if err != nil {
   695  		return nil, err
   696  	}
   697  
   698  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
   699  	message.Add("team_id", teamId)
   700  	message.Add("user_id", userId)
   701  	a.Publish(message)
   702  
   703  	return teamMember, nil
   704  }
   705  
   706  func (a *App) AddTeamMembers(teamId string, userIds []string, userRequestorId string) ([]*model.TeamMember, *model.AppError) {
   707  	var members []*model.TeamMember
   708  
   709  	for _, userId := range userIds {
   710  		if _, err := a.AddUserToTeam(teamId, userId, userRequestorId); err != nil {
   711  			return nil, err
   712  		}
   713  
   714  		teamMember, err := a.GetTeamMember(teamId, userId)
   715  		if err != nil {
   716  			return nil, err
   717  		}
   718  		members = append(members, teamMember)
   719  
   720  		message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
   721  		message.Add("team_id", teamId)
   722  		message.Add("user_id", userId)
   723  		a.Publish(message)
   724  	}
   725  
   726  	return members, nil
   727  }
   728  
   729  func (a *App) AddTeamMemberByToken(userId, tokenId string) (*model.TeamMember, *model.AppError) {
   730  	team, err := a.AddUserToTeamByToken(userId, tokenId)
   731  	if err != nil {
   732  		return nil, err
   733  	}
   734  
   735  	teamMember, err := a.GetTeamMember(team.Id, userId)
   736  	if err != nil {
   737  		return nil, err
   738  	}
   739  
   740  	return teamMember, nil
   741  }
   742  
   743  func (a *App) AddTeamMemberByInviteId(inviteId, userId string) (*model.TeamMember, *model.AppError) {
   744  	team, err := a.AddUserToTeamByInviteId(inviteId, userId)
   745  	if err != nil {
   746  		return nil, err
   747  	}
   748  
   749  	teamMember, err := a.GetTeamMember(team.Id, userId)
   750  	if err != nil {
   751  		return nil, err
   752  	}
   753  	return teamMember, nil
   754  }
   755  
   756  func (a *App) GetTeamUnread(teamId, userId string) (*model.TeamUnread, *model.AppError) {
   757  	result := <-a.Srv.Store.Team().GetChannelUnreadsForTeam(teamId, userId)
   758  	if result.Err != nil {
   759  		return nil, result.Err
   760  	}
   761  
   762  	channelUnreads := result.Data.([]*model.ChannelUnread)
   763  	var teamUnread = &model.TeamUnread{
   764  		MsgCount:     0,
   765  		MentionCount: 0,
   766  		TeamId:       teamId,
   767  	}
   768  
   769  	for _, cu := range channelUnreads {
   770  		teamUnread.MentionCount += cu.MentionCount
   771  
   772  		if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
   773  			teamUnread.MsgCount += cu.MsgCount
   774  		}
   775  	}
   776  
   777  	return teamUnread, nil
   778  }
   779  
   780  func (a *App) RemoveUserFromTeam(teamId string, userId string, requestorId string) *model.AppError {
   781  	tchan := a.Srv.Store.Team().Get(teamId)
   782  	uchan := a.Srv.Store.User().Get(userId)
   783  
   784  	result := <-tchan
   785  	if result.Err != nil {
   786  		return result.Err
   787  	}
   788  	team := result.Data.(*model.Team)
   789  
   790  	result = <-uchan
   791  	if result.Err != nil {
   792  		return result.Err
   793  	}
   794  	user := result.Data.(*model.User)
   795  
   796  	if err := a.LeaveTeam(team, user, requestorId); err != nil {
   797  		return err
   798  	}
   799  
   800  	return nil
   801  }
   802  
   803  func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string) *model.AppError {
   804  	teamMember, err := a.GetTeamMember(team.Id, user.Id)
   805  	if err != nil {
   806  		return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest)
   807  	}
   808  
   809  	var channelList *model.ChannelList
   810  
   811  	if result := <-a.Srv.Store.Channel().GetChannels(team.Id, user.Id, true); result.Err != nil {
   812  		if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
   813  			channelList = &model.ChannelList{}
   814  		} else {
   815  			return result.Err
   816  		}
   817  	} else {
   818  		channelList = result.Data.(*model.ChannelList)
   819  	}
   820  
   821  	for _, channel := range *channelList {
   822  		if !channel.IsGroupOrDirect() {
   823  			a.InvalidateCacheForChannelMembers(channel.Id)
   824  			if result := <-a.Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
   825  				return result.Err
   826  			}
   827  		}
   828  	}
   829  
   830  	result := <-a.Srv.Store.Channel().GetByName(team.Id, model.DEFAULT_CHANNEL, false)
   831  	if result.Err != nil {
   832  		return result.Err
   833  	}
   834  	channel := result.Data.(*model.Channel)
   835  
   836  	if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
   837  		if requestorId == user.Id {
   838  			if err := a.postLeaveTeamMessage(user, channel); err != nil {
   839  				mlog.Error(fmt.Sprint("Failed to post join/leave message", err))
   840  			}
   841  		} else {
   842  			if err := a.postRemoveFromTeamMessage(user, channel); err != nil {
   843  				mlog.Error(fmt.Sprint("Failed to post join/leave message", err))
   844  			}
   845  		}
   846  	}
   847  
   848  	// Send the websocket message before we actually do the remove so the user being removed gets it.
   849  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil)
   850  	message.Add("user_id", user.Id)
   851  	message.Add("team_id", team.Id)
   852  	a.Publish(message)
   853  
   854  	teamMember.Roles = ""
   855  	teamMember.DeleteAt = model.GetMillis()
   856  
   857  	if result := <-a.Srv.Store.Team().UpdateMember(teamMember); result.Err != nil {
   858  		return result.Err
   859  	}
   860  
   861  	if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
   862  		var actor *model.User
   863  		if requestorId != "" {
   864  			actor, _ = a.GetUser(requestorId)
   865  		}
   866  
   867  		a.Srv.Go(func() {
   868  			pluginContext := a.PluginContext()
   869  			pluginsEnvironment.RunMultiPluginHook(func(hooks plugin.Hooks) bool {
   870  				hooks.UserHasLeftTeam(pluginContext, teamMember, actor)
   871  				return true
   872  			}, plugin.UserHasLeftTeamId)
   873  		})
   874  	}
   875  
   876  	if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
   877  		return uua.Err
   878  	}
   879  
   880  	// delete the preferences that set the last channel used in the team and other team specific preferences
   881  	if result := <-a.Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil {
   882  		return result.Err
   883  	}
   884  
   885  	a.ClearSessionCacheForUser(user.Id)
   886  	a.InvalidateCacheForUser(user.Id)
   887  
   888  	return nil
   889  }
   890  
   891  func (a *App) postLeaveTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
   892  	post := &model.Post{
   893  		ChannelId: channel.Id,
   894  		Message:   fmt.Sprintf(utils.T("api.team.leave.left"), user.Username),
   895  		Type:      model.POST_LEAVE_TEAM,
   896  		UserId:    user.Id,
   897  		Props: model.StringInterface{
   898  			"username": user.Username,
   899  		},
   900  	}
   901  
   902  	if _, err := a.CreatePost(post, channel, false); err != nil {
   903  		return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   904  	}
   905  
   906  	return nil
   907  }
   908  
   909  func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
   910  	post := &model.Post{
   911  		ChannelId: channel.Id,
   912  		Message:   fmt.Sprintf(utils.T("api.team.remove_user_from_team.removed"), user.Username),
   913  		Type:      model.POST_REMOVE_FROM_TEAM,
   914  		UserId:    user.Id,
   915  		Props: model.StringInterface{
   916  			"username": user.Username,
   917  		},
   918  	}
   919  
   920  	if _, err := a.CreatePost(post, channel, false); err != nil {
   921  		return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   922  	}
   923  
   924  	return nil
   925  }
   926  
   927  func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string) *model.AppError {
   928  	if !*a.Config().ServiceSettings.EnableEmailInvitations {
   929  		return model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.disabled.app_error", nil, "", http.StatusNotImplemented)
   930  	}
   931  
   932  	if len(emailList) == 0 {
   933  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
   934  		return err
   935  	}
   936  
   937  	tchan := a.Srv.Store.Team().Get(teamId)
   938  	uchan := a.Srv.Store.User().Get(senderId)
   939  
   940  	result := <-tchan
   941  	if result.Err != nil {
   942  		return result.Err
   943  	}
   944  	team := result.Data.(*model.Team)
   945  
   946  	result = <-uchan
   947  	if result.Err != nil {
   948  		return result.Err
   949  	}
   950  	user := result.Data.(*model.User)
   951  
   952  	var invalidEmailList []string
   953  
   954  	for _, email := range emailList {
   955  		if !a.isTeamEmailAddressAllowed(email, team.AllowedDomains) {
   956  			invalidEmailList = append(invalidEmailList, email)
   957  		}
   958  	}
   959  
   960  	if len(invalidEmailList) > 0 {
   961  		s := strings.Join(invalidEmailList, ", ")
   962  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest)
   963  		return err
   964  	}
   965  
   966  	nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
   967  	a.SendInviteEmails(team, user.GetDisplayName(nameFormat), user.Id, emailList, a.GetSiteURL())
   968  
   969  	return nil
   970  }
   971  
   972  func (a *App) FindTeamByName(name string) bool {
   973  	if result := <-a.Srv.Store.Team().GetByName(name); result.Err != nil {
   974  		return false
   975  	}
   976  	return true
   977  }
   978  
   979  func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError) {
   980  	result := <-a.Srv.Store.Team().GetChannelUnreadsForAllTeams(excludeTeamId, userId)
   981  	if result.Err != nil {
   982  		return nil, result.Err
   983  	}
   984  	data := result.Data.([]*model.ChannelUnread)
   985  	members := []*model.TeamUnread{}
   986  	membersMap := make(map[string]*model.TeamUnread)
   987  
   988  	unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
   989  		tu.MentionCount += cu.MentionCount
   990  
   991  		if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
   992  			tu.MsgCount += cu.MsgCount
   993  		}
   994  
   995  		return tu
   996  	}
   997  
   998  	for i := range data {
   999  		id := data[i].TeamId
  1000  		if mu, ok := membersMap[id]; ok {
  1001  			membersMap[id] = unreads(data[i], mu)
  1002  		} else {
  1003  			membersMap[id] = unreads(data[i], &model.TeamUnread{
  1004  				MsgCount:     0,
  1005  				MentionCount: 0,
  1006  				TeamId:       id,
  1007  			})
  1008  		}
  1009  	}
  1010  
  1011  	for _, val := range membersMap {
  1012  		members = append(members, val)
  1013  	}
  1014  
  1015  	return members, nil
  1016  }
  1017  
  1018  func (a *App) PermanentDeleteTeamId(teamId string) *model.AppError {
  1019  	team, err := a.GetTeam(teamId)
  1020  	if err != nil {
  1021  		return err
  1022  	}
  1023  
  1024  	return a.PermanentDeleteTeam(team)
  1025  }
  1026  
  1027  func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError {
  1028  	team.DeleteAt = model.GetMillis()
  1029  	if result := <-a.Srv.Store.Team().Update(team); result.Err != nil {
  1030  		return result.Err
  1031  	}
  1032  
  1033  	if result := <-a.Srv.Store.Channel().GetTeamChannels(team.Id); result.Err != nil {
  1034  		if result.Err.Id != "store.sql_channel.get_channels.not_found.app_error" {
  1035  			return result.Err
  1036  		}
  1037  	} else {
  1038  		channels := result.Data.(*model.ChannelList)
  1039  		for _, c := range *channels {
  1040  			a.PermanentDeleteChannel(c)
  1041  		}
  1042  	}
  1043  
  1044  	if result := <-a.Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
  1045  		return result.Err
  1046  	}
  1047  
  1048  	if result := <-a.Srv.Store.Command().PermanentDeleteByTeam(team.Id); result.Err != nil {
  1049  		return result.Err
  1050  	}
  1051  
  1052  	if result := <-a.Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil {
  1053  		return result.Err
  1054  	}
  1055  
  1056  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
  1057  
  1058  	return nil
  1059  }
  1060  
  1061  func (a *App) SoftDeleteTeam(teamId string) *model.AppError {
  1062  	team, err := a.GetTeam(teamId)
  1063  	if err != nil {
  1064  		return err
  1065  	}
  1066  
  1067  	team.DeleteAt = model.GetMillis()
  1068  	if result := <-a.Srv.Store.Team().Update(team); result.Err != nil {
  1069  		return result.Err
  1070  	}
  1071  
  1072  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
  1073  
  1074  	return nil
  1075  }
  1076  
  1077  func (a *App) RestoreTeam(teamId string) *model.AppError {
  1078  	team, err := a.GetTeam(teamId)
  1079  	if err != nil {
  1080  		return err
  1081  	}
  1082  	team.DeleteAt = 0
  1083  	result := <-a.Srv.Store.Team().Update(team)
  1084  	if result.Err != nil {
  1085  		return result.Err
  1086  	}
  1087  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_RESTORE_TEAM)
  1088  	return nil
  1089  }
  1090  
  1091  func (a *App) GetTeamStats(teamId string) (*model.TeamStats, *model.AppError) {
  1092  	tchan := a.Srv.Store.Team().GetTotalMemberCount(teamId)
  1093  	achan := a.Srv.Store.Team().GetActiveMemberCount(teamId)
  1094  
  1095  	stats := &model.TeamStats{}
  1096  	stats.TeamId = teamId
  1097  
  1098  	result := <-tchan
  1099  	if result.Err != nil {
  1100  		return nil, result.Err
  1101  	}
  1102  	stats.TotalMemberCount = result.Data.(int64)
  1103  
  1104  	result = <-achan
  1105  	if result.Err != nil {
  1106  		return nil, result.Err
  1107  	}
  1108  	stats.ActiveMemberCount = result.Data.(int64)
  1109  
  1110  	return stats, nil
  1111  }
  1112  
  1113  func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
  1114  	tokenId := query.Get("t")
  1115  	inviteId := query.Get("id")
  1116  
  1117  	if len(tokenId) > 0 {
  1118  		result := <-a.Srv.Store.Token().GetByToken(tokenId)
  1119  		if result.Err != nil {
  1120  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
  1121  		}
  1122  
  1123  		token := result.Data.(*model.Token)
  1124  		if token.Type != TOKEN_TYPE_TEAM_INVITATION {
  1125  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
  1126  		}
  1127  
  1128  		if model.GetMillis()-token.CreateAt >= TEAM_INVITATION_EXPIRY_TIME {
  1129  			a.DeleteToken(token)
  1130  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest)
  1131  		}
  1132  
  1133  		tokenData := model.MapFromJson(strings.NewReader(token.Extra))
  1134  
  1135  		return tokenData["teamId"], nil
  1136  	}
  1137  	if len(inviteId) > 0 {
  1138  		result := <-a.Srv.Store.Team().GetByInviteId(inviteId)
  1139  		if result.Err == nil {
  1140  			return result.Data.(*model.Team).Id, nil
  1141  		}
  1142  		// soft fail, so we still create user but don't auto-join team
  1143  		mlog.Error(fmt.Sprintf("%v", result.Err))
  1144  	}
  1145  
  1146  	return "", nil
  1147  }
  1148  
  1149  func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
  1150  	if !a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_MANAGE_TEAM) {
  1151  		team.Sanitize()
  1152  	}
  1153  
  1154  	return team
  1155  }
  1156  
  1157  func (a *App) SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team {
  1158  	for _, team := range teams {
  1159  		a.SanitizeTeam(session, team)
  1160  	}
  1161  
  1162  	return teams
  1163  }
  1164  
  1165  func (a *App) GetTeamIcon(team *model.Team) ([]byte, *model.AppError) {
  1166  	if len(*a.Config().FileSettings.DriverName) == 0 {
  1167  		return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.filesettings_no_driver.app_error", nil, "", http.StatusNotImplemented)
  1168  	}
  1169  
  1170  	path := "teams/" + team.Id + "/teamIcon.png"
  1171  	data, err := a.ReadFile(path)
  1172  	if err != nil {
  1173  		return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.read_file.app_error", nil, err.Error(), http.StatusNotFound)
  1174  	}
  1175  
  1176  	return data, nil
  1177  }
  1178  
  1179  func (a *App) SetTeamIcon(teamId string, imageData *multipart.FileHeader) *model.AppError {
  1180  	file, err := imageData.Open()
  1181  	if err != nil {
  1182  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.open.app_error", nil, err.Error(), http.StatusBadRequest)
  1183  	}
  1184  	defer file.Close()
  1185  	return a.SetTeamIconFromMultiPartFile(teamId, file)
  1186  }
  1187  
  1188  func (a *App) SetTeamIconFromMultiPartFile(teamId string, file multipart.File) *model.AppError {
  1189  	team, getTeamErr := a.GetTeam(teamId)
  1190  
  1191  	if getTeamErr != nil {
  1192  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.get_team.app_error", nil, getTeamErr.Error(), http.StatusBadRequest)
  1193  	}
  1194  
  1195  	if len(*a.Config().FileSettings.DriverName) == 0 {
  1196  		return model.NewAppError("setTeamIcon", "api.team.set_team_icon.storage.app_error", nil, "", http.StatusNotImplemented)
  1197  	}
  1198  
  1199  	// Decode image config first to check dimensions before loading the whole thing into memory later on
  1200  	config, _, err := image.DecodeConfig(file)
  1201  	if err != nil {
  1202  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode_config.app_error", nil, err.Error(), http.StatusBadRequest)
  1203  	}
  1204  	if config.Width*config.Height > model.MaxImageSize {
  1205  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.too_large.app_error", nil, err.Error(), http.StatusBadRequest)
  1206  	}
  1207  
  1208  	file.Seek(0, 0)
  1209  
  1210  	return a.SetTeamIconFromFile(team, file)
  1211  }
  1212  
  1213  func (a *App) SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppError {
  1214  	// Decode image into Image object
  1215  	img, _, err := image.Decode(file)
  1216  	if err != nil {
  1217  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode.app_error", nil, err.Error(), http.StatusBadRequest)
  1218  	}
  1219  
  1220  	orientation, _ := getImageOrientation(file)
  1221  	img = makeImageUpright(img, orientation)
  1222  
  1223  	// Scale team icon
  1224  	teamIconWidthAndHeight := 128
  1225  	img = imaging.Fill(img, teamIconWidthAndHeight, teamIconWidthAndHeight, imaging.Center, imaging.Lanczos)
  1226  
  1227  	buf := new(bytes.Buffer)
  1228  	err = png.Encode(buf, img)
  1229  	if err != nil {
  1230  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.encode.app_error", nil, err.Error(), http.StatusInternalServerError)
  1231  	}
  1232  
  1233  	path := "teams/" + team.Id + "/teamIcon.png"
  1234  
  1235  	if _, err := a.WriteFile(buf, path); err != nil {
  1236  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.write_file.app_error", nil, "", http.StatusInternalServerError)
  1237  	}
  1238  
  1239  	curTime := model.GetMillis()
  1240  
  1241  	if result := <-a.Srv.Store.Team().UpdateLastTeamIconUpdate(team.Id, curTime); result.Err != nil {
  1242  		return model.NewAppError("SetTeamIcon", "api.team.team_icon.update.app_error", nil, result.Err.Error(), http.StatusBadRequest)
  1243  	}
  1244  
  1245  	// manually set time to avoid possible cluster inconsistencies
  1246  	team.LastTeamIconUpdate = curTime
  1247  
  1248  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM)
  1249  
  1250  	return nil
  1251  }
  1252  
  1253  func (a *App) RemoveTeamIcon(teamId string) *model.AppError {
  1254  	team, err := a.GetTeam(teamId)
  1255  	if err != nil {
  1256  		return model.NewAppError("RemoveTeamIcon", "api.team.remove_team_icon.get_team.app_error", nil, err.Error(), http.StatusBadRequest)
  1257  	}
  1258  
  1259  	if result := <-a.Srv.Store.Team().UpdateLastTeamIconUpdate(teamId, 0); result.Err != nil {
  1260  		return model.NewAppError("RemoveTeamIcon", "api.team.team_icon.update.app_error", nil, result.Err.Error(), http.StatusBadRequest)
  1261  	}
  1262  
  1263  	team.LastTeamIconUpdate = 0
  1264  
  1265  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM)
  1266  
  1267  	return nil
  1268  }
  1269  
  1270  func (a *App) InvalidateAllEmailInvites() *model.AppError {
  1271  	if result := <-a.Srv.Store.Token().RemoveAllTokensByType(TOKEN_TYPE_TEAM_INVITATION); result.Err != nil {
  1272  		return model.NewAppError("InvalidateAllEmailInvites", "api.team.invalidate_all_email_invites.app_error", nil, result.Err.Error(), http.StatusBadRequest)
  1273  	}
  1274  	return nil
  1275  }