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