github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/store/sqlstore/group_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  	"fmt"
     9  	"net/http"
    10  	"strings"
    11  
    12  	sq "github.com/Masterminds/squirrel"
    13  	"github.com/pkg/errors"
    14  
    15  	"github.com/mattermost/mattermost-server/v5/model"
    16  	"github.com/mattermost/mattermost-server/v5/store"
    17  )
    18  
    19  type selectType int
    20  
    21  const (
    22  	selectGroups selectType = iota
    23  	selectCountGroups
    24  )
    25  
    26  type groupTeam struct {
    27  	model.GroupSyncable
    28  	TeamId string `db:"TeamId"`
    29  }
    30  
    31  type groupChannel struct {
    32  	model.GroupSyncable
    33  	ChannelId string `db:"ChannelId"`
    34  }
    35  
    36  type groupTeamJoin struct {
    37  	groupTeam
    38  	TeamDisplayName string `db:"TeamDisplayName"`
    39  	TeamType        string `db:"TeamType"`
    40  }
    41  
    42  type groupChannelJoin struct {
    43  	groupChannel
    44  	ChannelDisplayName string `db:"ChannelDisplayName"`
    45  	TeamDisplayName    string `db:"TeamDisplayName"`
    46  	TeamType           string `db:"TeamType"`
    47  	ChannelType        string `db:"ChannelType"`
    48  	TeamID             string `db:"TeamId"`
    49  }
    50  
    51  type SqlGroupStore struct {
    52  	SqlStore
    53  }
    54  
    55  func newSqlGroupStore(sqlStore SqlStore) store.GroupStore {
    56  	s := &SqlGroupStore{SqlStore: sqlStore}
    57  	for _, db := range sqlStore.GetAllConns() {
    58  		groups := db.AddTableWithName(model.Group{}, "UserGroups").SetKeys(false, "Id")
    59  		groups.ColMap("Id").SetMaxSize(26)
    60  		groups.ColMap("Name").SetMaxSize(model.GroupNameMaxLength).SetUnique(true)
    61  		groups.ColMap("DisplayName").SetMaxSize(model.GroupDisplayNameMaxLength)
    62  		groups.ColMap("Description").SetMaxSize(model.GroupDescriptionMaxLength)
    63  		groups.ColMap("Source").SetMaxSize(model.GroupSourceMaxLength)
    64  		groups.ColMap("RemoteId").SetMaxSize(model.GroupRemoteIDMaxLength)
    65  		groups.SetUniqueTogether("Source", "RemoteId")
    66  
    67  		groupMembers := db.AddTableWithName(model.GroupMember{}, "GroupMembers").SetKeys(false, "GroupId", "UserId")
    68  		groupMembers.ColMap("GroupId").SetMaxSize(26)
    69  		groupMembers.ColMap("UserId").SetMaxSize(26)
    70  
    71  		groupTeams := db.AddTableWithName(groupTeam{}, "GroupTeams").SetKeys(false, "GroupId", "TeamId")
    72  		groupTeams.ColMap("GroupId").SetMaxSize(26)
    73  		groupTeams.ColMap("TeamId").SetMaxSize(26)
    74  
    75  		groupChannels := db.AddTableWithName(groupChannel{}, "GroupChannels").SetKeys(false, "GroupId", "ChannelId")
    76  		groupChannels.ColMap("GroupId").SetMaxSize(26)
    77  		groupChannels.ColMap("ChannelId").SetMaxSize(26)
    78  	}
    79  	return s
    80  }
    81  
    82  func (s *SqlGroupStore) createIndexesIfNotExists() {
    83  	s.CreateIndexIfNotExists("idx_groupmembers_create_at", "GroupMembers", "CreateAt")
    84  	s.CreateIndexIfNotExists("idx_usergroups_remote_id", "UserGroups", "RemoteId")
    85  	s.CreateIndexIfNotExists("idx_usergroups_delete_at", "UserGroups", "DeleteAt")
    86  	s.CreateIndexIfNotExists("idx_groupteams_teamid", "GroupTeams", "TeamId")
    87  	s.CreateIndexIfNotExists("idx_groupchannels_channelid", "GroupChannels", "ChannelId")
    88  	s.CreateColumnIfNotExistsNoDefault("Channels", "GroupConstrained", "tinyint(1)", "boolean")
    89  	s.CreateColumnIfNotExistsNoDefault("Teams", "GroupConstrained", "tinyint(1)", "boolean")
    90  	s.CreateIndexIfNotExists("idx_groupteams_schemeadmin", "GroupTeams", "SchemeAdmin")
    91  	s.CreateIndexIfNotExists("idx_groupchannels_schemeadmin", "GroupChannels", "SchemeAdmin")
    92  }
    93  
    94  func (s *SqlGroupStore) Create(group *model.Group) (*model.Group, *model.AppError) {
    95  	if len(group.Id) != 0 {
    96  		return nil, model.NewAppError("SqlGroupStore.GroupCreate", "model.group.id.app_error", nil, "", http.StatusBadRequest)
    97  	}
    98  
    99  	if err := group.IsValidForCreate(); err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	group.Id = model.NewId()
   104  	group.CreateAt = model.GetMillis()
   105  	group.UpdateAt = group.CreateAt
   106  
   107  	if err := s.GetMaster().Insert(group); err != nil {
   108  		if IsUniqueConstraintError(err, []string{"Name", "groups_name_key"}) {
   109  			return nil, model.NewAppError("SqlGroupStore.GroupCreate", "store.sql_group.unique_constraint", nil, err.Error(), http.StatusInternalServerError)
   110  		}
   111  		return nil, model.NewAppError("SqlGroupStore.GroupCreate", "store.insert_error", nil, err.Error(), http.StatusInternalServerError)
   112  	}
   113  
   114  	return group, nil
   115  }
   116  
   117  func (s *SqlGroupStore) Get(groupId string) (*model.Group, *model.AppError) {
   118  	var group *model.Group
   119  	if err := s.GetReplica().SelectOne(&group, "SELECT * from UserGroups WHERE Id = :Id", map[string]interface{}{"Id": groupId}); err != nil {
   120  		if err == sql.ErrNoRows {
   121  			return nil, model.NewAppError("SqlGroupStore.GroupGet", "store.sql_group.no_rows", nil, err.Error(), http.StatusNotFound)
   122  		}
   123  		return nil, model.NewAppError("SqlGroupStore.GroupGet", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   124  	}
   125  
   126  	return group, nil
   127  }
   128  
   129  func (s *SqlGroupStore) GetByName(name string, opts model.GroupSearchOpts) (*model.Group, *model.AppError) {
   130  	var group *model.Group
   131  	query := s.getQueryBuilder().Select("*").From("UserGroups").Where(sq.Eq{"Name": name})
   132  	if opts.FilterAllowReference {
   133  		query = query.Where("AllowReference = true")
   134  	}
   135  
   136  	queryString, args, err := query.ToSql()
   137  
   138  	if err != nil {
   139  		return nil, model.NewAppError("SqlGroupStore.GetByName", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   140  	}
   141  	if err := s.GetReplica().SelectOne(&group, queryString, args...); err != nil {
   142  		if err == sql.ErrNoRows {
   143  			return nil, model.NewAppError("SqlGroupStore.GroupGetByName", "store.sql_group.no_rows", nil, err.Error(), http.StatusNotFound)
   144  		}
   145  		return nil, model.NewAppError("SqlGroupStore.GroupGetByName", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   146  	}
   147  
   148  	return group, nil
   149  }
   150  
   151  func (s *SqlGroupStore) GetByIDs(groupIDs []string) ([]*model.Group, *model.AppError) {
   152  	var groups []*model.Group
   153  	query := s.getQueryBuilder().Select("*").From("UserGroups").Where(sq.Eq{"Id": groupIDs})
   154  	queryString, args, err := query.ToSql()
   155  	if err != nil {
   156  		return nil, model.NewAppError("SqlGroupStore.GetByIDs", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   157  	}
   158  	if _, err := s.GetReplica().Select(&groups, queryString, args...); err != nil {
   159  		return nil, model.NewAppError("SqlGroupStore.GetByIDs", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   160  	}
   161  	return groups, nil
   162  }
   163  
   164  func (s *SqlGroupStore) GetByRemoteID(remoteID string, groupSource model.GroupSource) (*model.Group, *model.AppError) {
   165  	var group *model.Group
   166  	if err := s.GetReplica().SelectOne(&group, "SELECT * from UserGroups WHERE RemoteId = :RemoteId AND Source = :Source", map[string]interface{}{"RemoteId": remoteID, "Source": groupSource}); err != nil {
   167  		if err == sql.ErrNoRows {
   168  			return nil, model.NewAppError("SqlGroupStore.GroupGetByRemoteID", "store.sql_group.no_rows", nil, err.Error(), http.StatusNotFound)
   169  		}
   170  		return nil, model.NewAppError("SqlGroupStore.GroupGetByRemoteID", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   171  	}
   172  
   173  	return group, nil
   174  }
   175  
   176  func (s *SqlGroupStore) GetAllBySource(groupSource model.GroupSource) ([]*model.Group, *model.AppError) {
   177  	var groups []*model.Group
   178  
   179  	if _, err := s.GetReplica().Select(&groups, "SELECT * from UserGroups WHERE DeleteAt = 0 AND Source = :Source", map[string]interface{}{"Source": groupSource}); err != nil {
   180  		return nil, model.NewAppError("SqlGroupStore.GroupGetAllBySource", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   181  	}
   182  
   183  	return groups, nil
   184  }
   185  
   186  func (s *SqlGroupStore) GetByUser(userId string) ([]*model.Group, *model.AppError) {
   187  	var groups []*model.Group
   188  
   189  	query := `
   190  		SELECT
   191  			UserGroups.*
   192  		FROM
   193  			GroupMembers
   194  			JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId
   195  		WHERE
   196  			GroupMembers.DeleteAt = 0
   197  			AND UserId = :UserId`
   198  
   199  	if _, err := s.GetReplica().Select(&groups, query, map[string]interface{}{"UserId": userId}); err != nil {
   200  		return nil, model.NewAppError("SqlGroupStore.GetByUser", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   201  	}
   202  
   203  	return groups, nil
   204  }
   205  
   206  func (s *SqlGroupStore) Update(group *model.Group) (*model.Group, *model.AppError) {
   207  	var retrievedGroup *model.Group
   208  	if err := s.GetReplica().SelectOne(&retrievedGroup, "SELECT * FROM UserGroups WHERE Id = :Id", map[string]interface{}{"Id": group.Id}); err != nil {
   209  		if err == sql.ErrNoRows {
   210  			return nil, model.NewAppError("SqlGroupStore.GroupUpdate", "store.sql_group.no_rows", nil, "id="+group.Id+","+err.Error(), http.StatusNotFound)
   211  		}
   212  		return nil, model.NewAppError("SqlGroupStore.GroupUpdate", "store.select_error", nil, "id="+group.Id+","+err.Error(), http.StatusInternalServerError)
   213  	}
   214  
   215  	// If updating DeleteAt it can only be to 0
   216  	if group.DeleteAt != retrievedGroup.DeleteAt && group.DeleteAt != 0 {
   217  		return nil, model.NewAppError("SqlGroupStore.GroupUpdate", "model.group.delete_at.app_error", nil, "", http.StatusInternalServerError)
   218  	}
   219  
   220  	// Reset these properties, don't update them based on input
   221  	group.CreateAt = retrievedGroup.CreateAt
   222  	group.UpdateAt = model.GetMillis()
   223  
   224  	if err := group.IsValidForUpdate(); err != nil {
   225  		return nil, err
   226  	}
   227  
   228  	rowsChanged, err := s.GetMaster().Update(group)
   229  	if err != nil {
   230  		if IsUniqueConstraintError(err, []string{"Name", "groups_name_key"}) {
   231  			return nil, model.NewAppError("SqlGroupStore.GroupUpdate", "store.sql_group.unique_constraint", nil, err.Error(), http.StatusInternalServerError)
   232  		}
   233  		return nil, model.NewAppError("SqlGroupStore.GroupUpdate", "store.update_error", nil, err.Error(), http.StatusInternalServerError)
   234  	}
   235  	if rowsChanged > 1 {
   236  		return nil, model.NewAppError("SqlGroupStore.GroupUpdate", "store.sql_group.more_than_one_row_changed", nil, "", http.StatusInternalServerError)
   237  	}
   238  
   239  	return group, nil
   240  }
   241  
   242  func (s *SqlGroupStore) Delete(groupID string) (*model.Group, *model.AppError) {
   243  	var group *model.Group
   244  	if err := s.GetReplica().SelectOne(&group, "SELECT * from UserGroups WHERE Id = :Id AND DeleteAt = 0", map[string]interface{}{"Id": groupID}); err != nil {
   245  		if err == sql.ErrNoRows {
   246  			return nil, model.NewAppError("SqlGroupStore.GroupDelete", "store.sql_group.no_rows", nil, "Id="+groupID+", "+err.Error(), http.StatusNotFound)
   247  		}
   248  		return nil, model.NewAppError("SqlGroupStore.GroupDelete", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   249  	}
   250  
   251  	time := model.GetMillis()
   252  	group.DeleteAt = time
   253  	group.UpdateAt = time
   254  
   255  	if _, err := s.GetMaster().Update(group); err != nil {
   256  		return nil, model.NewAppError("SqlGroupStore.GroupDelete", "store.update_error", nil, err.Error(), http.StatusInternalServerError)
   257  	}
   258  
   259  	return group, nil
   260  }
   261  
   262  func (s *SqlGroupStore) GetMemberUsers(groupID string) ([]*model.User, *model.AppError) {
   263  	var groupMembers []*model.User
   264  
   265  	query := `
   266  		SELECT
   267  			Users.*
   268  		FROM
   269  			GroupMembers
   270  			JOIN Users ON Users.Id = GroupMembers.UserId
   271  		WHERE
   272  			GroupMembers.DeleteAt = 0
   273  			AND Users.DeleteAt = 0
   274  			AND GroupId = :GroupId`
   275  
   276  	if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID}); err != nil {
   277  		return nil, model.NewAppError("SqlGroupStore.GetMemberUsers", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   278  	}
   279  
   280  	return groupMembers, nil
   281  }
   282  
   283  func (s *SqlGroupStore) GetMemberUsersPage(groupID string, page int, perPage int) ([]*model.User, *model.AppError) {
   284  	var groupMembers []*model.User
   285  
   286  	query := `
   287  		SELECT
   288  			Users.*
   289  		FROM
   290  			GroupMembers
   291  			JOIN Users ON Users.Id = GroupMembers.UserId
   292  		WHERE
   293  			GroupMembers.DeleteAt = 0
   294  			AND Users.DeleteAt = 0
   295  			AND GroupId = :GroupId
   296  		ORDER BY
   297  			GroupMembers.CreateAt DESC
   298  		LIMIT
   299  			:Limit
   300  		OFFSET
   301  			:Offset`
   302  
   303  	if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID, "Limit": perPage, "Offset": page * perPage}); err != nil {
   304  		return nil, model.NewAppError("SqlGroupStore.GroupGetMemberUsersPage", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   305  	}
   306  
   307  	return groupMembers, nil
   308  }
   309  
   310  func (s *SqlGroupStore) GetMemberCount(groupID string) (int64, *model.AppError) {
   311  	query := `
   312  		SELECT
   313  			count(*)
   314  		FROM
   315  			GroupMembers
   316  			JOIN Users ON Users.Id = GroupMembers.UserId
   317  		WHERE
   318  			GroupMembers.GroupId = :GroupId
   319  			AND Users.DeleteAt = 0`
   320  
   321  	count, err := s.GetReplica().SelectInt(query, map[string]interface{}{"GroupId": groupID})
   322  	if err != nil {
   323  		return int64(0), model.NewAppError("SqlGroupStore.GroupGetMemberUsersPage", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   324  	}
   325  
   326  	return count, nil
   327  }
   328  
   329  func (s *SqlGroupStore) GetMemberUsersInTeam(groupID string, teamID string) ([]*model.User, *model.AppError) {
   330  	var groupMembers []*model.User
   331  
   332  	query := `
   333  		SELECT
   334  			Users.*
   335  		FROM
   336  			GroupMembers
   337  			JOIN Users ON Users.Id = GroupMembers.UserId
   338  		WHERE
   339  			GroupId = :GroupId
   340  			AND GroupMembers.UserId IN (
   341  				SELECT TeamMembers.UserId
   342  				FROM TeamMembers
   343  				JOIN Teams ON Teams.Id = :TeamId
   344  				WHERE TeamMembers.TeamId = Teams.Id
   345  				AND TeamMembers.DeleteAt = 0
   346  			)
   347  			AND GroupMembers.DeleteAt = 0
   348  			AND Users.DeleteAt = 0
   349  		`
   350  
   351  	if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID, "TeamId": teamID}); err != nil {
   352  		return nil, model.NewAppError("SqlGroupStore.GetMemberUsersInTeam", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   353  	}
   354  
   355  	return groupMembers, nil
   356  }
   357  
   358  func (s *SqlGroupStore) GetMemberUsersNotInChannel(groupID string, channelID string) ([]*model.User, *model.AppError) {
   359  	var groupMembers []*model.User
   360  
   361  	query := `
   362  		SELECT
   363  			Users.*
   364  		FROM
   365  			GroupMembers
   366  			JOIN Users ON Users.Id = GroupMembers.UserId
   367  		WHERE
   368  			GroupId = :GroupId
   369  			AND GroupMembers.UserId NOT IN (
   370  				SELECT ChannelMembers.UserId
   371  				FROM ChannelMembers
   372  				WHERE ChannelMembers.ChannelId = :ChannelId
   373  			)
   374  			AND GroupMembers.UserId IN (
   375  				SELECT TeamMembers.UserId
   376  				FROM TeamMembers
   377  				JOIN Channels ON Channels.Id = :ChannelId
   378  				JOIN Teams ON Teams.Id = Channels.TeamId
   379  				WHERE TeamMembers.TeamId = Teams.Id
   380  				AND TeamMembers.DeleteAt = 0
   381  			)
   382  			AND GroupMembers.DeleteAt = 0
   383  			AND Users.DeleteAt = 0
   384  		`
   385  
   386  	if _, err := s.GetReplica().Select(&groupMembers, query, map[string]interface{}{"GroupId": groupID, "ChannelId": channelID}); err != nil {
   387  		return nil, model.NewAppError("SqlGroupStore.GetMemberUsersNotInChannel", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   388  	}
   389  
   390  	return groupMembers, nil
   391  }
   392  
   393  func (s *SqlGroupStore) UpsertMember(groupID string, userID string) (*model.GroupMember, *model.AppError) {
   394  	member := &model.GroupMember{
   395  		GroupId:  groupID,
   396  		UserId:   userID,
   397  		CreateAt: model.GetMillis(),
   398  	}
   399  
   400  	if err := member.IsValid(); err != nil {
   401  		return nil, err
   402  	}
   403  
   404  	var retrievedGroup *model.Group
   405  	if err := s.GetReplica().SelectOne(&retrievedGroup, "SELECT * FROM UserGroups WHERE Id = :Id", map[string]interface{}{"Id": groupID}); err != nil {
   406  		return nil, model.NewAppError("SqlGroupStore.GroupCreateOrRestoreMember", "store.insert_error", nil, "group_id="+member.GroupId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
   407  	}
   408  
   409  	var retrievedMember *model.GroupMember
   410  	if err := s.GetReplica().SelectOne(&retrievedMember, "SELECT * FROM GroupMembers WHERE GroupId = :GroupId AND UserId = :UserId", map[string]interface{}{"GroupId": member.GroupId, "UserId": member.UserId}); err != nil {
   411  		if err != sql.ErrNoRows {
   412  			return nil, model.NewAppError("SqlGroupStore.GroupCreateOrRestoreMember", "store.select_error", nil, "group_id="+member.GroupId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
   413  		}
   414  	}
   415  
   416  	if retrievedMember == nil {
   417  		if err := s.GetMaster().Insert(member); err != nil {
   418  			if IsUniqueConstraintError(err, []string{"GroupId", "UserId", "groupmembers_pkey", "PRIMARY"}) {
   419  				return nil, model.NewAppError("SqlGroupStore.GroupCreateOrRestoreMember", "store.sql_group.uniqueness_error", nil, "group_id="+member.GroupId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest)
   420  			}
   421  			return nil, model.NewAppError("SqlGroupStore.GroupCreateOrRestoreMember", "store.insert_error", nil, "group_id="+member.GroupId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
   422  		}
   423  	} else {
   424  		member.DeleteAt = 0
   425  		var rowsChanged int64
   426  		var err error
   427  		if rowsChanged, err = s.GetMaster().Update(member); err != nil {
   428  			return nil, model.NewAppError("SqlGroupStore.GroupCreateOrRestoreMember", "store.update_error", nil, "group_id="+member.GroupId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
   429  		}
   430  		if rowsChanged > 1 {
   431  			return nil, model.NewAppError("SqlGroupStore.GroupCreateOrRestoreMember", "store.sql_group.more_than_one_row_changed", nil, "", http.StatusInternalServerError)
   432  		}
   433  	}
   434  
   435  	return member, nil
   436  }
   437  
   438  func (s *SqlGroupStore) DeleteMember(groupID string, userID string) (*model.GroupMember, *model.AppError) {
   439  	var retrievedMember *model.GroupMember
   440  	if err := s.GetReplica().SelectOne(&retrievedMember, "SELECT * FROM GroupMembers WHERE GroupId = :GroupId AND UserId = :UserId AND DeleteAt = 0", map[string]interface{}{"GroupId": groupID, "UserId": userID}); err != nil {
   441  		if err == sql.ErrNoRows {
   442  			return nil, model.NewAppError("SqlGroupStore.GroupDeleteMember", "store.sql_group.no_rows", nil, "group_id="+groupID+"user_id="+userID+","+err.Error(), http.StatusNotFound)
   443  		}
   444  		return nil, model.NewAppError("SqlGroupStore.GroupDeleteMember", "store.select_error", nil, "group_id="+groupID+"user_id="+userID+","+err.Error(), http.StatusInternalServerError)
   445  	}
   446  
   447  	retrievedMember.DeleteAt = model.GetMillis()
   448  
   449  	if _, err := s.GetMaster().Update(retrievedMember); err != nil {
   450  		return nil, model.NewAppError("SqlGroupStore.GroupDeleteMember", "store.update_error", nil, err.Error(), http.StatusInternalServerError)
   451  	}
   452  
   453  	return retrievedMember, nil
   454  }
   455  
   456  func (s *SqlGroupStore) PermanentDeleteMembersByUser(userId string) *model.AppError {
   457  	if _, err := s.GetMaster().Exec("DELETE FROM GroupMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
   458  		return model.NewAppError("SqlGroupStore.GroupPermanentDeleteMembersByUser", "store.sql_group.permanent_delete_members_by_user.app_error", map[string]interface{}{"UserId": userId}, "", http.StatusInternalServerError)
   459  	}
   460  	return nil
   461  }
   462  
   463  func (s *SqlGroupStore) CreateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, *model.AppError) {
   464  	if err := groupSyncable.IsValid(); err != nil {
   465  		return nil, err
   466  	}
   467  
   468  	// Reset values that shouldn't be updatable by parameter
   469  	groupSyncable.DeleteAt = 0
   470  	groupSyncable.CreateAt = model.GetMillis()
   471  	groupSyncable.UpdateAt = groupSyncable.CreateAt
   472  
   473  	var insertErr error
   474  
   475  	switch groupSyncable.Type {
   476  	case model.GroupSyncableTypeTeam:
   477  		if _, err := s.Team().Get(groupSyncable.SyncableId); err != nil {
   478  			return nil, err
   479  		}
   480  
   481  		insertErr = s.GetMaster().Insert(groupSyncableToGroupTeam(groupSyncable))
   482  	case model.GroupSyncableTypeChannel:
   483  		if _, err := s.Channel().Get(groupSyncable.SyncableId, false); err != nil {
   484  			var nfErr *store.ErrNotFound
   485  			switch {
   486  			case errors.As(err, &nfErr):
   487  				return nil, model.NewAppError("CreateGroupSyncable", "store.sql_channel.get.existing.app_error", nil, nfErr.Error(), http.StatusNotFound)
   488  			default:
   489  				return nil, model.NewAppError("CreateGroupSyncable", "store.sql_channel.get.find.app_error", nil, err.Error(), http.StatusInternalServerError)
   490  			}
   491  		}
   492  
   493  		insertErr = s.GetMaster().Insert(groupSyncableToGroupChannel(groupSyncable))
   494  	default:
   495  		return nil, model.NewAppError("SqlGroupStore.GroupCreateGroupSyncable", "model.group_syncable.type.app_error", nil, "group_id="+groupSyncable.GroupId+", syncable_id="+groupSyncable.SyncableId, http.StatusInternalServerError)
   496  	}
   497  
   498  	if insertErr != nil {
   499  		return nil, model.NewAppError("SqlGroupStore.GroupCreateGroupSyncable", "store.insert_error", nil, "group_id="+groupSyncable.GroupId+", syncable_id="+groupSyncable.SyncableId+", "+insertErr.Error(), http.StatusInternalServerError)
   500  	}
   501  
   502  	return groupSyncable, nil
   503  }
   504  
   505  func (s *SqlGroupStore) GetGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError) {
   506  	groupSyncable, err := s.getGroupSyncable(groupID, syncableID, syncableType)
   507  	if err != nil {
   508  		if err == sql.ErrNoRows {
   509  			return nil, model.NewAppError("SqlGroupStore.GroupGetGroupSyncable", "store.sql_group.no_rows", nil, err.Error(), http.StatusNotFound)
   510  		}
   511  		return nil, model.NewAppError("SqlGroupStore.GroupGetGroupSyncable", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   512  	}
   513  
   514  	return groupSyncable, nil
   515  }
   516  
   517  func (s *SqlGroupStore) getGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, error) {
   518  	var err error
   519  	var result interface{}
   520  
   521  	switch syncableType {
   522  	case model.GroupSyncableTypeTeam:
   523  		result, err = s.GetReplica().Get(groupTeam{}, groupID, syncableID)
   524  	case model.GroupSyncableTypeChannel:
   525  		result, err = s.GetReplica().Get(groupChannel{}, groupID, syncableID)
   526  	}
   527  
   528  	if err != nil {
   529  		return nil, err
   530  	}
   531  
   532  	if result == nil {
   533  		return nil, sql.ErrNoRows
   534  	}
   535  
   536  	groupSyncable := model.GroupSyncable{}
   537  	switch syncableType {
   538  	case model.GroupSyncableTypeTeam:
   539  		groupTeam := result.(*groupTeam)
   540  		groupSyncable.SyncableId = groupTeam.TeamId
   541  		groupSyncable.GroupId = groupTeam.GroupId
   542  		groupSyncable.AutoAdd = groupTeam.AutoAdd
   543  		groupSyncable.CreateAt = groupTeam.CreateAt
   544  		groupSyncable.DeleteAt = groupTeam.DeleteAt
   545  		groupSyncable.UpdateAt = groupTeam.UpdateAt
   546  		groupSyncable.Type = syncableType
   547  	case model.GroupSyncableTypeChannel:
   548  		groupChannel := result.(*groupChannel)
   549  		groupSyncable.SyncableId = groupChannel.ChannelId
   550  		groupSyncable.GroupId = groupChannel.GroupId
   551  		groupSyncable.AutoAdd = groupChannel.AutoAdd
   552  		groupSyncable.CreateAt = groupChannel.CreateAt
   553  		groupSyncable.DeleteAt = groupChannel.DeleteAt
   554  		groupSyncable.UpdateAt = groupChannel.UpdateAt
   555  		groupSyncable.Type = syncableType
   556  	default:
   557  		return nil, fmt.Errorf("unable to convert syncableType: %s", syncableType.String())
   558  	}
   559  
   560  	return &groupSyncable, nil
   561  }
   562  
   563  func (s *SqlGroupStore) GetAllGroupSyncablesByGroupId(groupID string, syncableType model.GroupSyncableType) ([]*model.GroupSyncable, *model.AppError) {
   564  	args := map[string]interface{}{"GroupId": groupID}
   565  
   566  	appErrF := func(msg string) *model.AppError {
   567  		return model.NewAppError("SqlGroupStore.GroupGetAllGroupSyncablesByGroup", "store.select_error", nil, msg, http.StatusInternalServerError)
   568  	}
   569  
   570  	groupSyncables := []*model.GroupSyncable{}
   571  
   572  	switch syncableType {
   573  	case model.GroupSyncableTypeTeam:
   574  		sqlQuery := `
   575  			SELECT
   576  				GroupTeams.*,
   577  				Teams.DisplayName AS TeamDisplayName,
   578  				Teams.Type AS TeamType
   579  			FROM
   580  				GroupTeams
   581  				JOIN Teams ON Teams.Id = GroupTeams.TeamId
   582  			WHERE
   583  				GroupId = :GroupId AND GroupTeams.DeleteAt = 0`
   584  
   585  		results := []*groupTeamJoin{}
   586  		_, err := s.GetReplica().Select(&results, sqlQuery, args)
   587  		if err != nil {
   588  			return nil, appErrF(err.Error())
   589  		}
   590  		for _, result := range results {
   591  			groupSyncable := &model.GroupSyncable{
   592  				SyncableId:      result.TeamId,
   593  				GroupId:         result.GroupId,
   594  				AutoAdd:         result.AutoAdd,
   595  				CreateAt:        result.CreateAt,
   596  				DeleteAt:        result.DeleteAt,
   597  				UpdateAt:        result.UpdateAt,
   598  				Type:            syncableType,
   599  				TeamDisplayName: result.TeamDisplayName,
   600  				TeamType:        result.TeamType,
   601  				SchemeAdmin:     result.SchemeAdmin,
   602  			}
   603  			groupSyncables = append(groupSyncables, groupSyncable)
   604  		}
   605  	case model.GroupSyncableTypeChannel:
   606  		sqlQuery := `
   607  			SELECT
   608  				GroupChannels.*,
   609  				Channels.DisplayName AS ChannelDisplayName,
   610  				Teams.DisplayName AS TeamDisplayName,
   611  				Channels.Type As ChannelType,
   612  				Teams.Type As TeamType,
   613  				Teams.Id AS TeamId
   614  			FROM
   615  				GroupChannels
   616  				JOIN Channels ON Channels.Id = GroupChannels.ChannelId
   617  				JOIN Teams ON Teams.Id = Channels.TeamId
   618  			WHERE
   619  				GroupId = :GroupId AND GroupChannels.DeleteAt = 0`
   620  
   621  		results := []*groupChannelJoin{}
   622  		_, err := s.GetReplica().Select(&results, sqlQuery, args)
   623  		if err != nil {
   624  			return nil, appErrF(err.Error())
   625  		}
   626  		for _, result := range results {
   627  			groupSyncable := &model.GroupSyncable{
   628  				SyncableId:         result.ChannelId,
   629  				GroupId:            result.GroupId,
   630  				AutoAdd:            result.AutoAdd,
   631  				CreateAt:           result.CreateAt,
   632  				DeleteAt:           result.DeleteAt,
   633  				UpdateAt:           result.UpdateAt,
   634  				Type:               syncableType,
   635  				ChannelDisplayName: result.ChannelDisplayName,
   636  				ChannelType:        result.ChannelType,
   637  				TeamDisplayName:    result.TeamDisplayName,
   638  				TeamType:           result.TeamType,
   639  				TeamID:             result.TeamID,
   640  				SchemeAdmin:        result.SchemeAdmin,
   641  			}
   642  			groupSyncables = append(groupSyncables, groupSyncable)
   643  		}
   644  	}
   645  
   646  	return groupSyncables, nil
   647  }
   648  
   649  func (s *SqlGroupStore) UpdateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, *model.AppError) {
   650  	retrievedGroupSyncable, err := s.getGroupSyncable(groupSyncable.GroupId, groupSyncable.SyncableId, groupSyncable.Type)
   651  	if err != nil {
   652  		if err == sql.ErrNoRows {
   653  			return nil, model.NewAppError("SqlGroupStore.GroupUpdateGroupSyncable", "store.sql_group.no_rows", nil, err.Error(), http.StatusInternalServerError)
   654  		}
   655  		return nil, model.NewAppError("SqlGroupStore.GroupUpdateGroupSyncable", "store.select_error", nil, "GroupId="+groupSyncable.GroupId+", SyncableId="+groupSyncable.SyncableId+", SyncableType="+groupSyncable.Type.String()+", "+err.Error(), http.StatusInternalServerError)
   656  	}
   657  
   658  	if err := groupSyncable.IsValid(); err != nil {
   659  		return nil, err
   660  	}
   661  
   662  	// If updating DeleteAt it can only be to 0
   663  	if groupSyncable.DeleteAt != retrievedGroupSyncable.DeleteAt && groupSyncable.DeleteAt != 0 {
   664  		return nil, model.NewAppError("SqlGroupStore.GroupUpdateGroupSyncable", "model.group.delete_at.app_error", nil, "", http.StatusInternalServerError)
   665  	}
   666  
   667  	// Reset these properties, don't update them based on input
   668  	groupSyncable.CreateAt = retrievedGroupSyncable.CreateAt
   669  	groupSyncable.UpdateAt = model.GetMillis()
   670  
   671  	switch groupSyncable.Type {
   672  	case model.GroupSyncableTypeTeam:
   673  		_, err = s.GetMaster().Update(groupSyncableToGroupTeam(groupSyncable))
   674  	case model.GroupSyncableTypeChannel:
   675  		_, err = s.GetMaster().Update(groupSyncableToGroupChannel(groupSyncable))
   676  	default:
   677  		return nil, model.NewAppError("SqlGroupStore.GroupUpdateGroupSyncable", "model.group_syncable.type.app_error", nil, "group_id="+groupSyncable.GroupId+", syncable_id="+groupSyncable.SyncableId, http.StatusInternalServerError)
   678  	}
   679  
   680  	if err != nil {
   681  		return nil, model.NewAppError("SqlGroupStore.GroupUpdateGroupSyncable", "store.update_error", nil, err.Error(), http.StatusInternalServerError)
   682  	}
   683  
   684  	return groupSyncable, nil
   685  }
   686  
   687  func (s *SqlGroupStore) DeleteGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError) {
   688  	groupSyncable, err := s.getGroupSyncable(groupID, syncableID, syncableType)
   689  	if err != nil {
   690  		if err == sql.ErrNoRows {
   691  			return nil, model.NewAppError("SqlGroupStore.GroupDeleteGroupSyncable", "store.sql_group.no_rows", nil, "Id="+groupID+", "+err.Error(), http.StatusNotFound)
   692  		}
   693  		return nil, model.NewAppError("SqlGroupStore.GroupDeleteGroupSyncable", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   694  	}
   695  
   696  	if groupSyncable.DeleteAt != 0 {
   697  		return nil, model.NewAppError("SqlGroupStore.GroupDeleteGroupSyncable", "store.sql_group.group_syncable_already_deleted", nil, "group_id="+groupID+"syncable_id="+syncableID, http.StatusBadRequest)
   698  	}
   699  
   700  	time := model.GetMillis()
   701  	groupSyncable.DeleteAt = time
   702  	groupSyncable.UpdateAt = time
   703  
   704  	switch groupSyncable.Type {
   705  	case model.GroupSyncableTypeTeam:
   706  		_, err = s.GetMaster().Update(groupSyncableToGroupTeam(groupSyncable))
   707  	case model.GroupSyncableTypeChannel:
   708  		_, err = s.GetMaster().Update(groupSyncableToGroupChannel(groupSyncable))
   709  	default:
   710  		return nil, model.NewAppError("SqlGroupStore.GroupDeleteGroupSyncable", "model.group_syncable.type.app_error", nil, "group_id="+groupSyncable.GroupId+", syncable_id="+groupSyncable.SyncableId, http.StatusInternalServerError)
   711  	}
   712  
   713  	if err != nil {
   714  		return nil, model.NewAppError("SqlGroupStore.GroupDeleteGroupSyncable", "store.update_error", nil, err.Error(), http.StatusInternalServerError)
   715  	}
   716  
   717  	return groupSyncable, nil
   718  }
   719  
   720  func (s *SqlGroupStore) TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, *model.AppError) {
   721  	query := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupTeams.TeamId").
   722  		From("GroupMembers").
   723  		Join("GroupTeams ON GroupTeams.GroupId = GroupMembers.GroupId").
   724  		Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
   725  		Join("Teams ON Teams.Id = GroupTeams.TeamId").
   726  		JoinClause("LEFT OUTER JOIN TeamMembers ON TeamMembers.TeamId = GroupTeams.TeamId AND TeamMembers.UserId = GroupMembers.UserId").
   727  		Where(sq.Eq{
   728  			"TeamMembers.UserId":    nil,
   729  			"UserGroups.DeleteAt":   0,
   730  			"GroupTeams.DeleteAt":   0,
   731  			"GroupTeams.AutoAdd":    true,
   732  			"GroupMembers.DeleteAt": 0,
   733  			"Teams.DeleteAt":        0,
   734  		}).
   735  		Where("(GroupMembers.CreateAt >= ? OR GroupTeams.UpdateAt >= ?)", since, since)
   736  
   737  	if teamID != nil {
   738  		query = query.Where(sq.Eq{"Teams.Id": *teamID})
   739  	}
   740  
   741  	sql, params, err := query.ToSql()
   742  	if err != nil {
   743  		return nil, model.NewAppError("SqlGroupStore.TeamMembersToAdd", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   744  	}
   745  
   746  	var teamMembers []*model.UserTeamIDPair
   747  
   748  	_, err = s.GetReplica().Select(&teamMembers, sql, params...)
   749  	if err != nil {
   750  		return nil, model.NewAppError("SqlGroupStore.TeamMembersToAdd", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   751  	}
   752  
   753  	return teamMembers, nil
   754  }
   755  
   756  func (s *SqlGroupStore) ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, *model.AppError) {
   757  	query := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupChannels.ChannelId").
   758  		From("GroupMembers").
   759  		Join("GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId").
   760  		Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
   761  		Join("Channels ON Channels.Id = GroupChannels.ChannelId").
   762  		JoinClause("LEFT OUTER JOIN ChannelMemberHistory ON ChannelMemberHistory.ChannelId = GroupChannels.ChannelId AND ChannelMemberHistory.UserId = GroupMembers.UserId").
   763  		Where(sq.Eq{
   764  			"ChannelMemberHistory.UserId":    nil,
   765  			"ChannelMemberHistory.LeaveTime": nil,
   766  			"UserGroups.DeleteAt":            0,
   767  			"GroupChannels.DeleteAt":         0,
   768  			"GroupChannels.AutoAdd":          true,
   769  			"GroupMembers.DeleteAt":          0,
   770  			"Channels.DeleteAt":              0,
   771  		}).
   772  		Where("(GroupMembers.CreateAt >= ? OR GroupChannels.UpdateAt >= ?)", since, since)
   773  
   774  	if channelID != nil {
   775  		query = query.Where(sq.Eq{"Channels.Id": *channelID})
   776  	}
   777  
   778  	sql, params, err := query.ToSql()
   779  	if err != nil {
   780  		return nil, model.NewAppError("SqlGroupStore.ChannelMembersToAdd", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   781  	}
   782  
   783  	var channelMembers []*model.UserChannelIDPair
   784  
   785  	_, err = s.GetReplica().Select(&channelMembers, sql, params...)
   786  	if err != nil {
   787  		return nil, model.NewAppError("SqlGroupStore.ChannelMembersToAdd", "store.select_error", nil, "", http.StatusInternalServerError)
   788  	}
   789  
   790  	return channelMembers, nil
   791  }
   792  
   793  func groupSyncableToGroupTeam(groupSyncable *model.GroupSyncable) *groupTeam {
   794  	return &groupTeam{
   795  		GroupSyncable: *groupSyncable,
   796  		TeamId:        groupSyncable.SyncableId,
   797  	}
   798  }
   799  
   800  func groupSyncableToGroupChannel(groupSyncable *model.GroupSyncable) *groupChannel {
   801  	return &groupChannel{
   802  		GroupSyncable: *groupSyncable,
   803  		ChannelId:     groupSyncable.SyncableId,
   804  	}
   805  }
   806  
   807  func (s *SqlGroupStore) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError) {
   808  	whereStmt := `
   809  		(TeamMembers.TeamId,
   810  			TeamMembers.UserId)
   811  		NOT IN (
   812  			SELECT
   813  				Teams.Id AS TeamId,
   814  				GroupMembers.UserId
   815  			FROM
   816  				Teams
   817  				JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id
   818  				JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId
   819  				JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
   820  			WHERE
   821  				Teams.GroupConstrained = TRUE
   822  				AND GroupTeams.DeleteAt = 0
   823  				AND UserGroups.DeleteAt = 0
   824  				AND Teams.DeleteAt = 0
   825  				AND GroupMembers.DeleteAt = 0
   826  			GROUP BY
   827  				Teams.Id,
   828  				GroupMembers.UserId)`
   829  
   830  	query := s.getQueryBuilder().Select(
   831  		"TeamMembers.TeamId",
   832  		"TeamMembers.UserId",
   833  		"TeamMembers.Roles",
   834  		"TeamMembers.DeleteAt",
   835  		"TeamMembers.SchemeUser",
   836  		"TeamMembers.SchemeAdmin",
   837  		"(TeamMembers.SchemeGuest IS NOT NULL AND TeamMembers.SchemeGuest) AS SchemeGuest",
   838  	).
   839  		From("TeamMembers").
   840  		Join("Teams ON Teams.Id = TeamMembers.TeamId").
   841  		LeftJoin("Bots ON Bots.UserId = TeamMembers.UserId").
   842  		Where(sq.Eq{"TeamMembers.DeleteAt": 0, "Teams.DeleteAt": 0, "Teams.GroupConstrained": true, "Bots.UserId": nil}).
   843  		Where(whereStmt)
   844  
   845  	if teamID != nil {
   846  		query = query.Where(sq.Eq{"TeamMembers.TeamId": *teamID})
   847  	}
   848  
   849  	sql, params, err := query.ToSql()
   850  	if err != nil {
   851  		return nil, model.NewAppError("SqlGroupStore.TeamMembersToRemove", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   852  	}
   853  
   854  	var teamMembers []*model.TeamMember
   855  
   856  	_, err = s.GetReplica().Select(&teamMembers, sql, params...)
   857  	if err != nil {
   858  		return nil, model.NewAppError("SqlGroupStore.TeamMembersToRemove", "store.select_error", nil, "", http.StatusInternalServerError)
   859  	}
   860  
   861  	return teamMembers, nil
   862  }
   863  
   864  func (s *SqlGroupStore) CountGroupsByChannel(channelId string, opts model.GroupSearchOpts) (int64, *model.AppError) {
   865  	countQuery := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectCountGroups, channelId, opts)
   866  
   867  	countQueryString, args, err := countQuery.ToSql()
   868  	if err != nil {
   869  		return int64(0), model.NewAppError("SqlGroupStore.CountGroupsByChannel", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   870  	}
   871  
   872  	count, err := s.GetReplica().SelectInt(countQueryString, args...)
   873  	if err != nil {
   874  		return int64(0), model.NewAppError("SqlGroupStore.CountGroupsByChannel", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   875  	}
   876  
   877  	return count, nil
   878  }
   879  
   880  func (s *SqlGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
   881  	query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeChannel, selectGroups, channelId, opts)
   882  
   883  	if opts.PageOpts != nil {
   884  		offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage)
   885  		query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset)
   886  	}
   887  
   888  	queryString, args, err := query.ToSql()
   889  	if err != nil {
   890  		return nil, model.NewAppError("SqlGroupStore.GetGroupsByChannel", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   891  	}
   892  
   893  	var groups []*model.GroupWithSchemeAdmin
   894  
   895  	_, err = s.GetReplica().Select(&groups, queryString, args...)
   896  	if err != nil {
   897  		return nil, model.NewAppError("SqlGroupStore.GetGroupsByChannel", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   898  	}
   899  
   900  	return groups, nil
   901  }
   902  
   903  func (s *SqlGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.ChannelMember, *model.AppError) {
   904  	whereStmt := `
   905  		(ChannelMembers.ChannelId,
   906  			ChannelMembers.UserId)
   907  		NOT IN (
   908  			SELECT
   909  				Channels.Id AS ChannelId,
   910  				GroupMembers.UserId
   911  			FROM
   912  				Channels
   913  				JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id
   914  				JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId
   915  				JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
   916  			WHERE
   917  				Channels.GroupConstrained = TRUE
   918  				AND GroupChannels.DeleteAt = 0
   919  				AND UserGroups.DeleteAt = 0
   920  				AND Channels.DeleteAt = 0
   921  				AND GroupMembers.DeleteAt = 0
   922  			GROUP BY
   923  				Channels.Id,
   924  				GroupMembers.UserId)`
   925  
   926  	query := s.getQueryBuilder().Select(
   927  		"ChannelMembers.ChannelId",
   928  		"ChannelMembers.UserId",
   929  		"ChannelMembers.LastViewedAt",
   930  		"ChannelMembers.MsgCount",
   931  		"ChannelMembers.MentionCount",
   932  		"ChannelMembers.NotifyProps",
   933  		"ChannelMembers.LastUpdateAt",
   934  		"ChannelMembers.LastUpdateAt",
   935  		"ChannelMembers.SchemeUser",
   936  		"ChannelMembers.SchemeAdmin",
   937  		"(ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) AS SchemeGuest",
   938  	).
   939  		From("ChannelMembers").
   940  		Join("Channels ON Channels.Id = ChannelMembers.ChannelId").
   941  		LeftJoin("Bots ON Bots.UserId = ChannelMembers.UserId").
   942  		Where(sq.Eq{"Channels.DeleteAt": 0, "Channels.GroupConstrained": true, "Bots.UserId": nil}).
   943  		Where(whereStmt)
   944  
   945  	if channelID != nil {
   946  		query = query.Where(sq.Eq{"ChannelMembers.ChannelId": *channelID})
   947  	}
   948  
   949  	sql, params, err := query.ToSql()
   950  	if err != nil {
   951  		return nil, model.NewAppError("SqlGroupStore.ChannelMembersToRemove", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
   952  	}
   953  
   954  	var channelMembers []*model.ChannelMember
   955  
   956  	_, err = s.GetReplica().Select(&channelMembers, sql, params...)
   957  	if err != nil {
   958  		return nil, model.NewAppError("SqlGroupStore.ChannelMembersToRemove", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
   959  	}
   960  
   961  	return channelMembers, nil
   962  }
   963  
   964  func (s *SqlGroupStore) groupsBySyncableBaseQuery(st model.GroupSyncableType, t selectType, syncableID string, opts model.GroupSearchOpts) sq.SelectBuilder {
   965  	selectStrs := map[selectType]string{
   966  		selectGroups:      "ug.*, gs.SchemeAdmin AS SyncableSchemeAdmin",
   967  		selectCountGroups: "COUNT(*)",
   968  	}
   969  
   970  	var table string
   971  	var idCol string
   972  	if st == model.GroupSyncableTypeTeam {
   973  		table = "GroupTeams"
   974  		idCol = "TeamId"
   975  	} else {
   976  		table = "GroupChannels"
   977  		idCol = "ChannelId"
   978  	}
   979  
   980  	query := s.getQueryBuilder().
   981  		Select(selectStrs[t]).
   982  		From(fmt.Sprintf("%s gs", table)).
   983  		LeftJoin("UserGroups ug ON gs.GroupId = ug.Id").
   984  		Where(fmt.Sprintf("ug.DeleteAt = 0 AND gs.%s = ? AND gs.DeleteAt = 0", idCol), syncableID)
   985  
   986  	if opts.IncludeMemberCount && t == selectGroups {
   987  		query = s.getQueryBuilder().
   988  			Select(fmt.Sprintf("ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, Group%ss.SchemeAdmin AS SyncableSchemeAdmin", st)).
   989  			From("UserGroups ug").
   990  			LeftJoin("(SELECT GroupMembers.GroupId, COUNT(*) AS MemberCount FROM GroupMembers LEFT JOIN Users ON Users.Id = GroupMembers.UserId WHERE GroupMembers.DeleteAt = 0 AND Users.DeleteAt = 0 GROUP BY GroupId) AS Members ON Members.GroupId = ug.Id").
   991  			LeftJoin(fmt.Sprintf("%[1]s ON %[1]s.GroupId = ug.Id", table)).
   992  			Where(fmt.Sprintf("ug.DeleteAt = 0 AND %[1]s.DeleteAt = 0 AND %[1]s.%[2]s = ?", table, idCol), syncableID).
   993  			OrderBy("ug.DisplayName")
   994  	}
   995  
   996  	if opts.FilterAllowReference && t == selectGroups {
   997  		query = query.Where("ug.AllowReference = true")
   998  	}
   999  
  1000  	if len(opts.Q) > 0 {
  1001  		pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\"))
  1002  		operatorKeyword := "ILIKE"
  1003  		if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1004  			operatorKeyword = "LIKE"
  1005  		}
  1006  		query = query.Where(fmt.Sprintf("(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern)
  1007  	}
  1008  
  1009  	return query
  1010  }
  1011  
  1012  func (s *SqlGroupStore) getGroupsAssociatedToChannelsByTeam(st model.GroupSyncableType, teamID string, opts model.GroupSearchOpts) sq.SelectBuilder {
  1013  	query := s.getQueryBuilder().
  1014  		Select("gc.ChannelId, ug.*, gc.SchemeAdmin AS SyncableSchemeAdmin").
  1015  		From("UserGroups ug").
  1016  		LeftJoin(`
  1017  			(SELECT
  1018  				GroupChannels.GroupId, GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.SchemeAdmin
  1019  			FROM
  1020  				GroupChannels
  1021  			LEFT JOIN
  1022  				Channels ON (Channels.Id = GroupChannels.ChannelId)
  1023  			WHERE
  1024  				GroupChannels.DeleteAt = 0
  1025  				AND Channels.DeleteAt = 0
  1026  				AND Channels.TeamId = ?) AS gc ON gc.GroupId = ug.Id`, teamID).
  1027  		Where("ug.DeleteAt = 0 AND gc.DeleteAt = 0").
  1028  		OrderBy("ug.DisplayName")
  1029  
  1030  	if opts.IncludeMemberCount {
  1031  		query = s.getQueryBuilder().
  1032  			Select("gc.ChannelId, ug.*, coalesce(Members.MemberCount, 0) AS MemberCount, gc.SchemeAdmin AS SyncableSchemeAdmin").
  1033  			From("UserGroups ug").
  1034  			LeftJoin(`
  1035  				(SELECT
  1036  					GroupChannels.ChannelId, GroupChannels.DeleteAt, GroupChannels.GroupId, GroupChannels.SchemeAdmin
  1037  				FROM
  1038  					GroupChannels
  1039  				LEFT JOIN
  1040  					Channels ON (Channels.Id = GroupChannels.ChannelId)
  1041  				WHERE
  1042  					GroupChannels.DeleteAt = 0
  1043  					AND Channels.DeleteAt = 0
  1044  					AND Channels.TeamId = ?) AS gc ON gc.GroupId = ug.Id`, teamID).
  1045  			LeftJoin(`(
  1046  				SELECT
  1047  					GroupMembers.GroupId, COUNT(*) AS MemberCount
  1048  				FROM
  1049  					GroupMembers
  1050  				LEFT JOIN
  1051  					Users ON Users.Id = GroupMembers.UserId
  1052  				WHERE
  1053  					GroupMembers.DeleteAt = 0
  1054  					AND Users.DeleteAt = 0
  1055  				GROUP BY GroupId) AS Members
  1056  			ON Members.GroupId = ug.Id`).
  1057  			Where("ug.DeleteAt = 0 AND gc.DeleteAt = 0").
  1058  			OrderBy("ug.DisplayName")
  1059  	}
  1060  
  1061  	if opts.FilterAllowReference {
  1062  		query = query.Where("ug.AllowReference = true")
  1063  	}
  1064  
  1065  	if len(opts.Q) > 0 {
  1066  		pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\"))
  1067  		operatorKeyword := "ILIKE"
  1068  		if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1069  			operatorKeyword = "LIKE"
  1070  		}
  1071  		query = query.Where(fmt.Sprintf("(ug.Name %[1]s ? OR ug.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern)
  1072  	}
  1073  
  1074  	return query
  1075  }
  1076  
  1077  func (s *SqlGroupStore) CountGroupsByTeam(teamId string, opts model.GroupSearchOpts) (int64, *model.AppError) {
  1078  	countQuery := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectCountGroups, teamId, opts)
  1079  
  1080  	countQueryString, args, err := countQuery.ToSql()
  1081  	if err != nil {
  1082  		return int64(0), model.NewAppError("SqlGroupStore.CountGroupsByTeam", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1083  	}
  1084  
  1085  	count, err := s.GetReplica().SelectInt(countQueryString, args...)
  1086  	if err != nil {
  1087  		return int64(0), model.NewAppError("SqlGroupStore.CountGroupsByTeam", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1088  	}
  1089  
  1090  	return count, nil
  1091  }
  1092  
  1093  func (s *SqlGroupStore) GetGroupsByTeam(teamId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError) {
  1094  	query := s.groupsBySyncableBaseQuery(model.GroupSyncableTypeTeam, selectGroups, teamId, opts)
  1095  
  1096  	if opts.PageOpts != nil {
  1097  		offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage)
  1098  		query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset)
  1099  	}
  1100  
  1101  	queryString, args, err := query.ToSql()
  1102  	if err != nil {
  1103  		return nil, model.NewAppError("SqlGroupStore.GetGroupsByTeam", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1104  	}
  1105  
  1106  	var groups []*model.GroupWithSchemeAdmin
  1107  
  1108  	_, err = s.GetReplica().Select(&groups, queryString, args...)
  1109  	if err != nil {
  1110  		return nil, model.NewAppError("SqlGroupStore.GetGroupsByTeam", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1111  	}
  1112  
  1113  	return groups, nil
  1114  }
  1115  
  1116  func (s *SqlGroupStore) GetGroupsAssociatedToChannelsByTeam(teamId string, opts model.GroupSearchOpts) (map[string][]*model.GroupWithSchemeAdmin, *model.AppError) {
  1117  	query := s.getGroupsAssociatedToChannelsByTeam(model.GroupSyncableTypeTeam, teamId, opts)
  1118  
  1119  	if opts.PageOpts != nil {
  1120  		offset := uint64(opts.PageOpts.Page * opts.PageOpts.PerPage)
  1121  		query = query.OrderBy("ug.DisplayName").Limit(uint64(opts.PageOpts.PerPage)).Offset(offset)
  1122  	}
  1123  
  1124  	queryString, args, err := query.ToSql()
  1125  	if err != nil {
  1126  		return nil, model.NewAppError("SqlGroupStore.GetGroupsAssociatedToChannelsByTeam", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1127  	}
  1128  
  1129  	var tgroups []*model.GroupsAssociatedToChannelWithSchemeAdmin
  1130  
  1131  	_, err = s.GetReplica().Select(&tgroups, queryString, args...)
  1132  	if err != nil {
  1133  		return nil, model.NewAppError("SqlGroupStore.GetGroupsAssociatedToChannelsByTeam", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1134  	}
  1135  
  1136  	groups := map[string][]*model.GroupWithSchemeAdmin{}
  1137  	for _, tgroup := range tgroups {
  1138  		var group = model.GroupWithSchemeAdmin{}
  1139  		group.Group = tgroup.Group
  1140  		group.SchemeAdmin = tgroup.SchemeAdmin
  1141  
  1142  		if val, ok := groups[tgroup.ChannelId]; ok {
  1143  			groups[tgroup.ChannelId] = append(val, &group)
  1144  		} else {
  1145  			groups[tgroup.ChannelId] = []*model.GroupWithSchemeAdmin{&group}
  1146  		}
  1147  	}
  1148  
  1149  	return groups, nil
  1150  }
  1151  
  1152  func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts) ([]*model.Group, *model.AppError) {
  1153  	var groups []*model.Group
  1154  
  1155  	groupsQuery := s.getQueryBuilder().Select("g.*")
  1156  
  1157  	if opts.IncludeMemberCount {
  1158  		groupsQuery = s.getQueryBuilder().
  1159  			Select("g.*, coalesce(Members.MemberCount, 0) AS MemberCount").
  1160  			LeftJoin("(SELECT GroupMembers.GroupId, COUNT(*) AS MemberCount FROM GroupMembers LEFT JOIN Users ON Users.Id = GroupMembers.UserId WHERE GroupMembers.DeleteAt = 0 AND Users.DeleteAt = 0 GROUP BY GroupId) AS Members ON Members.GroupId = g.Id")
  1161  	}
  1162  
  1163  	groupsQuery = groupsQuery.
  1164  		From("UserGroups g").
  1165  		OrderBy("g.DisplayName")
  1166  
  1167  	if opts.Since > 0 {
  1168  		groupsQuery = groupsQuery.Where(sq.Gt{
  1169  			"g.UpdateAt": opts.Since,
  1170  		})
  1171  	} else {
  1172  		groupsQuery = groupsQuery.Where("g.DeleteAt = 0")
  1173  	}
  1174  
  1175  	if perPage != 0 {
  1176  		groupsQuery = groupsQuery.
  1177  			Limit(uint64(perPage)).
  1178  			Offset(uint64(page * perPage))
  1179  	}
  1180  
  1181  	if opts.FilterAllowReference {
  1182  		groupsQuery = groupsQuery.Where("g.AllowReference = true")
  1183  	}
  1184  
  1185  	if len(opts.Q) > 0 {
  1186  		pattern := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(opts.Q, "\\"))
  1187  		operatorKeyword := "ILIKE"
  1188  		if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1189  			operatorKeyword = "LIKE"
  1190  		}
  1191  		groupsQuery = groupsQuery.Where(fmt.Sprintf("(g.Name %[1]s ? OR g.DisplayName %[1]s ?)", operatorKeyword), pattern, pattern)
  1192  	}
  1193  
  1194  	if len(opts.NotAssociatedToTeam) == 26 {
  1195  		groupsQuery = groupsQuery.Where(`
  1196  			g.Id NOT IN (
  1197  				SELECT
  1198  					Id
  1199  				FROM
  1200  					UserGroups
  1201  					JOIN GroupTeams ON GroupTeams.GroupId = UserGroups.Id
  1202  				WHERE
  1203  					GroupTeams.DeleteAt = 0
  1204  					AND UserGroups.DeleteAt = 0
  1205  					AND GroupTeams.TeamId = ?
  1206  			)
  1207  		`, opts.NotAssociatedToTeam)
  1208  	}
  1209  
  1210  	if len(opts.NotAssociatedToChannel) == 26 {
  1211  		groupsQuery = groupsQuery.Where(`
  1212  			g.Id NOT IN (
  1213  				SELECT
  1214  					Id
  1215  				FROM
  1216  					UserGroups
  1217  					JOIN GroupChannels ON GroupChannels.GroupId = UserGroups.Id
  1218  				WHERE
  1219  					GroupChannels.DeleteAt = 0
  1220  					AND UserGroups.DeleteAt = 0
  1221  					AND GroupChannels.ChannelId = ?
  1222  			)
  1223  		`, opts.NotAssociatedToChannel)
  1224  	}
  1225  
  1226  	if opts.FilterParentTeamPermitted && len(opts.NotAssociatedToChannel) == 26 {
  1227  		groupsQuery = groupsQuery.Where(`
  1228  			CASE
  1229  			WHEN (
  1230  				SELECT
  1231  					Teams.GroupConstrained
  1232  				FROM
  1233  					Teams
  1234  					JOIN Channels ON Channels.TeamId = Teams.Id
  1235  				WHERE
  1236  					Channels.Id = ?
  1237  			) THEN g.Id IN (
  1238  				SELECT
  1239  					GroupId
  1240  				FROM
  1241  					GroupTeams
  1242  				WHERE
  1243  					GroupTeams.DeleteAt = 0
  1244  					AND GroupTeams.TeamId = (
  1245  						SELECT
  1246  							TeamId
  1247  						FROM
  1248  							Channels
  1249  						WHERE
  1250  							Id = ?
  1251  					)
  1252  			)
  1253  			ELSE TRUE
  1254  		END
  1255  		`, opts.NotAssociatedToChannel, opts.NotAssociatedToChannel)
  1256  	}
  1257  
  1258  	queryString, args, err := groupsQuery.ToSql()
  1259  	if err != nil {
  1260  		return nil, model.NewAppError("SqlGroupStore.GetGroups", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1261  	}
  1262  
  1263  	if _, err = s.GetReplica().Select(&groups, queryString, args...); err != nil {
  1264  		return nil, model.NewAppError("SqlGroupStore.GetGroups", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1265  	}
  1266  
  1267  	return groups, nil
  1268  }
  1269  
  1270  func (s *SqlGroupStore) teamMembersMinusGroupMembersQuery(teamID string, groupIDs []string, isCount bool) sq.SelectBuilder {
  1271  	var selectStr string
  1272  
  1273  	if isCount {
  1274  		selectStr = "count(DISTINCT Users.Id)"
  1275  	} else {
  1276  		tmpl := "Users.*, coalesce(TeamMembers.SchemeGuest, false), TeamMembers.SchemeAdmin, TeamMembers.SchemeUser, %s AS GroupIDs"
  1277  		if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1278  			selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)")
  1279  		} else {
  1280  			selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')")
  1281  		}
  1282  	}
  1283  
  1284  	subQuery := s.getQueryBuilder().Select("GroupMembers.UserId").
  1285  		From("GroupMembers").
  1286  		Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
  1287  		Where("GroupMembers.DeleteAt = 0").
  1288  		Where(fmt.Sprintf("GroupMembers.GroupId IN ('%s')", strings.Join(groupIDs, "', '")))
  1289  
  1290  	sql, _ := subQuery.MustSql()
  1291  
  1292  	query := s.getQueryBuilder().Select(selectStr).
  1293  		From("TeamMembers").
  1294  		Join("Teams ON Teams.Id = TeamMembers.TeamId").
  1295  		Join("Users ON Users.Id = TeamMembers.UserId").
  1296  		LeftJoin("Bots ON Bots.UserId = TeamMembers.UserId").
  1297  		LeftJoin("GroupMembers ON GroupMembers.UserId = Users.Id").
  1298  		LeftJoin("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
  1299  		Where("TeamMembers.DeleteAt = 0").
  1300  		Where("Teams.DeleteAt = 0").
  1301  		Where("Users.DeleteAt = 0").
  1302  		Where("Bots.UserId IS NULL").
  1303  		Where("Teams.Id = ?", teamID).
  1304  		Where(fmt.Sprintf("Users.Id NOT IN (%s)", sql))
  1305  
  1306  	if !isCount {
  1307  		query = query.GroupBy("Users.Id, TeamMembers.SchemeGuest, TeamMembers.SchemeAdmin, TeamMembers.SchemeUser")
  1308  	}
  1309  
  1310  	return query
  1311  }
  1312  
  1313  // TeamMembersMinusGroupMembers returns the set of users on the given team minus the set of users in the given
  1314  // groups.
  1315  func (s *SqlGroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, *model.AppError) {
  1316  	query := s.teamMembersMinusGroupMembersQuery(teamID, groupIDs, false)
  1317  	query = query.OrderBy("Users.Username ASC").Limit(uint64(perPage)).Offset(uint64(page * perPage))
  1318  
  1319  	queryString, args, err := query.ToSql()
  1320  	if err != nil {
  1321  		return nil, model.NewAppError("SqlGroupStore.TeamMembersMinusGroupMembers", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1322  	}
  1323  
  1324  	var users []*model.UserWithGroups
  1325  	if _, err = s.GetReplica().Select(&users, queryString, args...); err != nil {
  1326  		return nil, model.NewAppError("SqlGroupStore.TeamMembersMinusGroupMembers", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1327  	}
  1328  
  1329  	return users, nil
  1330  }
  1331  
  1332  // CountTeamMembersMinusGroupMembers returns the count of the set of users on the given team minus the set of users
  1333  // in the given groups.
  1334  func (s *SqlGroupStore) CountTeamMembersMinusGroupMembers(teamID string, groupIDs []string) (int64, *model.AppError) {
  1335  	queryString, args, err := s.teamMembersMinusGroupMembersQuery(teamID, groupIDs, true).ToSql()
  1336  	if err != nil {
  1337  		return 0, model.NewAppError("SqlGroupStore.CountTeamMembersMinusGroupMembers", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1338  	}
  1339  
  1340  	var count int64
  1341  	if count, err = s.GetReplica().SelectInt(queryString, args...); err != nil {
  1342  		return 0, model.NewAppError("SqlGroupStore.CountTeamMembersMinusGroupMembers", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1343  	}
  1344  
  1345  	return count, nil
  1346  }
  1347  
  1348  func (s *SqlGroupStore) channelMembersMinusGroupMembersQuery(channelID string, groupIDs []string, isCount bool) sq.SelectBuilder {
  1349  	var selectStr string
  1350  
  1351  	if isCount {
  1352  		selectStr = "count(DISTINCT Users.Id)"
  1353  	} else {
  1354  		tmpl := "Users.*, coalesce(ChannelMembers.SchemeGuest, false), ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser, %s AS GroupIDs"
  1355  		if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1356  			selectStr = fmt.Sprintf(tmpl, "group_concat(UserGroups.Id)")
  1357  		} else {
  1358  			selectStr = fmt.Sprintf(tmpl, "string_agg(UserGroups.Id, ',')")
  1359  		}
  1360  	}
  1361  
  1362  	subQuery := s.getQueryBuilder().Select("GroupMembers.UserId").
  1363  		From("GroupMembers").
  1364  		Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
  1365  		Where("GroupMembers.DeleteAt = 0").
  1366  		Where(fmt.Sprintf("GroupMembers.GroupId IN ('%s')", strings.Join(groupIDs, "', '")))
  1367  
  1368  	sql, _ := subQuery.MustSql()
  1369  
  1370  	query := s.getQueryBuilder().Select(selectStr).
  1371  		From("ChannelMembers").
  1372  		Join("Channels ON Channels.Id = ChannelMembers.ChannelId").
  1373  		Join("Users ON Users.Id = ChannelMembers.UserId").
  1374  		LeftJoin("Bots ON Bots.UserId = ChannelMembers.UserId").
  1375  		LeftJoin("GroupMembers ON GroupMembers.UserId = Users.Id").
  1376  		LeftJoin("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
  1377  		Where("Channels.DeleteAt = 0").
  1378  		Where("Users.DeleteAt = 0").
  1379  		Where("Bots.UserId IS NULL").
  1380  		Where("Channels.Id = ?", channelID).
  1381  		Where(fmt.Sprintf("Users.Id NOT IN (%s)", sql))
  1382  
  1383  	if !isCount {
  1384  		query = query.GroupBy("Users.Id, ChannelMembers.SchemeGuest, ChannelMembers.SchemeAdmin, ChannelMembers.SchemeUser")
  1385  	}
  1386  
  1387  	return query
  1388  }
  1389  
  1390  // ChannelMembersMinusGroupMembers returns the set of users in the given channel minus the set of users in the given
  1391  // groups.
  1392  func (s *SqlGroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs []string, page, perPage int) ([]*model.UserWithGroups, *model.AppError) {
  1393  	query := s.channelMembersMinusGroupMembersQuery(channelID, groupIDs, false)
  1394  	query = query.OrderBy("Users.Username ASC").Limit(uint64(perPage)).Offset(uint64(page * perPage))
  1395  
  1396  	queryString, args, err := query.ToSql()
  1397  	if err != nil {
  1398  		return nil, model.NewAppError("SqlGroupStore.ChannelMembersMinusGroupMembers", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1399  	}
  1400  
  1401  	var users []*model.UserWithGroups
  1402  	if _, err = s.GetReplica().Select(&users, queryString, args...); err != nil {
  1403  		return nil, model.NewAppError("SqlGroupStore.ChannelMembersMinusGroupMembers", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1404  	}
  1405  
  1406  	return users, nil
  1407  }
  1408  
  1409  // CountChannelMembersMinusGroupMembers returns the count of the set of users in the given channel minus the set of users
  1410  // in the given groups.
  1411  func (s *SqlGroupStore) CountChannelMembersMinusGroupMembers(channelID string, groupIDs []string) (int64, *model.AppError) {
  1412  	queryString, args, err := s.channelMembersMinusGroupMembersQuery(channelID, groupIDs, true).ToSql()
  1413  	if err != nil {
  1414  		return 0, model.NewAppError("SqlGroupStore.CountChannelMembersMinusGroupMembers", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1415  	}
  1416  
  1417  	var count int64
  1418  	if count, err = s.GetReplica().SelectInt(queryString, args...); err != nil {
  1419  		return 0, model.NewAppError("SqlGroupStore.CountChannelMembersMinusGroupMembers", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1420  	}
  1421  
  1422  	return count, nil
  1423  }
  1424  
  1425  func (s *SqlGroupStore) AdminRoleGroupsForSyncableMember(userID, syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
  1426  	var groupIds []string
  1427  
  1428  	sql := fmt.Sprintf(`
  1429  		SELECT
  1430  			GroupMembers.GroupId
  1431  		FROM
  1432  			GroupMembers
  1433  		INNER JOIN
  1434  			Group%[1]ss ON Group%[1]ss.GroupId = GroupMembers.GroupId
  1435  		WHERE
  1436  			GroupMembers.UserId = :UserId
  1437  			AND GroupMembers.DeleteAt = 0
  1438  			AND %[1]sId = :%[1]sId
  1439  			AND Group%[1]ss.DeleteAt = 0
  1440  			AND Group%[1]ss.SchemeAdmin = TRUE`, syncableType)
  1441  
  1442  	_, err := s.GetReplica().Select(&groupIds, sql, map[string]interface{}{"UserId": userID, fmt.Sprintf("%sId", syncableType): syncableID})
  1443  	if err != nil {
  1444  		return nil, model.NewAppError("SqlGroupStore AdminRoleGroupsForSyncableMember", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1445  	}
  1446  
  1447  	return groupIds, nil
  1448  }
  1449  
  1450  func (s *SqlGroupStore) PermittedSyncableAdmins(syncableID string, syncableType model.GroupSyncableType) ([]string, *model.AppError) {
  1451  	query := s.getQueryBuilder().Select("UserId").
  1452  		From(fmt.Sprintf("Group%ss", syncableType)).
  1453  		Join(fmt.Sprintf("GroupMembers ON GroupMembers.GroupId = Group%ss.GroupId AND Group%[1]ss.SchemeAdmin = TRUE AND GroupMembers.DeleteAt = 0", syncableType.String())).Where(fmt.Sprintf("Group%[1]ss.%[1]sId = ?", syncableType.String()), syncableID)
  1454  
  1455  	sql, args, err := query.ToSql()
  1456  	if err != nil {
  1457  		return nil, model.NewAppError("SqlGroupStore.PermittedSyncableAdmins", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1458  	}
  1459  
  1460  	var userIDs []string
  1461  	if _, err = s.GetReplica().Select(&userIDs, sql, args...); err != nil {
  1462  		return nil, model.NewAppError("SqlGroupStore.PermittedSyncableAdmins", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1463  	}
  1464  
  1465  	return userIDs, nil
  1466  }
  1467  
  1468  func (s *SqlGroupStore) GroupCount() (int64, *model.AppError) {
  1469  	return s.countTable("UserGroups")
  1470  }
  1471  
  1472  func (s *SqlGroupStore) GroupTeamCount() (int64, *model.AppError) {
  1473  	return s.countTable("GroupTeams")
  1474  }
  1475  
  1476  func (s *SqlGroupStore) GroupChannelCount() (int64, *model.AppError) {
  1477  	return s.countTable("GroupChannels")
  1478  }
  1479  
  1480  func (s *SqlGroupStore) GroupMemberCount() (int64, *model.AppError) {
  1481  	return s.countTable("GroupMembers")
  1482  }
  1483  
  1484  func (s *SqlGroupStore) DistinctGroupMemberCount() (int64, *model.AppError) {
  1485  	return s.countTableWithSelectAndWhere("COUNT(DISTINCT UserId)", "GroupMembers", nil)
  1486  }
  1487  
  1488  func (s *SqlGroupStore) GroupCountWithAllowReference() (int64, *model.AppError) {
  1489  	return s.countTableWithSelectAndWhere("COUNT(*)", "UserGroups", sq.Eq{"AllowReference": true, "DeleteAt": 0})
  1490  }
  1491  
  1492  func (s *SqlGroupStore) countTable(tableName string) (int64, *model.AppError) {
  1493  	return s.countTableWithSelectAndWhere("COUNT(*)", tableName, nil)
  1494  }
  1495  
  1496  func (s *SqlGroupStore) countTableWithSelectAndWhere(selectStr, tableName string, whereStmt map[string]interface{}) (int64, *model.AppError) {
  1497  	if whereStmt == nil {
  1498  		whereStmt = sq.Eq{"DeleteAt": 0}
  1499  	}
  1500  
  1501  	query := s.getQueryBuilder().Select(selectStr).From(tableName).Where(whereStmt)
  1502  
  1503  	sql, args, err := query.ToSql()
  1504  	if err != nil {
  1505  		return 0, model.NewAppError("SqlGroupStore.countTableWithSelect", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
  1506  	}
  1507  
  1508  	count, err := s.GetReplica().SelectInt(sql, args...)
  1509  	if err != nil {
  1510  		return 0, model.NewAppError("SqlGroupStore.countTableWithSelect", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
  1511  	}
  1512  
  1513  	return count, nil
  1514  }