github.com/psyb0t/mattermost-server@v4.6.1-0.20180125161845-5503a1351abf+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.sendUpdatedTeamEvent(oldTeam)
   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.sendUpdatedTeamEvent(updatedTeam)
   126  
   127  	return updatedTeam, nil
   128  }
   129  
   130  func (a *App) sendUpdatedTeamEvent(team *model.Team) {
   131  	sanitizedTeam := &model.Team{}
   132  	*sanitizedTeam = *team
   133  	sanitizedTeam.Sanitize()
   134  
   135  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_UPDATE_TEAM, "", "", "", 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 tmr := <-a.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil {
   301  			return nil, false, tmr.Err
   302  		} else {
   303  			return tmr.Data.(*model.TeamMember), false, nil
   304  		}
   305  	} else {
   306  		// Membership appears to be missing.  Lets try to add.
   307  		if tmr := <-a.Srv.Store.Team().SaveMember(tm, *a.Config().TeamSettings.MaxUsersPerTeam); tmr.Err != nil {
   308  			return nil, false, tmr.Err
   309  		} else {
   310  			return tmr.Data.(*model.TeamMember), false, nil
   311  		}
   312  	}
   313  }
   314  
   315  func (a *App) JoinUserToTeam(team *model.Team, user *model.User, userRequestorId string) *model.AppError {
   316  	if _, alreadyAdded, err := a.joinUserToTeam(team, user); err != nil {
   317  		return err
   318  	} else if alreadyAdded {
   319  		return nil
   320  	}
   321  
   322  	if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
   323  		return uua.Err
   324  	}
   325  
   326  	channelRole := model.CHANNEL_USER_ROLE_ID
   327  
   328  	if team.Email == user.Email {
   329  		channelRole = model.CHANNEL_USER_ROLE_ID + " " + model.CHANNEL_ADMIN_ROLE_ID
   330  	}
   331  
   332  	// Soft error if there is an issue joining the default channels
   333  	if err := a.JoinDefaultChannels(team.Id, user, channelRole, userRequestorId); err != nil {
   334  		l4g.Error(utils.T("api.user.create_user.joining.error"), user.Id, team.Id, err)
   335  	}
   336  
   337  	a.ClearSessionCacheForUser(user.Id)
   338  	a.InvalidateCacheForUser(user.Id)
   339  
   340  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", user.Id, nil)
   341  	message.Add("team_id", team.Id)
   342  	message.Add("user_id", user.Id)
   343  	a.Publish(message)
   344  
   345  	return nil
   346  }
   347  
   348  func (a *App) GetTeam(teamId string) (*model.Team, *model.AppError) {
   349  	if result := <-a.Srv.Store.Team().Get(teamId); result.Err != nil {
   350  		return nil, result.Err
   351  	} else {
   352  		return result.Data.(*model.Team), nil
   353  	}
   354  }
   355  
   356  func (a *App) GetTeamByName(name string) (*model.Team, *model.AppError) {
   357  	if result := <-a.Srv.Store.Team().GetByName(name); result.Err != nil {
   358  		result.Err.StatusCode = http.StatusNotFound
   359  		return nil, result.Err
   360  	} else {
   361  		return result.Data.(*model.Team), nil
   362  	}
   363  }
   364  
   365  func (a *App) GetTeamByInviteId(inviteId string) (*model.Team, *model.AppError) {
   366  	if result := <-a.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
   367  		return nil, result.Err
   368  	} else {
   369  		return result.Data.(*model.Team), nil
   370  	}
   371  }
   372  
   373  func (a *App) GetAllTeams() ([]*model.Team, *model.AppError) {
   374  	if result := <-a.Srv.Store.Team().GetAll(); result.Err != nil {
   375  		return nil, result.Err
   376  	} else {
   377  		return result.Data.([]*model.Team), nil
   378  	}
   379  }
   380  
   381  func (a *App) GetAllTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   382  	if result := <-a.Srv.Store.Team().GetAllPage(offset, limit); result.Err != nil {
   383  		return nil, result.Err
   384  	} else {
   385  		return result.Data.([]*model.Team), nil
   386  	}
   387  }
   388  
   389  func (a *App) GetAllOpenTeams() ([]*model.Team, *model.AppError) {
   390  	if result := <-a.Srv.Store.Team().GetAllTeamListing(); result.Err != nil {
   391  		return nil, result.Err
   392  	} else {
   393  		return result.Data.([]*model.Team), nil
   394  	}
   395  }
   396  
   397  func (a *App) SearchAllTeams(term string) ([]*model.Team, *model.AppError) {
   398  	if result := <-a.Srv.Store.Team().SearchAll(term); result.Err != nil {
   399  		return nil, result.Err
   400  	} else {
   401  		return result.Data.([]*model.Team), nil
   402  	}
   403  }
   404  
   405  func (a *App) SearchOpenTeams(term string) ([]*model.Team, *model.AppError) {
   406  	if result := <-a.Srv.Store.Team().SearchOpen(term); result.Err != nil {
   407  		return nil, result.Err
   408  	} else {
   409  		return result.Data.([]*model.Team), nil
   410  	}
   411  }
   412  
   413  func (a *App) GetAllOpenTeamsPage(offset int, limit int) ([]*model.Team, *model.AppError) {
   414  	if result := <-a.Srv.Store.Team().GetAllTeamPageListing(offset, limit); result.Err != nil {
   415  		return nil, result.Err
   416  	} else {
   417  		return result.Data.([]*model.Team), nil
   418  	}
   419  }
   420  
   421  func (a *App) GetTeamsForUser(userId string) ([]*model.Team, *model.AppError) {
   422  	if result := <-a.Srv.Store.Team().GetTeamsByUserId(userId); result.Err != nil {
   423  		return nil, result.Err
   424  	} else {
   425  		return result.Data.([]*model.Team), nil
   426  	}
   427  }
   428  
   429  func (a *App) GetTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
   430  	if result := <-a.Srv.Store.Team().GetMember(teamId, userId); result.Err != nil {
   431  		return nil, result.Err
   432  	} else {
   433  		return result.Data.(*model.TeamMember), nil
   434  	}
   435  }
   436  
   437  func (a *App) GetTeamMembersForUser(userId string) ([]*model.TeamMember, *model.AppError) {
   438  	if result := <-a.Srv.Store.Team().GetTeamsForUser(userId); result.Err != nil {
   439  		return nil, result.Err
   440  	} else {
   441  		return result.Data.([]*model.TeamMember), nil
   442  	}
   443  }
   444  
   445  func (a *App) GetTeamMembers(teamId string, offset int, limit int) ([]*model.TeamMember, *model.AppError) {
   446  	if result := <-a.Srv.Store.Team().GetMembers(teamId, offset, limit); result.Err != nil {
   447  		return nil, result.Err
   448  	} else {
   449  		return result.Data.([]*model.TeamMember), nil
   450  	}
   451  }
   452  
   453  func (a *App) GetTeamMembersByIds(teamId string, userIds []string) ([]*model.TeamMember, *model.AppError) {
   454  	if result := <-a.Srv.Store.Team().GetMembersByIds(teamId, userIds); result.Err != nil {
   455  		return nil, result.Err
   456  	} else {
   457  		return result.Data.([]*model.TeamMember), nil
   458  	}
   459  }
   460  
   461  func (a *App) AddTeamMember(teamId, userId string) (*model.TeamMember, *model.AppError) {
   462  	if _, err := a.AddUserToTeam(teamId, userId, ""); err != nil {
   463  		return nil, err
   464  	}
   465  
   466  	var teamMember *model.TeamMember
   467  	var err *model.AppError
   468  	if teamMember, err = a.GetTeamMember(teamId, userId); err != nil {
   469  		return nil, err
   470  	}
   471  
   472  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
   473  	message.Add("team_id", teamId)
   474  	message.Add("user_id", userId)
   475  	a.Publish(message)
   476  
   477  	return teamMember, nil
   478  }
   479  
   480  func (a *App) AddTeamMembers(teamId string, userIds []string, userRequestorId string) ([]*model.TeamMember, *model.AppError) {
   481  	var members []*model.TeamMember
   482  
   483  	for _, userId := range userIds {
   484  		if _, err := a.AddUserToTeam(teamId, userId, userRequestorId); err != nil {
   485  			return nil, err
   486  		}
   487  
   488  		if teamMember, err := a.GetTeamMember(teamId, userId); err != nil {
   489  			return nil, err
   490  		} else {
   491  			members = append(members, teamMember)
   492  		}
   493  
   494  		message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_ADDED_TO_TEAM, "", "", userId, nil)
   495  		message.Add("team_id", teamId)
   496  		message.Add("user_id", userId)
   497  		a.Publish(message)
   498  	}
   499  
   500  	return members, nil
   501  }
   502  
   503  func (a *App) AddTeamMemberByHash(userId, hash, data string) (*model.TeamMember, *model.AppError) {
   504  	var team *model.Team
   505  	var err *model.AppError
   506  
   507  	if team, err = a.AddUserToTeamByHash(userId, hash, data); err != nil {
   508  		return nil, err
   509  	}
   510  
   511  	if teamMember, err := a.GetTeamMember(team.Id, userId); err != nil {
   512  		return nil, err
   513  	} else {
   514  		return teamMember, nil
   515  	}
   516  }
   517  
   518  func (a *App) AddTeamMemberByInviteId(inviteId, userId string) (*model.TeamMember, *model.AppError) {
   519  	var team *model.Team
   520  	var err *model.AppError
   521  
   522  	if team, err = a.AddUserToTeamByInviteId(inviteId, userId); err != nil {
   523  		return nil, err
   524  	}
   525  
   526  	if teamMember, err := a.GetTeamMember(team.Id, userId); err != nil {
   527  		return nil, err
   528  	} else {
   529  		return teamMember, nil
   530  	}
   531  }
   532  
   533  func (a *App) GetTeamUnread(teamId, userId string) (*model.TeamUnread, *model.AppError) {
   534  	result := <-a.Srv.Store.Team().GetChannelUnreadsForTeam(teamId, userId)
   535  	if result.Err != nil {
   536  		return nil, result.Err
   537  	}
   538  
   539  	channelUnreads := result.Data.([]*model.ChannelUnread)
   540  	var teamUnread = &model.TeamUnread{
   541  		MsgCount:     0,
   542  		MentionCount: 0,
   543  		TeamId:       teamId,
   544  	}
   545  
   546  	for _, cu := range channelUnreads {
   547  		teamUnread.MentionCount += cu.MentionCount
   548  
   549  		if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION {
   550  			teamUnread.MsgCount += cu.MsgCount
   551  		}
   552  	}
   553  
   554  	return teamUnread, nil
   555  }
   556  
   557  func (a *App) RemoveUserFromTeam(teamId string, userId string, requestorId string) *model.AppError {
   558  	tchan := a.Srv.Store.Team().Get(teamId)
   559  	uchan := a.Srv.Store.User().Get(userId)
   560  
   561  	var team *model.Team
   562  	if result := <-tchan; result.Err != nil {
   563  		return result.Err
   564  	} else {
   565  		team = result.Data.(*model.Team)
   566  	}
   567  
   568  	var user *model.User
   569  	if result := <-uchan; result.Err != nil {
   570  		return result.Err
   571  	} else {
   572  		user = result.Data.(*model.User)
   573  	}
   574  
   575  	if err := a.LeaveTeam(team, user, requestorId); err != nil {
   576  		return err
   577  	}
   578  
   579  	return nil
   580  }
   581  
   582  func (a *App) LeaveTeam(team *model.Team, user *model.User, requestorId string) *model.AppError {
   583  	var teamMember *model.TeamMember
   584  	var err *model.AppError
   585  
   586  	if teamMember, err = a.GetTeamMember(team.Id, user.Id); err != nil {
   587  		return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest)
   588  	}
   589  
   590  	var channelList *model.ChannelList
   591  
   592  	if result := <-a.Srv.Store.Channel().GetChannels(team.Id, user.Id); result.Err != nil {
   593  		if result.Err.Id == "store.sql_channel.get_channels.not_found.app_error" {
   594  			channelList = &model.ChannelList{}
   595  		} else {
   596  			return result.Err
   597  		}
   598  
   599  	} else {
   600  		channelList = result.Data.(*model.ChannelList)
   601  	}
   602  
   603  	for _, channel := range *channelList {
   604  		if !channel.IsGroupOrDirect() {
   605  			a.InvalidateCacheForChannelMembers(channel.Id)
   606  			if result := <-a.Srv.Store.Channel().RemoveMember(channel.Id, user.Id); result.Err != nil {
   607  				return result.Err
   608  			}
   609  		}
   610  	}
   611  
   612  	var channel *model.Channel
   613  	if result := <-a.Srv.Store.Channel().GetByName(team.Id, model.DEFAULT_CHANNEL, false); result.Err != nil {
   614  		return result.Err
   615  	} else {
   616  		channel = result.Data.(*model.Channel)
   617  	}
   618  
   619  	if *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages {
   620  		if requestorId == user.Id {
   621  			if err := a.postLeaveTeamMessage(user, channel); err != nil {
   622  				l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
   623  			}
   624  		} else {
   625  			if err := a.postRemoveFromTeamMessage(user, channel); err != nil {
   626  				l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
   627  			}
   628  		}
   629  	}
   630  
   631  	// Send the websocket message before we actually do the remove so the user being removed gets it.
   632  	message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LEAVE_TEAM, team.Id, "", "", nil)
   633  	message.Add("user_id", user.Id)
   634  	message.Add("team_id", team.Id)
   635  	a.Publish(message)
   636  
   637  	teamMember.Roles = ""
   638  	teamMember.DeleteAt = model.GetMillis()
   639  
   640  	if result := <-a.Srv.Store.Team().UpdateMember(teamMember); result.Err != nil {
   641  		return result.Err
   642  	}
   643  
   644  	if uua := <-a.Srv.Store.User().UpdateUpdateAt(user.Id); uua.Err != nil {
   645  		return uua.Err
   646  	}
   647  
   648  	// delete the preferences that set the last channel used in the team and other team specific preferences
   649  	if result := <-a.Srv.Store.Preference().DeleteCategory(user.Id, team.Id); result.Err != nil {
   650  		return result.Err
   651  	}
   652  
   653  	a.ClearSessionCacheForUser(user.Id)
   654  	a.InvalidateCacheForUser(user.Id)
   655  
   656  	return nil
   657  }
   658  
   659  func (a *App) postLeaveTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
   660  	post := &model.Post{
   661  		ChannelId: channel.Id,
   662  		Message:   fmt.Sprintf(utils.T("api.team.leave.left"), user.Username),
   663  		Type:      model.POST_LEAVE_TEAM,
   664  		UserId:    user.Id,
   665  		Props: model.StringInterface{
   666  			"username": user.Username,
   667  		},
   668  	}
   669  
   670  	if _, err := a.CreatePost(post, channel, false); err != nil {
   671  		return model.NewAppError("postRemoveFromChannelMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   672  	}
   673  
   674  	return nil
   675  }
   676  
   677  func (a *App) postRemoveFromTeamMessage(user *model.User, channel *model.Channel) *model.AppError {
   678  	post := &model.Post{
   679  		ChannelId: channel.Id,
   680  		Message:   fmt.Sprintf(utils.T("api.team.remove_user_from_team.removed"), user.Username),
   681  		Type:      model.POST_REMOVE_FROM_TEAM,
   682  		UserId:    user.Id,
   683  		Props: model.StringInterface{
   684  			"removedUsername": user.Username,
   685  		},
   686  	}
   687  
   688  	if _, err := a.CreatePost(post, channel, false); err != nil {
   689  		return model.NewAppError("postRemoveFromTeamMessage", "api.channel.post_user_add_remove_message_and_forget.error", nil, err.Error(), http.StatusInternalServerError)
   690  	}
   691  
   692  	return nil
   693  }
   694  
   695  func (a *App) InviteNewUsersToTeam(emailList []string, teamId, senderId string) *model.AppError {
   696  	if len(emailList) == 0 {
   697  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.no_one.app_error", nil, "", http.StatusBadRequest)
   698  		return err
   699  	}
   700  
   701  	var invalidEmailList []string
   702  
   703  	for _, email := range emailList {
   704  		if !a.isTeamEmailAddressAllowed(email) {
   705  			invalidEmailList = append(invalidEmailList, email)
   706  		}
   707  	}
   708  
   709  	if len(invalidEmailList) > 0 {
   710  		s := strings.Join(invalidEmailList, ", ")
   711  		err := model.NewAppError("InviteNewUsersToTeam", "api.team.invite_members.invalid_email.app_error", map[string]interface{}{"Addresses": s}, "", http.StatusBadRequest)
   712  		return err
   713  	}
   714  
   715  	tchan := a.Srv.Store.Team().Get(teamId)
   716  	uchan := a.Srv.Store.User().Get(senderId)
   717  
   718  	var team *model.Team
   719  	if result := <-tchan; result.Err != nil {
   720  		return result.Err
   721  	} else {
   722  		team = result.Data.(*model.Team)
   723  	}
   724  
   725  	var user *model.User
   726  	if result := <-uchan; result.Err != nil {
   727  		return result.Err
   728  	} else {
   729  		user = result.Data.(*model.User)
   730  	}
   731  
   732  	nameFormat := *a.Config().TeamSettings.TeammateNameDisplay
   733  	a.SendInviteEmails(team, user.GetDisplayName(nameFormat), emailList, utils.GetSiteURL())
   734  
   735  	return nil
   736  }
   737  
   738  func (a *App) FindTeamByName(name string) bool {
   739  	if result := <-a.Srv.Store.Team().GetByName(name); result.Err != nil {
   740  		return false
   741  	} else {
   742  		return true
   743  	}
   744  }
   745  
   746  func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userId string) ([]*model.TeamUnread, *model.AppError) {
   747  	if result := <-a.Srv.Store.Team().GetChannelUnreadsForAllTeams(excludeTeamId, userId); result.Err != nil {
   748  		return nil, result.Err
   749  	} else {
   750  		data := result.Data.([]*model.ChannelUnread)
   751  		members := []*model.TeamUnread{}
   752  		membersMap := make(map[string]*model.TeamUnread)
   753  
   754  		unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
   755  			tu.MentionCount += cu.MentionCount
   756  
   757  			if cu.NotifyProps["mark_unread"] != model.CHANNEL_MARK_UNREAD_MENTION {
   758  				tu.MsgCount += cu.MsgCount
   759  			}
   760  
   761  			return tu
   762  		}
   763  
   764  		for i := range data {
   765  			id := data[i].TeamId
   766  			if mu, ok := membersMap[id]; ok {
   767  				membersMap[id] = unreads(data[i], mu)
   768  			} else {
   769  				membersMap[id] = unreads(data[i], &model.TeamUnread{
   770  					MsgCount:     0,
   771  					MentionCount: 0,
   772  					TeamId:       id,
   773  				})
   774  			}
   775  		}
   776  
   777  		for _, val := range membersMap {
   778  			members = append(members, val)
   779  		}
   780  
   781  		return members, nil
   782  	}
   783  }
   784  
   785  func (a *App) PermanentDeleteTeamId(teamId string) *model.AppError {
   786  	team, err := a.GetTeam(teamId)
   787  	if err != nil {
   788  		return err
   789  	}
   790  
   791  	return a.PermanentDeleteTeam(team)
   792  }
   793  
   794  func (a *App) PermanentDeleteTeam(team *model.Team) *model.AppError {
   795  	team.DeleteAt = model.GetMillis()
   796  	if result := <-a.Srv.Store.Team().Update(team); result.Err != nil {
   797  		return result.Err
   798  	}
   799  
   800  	if result := <-a.Srv.Store.Channel().GetTeamChannels(team.Id); result.Err != nil {
   801  		if result.Err.Id != "store.sql_channel.get_channels.not_found.app_error" {
   802  			return result.Err
   803  		}
   804  	} else {
   805  		channels := result.Data.(*model.ChannelList)
   806  		for _, c := range *channels {
   807  			a.PermanentDeleteChannel(c)
   808  		}
   809  	}
   810  
   811  	if result := <-a.Srv.Store.Team().RemoveAllMembersByTeam(team.Id); result.Err != nil {
   812  		return result.Err
   813  	}
   814  
   815  	if result := <-a.Srv.Store.Command().PermanentDeleteByTeam(team.Id); result.Err != nil {
   816  		return result.Err
   817  	}
   818  
   819  	if result := <-a.Srv.Store.Team().PermanentDelete(team.Id); result.Err != nil {
   820  		return result.Err
   821  	}
   822  
   823  	return nil
   824  }
   825  
   826  func (a *App) SoftDeleteTeam(teamId string) *model.AppError {
   827  	team, err := a.GetTeam(teamId)
   828  	if err != nil {
   829  		return err
   830  	}
   831  
   832  	team.DeleteAt = model.GetMillis()
   833  	if result := <-a.Srv.Store.Team().Update(team); result.Err != nil {
   834  		return result.Err
   835  	}
   836  
   837  	return nil
   838  }
   839  
   840  func (a *App) GetTeamStats(teamId string) (*model.TeamStats, *model.AppError) {
   841  	tchan := a.Srv.Store.Team().GetTotalMemberCount(teamId)
   842  	achan := a.Srv.Store.Team().GetActiveMemberCount(teamId)
   843  
   844  	stats := &model.TeamStats{}
   845  	stats.TeamId = teamId
   846  
   847  	if result := <-tchan; result.Err != nil {
   848  		return nil, result.Err
   849  	} else {
   850  		stats.TotalMemberCount = result.Data.(int64)
   851  	}
   852  
   853  	if result := <-achan; result.Err != nil {
   854  		return nil, result.Err
   855  	} else {
   856  		stats.ActiveMemberCount = result.Data.(int64)
   857  	}
   858  
   859  	return stats, nil
   860  }
   861  
   862  func (a *App) GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
   863  	hash := query.Get("h")
   864  	inviteId := query.Get("id")
   865  
   866  	if len(hash) > 0 {
   867  		data := query.Get("d")
   868  		props := model.MapFromJson(strings.NewReader(data))
   869  
   870  		if hash != utils.HashSha256(fmt.Sprintf("%v:%v", data, a.Config().EmailSettings.InviteSalt)) {
   871  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
   872  		}
   873  
   874  		t, err := strconv.ParseInt(props["time"], 10, 64)
   875  		if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
   876  			return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest)
   877  		}
   878  
   879  		return props["id"], nil
   880  	} else if len(inviteId) > 0 {
   881  		if result := <-a.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
   882  			// soft fail, so we still create user but don't auto-join team
   883  			l4g.Error("%v", result.Err)
   884  		} else {
   885  			return result.Data.(*model.Team).Id, nil
   886  		}
   887  	}
   888  
   889  	return "", nil
   890  }
   891  
   892  func (a *App) SanitizeTeam(session model.Session, team *model.Team) *model.Team {
   893  	if !a.SessionHasPermissionToTeam(session, team.Id, model.PERMISSION_MANAGE_TEAM) {
   894  		team.Sanitize()
   895  	}
   896  
   897  	return team
   898  }
   899  
   900  func (a *App) SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team {
   901  	for _, team := range teams {
   902  		a.SanitizeTeam(session, team)
   903  	}
   904  
   905  	return teams
   906  }