github.com/coincircle/mattermost-server@v4.8.1-0.20180321182714-9d701c704416+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  	"mime/multipart"
    12  	"net/http"
    13  	"net/url"
    14  	"strconv"
    15  	"strings"
    16  
    17  	l4g "github.com/alecthomas/log4go"
    18  	"github.com/disintegration/imaging"
    19  
    20  	"github.com/mattermost/mattermost-server/model"
    21  	"github.com/mattermost/mattermost-server/utils"
    22  )
    23  
    24  func (a *App) CreateTeam(team *model.Team) (*model.Team, *model.AppError) {
    25  	if result := <-a.Srv.Store.Team().Save(team); result.Err != nil {
    26  		return nil, result.Err
    27  	} else {
    28  		rteam := result.Data.(*model.Team)
    29  
    30  		if _, err := a.CreateDefaultChannels(rteam.Id); err != nil {
    31  			return nil, err
    32  		}
    33  
    34  		return rteam, nil
    35  	}
    36  }
    37  
    38  func (a *App) CreateTeamWithUser(team *model.Team, userId string) (*model.Team, *model.AppError) {
    39  	var user *model.User
    40  	var err *model.AppError
    41  	if user, err = a.GetUser(userId); err != nil {
    42  		return nil, err
    43  	} else {
    44  		team.Email = user.Email
    45  	}
    46  
    47  	if !a.isTeamEmailAllowed(user) {
    48  		return nil, model.NewAppError("isTeamEmailAllowed", "api.team.is_team_creation_allowed.domain.app_error", nil, "", http.StatusBadRequest)
    49  	}
    50  
    51  	var rteam *model.Team
    52  	if rteam, err = a.CreateTeam(team); 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) isTeamEmailAddressAllowed(email string) bool {
    64  	email = strings.ToLower(email)
    65  	// commas and @ signs are optional
    66  	// can be in the form of "@corp.mattermost.com, mattermost.com mattermost.org" -> corp.mattermost.com mattermost.com mattermost.org
    67  	domains := strings.Fields(strings.TrimSpace(strings.ToLower(strings.Replace(strings.Replace(a.Config().TeamSettings.RestrictCreationToDomains, "@", " ", -1), ",", " ", -1))))
    68  
    69  	matched := false
    70  	for _, d := range domains {
    71  		if strings.HasSuffix(email, "@"+d) {
    72  			matched = true
    73  			break
    74  		}
    75  	}
    76  
    77  	if len(a.Config().TeamSettings.RestrictCreationToDomains) > 0 && !matched {
    78  		return false
    79  	}
    80  
    81  	return true
    82  }
    83  
    84  func (a *App) isTeamEmailAllowed(user *model.User) bool {
    85  	email := strings.ToLower(user.Email)
    86  
    87  	if len(user.AuthService) > 0 && len(*user.AuthData) > 0 {
    88  		return true
    89  	}
    90  
    91  	return a.isTeamEmailAddressAllowed(email)
    92  }
    93  
    94  func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
    95  	var oldTeam *model.Team
    96  	var err *model.AppError
    97  	if oldTeam, err = a.GetTeam(team.Id); err != nil {
    98  		return nil, err
    99  	}
   100  
   101  	oldTeam.DisplayName = team.DisplayName
   102  	oldTeam.Description = team.Description
   103  	oldTeam.InviteId = team.InviteId
   104  	oldTeam.AllowOpenInvite = team.AllowOpenInvite
   105  	oldTeam.CompanyName = team.CompanyName
   106  	oldTeam.AllowedDomains = team.AllowedDomains
   107  
   108  	if result := <-a.Srv.Store.Team().Update(oldTeam); result.Err != nil {
   109  		return nil, result.Err
   110  	}
   111  
   112  	a.sendTeamEvent(oldTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   113  
   114  	return oldTeam, nil
   115  }
   116  
   117  func (a *App) PatchTeam(teamId string, patch *model.TeamPatch) (*model.Team, *model.AppError) {
   118  	team, err := a.GetTeam(teamId)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	team.Patch(patch)
   124  
   125  	updatedTeam, err := a.UpdateTeam(team)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  
   130  	a.sendTeamEvent(updatedTeam, model.WEBSOCKET_EVENT_UPDATE_TEAM)
   131  
   132  	return updatedTeam, nil
   133  }
   134  
   135  func (a *App) sendTeamEvent(team *model.Team, event string) {
   136  	sanitizedTeam := &model.Team{}
   137  	*sanitizedTeam = *team
   138  	sanitizedTeam.Sanitize()
   139  
   140  	message := model.NewWebSocketEvent(event, "", "", "", nil)
   141  	message.Add("team", sanitizedTeam.ToJson())
   142  	a.Publish(message)
   143  }
   144  
   145  func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) {
   146  	var member *model.TeamMember
   147  	if result := <-a.Srv.Store.Team().GetTeamsForUser(userId); result.Err != nil {
   148  		return nil, result.Err
   149  	} else {
   150  		members := result.Data.([]*model.TeamMember)
   151  		for _, m := range members {
   152  			if m.TeamId == teamId {
   153  				member = m
   154  			}
   155  		}
   156  	}
   157  
   158  	if member == nil {
   159  		err := model.NewAppError("UpdateTeamMemberRoles", "api.team.update_member_roles.not_a_member", nil, "userId="+userId+" teamId="+teamId, http.StatusBadRequest)
   160  		return nil, err
   161  	}
   162  
   163  	member.Roles = newRoles
   164  
   165  	if result := <-a.Srv.Store.Team().UpdateMember(member); result.Err != nil {
   166  		return nil, result.Err
   167  	}
   168  
   169  	a.ClearSessionCacheForUser(userId)
   170  
   171  	a.sendUpdatedMemberRoleEvent(userId, member)
   172  
   173  	return member, nil
   174  }
   175  
   176  func (a *App) sendUpdatedMemberRoleEvent(userId string, member *model.TeamMember) {
   177  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", userId, nil)
   178  	message.Add("member", member.ToJson())
   179  	a.Publish(message)
   180  }
   181  
   182  func (a *App) AddUserToTeam(teamId string, userId string, userRequestorId string) (*model.Team, *model.AppError) {
   183  	tchan := a.Srv.Store.Team().Get(teamId)
   184  	uchan := a.Srv.Store.User().Get(userId)
   185  
   186  	var team *model.Team
   187  	if result := <-tchan; result.Err != nil {
   188  		return nil, result.Err
   189  	} else {
   190  		team = result.Data.(*model.Team)
   191  	}
   192  
   193  	var user *model.User
   194  	if result := <-uchan; result.Err != nil {
   195  		return nil, result.Err
   196  	} else {
   197  		user = result.Data.(*model.User)
   198  	}
   199  
   200  	if err := a.JoinUserToTeam(team, user, userRequestorId); err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	return team, nil
   205  }
   206  
   207  func (a *App) AddUserToTeamByTeamId(teamId string, user *model.User) *model.AppError {
   208  	if result := <-a.Srv.Store.Team().Get(teamId); result.Err != nil {
   209  		return result.Err
   210  	} else {
   211  		return a.JoinUserToTeam(result.Data.(*model.Team), user, "")
   212  	}
   213  }
   214  
   215  func (a *App) AddUserToTeamByHash(userId string, hash string, data string) (*model.Team, *model.AppError) {
   216  	props := model.MapFromJson(strings.NewReader(data))
   217  
   218  	if hash != utils.HashSha256(fmt.Sprintf("%v:%v", data, a.Config().EmailSettings.InviteSalt)) {
   219  		return nil, model.NewAppError("JoinUserToTeamByHash", "api.user.create_user.signup_link_invalid.app_error", nil, "", http.StatusBadRequest)
   220  	}
   221  
   222  	t, timeErr := strconv.ParseInt(props["time"], 10, 64)
   223  	if timeErr != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
   224  		return nil, model.NewAppError("JoinUserToTeamByHash", "api.user.create_user.signup_link_expired.app_error", nil, "", http.StatusBadRequest)
   225  	}
   226  
   227  	tchan := a.Srv.Store.Team().Get(props["id"])
   228  	uchan := a.Srv.Store.User().Get(userId)
   229  
   230  	var team *model.Team
   231  	if result := <-tchan; result.Err != nil {
   232  		return nil, result.Err
   233  	} else {
   234  		team = result.Data.(*model.Team)
   235  	}
   236  
   237  	// verify that the team's invite id hasn't been changed since the invite was sent
   238  	if team.InviteId != props["invite_id"] {
   239  		return nil, model.NewAppError("JoinUserToTeamByHash", "api.user.create_user.signup_link_mismatched_invite_id.app_error", nil, "", http.StatusBadRequest)
   240  	}
   241  
   242  	var user *model.User
   243  	if result := <-uchan; result.Err != nil {
   244  		return nil, result.Err
   245  	} else {
   246  		user = result.Data.(*model.User)
   247  	}
   248  
   249  	if err := a.JoinUserToTeam(team, user, ""); err != nil {
   250  		return nil, err
   251  	}
   252  
   253  	return team, nil
   254  }
   255  
   256  func (a *App) AddUserToTeamByInviteId(inviteId string, userId string) (*model.Team, *model.AppError) {
   257  	tchan := a.Srv.Store.Team().GetByInviteId(inviteId)
   258  	uchan := a.Srv.Store.User().Get(userId)
   259  
   260  	var team *model.Team
   261  	if result := <-tchan; result.Err != nil {
   262  		return nil, result.Err
   263  	} else {
   264  		team = result.Data.(*model.Team)
   265  	}
   266  
   267  	var user *model.User
   268  	if result := <-uchan; result.Err != nil {
   269  		return nil, result.Err
   270  	} else {
   271  		user = result.Data.(*model.User)
   272  	}
   273  
   274  	if err := a.JoinUserToTeam(team, user, ""); err != nil {
   275  		return nil, err
   276  	}
   277  
   278  	return team, nil
   279  }
   280  
   281  // Returns three values:
   282  // 1. a pointer to the team member, if successful
   283  // 2. a boolean: true if the user has a non-deleted team member for that team already, otherwise false.
   284  // 3. a pointer to an AppError if something went wrong.
   285  func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMember, bool, *model.AppError) {
   286  	tm := &model.TeamMember{
   287  		TeamId: team.Id,
   288  		UserId: user.Id,
   289  		Roles:  model.TEAM_USER_ROLE_ID,
   290  	}
   291  
   292  	if team.Email == user.Email {
   293  		tm.Roles = model.TEAM_USER_ROLE_ID + " " + model.TEAM_ADMIN_ROLE_ID
   294  	}
   295  
   296  	if etmr := <-a.Srv.Store.Team().GetMember(team.Id, user.Id); etmr.Err == nil {
   297  		// Membership already exists.  Check if deleted and and update, otherwise do nothing
   298  		rtm := etmr.Data.(*model.TeamMember)
   299  
   300  		// Do nothing if already added
   301  		if rtm.DeleteAt == 0 {
   302  			return rtm, true, nil
   303  		}
   304  
   305  		if membersCount := <-a.Srv.Store.Team().GetActiveMemberCount(tm.TeamId); membersCount.Err != nil {
   306  			return nil, false, membersCount.Err
   307  		} else if membersCount.Data.(int64) >= int64(*a.Config().TeamSettings.MaxUsersPerTeam) {
   308  			return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.max_accounts.app_error", nil, "teamId="+tm.TeamId, http.StatusBadRequest)
   309  		} else {
   310  			if tmr := <-a.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
   311  				return nil, false, tmr.Err
   312  			} else {
   313  				return tmr.Data.(*model.TeamMember), false, nil
   314  			}
   315  		}
   316  	} else {
   317  		// Membership appears to be missing.  Lets try to add.
   318  		if tmr := <-a.Srv.Store.Team().SaveMember(tm, *a.Config().TeamSettings.MaxUsersPerTeam); tmr.Err != nil {
   319  			return nil, false, tmr.Err
   320  		} else {
   321  			return tmr.Data.(*model.TeamMember), false, nil
   322  		}
   323  	}
   324  }
   325  
   326  func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId string) *model.AppError {
   327  	if _, alreadyAdded, err := a.joinUserToTeam(team, user); err != nil {
   328  		return err
   329  	} else if alreadyAdded {
   330  		return nil
   331  	}
   332  
   333  	if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
   334  		return uua.Err
   335  	}
   336  
   337  	channelRole := model.CHANNEL_USER_ROLE_ID
   338  
   339  	if team.Email == user.Email {
   340  		channelRole = model.CHANNEL_USER_ROLE_ID + " " + model.CHANNEL_ADMIN_ROLE_ID
   341  	}
   342  
   343  	// Soft error if there is an issue joining the default channels
   344  	if err := a.JoinDefaultChannels(team.Id, user, channelRole, userRequestorId); err != nil {
   345  		l4g.Error(utils.T("api.user.create_user.joining.error"), user.Id, team.Id, err)
   346  	}
   347  
   348  	a.ClearSessionCacheForUser(user.Id)
   349  	a.InvalidateCacheForUser(user.Id)
   350  
   351  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil)
   352  	message.Add("team_id", team.Id)
   353  	message.Add("user_id", user.Id)
   354  	a.Publish(message)
   355  
   356  	return nil
   357  }
   358  
   359  func (a *App) GetTeam(teamId string) (*model.Team, *model.AppError) {
   360  	if result := <-a.Srv.Store.Team().Get(teamId); result.Err != nil {
   361  		return nil, result.Err
   362  	} else {
   363  		return result.Data.(*model.Team), nil
   364  	}
   365  }
   366  
   367  func (a *App) GetTeamByName(name string) (*model.Team, *model.AppError) {
   368  	if result := <-a.Srv.Store.Team().GetByName(name); result.Err != nil {
   369  		result.Err.StatusCode = http.StatusNotFound
   370  		return nil, result.Err
   371  	} else {
   372  		return result.Data.(*model.Team), nil
   373  	}
   374  }
   375  
   376  func (a *App) GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) {
   377  	if result := <-a.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
   378  		return nil, result.Err
   379  	} else {
   380  		return result.Data.(*model.Team), nil
   381  	}
   382  }
   383  
   384  func (a *App) GetAllTeams() ([]*model.Team, *model.AppError) {
   385  	if result := <-a.Srv.Store.Team().GetAll(); result.Err != nil {
   386  		return nil, result.Err
   387  	} else {
   388  		return result.Data.([]*model.Team), nil
   389  	}
   390  }
   391  
   392  func (a *App) GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   393  	if result := <-a.Srv.Store.Team().GetAllPage(offset, limit); result.Err != nil {
   394  		return nil, result.Err
   395  	} else {
   396  		return result.Data.([]*model.Team), nil
   397  	}
   398  }
   399  
   400  func (a *App) GetAllOpenTeams() ([]*model.Team, *model.AppError) {
   401  	if result := <-a.Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
   402  		return nil, result.Err
   403  	} else {
   404  		return result.Data.([]*model.Team), nil
   405  	}
   406  }
   407  
   408  func (a *App) SearchAllTeams(term string) ([]*model.Team, *model.AppError) {
   409  	if result := <-a.Srv.Store.Team().SearchAll(term); result.Err != nil {
   410  		return nil, result.Err
   411  	} else {
   412  		return result.Data.([]*model.Team), nil
   413  	}
   414  }
   415  
   416  func (a *App) SearchOpenTeams(term string) ([]*model.Team, *model.AppError) {
   417  	if result := <-a.Srv.Store.Team().SearchOpen(term); result.Err != nil {
   418  		return nil, result.Err
   419  	} else {
   420  		return result.Data.([]*model.Team), nil
   421  	}
   422  }
   423  
   424  func (a *App) GetAllOpenTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   425  	if result := <-a.Srv.Store.Team().GetAllTeamPageListing(offset, limit); result.Err != nil {
   426  		return nil, result.Err
   427  	} else {
   428  		return result.Data.([]*model.Team), nil
   429  	}
   430  }
   431  
   432  func (a *App) GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) {
   433  	if result := <-a.Srv.Store.Team().GetTeamsByUserId(userId); result.Err != nil {
   434  		return nil, result.Err
   435  	} else {
   436  		return result.Data.([]*model.Team), nil
   437  	}
   438  }
   439  
   440  func (a *App) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
   441  	if result := <-a.Srv.Store.Team().GetMember(teamId, userId); result.Err != nil {
   442  		return nil, result.Err
   443  	} else {
   444  		return result.Data.(*model.TeamMember), nil
   445  	}
   446  }
   447  
   448  func (a *App) GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError) {
   449  	if result := <-a.Srv.Store.Team().GetTeamsForUser(userId); result.Err != nil {
   450  		return nil, result.Err
   451  	} else {
   452  		return result.Data.([]*model.TeamMember), nil
   453  	}
   454  }
   455  
   456  func (a *App) GetTeamMembers(teamId string, offset int, limit int) ([]*model.TeamMember, *model.AppError) {
   457  	if result := <-a.Srv.Store.Team().GetMembers(teamId, offset, limit); result.Err != nil {
   458  		return nil, result.Err
   459  	} else {
   460  		return result.Data.([]*model.TeamMember), nil
   461  	}
   462  }
   463  
   464  func (a *App) GetTeamMembersByIds(teamId string, userIds []string) ([]*model.TeamMember, *model.AppError) {
   465  	if result := <-a.Srv.Store.Team().GetMembersByIds(teamId, userIds); result.Err != nil {
   466  		return nil, result.Err
   467  	} else {
   468  		return result.Data.([]*model.TeamMember), nil
   469  	}
   470  }
   471  
   472  func (a *App) AddTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
   473  	if _, err := a.AddUserToTeam(teamId, userId, ""); err != nil {
   474  		return nil, err
   475  	}
   476  
   477  	var teamMember *model.TeamMember
   478  	var err *model.AppError
   479  	if teamMember, err = a.GetTeamMember(teamId, userId); err != nil {
   480  		return nil, err
   481  	}
   482  
   483  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
   484  	message.Add("team_id", teamId)
   485  	message.Add("user_id", userId)
   486  	a.Publish(message)
   487  
   488  	return teamMember, nil
   489  }
   490  
   491  func (a *App) AddTeamMembers(teamId string, userIds []string, userRequestorId string) ([]*model.TeamMember, *model.AppError) {
   492  	var members []*model.TeamMember
   493  
   494  	for _, userId := range userIds {
   495  		if _, err := a.AddUserToTeam(teamId, userId, userRequestorId); err != nil {
   496  			return nil, err
   497  		}
   498  
   499  		if teamMember, err := a.GetTeamMember(teamId, userId); err != nil {
   500  			return nil, err
   501  		} else {
   502  			members = append(members, teamMember)
   503  		}
   504  
   505  		message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
   506  		message.Add("team_id", teamId)
   507  		message.Add("user_id", userId)
   508  		a.Publish(message)
   509  	}
   510  
   511  	return members, nil
   512  }
   513  
   514  func (a *App) AddTeamMemberByHash(userId, hash, data string) (*model.TeamMember, *model.AppError) {
   515  	var team *model.Team
   516  	var err *model.AppError
   517  
   518  	if team, err = a.AddUserToTeamByHash(userId, hash, data); err != nil {
   519  		return nil, err
   520  	}
   521  
   522  	if teamMember, err := a.GetTeamMember(team.Id, userId); err != nil {
   523  		return nil, err
   524  	} else {
   525  		return teamMember, nil
   526  	}
   527  }
   528  
   529  func (a *App) AddTeamMemberByInviteId(inviteId, userId string) (*model.TeamMember, *model.AppError) {
   530  	var team *model.Team
   531  	var err *model.AppError
   532  
   533  	if team, err = a.AddUserToTeamByInviteId(inviteId, userId); err != nil {
   534  		return nil, err
   535  	}
   536  
   537  	if teamMember, err := a.GetTeamMember(team.Id, userId); err != nil {
   538  		return nil, err
   539  	} else {
   540  		return teamMember, nil
   541  	}
   542  }
   543  
   544  func (a *App) GetTeamUnread(teamId, userId string) (*model.TeamUnread, *model.AppError) {
   545  	result := <-a.Srv.Store.Team().GetChannelUnreadsForTeam(teamId, userId)
   546  	if result.Err != nil {
   547  		return nil, result.Err
   548  	}
   549  
   550  	channelUnreads := result.Data.([]*model.ChannelUnread)
   551  	var teamUnread = &model.TeamUnread{
   552  		MsgCount:     0,
   553  		MentionCount: 0,
   554  		TeamId:       teamId,
   555  	}
   556  
   557  	for _, cu := range channelUnreads {
   558  		teamUnread.MentionCount += cu.MentionCount
   559  
   560  		if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION {
   561  			teamUnread.MsgCount += cu.MsgCount
   562  		}
   563  	}
   564  
   565  	return teamUnread, nil
   566  }
   567  
   568  func (a *App) RemoveUserFromTeam(teamId string, userId string, requestorId string) *model.AppError {
   569  	tchan := a.Srv.Store.Team().Get(teamId)
   570  	uchan := a.Srv.Store.User().Get(userId)
   571  
   572  	var team *model.Team
   573  	if result := <-tchan; result.Err != nil {
   574  		return result.Err
   575  	} else {
   576  		team = result.Data.(*model.Team)
   577  	}
   578  
   579  	var user *model.User
   580  	if result := <-uchan; result.Err != nil {
   581  		return result.Err
   582  	} else {
   583  		user = result.Data.(*model.User)
   584  	}
   585  
   586  	if err := a.LeaveTeam(team, user, requestorId); err != nil {
   587  		return err
   588  	}
   589  
   590  	return nil
   591  }
   592  
   593  func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string) *model.AppError {
   594  	var teamMember *model.TeamMember
   595  	var err *model.AppError
   596  
   597  	if teamMember, err = a.GetTeamMember(team.Id, user.Id); err != nil {
   598  		return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest)
   599  	}
   600  
   601  	var channelList *model.ChannelList
   602  
   603  	if result := <-a.Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil {
   604  		if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
   605  			channelList = &model.ChannelList{}
   606  		} else {
   607  			return result.Err
   608  		}
   609  
   610  	} else {
   611  		channelList = result.Data.(*model.ChannelList)
   612  	}
   613  
   614  	for _, channel := range *channelList {
   615  		if !channel.IsGroupOrDirect() {
   616  			a.InvalidateCacheForChannelMembers(channel.Id)
   617  			if result := <-a.Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
   618  				return result.Err
   619  			}
   620  		}
   621  	}
   622  
   623  	var channel *model.Channel
   624  	if result := <-a.Srv.Store.Channel().GetByName(team.Id, model.DEFAULT_CHANNEL, false); result.Err != nil {
   625  		return result.Err
   626  	} else {
   627  		channel = result.Data.(*model.Channel)
   628  	}
   629  
   630  	if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
   631  		if requestorId == user.Id {
   632  			if err := a.postLeaveTeamMessage(user, channel); err != nil {
   633  				l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
   634  			}
   635  		} else {
   636  			if err := a.postRemoveFromTeamMessage(user, channel); err != nil {
   637  				l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
   638  			}
   639  		}
   640  	}
   641  
   642  	// Send the websocket message before we actually do the remove so the user being removed gets it.
   643  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil)
   644  	message.Add("user_id", user.Id)
   645  	message.Add("team_id", team.Id)
   646  	a.Publish(message)
   647  
   648  	teamMember.Roles = ""
   649  	teamMember.DeleteAt = model.GetMillis()
   650  
   651  	if result := <-a.Srv.Store.Team().UpdateMember(teamMember); result.Err != nil {
   652  		return result.Err
   653  	}
   654  
   655  	if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
   656  		return uua.Err
   657  	}
   658  
   659  	// delete the preferences that set the last channel used in the team and other team specific preferences
   660  	if result := <-a.Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil {
   661  		return result.Err
   662  	}
   663  
   664  	a.ClearSessionCacheForUser(user.Id)
   665  	a.InvalidateCacheForUser(user.Id)
   666  
   667  	return nil
   668  }
   669  
   670  func (a *App) postLeaveTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
   671  	post := &model.Post{
   672  		ChannelId: channel.Id,
   673  		Message:   fmt.Sprintf(utils.T("api.team.leave.left"), user.Username),
   674  		Type:      model.POST_LEAVE_TEAM,
   675  		UserId:    user.Id,
   676  		Props: model.StringInterface{
   677  			"username": user.Username,
   678  		},
   679  	}
   680  
   681  	if _, err := a.CreatePost(post, channel, false); err != nil {
   682  		return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   683  	}
   684  
   685  	return nil
   686  }
   687  
   688  func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
   689  	post := &model.Post{
   690  		ChannelId: channel.Id,
   691  		Message:   fmt.Sprintf(utils.T("api.team.remove_user_from_team.removed"), user.Username),
   692  		Type:      model.POST_REMOVE_FROM_TEAM,
   693  		UserId:    user.Id,
   694  		Props: model.StringInterface{
   695  			"username": user.Username,
   696  		},
   697  	}
   698  
   699  	if _, err := a.CreatePost(post, channel, false); err != nil {
   700  		return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   701  	}
   702  
   703  	return nil
   704  }
   705  
   706  func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string) *model.AppError {
   707  	if len(emailList) == 0 {
   708  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
   709  		return err
   710  	}
   711  
   712  	var invalidEmailList []string
   713  
   714  	for _, email := range emailList {
   715  		if !a.isTeamEmailAddressAllowed(email) {
   716  			invalidEmailList = append(invalidEmailList, email)
   717  		}
   718  	}
   719  
   720  	if len(invalidEmailList) > 0 {
   721  		s := strings.Join(invalidEmailList, ", ")
   722  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest)
   723  		return err
   724  	}
   725  
   726  	tchan := a.Srv.Store.Team().Get(teamId)
   727  	uchan := a.Srv.Store.User().Get(senderId)
   728  
   729  	var team *model.Team
   730  	if result := <-tchan; result.Err != nil {
   731  		return result.Err
   732  	} else {
   733  		team = result.Data.(*model.Team)
   734  	}
   735  
   736  	var user *model.User
   737  	if result := <-uchan; result.Err != nil {
   738  		return result.Err
   739  	} else {
   740  		user = result.Data.(*model.User)
   741  	}
   742  
   743  	nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
   744  	a.SendInviteEmails(team, user.GetDisplayName(nameFormat), emailList, a.GetSiteURL())
   745  
   746  	return nil
   747  }
   748  
   749  func (a *App) FindTeamByName(name string) bool {
   750  	if result := <-a.Srv.Store.Team().GetByName(name); result.Err != nil {
   751  		return false
   752  	} else {
   753  		return true
   754  	}
   755  }
   756  
   757  func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError) {
   758  	if result := <-a.Srv.Store.Team().GetChannelUnreadsForAllTeams(excludeTeamId, userId); result.Err != nil {
   759  		return nil, result.Err
   760  	} else {
   761  		data := result.Data.([]*model.ChannelUnread)
   762  		members := []*model.TeamUnread{}
   763  		membersMap := make(map[string]*model.TeamUnread)
   764  
   765  		unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
   766  			tu.MentionCount += cu.MentionCount
   767  
   768  			if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION {
   769  				tu.MsgCount += cu.MsgCount
   770  			}
   771  
   772  			return tu
   773  		}
   774  
   775  		for i := range data {
   776  			id := data[i].TeamId
   777  			if mu, ok := membersMap[id]; ok {
   778  				membersMap[id] = unreads(data[i], mu)
   779  			} else {
   780  				membersMap[id] = unreads(data[i], &model.TeamUnread{
   781  					MsgCount:     0,
   782  					MentionCount: 0,
   783  					TeamId:       id,
   784  				})
   785  			}
   786  		}
   787  
   788  		for _, val := range membersMap {
   789  			members = append(members, val)
   790  		}
   791  
   792  		return members, nil
   793  	}
   794  }
   795  
   796  func (a *App) PermanentDeleteTeamId(teamId string) *model.AppError {
   797  	team, err := a.GetTeam(teamId)
   798  	if err != nil {
   799  		return err
   800  	}
   801  
   802  	return a.PermanentDeleteTeam(team)
   803  }
   804  
   805  func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError {
   806  	team.DeleteAt = model.GetMillis()
   807  	if result := <-a.Srv.Store.Team().Update(team); result.Err != nil {
   808  		return result.Err
   809  	}
   810  
   811  	if result := <-a.Srv.Store.Channel().GetTeamChannels(team.Id); result.Err != nil {
   812  		if result.Err.Id != "store.sql_channel.get_channels.not_found.app_error" {
   813  			return result.Err
   814  		}
   815  	} else {
   816  		channels := result.Data.(*model.ChannelList)
   817  		for _, c := range *channels {
   818  			a.PermanentDeleteChannel(c)
   819  		}
   820  	}
   821  
   822  	if result := <-a.Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
   823  		return result.Err
   824  	}
   825  
   826  	if result := <-a.Srv.Store.Command().PermanentDeleteByTeam(team.Id); result.Err != nil {
   827  		return result.Err
   828  	}
   829  
   830  	if result := <-a.Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil {
   831  		return result.Err
   832  	}
   833  
   834  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
   835  
   836  	return nil
   837  }
   838  
   839  func (a *App) SoftDeleteTeam(teamId string) *model.AppError {
   840  	team, err := a.GetTeam(teamId)
   841  	if err != nil {
   842  		return err
   843  	}
   844  
   845  	team.DeleteAt = model.GetMillis()
   846  	if result := <-a.Srv.Store.Team().Update(team); result.Err != nil {
   847  		return result.Err
   848  	}
   849  
   850  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_DELETE_TEAM)
   851  
   852  	return nil
   853  }
   854  
   855  func (a *App) GetTeamStats(teamId string) (*model.TeamStats, *model.AppError) {
   856  	tchan := a.Srv.Store.Team().GetTotalMemberCount(teamId)
   857  	achan := a.Srv.Store.Team().GetActiveMemberCount(teamId)
   858  
   859  	stats := &model.TeamStats{}
   860  	stats.TeamId = teamId
   861  
   862  	if result := <-tchan; result.Err != nil {
   863  		return nil, result.Err
   864  	} else {
   865  		stats.TotalMemberCount = result.Data.(int64)
   866  	}
   867  
   868  	if result := <-achan; result.Err != nil {
   869  		return nil, result.Err
   870  	} else {
   871  		stats.ActiveMemberCount = result.Data.(int64)
   872  	}
   873  
   874  	return stats, nil
   875  }
   876  
   877  func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
   878  	hash := query.Get("h")
   879  	inviteId := query.Get("id")
   880  
   881  	if len(hash) > 0 {
   882  		data := query.Get("d")
   883  		props := model.MapFromJson(strings.NewReader(data))
   884  
   885  		if hash != utils.HashSha256(fmt.Sprintf("%v:%v", data, a.Config().EmailSettings.InviteSalt)) {
   886  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
   887  		}
   888  
   889  		t, err := strconv.ParseInt(props["time"], 10, 64)
   890  		if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
   891  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest)
   892  		}
   893  
   894  		return props["id"], nil
   895  	} else if len(inviteId) > 0 {
   896  		if result := <-a.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
   897  			// soft fail, so we still create user but don't auto-join team
   898  			l4g.Error("%v", result.Err)
   899  		} else {
   900  			return result.Data.(*model.Team).Id, nil
   901  		}
   902  	}
   903  
   904  	return "", nil
   905  }
   906  
   907  func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
   908  	if !a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_MANAGE_TEAM) {
   909  		team.Sanitize()
   910  	}
   911  
   912  	return team
   913  }
   914  
   915  func (a *App) SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team {
   916  	for _, team := range teams {
   917  		a.SanitizeTeam(session, team)
   918  	}
   919  
   920  	return teams
   921  }
   922  
   923  func (a *App) GetTeamIcon(team *model.Team) ([]byte, *model.AppError) {
   924  	if len(*a.Config().FileSettings.DriverName) == 0 {
   925  		return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.filesettings_no_driver.app_error", nil, "", http.StatusNotImplemented)
   926  	} else {
   927  		path := "teams/" + team.Id + "/teamIcon.png"
   928  		if data, err := a.ReadFile(path); err != nil {
   929  			return nil, model.NewAppError("GetTeamIcon", "api.team.get_team_icon.read_file.app_error", nil, err.Error(), http.StatusNotFound)
   930  		} else {
   931  			return data, nil
   932  		}
   933  	}
   934  }
   935  
   936  func (a *App) SetTeamIcon(teamId string, imageData *multipart.FileHeader) *model.AppError {
   937  	file, err := imageData.Open()
   938  	if err != nil {
   939  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.open.app_error", nil, err.Error(), http.StatusBadRequest)
   940  	}
   941  	defer file.Close()
   942  	return a.SetTeamIconFromFile(teamId, file)
   943  }
   944  
   945  func (a *App) SetTeamIconFromFile(teamId string, file multipart.File) *model.AppError {
   946  
   947  	team, getTeamErr := a.GetTeam(teamId)
   948  
   949  	if getTeamErr != nil {
   950  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.get_team.app_error", nil, getTeamErr.Error(), http.StatusBadRequest)
   951  	}
   952  
   953  	if len(*a.Config().FileSettings.DriverName) == 0 {
   954  		return model.NewAppError("setTeamIcon", "api.team.set_team_icon.storage.app_error", nil, "", http.StatusNotImplemented)
   955  	}
   956  
   957  	// Decode image config first to check dimensions before loading the whole thing into memory later on
   958  	config, _, err := image.DecodeConfig(file)
   959  	if err != nil {
   960  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode_config.app_error", nil, err.Error(), http.StatusBadRequest)
   961  	} else if config.Width*config.Height > model.MaxImageSize {
   962  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.too_large.app_error", nil, err.Error(), http.StatusBadRequest)
   963  	}
   964  
   965  	file.Seek(0, 0)
   966  
   967  	// Decode image into Image object
   968  	img, _, err := image.Decode(file)
   969  	if err != nil {
   970  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.decode.app_error", nil, err.Error(), http.StatusBadRequest)
   971  	}
   972  
   973  	file.Seek(0, 0)
   974  
   975  	orientation, _ := getImageOrientation(file)
   976  	img = makeImageUpright(img, orientation)
   977  
   978  	// Scale team icon
   979  	teamIconWidthAndHeight := 128
   980  	img = imaging.Fill(img, teamIconWidthAndHeight, teamIconWidthAndHeight, imaging.Center, imaging.Lanczos)
   981  
   982  	buf := new(bytes.Buffer)
   983  	err = png.Encode(buf, img)
   984  	if err != nil {
   985  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.encode.app_error", nil, err.Error(), http.StatusInternalServerError)
   986  	}
   987  
   988  	path := "teams/" + teamId + "/teamIcon.png"
   989  
   990  	if err := a.WriteFile(buf.Bytes(), path); err != nil {
   991  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.write_file.app_error", nil, "", http.StatusInternalServerError)
   992  	}
   993  
   994  	curTime := model.GetMillis()
   995  
   996  	if result := <-a.Srv.Store.Team().UpdateLastTeamIconUpdate(teamId, curTime); result.Err != nil {
   997  		return model.NewAppError("SetTeamIcon", "api.team.set_team_icon.update.app_error", nil, result.Err.Error(), http.StatusBadRequest)
   998  	}
   999  
  1000  	// manually set time to avoid possible cluster inconsistencies
  1001  	team.LastTeamIconUpdate = curTime
  1002  
  1003  	a.sendTeamEvent(team, model.WEBSOCKET_EVENT_UPDATE_TEAM)
  1004  
  1005  	return nil
  1006  }