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