github.com/mad-app/mattermost-server@v5.11.1+incompatible/store/sqlstore/team_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"database/sql"
     8  	"net/http"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/mattermost/gorp"
    13  	"github.com/mattermost/mattermost-server/model"
    14  	"github.com/mattermost/mattermost-server/store"
    15  )
    16  
    17  const (
    18  	TEAM_MEMBER_EXISTS_ERROR = "store.sql_team.save_member.exists.app_error"
    19  )
    20  
    21  type SqlTeamStore struct {
    22  	SqlStore
    23  }
    24  
    25  type teamMember struct {
    26  	TeamId      string
    27  	UserId      string
    28  	Roles       string
    29  	DeleteAt    int64
    30  	SchemeUser  sql.NullBool
    31  	SchemeAdmin sql.NullBool
    32  }
    33  
    34  func NewTeamMemberFromModel(tm *model.TeamMember) *teamMember {
    35  	return &teamMember{
    36  		TeamId:      tm.TeamId,
    37  		UserId:      tm.UserId,
    38  		Roles:       tm.ExplicitRoles,
    39  		DeleteAt:    tm.DeleteAt,
    40  		SchemeUser:  sql.NullBool{Valid: true, Bool: tm.SchemeUser},
    41  		SchemeAdmin: sql.NullBool{Valid: true, Bool: tm.SchemeAdmin},
    42  	}
    43  }
    44  
    45  type teamMemberWithSchemeRoles struct {
    46  	TeamId                     string
    47  	UserId                     string
    48  	Roles                      string
    49  	DeleteAt                   int64
    50  	SchemeUser                 sql.NullBool
    51  	SchemeAdmin                sql.NullBool
    52  	TeamSchemeDefaultUserRole  sql.NullString
    53  	TeamSchemeDefaultAdminRole sql.NullString
    54  }
    55  
    56  type teamMemberWithSchemeRolesList []teamMemberWithSchemeRoles
    57  
    58  func (db teamMemberWithSchemeRoles) ToModel() *model.TeamMember {
    59  	var roles []string
    60  	var explicitRoles []string
    61  
    62  	// Identify any scheme derived roles that are in "Roles" field due to not yet being migrated, and exclude
    63  	// them from ExplicitRoles field.
    64  	schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
    65  	schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
    66  	for _, role := range strings.Fields(db.Roles) {
    67  		isImplicit := false
    68  		if role == model.TEAM_USER_ROLE_ID {
    69  			// We have an implicit role via the system scheme. Override the "schemeUser" field to true.
    70  			schemeUser = true
    71  			isImplicit = true
    72  		} else if role == model.TEAM_ADMIN_ROLE_ID {
    73  			// We have an implicit role via the system scheme.
    74  			schemeAdmin = true
    75  			isImplicit = true
    76  		}
    77  
    78  		if !isImplicit {
    79  			explicitRoles = append(explicitRoles, role)
    80  		}
    81  		roles = append(roles, role)
    82  	}
    83  
    84  	// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
    85  	// them to the Roles field for backwards compatibility reasons.
    86  	var schemeImpliedRoles []string
    87  	if db.SchemeUser.Valid && db.SchemeUser.Bool {
    88  		if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
    89  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
    90  		} else {
    91  			schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_USER_ROLE_ID)
    92  		}
    93  	}
    94  	if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
    95  		if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
    96  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
    97  		} else {
    98  			schemeImpliedRoles = append(schemeImpliedRoles, model.TEAM_ADMIN_ROLE_ID)
    99  		}
   100  	}
   101  	for _, impliedRole := range schemeImpliedRoles {
   102  		alreadyThere := false
   103  		for _, role := range roles {
   104  			if role == impliedRole {
   105  				alreadyThere = true
   106  			}
   107  		}
   108  		if !alreadyThere {
   109  			roles = append(roles, impliedRole)
   110  		}
   111  	}
   112  
   113  	tm := &model.TeamMember{
   114  		TeamId:        db.TeamId,
   115  		UserId:        db.UserId,
   116  		Roles:         strings.Join(roles, " "),
   117  		DeleteAt:      db.DeleteAt,
   118  		SchemeUser:    schemeUser,
   119  		SchemeAdmin:   schemeAdmin,
   120  		ExplicitRoles: strings.Join(explicitRoles, " "),
   121  	}
   122  	return tm
   123  }
   124  
   125  func (db teamMemberWithSchemeRolesList) ToModel() []*model.TeamMember {
   126  	tms := make([]*model.TeamMember, 0)
   127  
   128  	for _, tm := range db {
   129  		tms = append(tms, tm.ToModel())
   130  	}
   131  
   132  	return tms
   133  }
   134  
   135  func NewSqlTeamStore(sqlStore SqlStore) store.TeamStore {
   136  	s := &SqlTeamStore{sqlStore}
   137  
   138  	for _, db := range sqlStore.GetAllConns() {
   139  		table := db.AddTableWithName(model.Team{}, "Teams").SetKeys(false, "Id")
   140  		table.ColMap("Id").SetMaxSize(26)
   141  		table.ColMap("DisplayName").SetMaxSize(64)
   142  		table.ColMap("Name").SetMaxSize(64).SetUnique(true)
   143  		table.ColMap("Description").SetMaxSize(255)
   144  		table.ColMap("Email").SetMaxSize(128)
   145  		table.ColMap("CompanyName").SetMaxSize(64)
   146  		table.ColMap("AllowedDomains").SetMaxSize(500)
   147  		table.ColMap("InviteId").SetMaxSize(32)
   148  
   149  		tablem := db.AddTableWithName(teamMember{}, "TeamMembers").SetKeys(false, "TeamId", "UserId")
   150  		tablem.ColMap("TeamId").SetMaxSize(26)
   151  		tablem.ColMap("UserId").SetMaxSize(26)
   152  		tablem.ColMap("Roles").SetMaxSize(64)
   153  	}
   154  
   155  	return s
   156  }
   157  
   158  func (s SqlTeamStore) CreateIndexesIfNotExists() {
   159  	s.CreateIndexIfNotExists("idx_teams_name", "Teams", "Name")
   160  	s.RemoveIndexIfExists("idx_teams_description", "Teams")
   161  	s.CreateIndexIfNotExists("idx_teams_invite_id", "Teams", "InviteId")
   162  	s.CreateIndexIfNotExists("idx_teams_update_at", "Teams", "UpdateAt")
   163  	s.CreateIndexIfNotExists("idx_teams_create_at", "Teams", "CreateAt")
   164  	s.CreateIndexIfNotExists("idx_teams_delete_at", "Teams", "DeleteAt")
   165  
   166  	s.CreateIndexIfNotExists("idx_teammembers_team_id", "TeamMembers", "TeamId")
   167  	s.CreateIndexIfNotExists("idx_teammembers_user_id", "TeamMembers", "UserId")
   168  	s.CreateIndexIfNotExists("idx_teammembers_delete_at", "TeamMembers", "DeleteAt")
   169  }
   170  
   171  func (s SqlTeamStore) Save(team *model.Team) store.StoreChannel {
   172  	return store.Do(func(result *store.StoreResult) {
   173  		if len(team.Id) > 0 {
   174  			result.Err = model.NewAppError("SqlTeamStore.Save",
   175  				"store.sql_team.save.existing.app_error", nil, "id="+team.Id, http.StatusBadRequest)
   176  			return
   177  		}
   178  
   179  		team.PreSave()
   180  
   181  		if result.Err = team.IsValid(); result.Err != nil {
   182  			return
   183  		}
   184  
   185  		if err := s.GetMaster().Insert(team); err != nil {
   186  			if IsUniqueConstraintError(err, []string{"Name", "teams_name_key"}) {
   187  				result.Err = model.NewAppError("SqlTeamStore.Save", "store.sql_team.save.domain_exists.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusBadRequest)
   188  				return
   189  			}
   190  			result.Err = model.NewAppError("SqlTeamStore.Save", "store.sql_team.save.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusInternalServerError)
   191  			return
   192  		}
   193  		result.Data = team
   194  	})
   195  }
   196  
   197  func (s SqlTeamStore) Update(team *model.Team) store.StoreChannel {
   198  	return store.Do(func(result *store.StoreResult) {
   199  		team.PreUpdate()
   200  
   201  		if result.Err = team.IsValid(); result.Err != nil {
   202  			return
   203  		}
   204  
   205  		oldResult, err := s.GetMaster().Get(model.Team{}, team.Id)
   206  		if err != nil {
   207  			result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.finding.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusInternalServerError)
   208  			return
   209  		}
   210  
   211  		if oldResult == nil {
   212  			result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.find.app_error", nil, "id="+team.Id, http.StatusBadRequest)
   213  			return
   214  		}
   215  
   216  		oldTeam := oldResult.(*model.Team)
   217  		team.CreateAt = oldTeam.CreateAt
   218  		team.UpdateAt = model.GetMillis()
   219  
   220  		count, err := s.GetMaster().Update(team)
   221  		if err != nil {
   222  			result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.updating.app_error", nil, "id="+team.Id+", "+err.Error(), http.StatusInternalServerError)
   223  			return
   224  		}
   225  		if count != 1 {
   226  			result.Err = model.NewAppError("SqlTeamStore.Update", "store.sql_team.update.app_error", nil, "id="+team.Id, http.StatusInternalServerError)
   227  			return
   228  		}
   229  
   230  		result.Data = team
   231  	})
   232  }
   233  
   234  func (s SqlTeamStore) UpdateDisplayName(name string, teamId string) store.StoreChannel {
   235  	return store.Do(func(result *store.StoreResult) {
   236  		if _, err := s.GetMaster().Exec("UPDATE Teams SET DisplayName = :Name WHERE Id = :Id", map[string]interface{}{"Name": name, "Id": teamId}); err != nil {
   237  			result.Err = model.NewAppError("SqlTeamStore.UpdateName", "store.sql_team.update_display_name.app_error", nil, "team_id="+teamId, http.StatusInternalServerError)
   238  			return
   239  		}
   240  
   241  		result.Data = teamId
   242  	})
   243  }
   244  
   245  func (s SqlTeamStore) Get(id string) store.StoreChannel {
   246  	return store.Do(func(result *store.StoreResult) {
   247  		obj, err := s.GetReplica().Get(model.Team{}, id)
   248  		if err != nil {
   249  			result.Err = model.NewAppError("SqlTeamStore.Get", "store.sql_team.get.finding.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
   250  			return
   251  		}
   252  		if obj == nil {
   253  			result.Err = model.NewAppError("SqlTeamStore.Get", "store.sql_team.get.find.app_error", nil, "id="+id, http.StatusNotFound)
   254  			return
   255  		}
   256  
   257  		team := obj.(*model.Team)
   258  
   259  		result.Data = team
   260  	})
   261  }
   262  
   263  func (s SqlTeamStore) GetByInviteId(inviteId string) store.StoreChannel {
   264  	return store.Do(func(result *store.StoreResult) {
   265  		team := model.Team{}
   266  
   267  		if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE InviteId = :InviteId", map[string]interface{}{"InviteId": inviteId}); err != nil {
   268  			result.Err = model.NewAppError("SqlTeamStore.GetByInviteId", "store.sql_team.get_by_invite_id.finding.app_error", nil, "inviteId="+inviteId+", "+err.Error(), http.StatusNotFound)
   269  			return
   270  		}
   271  
   272  		if len(inviteId) == 0 || team.InviteId != inviteId {
   273  			result.Err = model.NewAppError("SqlTeamStore.GetByInviteId", "store.sql_team.get_by_invite_id.find.app_error", nil, "inviteId="+inviteId, http.StatusNotFound)
   274  			return
   275  		}
   276  
   277  		result.Data = &team
   278  	})
   279  }
   280  
   281  func (s SqlTeamStore) GetByName(name string) store.StoreChannel {
   282  	return store.Do(func(result *store.StoreResult) {
   283  		team := model.Team{}
   284  
   285  		if err := s.GetReplica().SelectOne(&team, "SELECT * FROM Teams WHERE Name = :Name", map[string]interface{}{"Name": name}); err != nil {
   286  			result.Err = model.NewAppError("SqlTeamStore.GetByName", "store.sql_team.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError)
   287  			return
   288  		}
   289  
   290  		result.Data = &team
   291  	})
   292  }
   293  
   294  func (s SqlTeamStore) SearchByName(name string) store.StoreChannel {
   295  	return store.Do(func(result *store.StoreResult) {
   296  		var teams []*model.Team
   297  
   298  		if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Name LIKE :Name", map[string]interface{}{"Name": name + "%"}); err != nil {
   299  			result.Err = model.NewAppError("SqlTeamStore.SearchByName", "store.sql_team.get_by_name.app_error", nil, "name="+name+", "+err.Error(), http.StatusInternalServerError)
   300  			return
   301  		}
   302  
   303  		result.Data = teams
   304  	})
   305  }
   306  
   307  func (s SqlTeamStore) SearchAll(term string) store.StoreChannel {
   308  	return store.Do(func(result *store.StoreResult) {
   309  		var teams []*model.Team
   310  
   311  		if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Name LIKE :Term OR DisplayName LIKE :Term", map[string]interface{}{"Term": term + "%"}); err != nil {
   312  			result.Err = model.NewAppError("SqlTeamStore.SearchAll", "store.sql_team.search_all_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError)
   313  			return
   314  		}
   315  
   316  		result.Data = teams
   317  	})
   318  }
   319  
   320  func (s SqlTeamStore) SearchOpen(term string) store.StoreChannel {
   321  	return store.Do(func(result *store.StoreResult) {
   322  		var teams []*model.Team
   323  
   324  		if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE Type = 'O' AND AllowOpenInvite = true AND (Name LIKE :Term OR DisplayName LIKE :Term)", map[string]interface{}{"Term": term + "%"}); err != nil {
   325  			result.Err = model.NewAppError("SqlTeamStore.SearchOpen", "store.sql_team.search_open_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError)
   326  			return
   327  		}
   328  
   329  		result.Data = teams
   330  	})
   331  }
   332  
   333  func (s SqlTeamStore) SearchPrivate(term string) store.StoreChannel {
   334  	return store.Do(func(result *store.StoreResult) {
   335  		var teams []*model.Team
   336  
   337  		if _, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE (Type != 'O' OR AllowOpenInvite = false) AND (Name LIKE :Term OR DisplayName LIKE :Term)", map[string]interface{}{"Term": term + "%"}); err != nil {
   338  			result.Err = model.NewAppError("SqlTeamStore.SearchPrivate", "store.sql_team.search_private_team.app_error", nil, "term="+term+", "+err.Error(), http.StatusInternalServerError)
   339  			return
   340  		}
   341  
   342  		result.Data = teams
   343  	})
   344  }
   345  
   346  func (s SqlTeamStore) GetAll() store.StoreChannel {
   347  	return store.Do(func(result *store.StoreResult) {
   348  		var data []*model.Team
   349  		if _, err := s.GetReplica().Select(&data, "SELECT * FROM Teams ORDER BY DisplayName"); err != nil {
   350  			result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   351  			return
   352  		}
   353  
   354  		result.Data = data
   355  	})
   356  }
   357  
   358  func (s SqlTeamStore) GetAllPage(offset int, limit int) store.StoreChannel {
   359  	return store.Do(func(result *store.StoreResult) {
   360  		var data []*model.Team
   361  		if _, err := s.GetReplica().Select(&data, "SELECT * FROM Teams ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil {
   362  			result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   363  			return
   364  		}
   365  
   366  		result.Data = data
   367  	})
   368  }
   369  
   370  func (s SqlTeamStore) GetTeamsByUserId(userId string) store.StoreChannel {
   371  	return store.Do(func(result *store.StoreResult) {
   372  		var data []*model.Team
   373  		if _, err := s.GetReplica().Select(&data, "SELECT Teams.* FROM Teams, TeamMembers WHERE TeamMembers.TeamId = Teams.Id AND TeamMembers.UserId = :UserId AND TeamMembers.DeleteAt = 0 AND Teams.DeleteAt = 0", map[string]interface{}{"UserId": userId}); err != nil {
   374  			result.Err = model.NewAppError("SqlTeamStore.GetTeamsByUserId", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   375  			return
   376  		}
   377  
   378  		result.Data = data
   379  	})
   380  }
   381  
   382  func (s SqlTeamStore) GetAllPrivateTeamListing() store.StoreChannel {
   383  	return store.Do(func(result *store.StoreResult) {
   384  		query := "SELECT * FROM Teams WHERE AllowOpenInvite = 0 ORDER BY DisplayName"
   385  
   386  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   387  			query = "SELECT * FROM Teams WHERE AllowOpenInvite = false ORDER BY DisplayName"
   388  		}
   389  
   390  		var data []*model.Team
   391  		if _, err := s.GetReplica().Select(&data, query); err != nil {
   392  			result.Err = model.NewAppError("SqlTeamStore.GetAllPrivateTeamListing", "store.sql_team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   393  			return
   394  		}
   395  
   396  		result.Data = data
   397  	})
   398  }
   399  
   400  func (s SqlTeamStore) GetAllPrivateTeamPageListing(offset int, limit int) store.StoreChannel {
   401  	return store.Do(func(result *store.StoreResult) {
   402  		query := "SELECT * FROM Teams WHERE AllowOpenInvite = 0 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset"
   403  
   404  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   405  			query = "SELECT * FROM Teams WHERE AllowOpenInvite = false ORDER BY DisplayName LIMIT :Limit OFFSET :Offset"
   406  		}
   407  
   408  		var data []*model.Team
   409  		if _, err := s.GetReplica().Select(&data, query, map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil {
   410  			result.Err = model.NewAppError("SqlTeamStore.GetAllPrivateTeamListing", "store.sql_team.get_all_private_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   411  			return
   412  		}
   413  
   414  		result.Data = data
   415  	})
   416  }
   417  
   418  func (s SqlTeamStore) GetAllTeamListing() store.StoreChannel {
   419  	return store.Do(func(result *store.StoreResult) {
   420  		query := "SELECT * FROM Teams WHERE AllowOpenInvite = 1 ORDER BY DisplayName"
   421  
   422  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   423  			query = "SELECT * FROM Teams WHERE AllowOpenInvite = true ORDER BY DisplayName"
   424  		}
   425  
   426  		var data []*model.Team
   427  		if _, err := s.GetReplica().Select(&data, query); err != nil {
   428  			result.Err = model.NewAppError("SqlTeamStore.GetAllTeamListing", "store.sql_team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   429  			return
   430  		}
   431  
   432  		result.Data = data
   433  	})
   434  }
   435  
   436  func (s SqlTeamStore) GetAllTeamPageListing(offset int, limit int) store.StoreChannel {
   437  	return store.Do(func(result *store.StoreResult) {
   438  		query := "SELECT * FROM Teams WHERE AllowOpenInvite = 1 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset"
   439  
   440  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   441  			query = "SELECT * FROM Teams WHERE AllowOpenInvite = true ORDER BY DisplayName LIMIT :Limit OFFSET :Offset"
   442  		}
   443  
   444  		var data []*model.Team
   445  		if _, err := s.GetReplica().Select(&data, query, map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil {
   446  			result.Err = model.NewAppError("SqlTeamStore.GetAllTeamListing", "store.sql_team.get_all_team_listing.app_error", nil, err.Error(), http.StatusInternalServerError)
   447  			return
   448  		}
   449  
   450  		result.Data = data
   451  	})
   452  }
   453  
   454  func (s SqlTeamStore) PermanentDelete(teamId string) store.StoreChannel {
   455  	return store.Do(func(result *store.StoreResult) {
   456  		if _, err := s.GetMaster().Exec("DELETE FROM Teams WHERE Id = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
   457  			result.Err = model.NewAppError("SqlTeamStore.Delete", "store.sql_team.permanent_delete.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError)
   458  			return
   459  		}
   460  	})
   461  }
   462  
   463  func (s SqlTeamStore) AnalyticsTeamCount() store.StoreChannel {
   464  	return store.Do(func(result *store.StoreResult) {
   465  		c, err := s.GetReplica().SelectInt("SELECT COUNT(*) FROM Teams WHERE DeleteAt = 0", map[string]interface{}{})
   466  		if err != nil {
   467  			result.Err = model.NewAppError("SqlTeamStore.AnalyticsTeamCount", "store.sql_team.analytics_team_count.app_error", nil, err.Error(), http.StatusInternalServerError)
   468  			return
   469  		}
   470  		result.Data = c
   471  	})
   472  }
   473  
   474  var TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY = `
   475  	SELECT
   476  		TeamMembers.*,
   477  		TeamScheme.DefaultTeamUserRole TeamSchemeDefaultUserRole,
   478  		TeamScheme.DefaultTeamAdminRole TeamSchemeDefaultAdminRole
   479  	FROM
   480  		TeamMembers
   481  	LEFT JOIN
   482  		Teams ON TeamMembers.TeamId = Teams.Id
   483  	LEFT JOIN
   484  		Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
   485  `
   486  
   487  func (s SqlTeamStore) SaveMember(member *model.TeamMember, maxUsersPerTeam int) store.StoreChannel {
   488  	return store.Do(func(result *store.StoreResult) {
   489  		if result.Err = member.IsValid(); result.Err != nil {
   490  			return
   491  		}
   492  
   493  		dbMember := NewTeamMemberFromModel(member)
   494  
   495  		if maxUsersPerTeam >= 0 {
   496  			count, err := s.GetMaster().SelectInt(
   497  				`SELECT
   498  					COUNT(0)
   499  				FROM
   500  					TeamMembers
   501  				INNER JOIN
   502  					Users
   503  				ON
   504  					TeamMembers.UserId = Users.Id
   505  				WHERE
   506  					TeamId = :TeamId
   507  					AND TeamMembers.DeleteAt = 0
   508  					AND Users.DeleteAt = 0`, map[string]interface{}{"TeamId": member.TeamId})
   509  
   510  			if err != nil {
   511  				result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.member_count.app_error", nil, "teamId="+member.TeamId+", "+err.Error(), http.StatusInternalServerError)
   512  				return
   513  			}
   514  
   515  			if count >= int64(maxUsersPerTeam) {
   516  				result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.max_accounts.app_error", nil, "teamId="+member.TeamId, http.StatusBadRequest)
   517  				return
   518  			}
   519  		}
   520  
   521  		if err := s.GetMaster().Insert(dbMember); err != nil {
   522  			if IsUniqueConstraintError(err, []string{"TeamId", "teammembers_pkey", "PRIMARY"}) {
   523  				result.Err = model.NewAppError("SqlTeamStore.SaveMember", TEAM_MEMBER_EXISTS_ERROR, nil, "team_id="+member.TeamId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest)
   524  				return
   525  			}
   526  			result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.save_member.save.app_error", nil, "team_id="+member.TeamId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
   527  			return
   528  		}
   529  
   530  		var retrievedMember teamMemberWithSchemeRoles
   531  		if err := s.GetMaster().SelectOne(&retrievedMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": dbMember.TeamId, "UserId": dbMember.UserId}); err != nil {
   532  			if err == sql.ErrNoRows {
   533  				result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound)
   534  				return
   535  			}
   536  			result.Err = model.NewAppError("SqlTeamStore.SaveMember", "store.sql_team.get_member.app_error", nil, "team_id="+dbMember.TeamId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusInternalServerError)
   537  			return
   538  		}
   539  		result.Data = retrievedMember.ToModel()
   540  	})
   541  }
   542  
   543  func (s SqlTeamStore) UpdateMember(member *model.TeamMember) store.StoreChannel {
   544  	return store.Do(func(result *store.StoreResult) {
   545  		member.PreUpdate()
   546  
   547  		if result.Err = member.IsValid(); result.Err != nil {
   548  			return
   549  		}
   550  
   551  		if _, err := s.GetMaster().Update(NewTeamMemberFromModel(member)); err != nil {
   552  			result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.save_member.save.app_error", nil, err.Error(), http.StatusInternalServerError)
   553  			return
   554  		}
   555  
   556  		var retrievedMember teamMemberWithSchemeRoles
   557  		if err := s.GetMaster().SelectOne(&retrievedMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": member.TeamId, "UserId": member.UserId}); err != nil {
   558  			if err == sql.ErrNoRows {
   559  				result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.missing.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound)
   560  				return
   561  			}
   562  			result.Err = model.NewAppError("SqlTeamStore.UpdateMember", "store.sql_team.get_member.app_error", nil, "team_id="+member.TeamId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
   563  			return
   564  		}
   565  
   566  		result.Data = retrievedMember.ToModel()
   567  	})
   568  }
   569  
   570  func (s SqlTeamStore) GetMember(teamId string, userId string) store.StoreChannel {
   571  	return store.Do(func(result *store.StoreResult) {
   572  		var dbMember teamMemberWithSchemeRoles
   573  		err := s.GetReplica().SelectOne(&dbMember, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId})
   574  		if err != nil {
   575  			if err == sql.ErrNoRows {
   576  				result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.missing.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusNotFound)
   577  				return
   578  			}
   579  			result.Err = model.NewAppError("SqlTeamStore.GetMember", "store.sql_team.get_member.app_error", nil, "teamId="+teamId+" userId="+userId+" "+err.Error(), http.StatusInternalServerError)
   580  			return
   581  		}
   582  		result.Data = dbMember.ToModel()
   583  	})
   584  }
   585  
   586  func (s SqlTeamStore) GetMembers(teamId string, offset int, limit int) store.StoreChannel {
   587  	return store.Do(func(result *store.StoreResult) {
   588  		var dbMembers teamMemberWithSchemeRolesList
   589  		_, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.DeleteAt = 0 LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset})
   590  		if err != nil {
   591  			result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError)
   592  			return
   593  		}
   594  
   595  		result.Data = dbMembers.ToModel()
   596  	})
   597  }
   598  
   599  func (s SqlTeamStore) GetTotalMemberCount(teamId string) store.StoreChannel {
   600  	return store.Do(func(result *store.StoreResult) {
   601  		count, err := s.GetReplica().SelectInt(`
   602  			SELECT
   603  				count(*)
   604  			FROM
   605  				TeamMembers,
   606  				Users
   607  			WHERE
   608  				TeamMembers.UserId = Users.Id
   609  				AND TeamMembers.TeamId = :TeamId
   610  				AND TeamMembers.DeleteAt = 0`, map[string]interface{}{"TeamId": teamId})
   611  		if err != nil {
   612  			result.Err = model.NewAppError("SqlTeamStore.GetTotalMemberCount", "store.sql_team.get_member_count.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError)
   613  			return
   614  		}
   615  
   616  		result.Data = count
   617  	})
   618  }
   619  
   620  func (s SqlTeamStore) GetActiveMemberCount(teamId string) store.StoreChannel {
   621  	return store.Do(func(result *store.StoreResult) {
   622  		count, err := s.GetReplica().SelectInt(`
   623  			SELECT
   624  				count(*)
   625  			FROM
   626  				TeamMembers,
   627  				Users
   628  			WHERE
   629  				TeamMembers.UserId = Users.Id
   630  				AND TeamMembers.TeamId = :TeamId
   631  				AND TeamMembers.DeleteAt = 0
   632  				AND Users.DeleteAt = 0`, map[string]interface{}{"TeamId": teamId})
   633  		if err != nil {
   634  			result.Err = model.NewAppError("SqlTeamStore.GetActiveMemberCount", "store.sql_team.get_member_count.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError)
   635  			return
   636  		}
   637  
   638  		result.Data = count
   639  	})
   640  }
   641  
   642  func (s SqlTeamStore) GetMembersByIds(teamId string, userIds []string) store.StoreChannel {
   643  	return store.Do(func(result *store.StoreResult) {
   644  		var dbMembers teamMemberWithSchemeRolesList
   645  		props := make(map[string]interface{})
   646  		idQuery := ""
   647  
   648  		for index, userId := range userIds {
   649  			if len(idQuery) > 0 {
   650  				idQuery += ", "
   651  			}
   652  
   653  			props["userId"+strconv.Itoa(index)] = userId
   654  			idQuery += ":userId" + strconv.Itoa(index)
   655  		}
   656  
   657  		props["TeamId"] = teamId
   658  
   659  		if _, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.TeamId = :TeamId AND TeamMembers.UserId IN ("+idQuery+") AND TeamMembers.DeleteAt = 0", props); err != nil {
   660  			result.Err = model.NewAppError("SqlTeamStore.GetMembersByIds", "store.sql_team.get_members_by_ids.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError)
   661  			return
   662  		}
   663  		result.Data = dbMembers.ToModel()
   664  	})
   665  }
   666  
   667  func (s SqlTeamStore) GetTeamsForUser(userId string) store.StoreChannel {
   668  	return store.Do(func(result *store.StoreResult) {
   669  		var dbMembers teamMemberWithSchemeRolesList
   670  		_, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.UserId = :UserId", map[string]interface{}{"UserId": userId})
   671  		if err != nil {
   672  			result.Err = model.NewAppError("SqlTeamStore.GetMembers", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError)
   673  			return
   674  		}
   675  
   676  		result.Data = dbMembers.ToModel()
   677  	})
   678  }
   679  
   680  func (s SqlTeamStore) GetTeamsForUserWithPagination(userId string, page, perPage int) store.StoreChannel {
   681  	return store.Do(func(result *store.StoreResult) {
   682  		var dbMembers teamMemberWithSchemeRolesList
   683  		offset := page * perPage
   684  		_, err := s.GetReplica().Select(&dbMembers, TEAM_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE TeamMembers.UserId = :UserId Limit :Limit Offset :Offset", map[string]interface{}{"UserId": userId, "Limit": perPage, "Offset": offset})
   685  		if err != nil {
   686  			result.Err = model.NewAppError("SqlTeamStore.GetTeamsForUserWithPagination", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError)
   687  			return
   688  		}
   689  
   690  		result.Data = dbMembers.ToModel()
   691  	})
   692  }
   693  
   694  func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) store.StoreChannel {
   695  	return store.Do(func(result *store.StoreResult) {
   696  		var data []*model.ChannelUnread
   697  		_, err := s.GetReplica().Select(&data,
   698  			`SELECT
   699  				Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
   700  			FROM
   701  				Channels, ChannelMembers
   702  			WHERE
   703  				Id = ChannelId
   704                  AND UserId = :UserId
   705                  AND DeleteAt = 0
   706                  AND TeamId != :TeamId`,
   707  			map[string]interface{}{"UserId": userId, "TeamId": excludeTeamId})
   708  
   709  		if err != nil {
   710  			result.Err = model.NewAppError("SqlTeamStore.GetChannelUnreadsForAllTeams", "store.sql_team.get_unread.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError)
   711  			return
   712  		}
   713  		result.Data = data
   714  	})
   715  }
   716  
   717  func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) store.StoreChannel {
   718  	return store.Do(func(result *store.StoreResult) {
   719  		var data []*model.ChannelUnread
   720  		_, err := s.GetReplica().Select(&data,
   721  			`SELECT
   722  				Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
   723  			FROM
   724  				Channels, ChannelMembers
   725  			WHERE
   726  				Id = ChannelId
   727                  AND UserId = :UserId
   728                  AND TeamId = :TeamId
   729                  AND DeleteAt = 0`,
   730  			map[string]interface{}{"TeamId": teamId, "UserId": userId})
   731  
   732  		if err != nil {
   733  			result.Err = model.NewAppError("SqlTeamStore.GetChannelUnreadsForTeam", "store.sql_team.get_unread.app_error", nil, "teamId="+teamId+" "+err.Error(), http.StatusInternalServerError)
   734  			return
   735  		}
   736  		result.Data = data
   737  	})
   738  }
   739  
   740  func (s SqlTeamStore) RemoveMember(teamId string, userId string) store.StoreChannel {
   741  	return store.Do(func(result *store.StoreResult) {
   742  		_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId AND UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId})
   743  		if err != nil {
   744  			result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
   745  		}
   746  	})
   747  }
   748  
   749  func (s SqlTeamStore) RemoveAllMembersByTeam(teamId string) store.StoreChannel {
   750  	return store.Do(func(result *store.StoreResult) {
   751  		_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId})
   752  		if err != nil {
   753  			result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError)
   754  		}
   755  	})
   756  }
   757  
   758  func (s SqlTeamStore) RemoveAllMembersByUser(userId string) store.StoreChannel {
   759  	return store.Do(func(result *store.StoreResult) {
   760  		_, err := s.GetMaster().Exec("DELETE FROM TeamMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId})
   761  		if err != nil {
   762  			result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_team.remove_member.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
   763  		}
   764  	})
   765  }
   766  
   767  func (us SqlTeamStore) UpdateLastTeamIconUpdate(teamId string, curTime int64) store.StoreChannel {
   768  	return store.Do(func(result *store.StoreResult) {
   769  		if _, err := us.GetMaster().Exec("UPDATE Teams SET LastTeamIconUpdate = :Time, UpdateAt = :Time WHERE Id = :teamId", map[string]interface{}{"Time": curTime, "teamId": teamId}); err != nil {
   770  			result.Err = model.NewAppError("SqlTeamStore.UpdateLastTeamIconUpdate", "store.sql_team.update_last_team_icon_update.app_error", nil, "team_id="+teamId, http.StatusInternalServerError)
   771  			return
   772  		}
   773  		result.Data = teamId
   774  	})
   775  }
   776  
   777  func (s SqlTeamStore) GetTeamsByScheme(schemeId string, offset int, limit int) store.StoreChannel {
   778  	return store.Do(func(result *store.StoreResult) {
   779  		var teams []*model.Team
   780  		_, err := s.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE SchemeId = :SchemeId ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"SchemeId": schemeId, "Offset": offset, "Limit": limit})
   781  		if err != nil {
   782  			result.Err = model.NewAppError("SqlTeamStore.GetTeamsByScheme", "store.sql_team.get_by_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError)
   783  			return
   784  		}
   785  		result.Data = teams
   786  	})
   787  }
   788  
   789  // This function does the Advanced Permissions Phase 2 migration for TeamMember objects. It performs the migration
   790  // in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid
   791  // causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function
   792  // *after* the new Schemes functionality has been used on an installation will have unintended consequences.
   793  func (s SqlTeamStore) MigrateTeamMembers(fromTeamId string, fromUserId string) store.StoreChannel {
   794  	return store.Do(func(result *store.StoreResult) {
   795  		var transaction *gorp.Transaction
   796  		var err error
   797  
   798  		if transaction, err = s.GetMaster().Begin(); err != nil {
   799  			result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   800  			return
   801  		}
   802  		defer finalizeTransaction(transaction)
   803  
   804  		var teamMembers []teamMember
   805  		if _, err := transaction.Select(&teamMembers, "SELECT * from TeamMembers WHERE (TeamId, UserId) > (:FromTeamId, :FromUserId) ORDER BY TeamId, UserId LIMIT 100", map[string]interface{}{"FromTeamId": fromTeamId, "FromUserId": fromUserId}); err != nil {
   806  			result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.select.app_error", nil, err.Error(), http.StatusInternalServerError)
   807  			return
   808  		}
   809  
   810  		if len(teamMembers) == 0 {
   811  			// No more team members in query result means that the migration has finished.
   812  			return
   813  		}
   814  
   815  		for _, member := range teamMembers {
   816  			roles := strings.Fields(member.Roles)
   817  			var newRoles []string
   818  			if !member.SchemeAdmin.Valid {
   819  				member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true}
   820  			}
   821  			if !member.SchemeUser.Valid {
   822  				member.SchemeUser = sql.NullBool{Bool: false, Valid: true}
   823  			}
   824  			for _, role := range roles {
   825  				if role == model.TEAM_ADMIN_ROLE_ID {
   826  					member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true}
   827  				} else if role == model.TEAM_USER_ROLE_ID {
   828  					member.SchemeUser = sql.NullBool{Bool: true, Valid: true}
   829  				} else {
   830  					newRoles = append(newRoles, role)
   831  				}
   832  			}
   833  			member.Roles = strings.Join(newRoles, " ")
   834  
   835  			if _, err := transaction.Update(&member); err != nil {
   836  				result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.update.app_error", nil, err.Error(), http.StatusInternalServerError)
   837  				return
   838  			}
   839  
   840  		}
   841  
   842  		if err := transaction.Commit(); err != nil {
   843  			result.Err = model.NewAppError("SqlTeamStore.MigrateTeamMembers", "store.sql_team.migrate_team_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   844  			return
   845  		}
   846  
   847  		data := make(map[string]string)
   848  		data["TeamId"] = teamMembers[len(teamMembers)-1].TeamId
   849  		data["UserId"] = teamMembers[len(teamMembers)-1].UserId
   850  		result.Data = data
   851  	})
   852  }
   853  
   854  func (s SqlTeamStore) ResetAllTeamSchemes() store.StoreChannel {
   855  	return store.Do(func(result *store.StoreResult) {
   856  		if _, err := s.GetMaster().Exec("UPDATE Teams SET SchemeId=''"); err != nil {
   857  			result.Err = model.NewAppError("SqlTeamStore.ResetAllTeamSchemes", "store.sql_team.reset_all_team_schemes.app_error", nil, err.Error(), http.StatusInternalServerError)
   858  		}
   859  	})
   860  }
   861  
   862  func (s SqlTeamStore) ClearAllCustomRoleAssignments() store.StoreChannel {
   863  	return store.Do(func(result *store.StoreResult) {
   864  		builtInRoles := model.MakeDefaultRoles()
   865  		lastUserId := strings.Repeat("0", 26)
   866  		lastTeamId := strings.Repeat("0", 26)
   867  
   868  		for {
   869  			var transaction *gorp.Transaction
   870  			var err error
   871  
   872  			if transaction, err = s.GetMaster().Begin(); err != nil {
   873  				result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   874  				return
   875  			}
   876  			defer finalizeTransaction(transaction)
   877  
   878  			var teamMembers []*teamMember
   879  			if _, err := transaction.Select(&teamMembers, "SELECT * from TeamMembers WHERE (TeamId, UserId) > (:TeamId, :UserId) ORDER BY TeamId, UserId LIMIT 1000", map[string]interface{}{"TeamId": lastTeamId, "UserId": lastUserId}); err != nil {
   880  				result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.select.app_error", nil, err.Error(), http.StatusInternalServerError)
   881  				return
   882  			}
   883  
   884  			if len(teamMembers) == 0 {
   885  				break
   886  			}
   887  
   888  			for _, member := range teamMembers {
   889  				lastUserId = member.UserId
   890  				lastTeamId = member.TeamId
   891  
   892  				var newRoles []string
   893  
   894  				for _, role := range strings.Fields(member.Roles) {
   895  					for name := range builtInRoles {
   896  						if name == role {
   897  							newRoles = append(newRoles, role)
   898  							break
   899  						}
   900  					}
   901  				}
   902  
   903  				newRolesString := strings.Join(newRoles, " ")
   904  				if newRolesString != member.Roles {
   905  					if _, err := transaction.Exec("UPDATE TeamMembers SET Roles = :Roles WHERE UserId = :UserId AND TeamId = :TeamId", map[string]interface{}{"Roles": newRolesString, "TeamId": member.TeamId, "UserId": member.UserId}); err != nil {
   906  						result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.update.app_error", nil, err.Error(), http.StatusInternalServerError)
   907  						return
   908  					}
   909  				}
   910  			}
   911  
   912  			if err := transaction.Commit(); err != nil {
   913  				result.Err = model.NewAppError("SqlTeamStore.ClearAllCustomRoleAssignments", "store.sql_team.clear_all_custom_role_assignments.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   914  				return
   915  			}
   916  		}
   917  	})
   918  }
   919  
   920  func (s SqlTeamStore) AnalyticsGetTeamCountForScheme(schemeId string) store.StoreChannel {
   921  	return store.Do(func(result *store.StoreResult) {
   922  		count, err := s.GetReplica().SelectInt("SELECT count(*) FROM Teams WHERE SchemeId = :SchemeId AND DeleteAt = 0", map[string]interface{}{"SchemeId": schemeId})
   923  		if err != nil {
   924  			result.Err = model.NewAppError("SqlTeamStore.AnalyticsGetTeamCountForScheme", "store.sql_team.analytics_get_team_count_for_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError)
   925  			return
   926  		}
   927  		result.Data = count
   928  	})
   929  }
   930  
   931  func (s SqlTeamStore) GetAllForExportAfter(limit int, afterId string) store.StoreChannel {
   932  	return store.Do(func(result *store.StoreResult) {
   933  		var data []*model.TeamForExport
   934  		if _, err := s.GetReplica().Select(&data, `
   935  			SELECT
   936  				Teams.*,
   937  				Schemes.Name as SchemeName
   938  			FROM
   939  				Teams
   940  			LEFT JOIN
   941  				Schemes ON Teams.SchemeId = Schemes.Id
   942  			WHERE
   943  				Teams.Id > :AfterId
   944  			ORDER BY
   945  				Id
   946  			LIMIT
   947  				:Limit`,
   948  			map[string]interface{}{"AfterId": afterId, "Limit": limit}); err != nil {
   949  			result.Err = model.NewAppError("SqlTeamStore.GetAllTeams", "store.sql_team.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
   950  			return
   951  		}
   952  
   953  		result.Data = data
   954  	})
   955  }
   956  
   957  func (s SqlTeamStore) GetTeamMembersForExport(userId string) store.StoreChannel {
   958  	return store.Do(func(result *store.StoreResult) {
   959  		var members []*model.TeamMemberForExport
   960  		_, err := s.GetReplica().Select(&members, `
   961  	SELECT
   962  		TeamMembers.*,
   963  		Teams.Name as TeamName
   964  	FROM
   965  		TeamMembers
   966  	INNER JOIN
   967  		Teams ON TeamMembers.TeamId = Teams.Id
   968  	WHERE
   969  		TeamMembers.UserId = :UserId
   970  		AND Teams.DeleteAt = 0`,
   971  			map[string]interface{}{"UserId": userId})
   972  		if err != nil {
   973  			result.Err = model.NewAppError("SqlTeamStore.GetTeamMembersForExport", "store.sql_team.get_members.app_error", nil, "userId="+userId+" "+err.Error(), http.StatusInternalServerError)
   974  			return
   975  		}
   976  
   977  		result.Data = members
   978  	})
   979  }