github.com/haalcala/mattermost-server-change-repo@v0.0.0-20210713015153-16753fbeee5f/store/sqlstore/channel_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  	"sort"
    10  	"strconv"
    11  	"strings"
    12  	"time"
    13  
    14  	sq "github.com/Masterminds/squirrel"
    15  	"github.com/mattermost/gorp"
    16  	"github.com/pkg/errors"
    17  
    18  	"github.com/mattermost/mattermost-server/v5/einterfaces"
    19  	"github.com/mattermost/mattermost-server/v5/mlog"
    20  	"github.com/mattermost/mattermost-server/v5/model"
    21  	"github.com/mattermost/mattermost-server/v5/services/cache"
    22  	"github.com/mattermost/mattermost-server/v5/store"
    23  )
    24  
    25  const (
    26  	AllChannelMembersForUserCacheSize     = model.SESSION_CACHE_SIZE
    27  	AllChannelMembersForUserCacheDuration = 15 * time.Minute // 15 mins
    28  
    29  	AllChannelMembersNotifyPropsForChannelCacheSize     = model.SESSION_CACHE_SIZE
    30  	AllChannelMembersNotifyPropsForChannelCacheDuration = 30 * time.Minute // 30 mins
    31  
    32  	ChannelCacheDuration = 15 * time.Minute // 15 mins
    33  )
    34  
    35  type SqlChannelStore struct {
    36  	*SqlStore
    37  	metrics einterfaces.MetricsInterface
    38  }
    39  
    40  type channelMember struct {
    41  	ChannelId    string
    42  	UserId       string
    43  	Roles        string
    44  	LastViewedAt int64
    45  	MsgCount     int64
    46  	MentionCount int64
    47  	NotifyProps  model.StringMap
    48  	LastUpdateAt int64
    49  	SchemeUser   sql.NullBool
    50  	SchemeAdmin  sql.NullBool
    51  	SchemeGuest  sql.NullBool
    52  }
    53  
    54  func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
    55  	return &channelMember{
    56  		ChannelId:    cm.ChannelId,
    57  		UserId:       cm.UserId,
    58  		Roles:        cm.ExplicitRoles,
    59  		LastViewedAt: cm.LastViewedAt,
    60  		MsgCount:     cm.MsgCount,
    61  		MentionCount: cm.MentionCount,
    62  		NotifyProps:  cm.NotifyProps,
    63  		LastUpdateAt: cm.LastUpdateAt,
    64  		SchemeGuest:  sql.NullBool{Valid: true, Bool: cm.SchemeGuest},
    65  		SchemeUser:   sql.NullBool{Valid: true, Bool: cm.SchemeUser},
    66  		SchemeAdmin:  sql.NullBool{Valid: true, Bool: cm.SchemeAdmin},
    67  	}
    68  }
    69  
    70  type channelMemberWithSchemeRoles struct {
    71  	ChannelId                     string
    72  	UserId                        string
    73  	Roles                         string
    74  	LastViewedAt                  int64
    75  	MsgCount                      int64
    76  	MentionCount                  int64
    77  	NotifyProps                   model.StringMap
    78  	LastUpdateAt                  int64
    79  	SchemeGuest                   sql.NullBool
    80  	SchemeUser                    sql.NullBool
    81  	SchemeAdmin                   sql.NullBool
    82  	TeamSchemeDefaultGuestRole    sql.NullString
    83  	TeamSchemeDefaultUserRole     sql.NullString
    84  	TeamSchemeDefaultAdminRole    sql.NullString
    85  	ChannelSchemeDefaultGuestRole sql.NullString
    86  	ChannelSchemeDefaultUserRole  sql.NullString
    87  	ChannelSchemeDefaultAdminRole sql.NullString
    88  }
    89  
    90  func channelMemberSliceColumns() []string {
    91  	return []string{"ChannelId", "UserId", "Roles", "LastViewedAt", "MsgCount", "MentionCount", "NotifyProps", "LastUpdateAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
    92  }
    93  
    94  func channelMemberToSlice(member *model.ChannelMember) []interface{} {
    95  	resultSlice := []interface{}{}
    96  	resultSlice = append(resultSlice, member.ChannelId)
    97  	resultSlice = append(resultSlice, member.UserId)
    98  	resultSlice = append(resultSlice, member.ExplicitRoles)
    99  	resultSlice = append(resultSlice, member.LastViewedAt)
   100  	resultSlice = append(resultSlice, member.MsgCount)
   101  	resultSlice = append(resultSlice, member.MentionCount)
   102  	resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps))
   103  	resultSlice = append(resultSlice, member.LastUpdateAt)
   104  	resultSlice = append(resultSlice, member.SchemeUser)
   105  	resultSlice = append(resultSlice, member.SchemeAdmin)
   106  	resultSlice = append(resultSlice, member.SchemeGuest)
   107  	return resultSlice
   108  }
   109  
   110  type channelMemberWithSchemeRolesList []channelMemberWithSchemeRoles
   111  
   112  func getChannelRoles(schemeGuest, schemeUser, schemeAdmin bool, defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole, defaultChannelGuestRole, defaultChannelUserRole, defaultChannelAdminRole string,
   113  	roles []string) rolesInfo {
   114  	result := rolesInfo{
   115  		roles:         []string{},
   116  		explicitRoles: []string{},
   117  		schemeGuest:   schemeGuest,
   118  		schemeUser:    schemeUser,
   119  		schemeAdmin:   schemeAdmin,
   120  	}
   121  
   122  	// Identify any scheme derived roles that are in "Roles" field due to not yet being migrated, and exclude
   123  	// them from ExplicitRoles field.
   124  	for _, role := range roles {
   125  		switch role {
   126  		case model.CHANNEL_GUEST_ROLE_ID:
   127  			result.schemeGuest = true
   128  		case model.CHANNEL_USER_ROLE_ID:
   129  			result.schemeUser = true
   130  		case model.CHANNEL_ADMIN_ROLE_ID:
   131  			result.schemeAdmin = true
   132  		default:
   133  			result.explicitRoles = append(result.explicitRoles, role)
   134  			result.roles = append(result.roles, role)
   135  		}
   136  	}
   137  
   138  	// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
   139  	// them to the Roles field for backwards compatibility reasons.
   140  	var schemeImpliedRoles []string
   141  	if result.schemeGuest {
   142  		if defaultChannelGuestRole != "" {
   143  			schemeImpliedRoles = append(schemeImpliedRoles, defaultChannelGuestRole)
   144  		} else if defaultTeamGuestRole != "" {
   145  			schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamGuestRole)
   146  		} else {
   147  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_GUEST_ROLE_ID)
   148  		}
   149  	}
   150  	if result.schemeUser {
   151  		if defaultChannelUserRole != "" {
   152  			schemeImpliedRoles = append(schemeImpliedRoles, defaultChannelUserRole)
   153  		} else if defaultTeamUserRole != "" {
   154  			schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamUserRole)
   155  		} else {
   156  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID)
   157  		}
   158  	}
   159  	if result.schemeAdmin {
   160  		if defaultChannelAdminRole != "" {
   161  			schemeImpliedRoles = append(schemeImpliedRoles, defaultChannelAdminRole)
   162  		} else if defaultTeamAdminRole != "" {
   163  			schemeImpliedRoles = append(schemeImpliedRoles, defaultTeamAdminRole)
   164  		} else {
   165  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID)
   166  		}
   167  	}
   168  	for _, impliedRole := range schemeImpliedRoles {
   169  		alreadyThere := false
   170  		for _, role := range result.roles {
   171  			if role == impliedRole {
   172  				alreadyThere = true
   173  				break
   174  			}
   175  		}
   176  		if !alreadyThere {
   177  			result.roles = append(result.roles, impliedRole)
   178  		}
   179  	}
   180  	return result
   181  }
   182  
   183  func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
   184  	// Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated,
   185  	// and exclude them from ExplicitRoles field.
   186  	schemeGuest := db.SchemeGuest.Valid && db.SchemeGuest.Bool
   187  	schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
   188  	schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
   189  
   190  	defaultTeamGuestRole := ""
   191  	if db.TeamSchemeDefaultGuestRole.Valid {
   192  		defaultTeamGuestRole = db.TeamSchemeDefaultGuestRole.String
   193  	}
   194  
   195  	defaultTeamUserRole := ""
   196  	if db.TeamSchemeDefaultUserRole.Valid {
   197  		defaultTeamUserRole = db.TeamSchemeDefaultUserRole.String
   198  	}
   199  
   200  	defaultTeamAdminRole := ""
   201  	if db.TeamSchemeDefaultAdminRole.Valid {
   202  		defaultTeamAdminRole = db.TeamSchemeDefaultAdminRole.String
   203  	}
   204  
   205  	defaultChannelGuestRole := ""
   206  	if db.ChannelSchemeDefaultGuestRole.Valid {
   207  		defaultChannelGuestRole = db.ChannelSchemeDefaultGuestRole.String
   208  	}
   209  
   210  	defaultChannelUserRole := ""
   211  	if db.ChannelSchemeDefaultUserRole.Valid {
   212  		defaultChannelUserRole = db.ChannelSchemeDefaultUserRole.String
   213  	}
   214  
   215  	defaultChannelAdminRole := ""
   216  	if db.ChannelSchemeDefaultAdminRole.Valid {
   217  		defaultChannelAdminRole = db.ChannelSchemeDefaultAdminRole.String
   218  	}
   219  
   220  	rolesResult := getChannelRoles(
   221  		schemeGuest, schemeUser, schemeAdmin,
   222  		defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole,
   223  		defaultChannelGuestRole, defaultChannelUserRole, defaultChannelAdminRole,
   224  		strings.Fields(db.Roles),
   225  	)
   226  	return &model.ChannelMember{
   227  		ChannelId:     db.ChannelId,
   228  		UserId:        db.UserId,
   229  		Roles:         strings.Join(rolesResult.roles, " "),
   230  		LastViewedAt:  db.LastViewedAt,
   231  		MsgCount:      db.MsgCount,
   232  		MentionCount:  db.MentionCount,
   233  		NotifyProps:   db.NotifyProps,
   234  		LastUpdateAt:  db.LastUpdateAt,
   235  		SchemeAdmin:   rolesResult.schemeAdmin,
   236  		SchemeUser:    rolesResult.schemeUser,
   237  		SchemeGuest:   rolesResult.schemeGuest,
   238  		ExplicitRoles: strings.Join(rolesResult.explicitRoles, " "),
   239  	}
   240  }
   241  
   242  func (db channelMemberWithSchemeRolesList) ToModel() *model.ChannelMembers {
   243  	cms := model.ChannelMembers{}
   244  
   245  	for _, cm := range db {
   246  		cms = append(cms, *cm.ToModel())
   247  	}
   248  
   249  	return &cms
   250  }
   251  
   252  type allChannelMember struct {
   253  	ChannelId                     string
   254  	Roles                         string
   255  	SchemeGuest                   sql.NullBool
   256  	SchemeUser                    sql.NullBool
   257  	SchemeAdmin                   sql.NullBool
   258  	TeamSchemeDefaultGuestRole    sql.NullString
   259  	TeamSchemeDefaultUserRole     sql.NullString
   260  	TeamSchemeDefaultAdminRole    sql.NullString
   261  	ChannelSchemeDefaultGuestRole sql.NullString
   262  	ChannelSchemeDefaultUserRole  sql.NullString
   263  	ChannelSchemeDefaultAdminRole sql.NullString
   264  }
   265  
   266  type allChannelMembers []allChannelMember
   267  
   268  func (db allChannelMember) Process() (string, string) {
   269  	roles := strings.Fields(db.Roles)
   270  
   271  	// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
   272  	// them to the Roles field for backwards compatibility reasons.
   273  	var schemeImpliedRoles []string
   274  	if db.SchemeGuest.Valid && db.SchemeGuest.Bool {
   275  		if db.ChannelSchemeDefaultGuestRole.Valid && db.ChannelSchemeDefaultGuestRole.String != "" {
   276  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultGuestRole.String)
   277  		} else if db.TeamSchemeDefaultGuestRole.Valid && db.TeamSchemeDefaultGuestRole.String != "" {
   278  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultGuestRole.String)
   279  		} else {
   280  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_GUEST_ROLE_ID)
   281  		}
   282  	}
   283  	if db.SchemeUser.Valid && db.SchemeUser.Bool {
   284  		if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" {
   285  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String)
   286  		} else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
   287  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
   288  		} else {
   289  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID)
   290  		}
   291  	}
   292  	if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
   293  		if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" {
   294  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String)
   295  		} else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
   296  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
   297  		} else {
   298  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID)
   299  		}
   300  	}
   301  	for _, impliedRole := range schemeImpliedRoles {
   302  		alreadyThere := false
   303  		for _, role := range roles {
   304  			if role == impliedRole {
   305  				alreadyThere = true
   306  			}
   307  		}
   308  		if !alreadyThere {
   309  			roles = append(roles, impliedRole)
   310  		}
   311  	}
   312  
   313  	return db.ChannelId, strings.Join(roles, " ")
   314  }
   315  
   316  func (db allChannelMembers) ToMapStringString() map[string]string {
   317  	result := make(map[string]string)
   318  
   319  	for _, item := range db {
   320  		key, value := item.Process()
   321  		result[key] = value
   322  	}
   323  
   324  	return result
   325  }
   326  
   327  // publicChannel is a subset of the metadata corresponding to public channels only.
   328  type publicChannel struct {
   329  	Id          string `json:"id"`
   330  	DeleteAt    int64  `json:"delete_at"`
   331  	TeamId      string `json:"team_id"`
   332  	DisplayName string `json:"display_name"`
   333  	Name        string `json:"name"`
   334  	Header      string `json:"header"`
   335  	Purpose     string `json:"purpose"`
   336  }
   337  
   338  var allChannelMembersForUserCache = cache.NewLRU(cache.LRUOptions{
   339  	Size: AllChannelMembersForUserCacheSize,
   340  })
   341  var allChannelMembersNotifyPropsForChannelCache = cache.NewLRU(cache.LRUOptions{
   342  	Size: AllChannelMembersNotifyPropsForChannelCacheSize,
   343  })
   344  var channelByNameCache = cache.NewLRU(cache.LRUOptions{
   345  	Size: model.CHANNEL_CACHE_SIZE,
   346  })
   347  
   348  func (s SqlChannelStore) ClearCaches() {
   349  	allChannelMembersForUserCache.Purge()
   350  	allChannelMembersNotifyPropsForChannelCache.Purge()
   351  	channelByNameCache.Purge()
   352  
   353  	if s.metrics != nil {
   354  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Purge")
   355  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Purge")
   356  		s.metrics.IncrementMemCacheInvalidationCounter("Channel By Name - Purge")
   357  	}
   358  }
   359  
   360  func newSqlChannelStore(sqlStore *SqlStore, metrics einterfaces.MetricsInterface) store.ChannelStore {
   361  	s := &SqlChannelStore{
   362  		SqlStore: sqlStore,
   363  		metrics:  metrics,
   364  	}
   365  
   366  	for _, db := range sqlStore.GetAllConns() {
   367  		table := db.AddTableWithName(model.Channel{}, "Channels").SetKeys(false, "Id")
   368  		table.ColMap("Id").SetMaxSize(26)
   369  		table.ColMap("TeamId").SetMaxSize(26)
   370  		table.ColMap("Type").SetMaxSize(1)
   371  		table.ColMap("DisplayName").SetMaxSize(64)
   372  		table.ColMap("Name").SetMaxSize(64)
   373  		table.SetUniqueTogether("Name", "TeamId")
   374  		table.ColMap("Header").SetMaxSize(1024)
   375  		table.ColMap("Purpose").SetMaxSize(250)
   376  		table.ColMap("CreatorId").SetMaxSize(26)
   377  		table.ColMap("SchemeId").SetMaxSize(26)
   378  
   379  		tablem := db.AddTableWithName(channelMember{}, "ChannelMembers").SetKeys(false, "ChannelId", "UserId")
   380  		tablem.ColMap("ChannelId").SetMaxSize(26)
   381  		tablem.ColMap("UserId").SetMaxSize(26)
   382  		tablem.ColMap("Roles").SetMaxSize(64)
   383  		tablem.ColMap("NotifyProps").SetMaxSize(2000)
   384  
   385  		tablePublicChannels := db.AddTableWithName(publicChannel{}, "PublicChannels").SetKeys(false, "Id")
   386  		tablePublicChannels.ColMap("Id").SetMaxSize(26)
   387  		tablePublicChannels.ColMap("TeamId").SetMaxSize(26)
   388  		tablePublicChannels.ColMap("DisplayName").SetMaxSize(64)
   389  		tablePublicChannels.ColMap("Name").SetMaxSize(64)
   390  		tablePublicChannels.SetUniqueTogether("Name", "TeamId")
   391  		tablePublicChannels.ColMap("Header").SetMaxSize(1024)
   392  		tablePublicChannels.ColMap("Purpose").SetMaxSize(250)
   393  
   394  		tableSidebarCategories := db.AddTableWithName(model.SidebarCategory{}, "SidebarCategories").SetKeys(false, "Id")
   395  		tableSidebarCategories.ColMap("Id").SetMaxSize(128)
   396  		tableSidebarCategories.ColMap("UserId").SetMaxSize(26)
   397  		tableSidebarCategories.ColMap("TeamId").SetMaxSize(26)
   398  		tableSidebarCategories.ColMap("Sorting").SetMaxSize(64)
   399  		tableSidebarCategories.ColMap("Type").SetMaxSize(64)
   400  		tableSidebarCategories.ColMap("DisplayName").SetMaxSize(64)
   401  
   402  		tableSidebarChannels := db.AddTableWithName(model.SidebarChannel{}, "SidebarChannels").SetKeys(false, "ChannelId", "UserId", "CategoryId")
   403  		tableSidebarChannels.ColMap("ChannelId").SetMaxSize(26)
   404  		tableSidebarChannels.ColMap("UserId").SetMaxSize(26)
   405  		tableSidebarChannels.ColMap("CategoryId").SetMaxSize(128)
   406  	}
   407  
   408  	return s
   409  }
   410  
   411  func (s SqlChannelStore) createIndexesIfNotExists() {
   412  	s.CreateIndexIfNotExists("idx_channels_team_id", "Channels", "TeamId")
   413  	s.CreateIndexIfNotExists("idx_channels_name", "Channels", "Name")
   414  	s.CreateIndexIfNotExists("idx_channels_update_at", "Channels", "UpdateAt")
   415  	s.CreateIndexIfNotExists("idx_channels_create_at", "Channels", "CreateAt")
   416  	s.CreateIndexIfNotExists("idx_channels_delete_at", "Channels", "DeleteAt")
   417  
   418  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   419  		s.CreateIndexIfNotExists("idx_channels_name_lower", "Channels", "lower(Name)")
   420  		s.CreateIndexIfNotExists("idx_channels_displayname_lower", "Channels", "lower(DisplayName)")
   421  	}
   422  
   423  	s.CreateIndexIfNotExists("idx_channelmembers_channel_id", "ChannelMembers", "ChannelId")
   424  	s.CreateIndexIfNotExists("idx_channelmembers_user_id", "ChannelMembers", "UserId")
   425  
   426  	s.CreateFullTextIndexIfNotExists("idx_channel_search_txt", "Channels", "Name, DisplayName, Purpose")
   427  
   428  	s.CreateIndexIfNotExists("idx_publicchannels_team_id", "PublicChannels", "TeamId")
   429  	s.CreateIndexIfNotExists("idx_publicchannels_name", "PublicChannels", "Name")
   430  	s.CreateIndexIfNotExists("idx_publicchannels_delete_at", "PublicChannels", "DeleteAt")
   431  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   432  		s.CreateIndexIfNotExists("idx_publicchannels_name_lower", "PublicChannels", "lower(Name)")
   433  		s.CreateIndexIfNotExists("idx_publicchannels_displayname_lower", "PublicChannels", "lower(DisplayName)")
   434  	}
   435  	s.CreateFullTextIndexIfNotExists("idx_publicchannels_search_txt", "PublicChannels", "Name, DisplayName, Purpose")
   436  	s.CreateIndexIfNotExists("idx_channels_scheme_id", "Channels", "SchemeId")
   437  }
   438  
   439  // MigratePublicChannels initializes the PublicChannels table with data created before this version
   440  // of the Mattermost server kept it up-to-date.
   441  func (s SqlChannelStore) MigratePublicChannels() error {
   442  	if _, err := s.GetMaster().Exec(`
   443  		INSERT INTO PublicChannels
   444  		    (Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
   445  		SELECT
   446  		    c.Id, c.DeleteAt, c.TeamId, c.DisplayName, c.Name, c.Header, c.Purpose
   447  		FROM
   448  		    Channels c
   449  		LEFT JOIN
   450  		    PublicChannels pc ON (pc.Id = c.Id)
   451  		WHERE
   452  		    c.Type = 'O'
   453  		AND pc.Id IS NULL
   454  	`); err != nil {
   455  		return err
   456  	}
   457  
   458  	return nil
   459  }
   460  
   461  func (s SqlChannelStore) upsertPublicChannelT(transaction *gorp.Transaction, channel *model.Channel) error {
   462  	publicChannel := &publicChannel{
   463  		Id:          channel.Id,
   464  		DeleteAt:    channel.DeleteAt,
   465  		TeamId:      channel.TeamId,
   466  		DisplayName: channel.DisplayName,
   467  		Name:        channel.Name,
   468  		Header:      channel.Header,
   469  		Purpose:     channel.Purpose,
   470  	}
   471  
   472  	if channel.Type != model.CHANNEL_OPEN {
   473  		if _, err := transaction.Delete(publicChannel); err != nil {
   474  			return errors.Wrap(err, "failed to delete public channel")
   475  		}
   476  
   477  		return nil
   478  	}
   479  
   480  	if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
   481  		// Leverage native upsert for MySQL, since RowsAffected returns 0 if the row exists
   482  		// but no changes were made, breaking the update-then-insert paradigm below when
   483  		// the row already exists. (Postgres 9.4 doesn't support native upsert.)
   484  		if _, err := transaction.Exec(`
   485  			INSERT INTO
   486  			    PublicChannels(Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
   487  			VALUES
   488  			    (:Id, :DeleteAt, :TeamId, :DisplayName, :Name, :Header, :Purpose)
   489  			ON DUPLICATE KEY UPDATE
   490  			    DeleteAt = :DeleteAt,
   491  			    TeamId = :TeamId,
   492  			    DisplayName = :DisplayName,
   493  			    Name = :Name,
   494  			    Header = :Header,
   495  			    Purpose = :Purpose;
   496  		`, map[string]interface{}{
   497  			"Id":          publicChannel.Id,
   498  			"DeleteAt":    publicChannel.DeleteAt,
   499  			"TeamId":      publicChannel.TeamId,
   500  			"DisplayName": publicChannel.DisplayName,
   501  			"Name":        publicChannel.Name,
   502  			"Header":      publicChannel.Header,
   503  			"Purpose":     publicChannel.Purpose,
   504  		}); err != nil {
   505  			return errors.Wrap(err, "failed to insert public channel")
   506  		}
   507  	} else {
   508  		count, err := transaction.Update(publicChannel)
   509  		if err != nil {
   510  			return errors.Wrap(err, "failed to update public channel")
   511  		}
   512  		if count > 0 {
   513  			return nil
   514  		}
   515  
   516  		if err := transaction.Insert(publicChannel); err != nil {
   517  			return errors.Wrap(err, "failed to insert public channel")
   518  		}
   519  	}
   520  
   521  	return nil
   522  }
   523  
   524  // Save writes the (non-direct) channel channel to the database.
   525  func (s SqlChannelStore) Save(channel *model.Channel, maxChannelsPerTeam int64) (*model.Channel, error) {
   526  	if channel.DeleteAt != 0 {
   527  		return nil, store.NewErrInvalidInput("Channel", "DeleteAt", channel.DeleteAt)
   528  	}
   529  
   530  	if channel.Type == model.CHANNEL_DIRECT {
   531  		return nil, store.NewErrInvalidInput("Channel", "Type", channel.Type)
   532  	}
   533  
   534  	var newChannel *model.Channel
   535  	transaction, err := s.GetMaster().Begin()
   536  	if err != nil {
   537  		return nil, errors.Wrap(err, "begin_transaction")
   538  	}
   539  	defer finalizeTransaction(transaction)
   540  
   541  	newChannel, err = s.saveChannelT(transaction, channel, maxChannelsPerTeam)
   542  	if err != nil {
   543  		return newChannel, err
   544  	}
   545  
   546  	// Additionally propagate the write to the PublicChannels table.
   547  	if err = s.upsertPublicChannelT(transaction, newChannel); err != nil {
   548  		return nil, errors.Wrap(err, "upsert_public_channel")
   549  	}
   550  
   551  	if err = transaction.Commit(); err != nil {
   552  		return nil, errors.Wrap(err, "commit_transaction")
   553  	}
   554  	// There are cases when in case of conflict, the original channel value is returned.
   555  	// So we return both and let the caller do the checks.
   556  	return newChannel, err
   557  }
   558  
   559  func (s SqlChannelStore) CreateDirectChannel(user *model.User, otherUser *model.User) (*model.Channel, error) {
   560  	channel := new(model.Channel)
   561  
   562  	channel.DisplayName = ""
   563  	channel.Name = model.GetDMNameFromIds(otherUser.Id, user.Id)
   564  
   565  	channel.Header = ""
   566  	channel.Type = model.CHANNEL_DIRECT
   567  
   568  	cm1 := &model.ChannelMember{
   569  		UserId:      user.Id,
   570  		NotifyProps: model.GetDefaultChannelNotifyProps(),
   571  		SchemeGuest: user.IsGuest(),
   572  		SchemeUser:  !user.IsGuest(),
   573  	}
   574  	cm2 := &model.ChannelMember{
   575  		UserId:      otherUser.Id,
   576  		NotifyProps: model.GetDefaultChannelNotifyProps(),
   577  		SchemeGuest: otherUser.IsGuest(),
   578  		SchemeUser:  !otherUser.IsGuest(),
   579  	}
   580  
   581  	return s.SaveDirectChannel(channel, cm1, cm2)
   582  }
   583  
   584  func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) (*model.Channel, error) {
   585  	if directchannel.DeleteAt != 0 {
   586  		return nil, store.NewErrInvalidInput("Channel", "DeleteAt", directchannel.DeleteAt)
   587  	}
   588  
   589  	if directchannel.Type != model.CHANNEL_DIRECT {
   590  		return nil, store.NewErrInvalidInput("Channel", "Type", directchannel.Type)
   591  	}
   592  
   593  	transaction, err := s.GetMaster().Begin()
   594  	if err != nil {
   595  		return nil, errors.Wrap(err, "begin_transaction")
   596  	}
   597  	defer finalizeTransaction(transaction)
   598  
   599  	directchannel.TeamId = ""
   600  	newChannel, err := s.saveChannelT(transaction, directchannel, 0)
   601  	if err != nil {
   602  		return newChannel, err
   603  	}
   604  
   605  	// Members need new channel ID
   606  	member1.ChannelId = newChannel.Id
   607  	member2.ChannelId = newChannel.Id
   608  
   609  	if member1.UserId != member2.UserId {
   610  		_, err = s.saveMultipleMembers([]*model.ChannelMember{member1, member2})
   611  	} else {
   612  		_, err = s.saveMemberT(member2)
   613  	}
   614  	if err != nil {
   615  		return nil, err
   616  	}
   617  
   618  	if err := transaction.Commit(); err != nil {
   619  		return nil, errors.Wrap(err, "commit_transaction")
   620  	}
   621  
   622  	return newChannel, nil
   623  
   624  }
   625  
   626  func (s SqlChannelStore) saveChannelT(transaction *gorp.Transaction, channel *model.Channel, maxChannelsPerTeam int64) (*model.Channel, error) {
   627  	if channel.Id != "" {
   628  		return nil, store.NewErrInvalidInput("Channel", "Id", channel.Id)
   629  	}
   630  
   631  	channel.PreSave()
   632  	if err := channel.IsValid(); err != nil { // TODO: this needs to return plain error in v6.
   633  		return nil, err // we just pass through the error as-is for now.
   634  	}
   635  
   636  	if channel.Type != model.CHANNEL_DIRECT && channel.Type != model.CHANNEL_GROUP && maxChannelsPerTeam >= 0 {
   637  		if count, err := transaction.SelectInt("SELECT COUNT(0) FROM Channels WHERE TeamId = :TeamId AND DeleteAt = 0 AND (Type = 'O' OR Type = 'P')", map[string]interface{}{"TeamId": channel.TeamId}); err != nil {
   638  			return nil, errors.Wrapf(err, "save_channel_count: teamId=%s", channel.TeamId)
   639  		} else if count >= maxChannelsPerTeam {
   640  			return nil, store.NewErrLimitExceeded("channels_per_team", int(count), "teamId="+channel.TeamId)
   641  		}
   642  	}
   643  
   644  	if err := transaction.Insert(channel); err != nil {
   645  		if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) {
   646  			dupChannel := model.Channel{}
   647  			s.GetMaster().SelectOne(&dupChannel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name = :Name", map[string]interface{}{"TeamId": channel.TeamId, "Name": channel.Name})
   648  			return &dupChannel, store.NewErrConflict("Channel", err, "id="+channel.Id)
   649  		}
   650  		return nil, errors.Wrapf(err, "save_channel: id=%s", channel.Id)
   651  	}
   652  	return channel, nil
   653  }
   654  
   655  // Update writes the updated channel to the database.
   656  func (s SqlChannelStore) Update(channel *model.Channel) (*model.Channel, error) {
   657  	transaction, err := s.GetMaster().Begin()
   658  	if err != nil {
   659  		return nil, errors.Wrap(err, "begin_transaction")
   660  	}
   661  	defer finalizeTransaction(transaction)
   662  
   663  	updatedChannel, err := s.updateChannelT(transaction, channel)
   664  	if err != nil {
   665  		return nil, err
   666  	}
   667  
   668  	// Additionally propagate the write to the PublicChannels table.
   669  	if err := s.upsertPublicChannelT(transaction, updatedChannel); err != nil {
   670  		return nil, errors.Wrap(err, "upsertPublicChannelT: failed to upsert channel")
   671  	}
   672  
   673  	if err := transaction.Commit(); err != nil {
   674  		return nil, errors.Wrap(err, "commit_transaction")
   675  	}
   676  	return updatedChannel, nil
   677  }
   678  
   679  func (s SqlChannelStore) updateChannelT(transaction *gorp.Transaction, channel *model.Channel) (*model.Channel, error) {
   680  	channel.PreUpdate()
   681  
   682  	if channel.DeleteAt != 0 {
   683  		return nil, store.NewErrInvalidInput("Channel", "DeleteAt", channel.DeleteAt)
   684  	}
   685  
   686  	if err := channel.IsValid(); err != nil {
   687  		return nil, err
   688  	}
   689  
   690  	count, err := transaction.Update(channel)
   691  	if err != nil {
   692  		if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) {
   693  			dupChannel := model.Channel{}
   694  			s.GetReplica().SelectOne(&dupChannel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name= :Name AND DeleteAt > 0", map[string]interface{}{"TeamId": channel.TeamId, "Name": channel.Name})
   695  			if dupChannel.DeleteAt > 0 {
   696  				return nil, store.NewErrInvalidInput("Channel", "Id", channel.Id)
   697  			}
   698  			return nil, store.NewErrInvalidInput("Channel", "Id", channel.Id)
   699  		}
   700  		return nil, errors.Wrapf(err, "failed to update channel with id=%s", channel.Id)
   701  	}
   702  
   703  	if count > 1 {
   704  		return nil, fmt.Errorf("the expected number of channels to be updated is <=1 but was %d", count)
   705  	}
   706  
   707  	return channel, nil
   708  }
   709  
   710  func (s SqlChannelStore) GetChannelUnread(channelId, userId string) (*model.ChannelUnread, error) {
   711  	var unreadChannel model.ChannelUnread
   712  	err := s.GetReplica().SelectOne(&unreadChannel,
   713  		`SELECT
   714  				Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
   715  			FROM
   716  				Channels, ChannelMembers
   717  			WHERE
   718  				Id = ChannelId
   719                  AND Id = :ChannelId
   720                  AND UserId = :UserId
   721                  AND DeleteAt = 0`,
   722  		map[string]interface{}{"ChannelId": channelId, "UserId": userId})
   723  
   724  	if err != nil {
   725  		if err == sql.ErrNoRows {
   726  			return nil, store.NewErrNotFound("Channel", fmt.Sprintf("channelId=%s,userId=%s", channelId, userId))
   727  		}
   728  		return nil, errors.Wrapf(err, "failed to get Channel with channelId=%s and userId=%s", channelId, userId)
   729  	}
   730  	return &unreadChannel, nil
   731  }
   732  
   733  //nolint:unparam
   734  func (s SqlChannelStore) InvalidateChannel(id string) {
   735  }
   736  
   737  func (s SqlChannelStore) InvalidateChannelByName(teamId, name string) {
   738  	channelByNameCache.Remove(teamId + name)
   739  	if s.metrics != nil {
   740  		s.metrics.IncrementMemCacheInvalidationCounter("Channel by Name - Remove by TeamId and Name")
   741  	}
   742  }
   743  
   744  //nolint:unparam
   745  func (s SqlChannelStore) Get(id string, allowFromCache bool) (*model.Channel, error) {
   746  	return s.get(id, false)
   747  }
   748  
   749  func (s SqlChannelStore) GetPinnedPosts(channelId string) (*model.PostList, error) {
   750  	pl := model.NewPostList()
   751  
   752  	var posts []*model.Post
   753  	if _, err := s.GetReplica().Select(&posts, "SELECT *, (SELECT count(Posts.Id) FROM Posts WHERE Posts.RootId = (CASE WHEN p.RootId = '' THEN p.Id ELSE p.RootId END) AND Posts.DeleteAt = 0) as ReplyCount  FROM Posts p WHERE IsPinned = true AND ChannelId = :ChannelId AND DeleteAt = 0 ORDER BY CreateAt ASC", map[string]interface{}{"ChannelId": channelId}); err != nil {
   754  		return nil, errors.Wrap(err, "failed to find Posts")
   755  	}
   756  	for _, post := range posts {
   757  		pl.AddPost(post)
   758  		pl.AddOrder(post.Id)
   759  	}
   760  	return pl, nil
   761  }
   762  
   763  func (s SqlChannelStore) GetFromMaster(id string) (*model.Channel, error) {
   764  	return s.get(id, true)
   765  }
   766  
   767  func (s SqlChannelStore) get(id string, master bool) (*model.Channel, error) {
   768  	var db *gorp.DbMap
   769  
   770  	if master {
   771  		db = s.GetMaster()
   772  	} else {
   773  		db = s.GetReplica()
   774  	}
   775  
   776  	obj, err := db.Get(model.Channel{}, id)
   777  	if err != nil {
   778  		return nil, errors.Wrapf(err, "failed to find channel with id = %s", id)
   779  	}
   780  
   781  	if obj == nil {
   782  		return nil, store.NewErrNotFound("Channel", id)
   783  	}
   784  
   785  	ch := obj.(*model.Channel)
   786  	return ch, nil
   787  }
   788  
   789  // Delete records the given deleted timestamp to the channel in question.
   790  func (s SqlChannelStore) Delete(channelId string, time int64) error {
   791  	return s.SetDeleteAt(channelId, time, time)
   792  }
   793  
   794  // Restore reverts a previous deleted timestamp from the channel in question.
   795  func (s SqlChannelStore) Restore(channelId string, time int64) error {
   796  	return s.SetDeleteAt(channelId, 0, time)
   797  }
   798  
   799  // SetDeleteAt records the given deleted and updated timestamp to the channel in question.
   800  func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64) error {
   801  	defer s.InvalidateChannel(channelId)
   802  
   803  	transaction, err := s.GetMaster().Begin()
   804  	if err != nil {
   805  		return errors.Wrap(err, "SetDeleteAt: begin_transaction")
   806  	}
   807  	defer finalizeTransaction(transaction)
   808  
   809  	err = s.setDeleteAtT(transaction, channelId, deleteAt, updateAt)
   810  	if err != nil {
   811  		return errors.Wrap(err, "setDeleteAtT")
   812  	}
   813  
   814  	// Additionally propagate the write to the PublicChannels table.
   815  	if _, err := transaction.Exec(`
   816  			UPDATE
   817  			    PublicChannels
   818  			SET
   819  			    DeleteAt = :DeleteAt
   820  			WHERE
   821  			    Id = :ChannelId
   822  		`, map[string]interface{}{
   823  		"DeleteAt":  deleteAt,
   824  		"ChannelId": channelId,
   825  	}); err != nil {
   826  		return errors.Wrapf(err, "failed to delete public channels with id=%s", channelId)
   827  	}
   828  
   829  	if err := transaction.Commit(); err != nil {
   830  		return errors.Wrapf(err, "SetDeleteAt: commit_transaction")
   831  	}
   832  
   833  	return nil
   834  }
   835  
   836  func (s SqlChannelStore) setDeleteAtT(transaction *gorp.Transaction, channelId string, deleteAt, updateAt int64) error {
   837  	_, err := transaction.Exec("Update Channels SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :ChannelId", map[string]interface{}{"DeleteAt": deleteAt, "UpdateAt": updateAt, "ChannelId": channelId})
   838  	if err != nil {
   839  		return errors.Wrapf(err, "failed to delete channel with id=%s", channelId)
   840  	}
   841  
   842  	return nil
   843  }
   844  
   845  // PermanentDeleteByTeam removes all channels for the given team from the database.
   846  func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) error {
   847  	transaction, err := s.GetMaster().Begin()
   848  	if err != nil {
   849  		return errors.Wrap(err, "PermanentDeleteByTeam: begin_transaction")
   850  	}
   851  	defer finalizeTransaction(transaction)
   852  
   853  	if err := s.permanentDeleteByTeamtT(transaction, teamId); err != nil {
   854  		return errors.Wrap(err, "permanentDeleteByTeamtT")
   855  	}
   856  
   857  	// Additionally propagate the deletions to the PublicChannels table.
   858  	if _, err := transaction.Exec(`
   859  			DELETE FROM
   860  			    PublicChannels
   861  			WHERE
   862  			    TeamId = :TeamId
   863  		`, map[string]interface{}{
   864  		"TeamId": teamId,
   865  	}); err != nil {
   866  		return errors.Wrapf(err, "failed to delete public channels by team with teamId=%s", teamId)
   867  	}
   868  
   869  	if err := transaction.Commit(); err != nil {
   870  		return errors.Wrap(err, "PermanentDeleteByTeam: commit_transaction")
   871  	}
   872  
   873  	return nil
   874  }
   875  
   876  func (s SqlChannelStore) permanentDeleteByTeamtT(transaction *gorp.Transaction, teamId string) error {
   877  	if _, err := transaction.Exec("DELETE FROM Channels WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
   878  		return errors.Wrapf(err, "failed to delete channel by team with teamId=%s", teamId)
   879  	}
   880  
   881  	return nil
   882  }
   883  
   884  // PermanentDelete removes the given channel from the database.
   885  func (s SqlChannelStore) PermanentDelete(channelId string) error {
   886  	transaction, err := s.GetMaster().Begin()
   887  	if err != nil {
   888  		return errors.Wrap(err, "PermanentDelete: begin_transaction")
   889  	}
   890  	defer finalizeTransaction(transaction)
   891  
   892  	if err := s.permanentDeleteT(transaction, channelId); err != nil {
   893  		return errors.Wrap(err, "permanentDeleteT")
   894  	}
   895  
   896  	// Additionally propagate the deletion to the PublicChannels table.
   897  	if _, err := transaction.Exec(`
   898  			DELETE FROM
   899  			    PublicChannels
   900  			WHERE
   901  			    Id = :ChannelId
   902  		`, map[string]interface{}{
   903  		"ChannelId": channelId,
   904  	}); err != nil {
   905  		return errors.Wrapf(err, "failed to delete public channels with id=%s", channelId)
   906  	}
   907  
   908  	if err := transaction.Commit(); err != nil {
   909  		return errors.Wrap(err, "PermanentDelete: commit_transaction")
   910  	}
   911  
   912  	return nil
   913  }
   914  
   915  func (s SqlChannelStore) permanentDeleteT(transaction *gorp.Transaction, channelId string) error {
   916  	if _, err := transaction.Exec("DELETE FROM Channels WHERE Id = :ChannelId", map[string]interface{}{"ChannelId": channelId}); err != nil {
   917  		return errors.Wrapf(err, "failed to delete channel with id=%s", channelId)
   918  	}
   919  
   920  	return nil
   921  }
   922  
   923  func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) error {
   924  	_, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelId})
   925  	if err != nil {
   926  		return errors.Wrapf(err, "failed to delete Channel with channelId=%s", channelId)
   927  	}
   928  
   929  	return nil
   930  }
   931  
   932  func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool, lastDeleteAt int) (*model.ChannelList, error) {
   933  	query := s.getQueryBuilder().
   934  		Select("Channels.*").
   935  		From("Channels, ChannelMembers").
   936  		Where(
   937  			sq.And{
   938  				sq.Expr("Id = ChannelId"),
   939  				sq.Eq{"UserId": userId},
   940  				sq.Or{
   941  					sq.Eq{"TeamId": teamId},
   942  					sq.Eq{"TeamId": ""},
   943  				},
   944  			},
   945  		).
   946  		OrderBy("DisplayName")
   947  
   948  	if includeDeleted {
   949  		if lastDeleteAt != 0 {
   950  			// We filter by non-archived, and archived >= a timestamp.
   951  			query = query.Where(sq.Or{
   952  				sq.Eq{"DeleteAt": 0},
   953  				sq.GtOrEq{"DeleteAt": lastDeleteAt},
   954  			})
   955  		}
   956  		// If lastDeleteAt is not set, we include everything. That means no filter is needed.
   957  	} else {
   958  		// Don't include archived channels.
   959  		query = query.Where(sq.Eq{"DeleteAt": 0})
   960  	}
   961  
   962  	channels := &model.ChannelList{}
   963  	sql, args, err := query.ToSql()
   964  	if err != nil {
   965  		return nil, errors.Wrapf(err, "getchannels_tosql")
   966  	}
   967  
   968  	_, err = s.GetReplica().Select(channels, sql, args...)
   969  	if err != nil {
   970  		return nil, errors.Wrapf(err, "failed to get channels with TeamId=%s and UserId=%s", teamId, userId)
   971  	}
   972  
   973  	if len(*channels) == 0 {
   974  		return nil, store.NewErrNotFound("Channel", "userId="+userId)
   975  	}
   976  
   977  	return channels, nil
   978  }
   979  
   980  func (s SqlChannelStore) GetAllChannels(offset, limit int, opts store.ChannelSearchOpts) (*model.ChannelListWithTeamData, error) {
   981  	query := s.getAllChannelsQuery(opts, false)
   982  
   983  	query = query.OrderBy("c.DisplayName, Teams.DisplayName").Limit(uint64(limit)).Offset(uint64(offset))
   984  
   985  	queryString, args, err := query.ToSql()
   986  	if err != nil {
   987  		return nil, errors.Wrap(err, "failed to create query")
   988  	}
   989  
   990  	data := &model.ChannelListWithTeamData{}
   991  	_, err = s.GetReplica().Select(data, queryString, args...)
   992  
   993  	if err != nil {
   994  		return nil, errors.Wrap(err, "failed to get all channels")
   995  	}
   996  
   997  	return data, nil
   998  }
   999  
  1000  func (s SqlChannelStore) GetAllChannelsCount(opts store.ChannelSearchOpts) (int64, error) {
  1001  	query := s.getAllChannelsQuery(opts, true)
  1002  
  1003  	queryString, args, err := query.ToSql()
  1004  	if err != nil {
  1005  		return 0, errors.Wrap(err, "failed to create query")
  1006  	}
  1007  
  1008  	count, err := s.GetReplica().SelectInt(queryString, args...)
  1009  	if err != nil {
  1010  		return 0, errors.Wrap(err, "failed to count all channels")
  1011  	}
  1012  
  1013  	return count, nil
  1014  }
  1015  
  1016  func (s SqlChannelStore) getAllChannelsQuery(opts store.ChannelSearchOpts, forCount bool) sq.SelectBuilder {
  1017  	var selectStr string
  1018  	if forCount {
  1019  		selectStr = "count(c.Id)"
  1020  	} else {
  1021  		selectStr = "c.*, Teams.DisplayName AS TeamDisplayName, Teams.Name AS TeamName, Teams.UpdateAt AS TeamUpdateAt"
  1022  	}
  1023  
  1024  	query := s.getQueryBuilder().
  1025  		Select(selectStr).
  1026  		From("Channels AS c").
  1027  		Where(sq.Eq{"c.Type": []string{model.CHANNEL_PRIVATE, model.CHANNEL_OPEN}})
  1028  
  1029  	if !forCount {
  1030  		query = query.Join("Teams ON Teams.Id = c.TeamId")
  1031  	}
  1032  
  1033  	if !opts.IncludeDeleted {
  1034  		query = query.Where(sq.Eq{"c.DeleteAt": int(0)})
  1035  	}
  1036  
  1037  	if opts.NotAssociatedToGroup != "" {
  1038  		query = query.Where("c.Id NOT IN (SELECT ChannelId FROM GroupChannels WHERE GroupChannels.GroupId = ? AND GroupChannels.DeleteAt = 0)", opts.NotAssociatedToGroup)
  1039  	}
  1040  
  1041  	if len(opts.ExcludeChannelNames) > 0 {
  1042  		query = query.Where(sq.NotEq{"c.Name": opts.ExcludeChannelNames})
  1043  	}
  1044  
  1045  	return query
  1046  }
  1047  
  1048  func (s SqlChannelStore) GetMoreChannels(teamId string, userId string, offset int, limit int) (*model.ChannelList, error) {
  1049  	channels := &model.ChannelList{}
  1050  	_, err := s.GetReplica().Select(channels, `
  1051  		SELECT
  1052  			Channels.*
  1053  		FROM
  1054  			Channels
  1055  		JOIN
  1056  			PublicChannels c ON (c.Id = Channels.Id)
  1057  		WHERE
  1058  			c.TeamId = :TeamId
  1059  		AND c.DeleteAt = 0
  1060  		AND c.Id NOT IN (
  1061  			SELECT
  1062  				c.Id
  1063  			FROM
  1064  				PublicChannels c
  1065  			JOIN
  1066  				ChannelMembers cm ON (cm.ChannelId = c.Id)
  1067  			WHERE
  1068  				c.TeamId = :TeamId
  1069  			AND cm.UserId = :UserId
  1070  			AND c.DeleteAt = 0
  1071  		)
  1072  		ORDER BY
  1073  			c.DisplayName
  1074  		LIMIT :Limit
  1075  		OFFSET :Offset
  1076  		`, map[string]interface{}{
  1077  		"TeamId": teamId,
  1078  		"UserId": userId,
  1079  		"Limit":  limit,
  1080  		"Offset": offset,
  1081  	})
  1082  
  1083  	if err != nil {
  1084  		return nil, errors.Wrapf(err, "failed getting channels with teamId=%s and userId=%s", teamId, userId)
  1085  	}
  1086  
  1087  	return channels, nil
  1088  }
  1089  
  1090  func (s SqlChannelStore) GetPrivateChannelsForTeam(teamId string, offset int, limit int) (*model.ChannelList, error) {
  1091  	channels := &model.ChannelList{}
  1092  
  1093  	builder := s.getQueryBuilder().
  1094  		Select("*").
  1095  		From("Channels").
  1096  		Where(sq.Eq{"Type": model.CHANNEL_PRIVATE, "TeamId": teamId, "DeleteAt": 0}).
  1097  		OrderBy("DisplayName").
  1098  		Limit(uint64(limit)).
  1099  		Offset(uint64(offset))
  1100  
  1101  	query, args, err := builder.ToSql()
  1102  	if err != nil {
  1103  		return nil, errors.Wrap(err, "channels_tosql")
  1104  	}
  1105  
  1106  	_, err = s.GetReplica().Select(channels, query, args...)
  1107  	if err != nil {
  1108  		return nil, errors.Wrapf(err, "failed to find chaneld with teamId=%s", teamId)
  1109  	}
  1110  	return channels, nil
  1111  }
  1112  
  1113  func (s SqlChannelStore) GetPublicChannelsForTeam(teamId string, offset int, limit int) (*model.ChannelList, error) {
  1114  	channels := &model.ChannelList{}
  1115  	_, err := s.GetReplica().Select(channels, `
  1116  		SELECT
  1117  			Channels.*
  1118  		FROM
  1119  			Channels
  1120  		JOIN
  1121  			PublicChannels pc ON (pc.Id = Channels.Id)
  1122  		WHERE
  1123  			pc.TeamId = :TeamId
  1124  		AND pc.DeleteAt = 0
  1125  		ORDER BY pc.DisplayName
  1126  		LIMIT :Limit
  1127  		OFFSET :Offset
  1128  		`, map[string]interface{}{
  1129  		"TeamId": teamId,
  1130  		"Limit":  limit,
  1131  		"Offset": offset,
  1132  	})
  1133  
  1134  	if err != nil {
  1135  		return nil, errors.Wrapf(err, "failed to find chaneld with teamId=%s", teamId)
  1136  	}
  1137  
  1138  	return channels, nil
  1139  }
  1140  
  1141  func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) (*model.ChannelList, error) {
  1142  	props := make(map[string]interface{})
  1143  	props["teamId"] = teamId
  1144  
  1145  	idQuery := ""
  1146  
  1147  	for index, channelId := range channelIds {
  1148  		if idQuery != "" {
  1149  			idQuery += ", "
  1150  		}
  1151  
  1152  		props["channelId"+strconv.Itoa(index)] = channelId
  1153  		idQuery += ":channelId" + strconv.Itoa(index)
  1154  	}
  1155  
  1156  	data := &model.ChannelList{}
  1157  	_, err := s.GetReplica().Select(data, `
  1158  		SELECT
  1159  			Channels.*
  1160  		FROM
  1161  			Channels
  1162  		JOIN
  1163  			PublicChannels pc ON (pc.Id = Channels.Id)
  1164  		WHERE
  1165  			pc.TeamId = :teamId
  1166  		AND pc.DeleteAt = 0
  1167  		AND pc.Id IN (`+idQuery+`)
  1168  		ORDER BY pc.DisplayName
  1169  		`, props)
  1170  
  1171  	if err != nil {
  1172  		return nil, errors.Wrap(err, "failed to find Channels")
  1173  	}
  1174  
  1175  	if len(*data) == 0 {
  1176  		return nil, store.NewErrNotFound("Channel", fmt.Sprintf("teamId=%s, channelIds=%v", teamId, channelIds))
  1177  	}
  1178  
  1179  	return data, nil
  1180  }
  1181  
  1182  type channelIdWithCountAndUpdateAt struct {
  1183  	Id            string
  1184  	TotalMsgCount int64
  1185  	UpdateAt      int64
  1186  }
  1187  
  1188  func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) (*model.ChannelCounts, error) {
  1189  	var data []channelIdWithCountAndUpdateAt
  1190  	_, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND (TeamId = :TeamId OR TeamId = '') AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
  1191  
  1192  	if err != nil {
  1193  		return nil, errors.Wrapf(err, "failed to get channels count with teamId=%s and userId=%s", teamId, userId)
  1194  	}
  1195  
  1196  	counts := &model.ChannelCounts{Counts: make(map[string]int64), UpdateTimes: make(map[string]int64)}
  1197  	for i := range data {
  1198  		v := data[i]
  1199  		counts.Counts[v.Id] = v.TotalMsgCount
  1200  		counts.UpdateTimes[v.Id] = v.UpdateAt
  1201  	}
  1202  
  1203  	return counts, nil
  1204  }
  1205  
  1206  func (s SqlChannelStore) GetTeamChannels(teamId string) (*model.ChannelList, error) {
  1207  	data := &model.ChannelList{}
  1208  	_, err := s.GetReplica().Select(data, "SELECT * FROM Channels WHERE TeamId = :TeamId And Type != 'D' ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId})
  1209  
  1210  	if err != nil {
  1211  		return nil, errors.Wrapf(err, "failed to find Channels with teamId=%s", teamId)
  1212  	}
  1213  
  1214  	if len(*data) == 0 {
  1215  		return nil, store.NewErrNotFound("Channel", fmt.Sprintf("teamId=%s", teamId))
  1216  	}
  1217  
  1218  	return data, nil
  1219  }
  1220  
  1221  func (s SqlChannelStore) GetByName(teamId string, name string, allowFromCache bool) (*model.Channel, error) {
  1222  	return s.getByName(teamId, name, false, allowFromCache)
  1223  }
  1224  
  1225  func (s SqlChannelStore) GetByNames(teamId string, names []string, allowFromCache bool) ([]*model.Channel, error) {
  1226  	var channels []*model.Channel
  1227  
  1228  	if allowFromCache {
  1229  		var misses []string
  1230  		visited := make(map[string]struct{})
  1231  		for _, name := range names {
  1232  			if _, ok := visited[name]; ok {
  1233  				continue
  1234  			}
  1235  			visited[name] = struct{}{}
  1236  			var cacheItem *model.Channel
  1237  			if err := channelByNameCache.Get(teamId+name, &cacheItem); err == nil {
  1238  				channels = append(channels, cacheItem)
  1239  			} else {
  1240  				misses = append(misses, name)
  1241  			}
  1242  		}
  1243  		names = misses
  1244  	}
  1245  
  1246  	if len(names) > 0 {
  1247  		props := map[string]interface{}{}
  1248  		var namePlaceholders []string
  1249  		for _, name := range names {
  1250  			key := fmt.Sprintf("Name%v", len(namePlaceholders))
  1251  			props[key] = name
  1252  			namePlaceholders = append(namePlaceholders, ":"+key)
  1253  		}
  1254  
  1255  		var query string
  1256  		if teamId == "" {
  1257  			query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND DeleteAt = 0`
  1258  		} else {
  1259  			props["TeamId"] = teamId
  1260  			query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND TeamId = :TeamId AND DeleteAt = 0`
  1261  		}
  1262  
  1263  		var dbChannels []*model.Channel
  1264  		if _, err := s.GetReplica().Select(&dbChannels, query, props); err != nil && err != sql.ErrNoRows {
  1265  			msg := fmt.Sprintf("failed to get channels with names=%v", names)
  1266  			if teamId != "" {
  1267  				msg += fmt.Sprintf("teamId=%s", teamId)
  1268  			}
  1269  			return nil, errors.Wrap(err, msg)
  1270  		}
  1271  		for _, channel := range dbChannels {
  1272  			channelByNameCache.SetWithExpiry(teamId+channel.Name, channel, ChannelCacheDuration)
  1273  			channels = append(channels, channel)
  1274  		}
  1275  		// Not all channels are in cache. Increment aggregate miss counter.
  1276  		if s.metrics != nil {
  1277  			s.metrics.IncrementMemCacheMissCounter("Channel By Name - Aggregate")
  1278  		}
  1279  	} else {
  1280  		// All of the channel names are in cache. Increment aggregate hit counter.
  1281  		if s.metrics != nil {
  1282  			s.metrics.IncrementMemCacheHitCounter("Channel By Name - Aggregate")
  1283  		}
  1284  	}
  1285  
  1286  	return channels, nil
  1287  }
  1288  
  1289  func (s SqlChannelStore) GetByNameIncludeDeleted(teamId string, name string, allowFromCache bool) (*model.Channel, error) {
  1290  	return s.getByName(teamId, name, true, allowFromCache)
  1291  }
  1292  
  1293  func (s SqlChannelStore) getByName(teamId string, name string, includeDeleted bool, allowFromCache bool) (*model.Channel, error) {
  1294  	var query string
  1295  	if includeDeleted {
  1296  		query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name"
  1297  	} else {
  1298  		query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt = 0"
  1299  	}
  1300  	channel := model.Channel{}
  1301  
  1302  	if allowFromCache {
  1303  		var cacheItem *model.Channel
  1304  		if err := channelByNameCache.Get(teamId+name, &cacheItem); err == nil {
  1305  			if s.metrics != nil {
  1306  				s.metrics.IncrementMemCacheHitCounter("Channel By Name")
  1307  			}
  1308  			return cacheItem, nil
  1309  		}
  1310  		if s.metrics != nil {
  1311  			s.metrics.IncrementMemCacheMissCounter("Channel By Name")
  1312  		}
  1313  	}
  1314  
  1315  	if err := s.GetReplica().SelectOne(&channel, query, map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil {
  1316  		if err == sql.ErrNoRows {
  1317  			return nil, store.NewErrNotFound("Channel", fmt.Sprintf("TeamId=%s&Name=%s", teamId, name))
  1318  		}
  1319  		return nil, errors.Wrapf(err, "failed to find channel with TeamId=%s and Name=%s", teamId, name)
  1320  	}
  1321  
  1322  	channelByNameCache.SetWithExpiry(teamId+name, &channel, ChannelCacheDuration)
  1323  	return &channel, nil
  1324  }
  1325  
  1326  func (s SqlChannelStore) GetDeletedByName(teamId string, name string) (*model.Channel, error) {
  1327  	channel := model.Channel{}
  1328  
  1329  	if err := s.GetReplica().SelectOne(&channel, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt != 0", map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil {
  1330  		if err == sql.ErrNoRows {
  1331  			return nil, store.NewErrNotFound("Channel", fmt.Sprintf("name=%s", name))
  1332  		}
  1333  		return nil, errors.Wrapf(err, "failed to get channel by teamId=%s and name=%s", teamId, name)
  1334  	}
  1335  
  1336  	return &channel, nil
  1337  }
  1338  
  1339  func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int, userId string) (*model.ChannelList, error) {
  1340  	channels := &model.ChannelList{}
  1341  
  1342  	query := `
  1343  		SELECT * FROM Channels
  1344  		WHERE (TeamId = :TeamId OR TeamId = '')
  1345  		AND DeleteAt != 0
  1346  		AND Type != 'P'
  1347  		UNION
  1348  			SELECT * FROM Channels
  1349  			WHERE (TeamId = :TeamId OR TeamId = '')
  1350  			AND DeleteAt != 0
  1351  			AND Type = 'P'
  1352  			AND Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId)
  1353  		ORDER BY DisplayName LIMIT :Limit OFFSET :Offset
  1354  	`
  1355  
  1356  	if _, err := s.GetReplica().Select(channels, query, map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset, "UserId": userId}); err != nil {
  1357  		if err == sql.ErrNoRows {
  1358  			return nil, store.NewErrNotFound("Channel", fmt.Sprintf("TeamId=%s,UserId=%s", teamId, userId))
  1359  		}
  1360  		return nil, errors.Wrapf(err, "failed to get deleted channels with TeamId=%s and UserId=%s", teamId, userId)
  1361  	}
  1362  
  1363  	return channels, nil
  1364  }
  1365  
  1366  var ChannelMembersWithSchemeSelectQuery = `
  1367  	SELECT
  1368  		ChannelMembers.*,
  1369  		TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole,
  1370  		TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1371  		TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1372  		ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole,
  1373  		ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1374  		ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1375  	FROM
  1376  		ChannelMembers
  1377  	INNER JOIN
  1378  		Channels ON ChannelMembers.ChannelId = Channels.Id
  1379  	LEFT JOIN
  1380  		Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1381  	LEFT JOIN
  1382  		Teams ON Channels.TeamId = Teams.Id
  1383  	LEFT JOIN
  1384  		Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1385  `
  1386  
  1387  func (s SqlChannelStore) SaveMultipleMembers(members []*model.ChannelMember) ([]*model.ChannelMember, error) {
  1388  	for _, member := range members {
  1389  		defer s.InvalidateAllChannelMembersForUser(member.UserId)
  1390  	}
  1391  
  1392  	transaction, err := s.GetMaster().Begin()
  1393  	if err != nil {
  1394  		return nil, errors.Wrap(err, "begin_transaction")
  1395  	}
  1396  	defer finalizeTransaction(transaction)
  1397  
  1398  	newMembers, err := s.saveMultipleMembers(members)
  1399  	if err != nil {
  1400  		return nil, err
  1401  	}
  1402  
  1403  	if err := transaction.Commit(); err != nil {
  1404  		return nil, errors.Wrap(err, "commit_transaction")
  1405  	}
  1406  
  1407  	return newMembers, nil
  1408  }
  1409  
  1410  func (s SqlChannelStore) SaveMember(member *model.ChannelMember) (*model.ChannelMember, error) {
  1411  	newMembers, err := s.SaveMultipleMembers([]*model.ChannelMember{member})
  1412  	if err != nil {
  1413  		return nil, err
  1414  	}
  1415  	return newMembers[0], nil
  1416  }
  1417  
  1418  func (s SqlChannelStore) saveMultipleMembers(members []*model.ChannelMember) ([]*model.ChannelMember, error) {
  1419  	newChannelMembers := map[string]int{}
  1420  	users := map[string]bool{}
  1421  	for _, member := range members {
  1422  		if val, ok := newChannelMembers[member.ChannelId]; val < 1 || !ok {
  1423  			newChannelMembers[member.ChannelId] = 1
  1424  		} else {
  1425  			newChannelMembers[member.ChannelId]++
  1426  		}
  1427  		users[member.UserId] = true
  1428  
  1429  		member.PreSave()
  1430  		if err := member.IsValid(); err != nil { // TODO: this needs to return plain error in v6.
  1431  			return nil, err
  1432  		}
  1433  	}
  1434  
  1435  	channels := []string{}
  1436  	for channel := range newChannelMembers {
  1437  		channels = append(channels, channel)
  1438  	}
  1439  
  1440  	defaultChannelRolesByChannel := map[string]struct {
  1441  		Id    string
  1442  		Guest sql.NullString
  1443  		User  sql.NullString
  1444  		Admin sql.NullString
  1445  	}{}
  1446  
  1447  	channelRolesQuery := s.getQueryBuilder().
  1448  		Select(
  1449  			"Channels.Id as Id",
  1450  			"ChannelScheme.DefaultChannelGuestRole as Guest",
  1451  			"ChannelScheme.DefaultChannelUserRole as User",
  1452  			"ChannelScheme.DefaultChannelAdminRole as Admin",
  1453  		).
  1454  		From("Channels").
  1455  		LeftJoin("Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id").
  1456  		Where(sq.Eq{"Channels.Id": channels})
  1457  
  1458  	channelRolesSql, channelRolesArgs, err := channelRolesQuery.ToSql()
  1459  	if err != nil {
  1460  		return nil, errors.Wrap(err, "channel_roles_tosql")
  1461  	}
  1462  
  1463  	var defaultChannelsRoles []struct {
  1464  		Id    string
  1465  		Guest sql.NullString
  1466  		User  sql.NullString
  1467  		Admin sql.NullString
  1468  	}
  1469  	_, err = s.GetMaster().Select(&defaultChannelsRoles, channelRolesSql, channelRolesArgs...)
  1470  	if err != nil {
  1471  		return nil, errors.Wrap(err, "default_channel_roles_select")
  1472  	}
  1473  
  1474  	for _, defaultRoles := range defaultChannelsRoles {
  1475  		defaultChannelRolesByChannel[defaultRoles.Id] = defaultRoles
  1476  	}
  1477  
  1478  	defaultTeamRolesByChannel := map[string]struct {
  1479  		Id    string
  1480  		Guest sql.NullString
  1481  		User  sql.NullString
  1482  		Admin sql.NullString
  1483  	}{}
  1484  
  1485  	teamRolesQuery := s.getQueryBuilder().
  1486  		Select(
  1487  			"Channels.Id as Id",
  1488  			"TeamScheme.DefaultChannelGuestRole as Guest",
  1489  			"TeamScheme.DefaultChannelUserRole as User",
  1490  			"TeamScheme.DefaultChannelAdminRole as Admin",
  1491  		).
  1492  		From("Channels").
  1493  		LeftJoin("Teams ON Teams.Id = Channels.TeamId").
  1494  		LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
  1495  		Where(sq.Eq{"Channels.Id": channels})
  1496  
  1497  	teamRolesSql, teamRolesArgs, err := teamRolesQuery.ToSql()
  1498  	if err != nil {
  1499  		return nil, errors.Wrap(err, "team_roles_tosql")
  1500  	}
  1501  
  1502  	var defaultTeamsRoles []struct {
  1503  		Id    string
  1504  		Guest sql.NullString
  1505  		User  sql.NullString
  1506  		Admin sql.NullString
  1507  	}
  1508  	_, err = s.GetMaster().Select(&defaultTeamsRoles, teamRolesSql, teamRolesArgs...)
  1509  	if err != nil {
  1510  		return nil, errors.Wrap(err, "default_team_roles_select")
  1511  	}
  1512  
  1513  	for _, defaultRoles := range defaultTeamsRoles {
  1514  		defaultTeamRolesByChannel[defaultRoles.Id] = defaultRoles
  1515  	}
  1516  
  1517  	query := s.getQueryBuilder().Insert("ChannelMembers").Columns(channelMemberSliceColumns()...)
  1518  	for _, member := range members {
  1519  		query = query.Values(channelMemberToSlice(member)...)
  1520  	}
  1521  
  1522  	sql, args, err := query.ToSql()
  1523  	if err != nil {
  1524  		return nil, errors.Wrap(err, "channel_members_tosql")
  1525  	}
  1526  
  1527  	if _, err := s.GetMaster().Exec(sql, args...); err != nil {
  1528  		if IsUniqueConstraintError(err, []string{"ChannelId", "channelmembers_pkey", "PRIMARY"}) {
  1529  			return nil, store.NewErrConflict("ChannelMembers", err, "")
  1530  		}
  1531  		return nil, errors.Wrap(err, "channel_members_save")
  1532  	}
  1533  
  1534  	newMembers := []*model.ChannelMember{}
  1535  	for _, member := range members {
  1536  		defaultTeamGuestRole := defaultTeamRolesByChannel[member.ChannelId].Guest.String
  1537  		defaultTeamUserRole := defaultTeamRolesByChannel[member.ChannelId].User.String
  1538  		defaultTeamAdminRole := defaultTeamRolesByChannel[member.ChannelId].Admin.String
  1539  		defaultChannelGuestRole := defaultChannelRolesByChannel[member.ChannelId].Guest.String
  1540  		defaultChannelUserRole := defaultChannelRolesByChannel[member.ChannelId].User.String
  1541  		defaultChannelAdminRole := defaultChannelRolesByChannel[member.ChannelId].Admin.String
  1542  		rolesResult := getChannelRoles(
  1543  			member.SchemeGuest, member.SchemeUser, member.SchemeAdmin,
  1544  			defaultTeamGuestRole, defaultTeamUserRole, defaultTeamAdminRole,
  1545  			defaultChannelGuestRole, defaultChannelUserRole, defaultChannelAdminRole,
  1546  			strings.Fields(member.ExplicitRoles),
  1547  		)
  1548  		newMember := *member
  1549  		newMember.SchemeGuest = rolesResult.schemeGuest
  1550  		newMember.SchemeUser = rolesResult.schemeUser
  1551  		newMember.SchemeAdmin = rolesResult.schemeAdmin
  1552  		newMember.Roles = strings.Join(rolesResult.roles, " ")
  1553  		newMember.ExplicitRoles = strings.Join(rolesResult.explicitRoles, " ")
  1554  		newMembers = append(newMembers, &newMember)
  1555  	}
  1556  	return newMembers, nil
  1557  }
  1558  
  1559  func (s SqlChannelStore) saveMemberT(member *model.ChannelMember) (*model.ChannelMember, error) {
  1560  	members, err := s.saveMultipleMembers([]*model.ChannelMember{member})
  1561  	if err != nil {
  1562  		return nil, err
  1563  	}
  1564  	return members[0], nil
  1565  }
  1566  
  1567  func (s SqlChannelStore) UpdateMultipleMembers(members []*model.ChannelMember) ([]*model.ChannelMember, error) {
  1568  	for _, member := range members {
  1569  		member.PreUpdate()
  1570  
  1571  		if err := member.IsValid(); err != nil {
  1572  			return nil, err
  1573  		}
  1574  	}
  1575  
  1576  	var transaction *gorp.Transaction
  1577  	var err error
  1578  
  1579  	if transaction, err = s.GetMaster().Begin(); err != nil {
  1580  		return nil, errors.Wrap(err, "begin_transaction")
  1581  	}
  1582  	defer finalizeTransaction(transaction)
  1583  
  1584  	updatedMembers := []*model.ChannelMember{}
  1585  	for _, member := range members {
  1586  		if _, err := transaction.Update(NewChannelMemberFromModel(member)); err != nil {
  1587  			return nil, errors.Wrap(err, "failed to update ChannelMember")
  1588  		}
  1589  
  1590  		// TODO: Get this out of the transaction when is possible
  1591  		var dbMember channelMemberWithSchemeRoles
  1592  		if err := transaction.SelectOne(&dbMember, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
  1593  			if err == sql.ErrNoRows {
  1594  				return nil, store.NewErrNotFound("ChannelMember", fmt.Sprintf("channelId=%s, userId=%s", member.ChannelId, member.UserId))
  1595  			}
  1596  			return nil, errors.Wrapf(err, "failed to get ChannelMember with channelId=%s and userId=%s", member.ChannelId, member.UserId)
  1597  		}
  1598  		updatedMembers = append(updatedMembers, dbMember.ToModel())
  1599  	}
  1600  
  1601  	if err := transaction.Commit(); err != nil {
  1602  		return nil, errors.Wrap(err, "commit_transaction")
  1603  	}
  1604  	return updatedMembers, nil
  1605  }
  1606  
  1607  func (s SqlChannelStore) UpdateMember(member *model.ChannelMember) (*model.ChannelMember, error) {
  1608  	updatedMembers, err := s.UpdateMultipleMembers([]*model.ChannelMember{member})
  1609  	if err != nil {
  1610  		return nil, err
  1611  	}
  1612  	return updatedMembers[0], nil
  1613  }
  1614  
  1615  func (s SqlChannelStore) GetMembers(channelId string, offset, limit int) (*model.ChannelMembers, error) {
  1616  	var dbMembers channelMemberWithSchemeRolesList
  1617  	_, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelId = :ChannelId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"ChannelId": channelId, "Limit": limit, "Offset": offset})
  1618  	if err != nil {
  1619  		return nil, errors.Wrapf(err, "failed to get ChannelMembers with channelId=%s", channelId)
  1620  	}
  1621  
  1622  	return dbMembers.ToModel(), nil
  1623  }
  1624  
  1625  func (s SqlChannelStore) GetChannelMembersTimezones(channelId string) ([]model.StringMap, error) {
  1626  	var dbMembersTimezone []model.StringMap
  1627  	_, err := s.GetReplica().Select(&dbMembersTimezone, `
  1628  		SELECT
  1629  			Users.Timezone
  1630  		FROM
  1631  			ChannelMembers
  1632  		LEFT JOIN
  1633  			Users  ON ChannelMembers.UserId = Id
  1634  		WHERE ChannelId = :ChannelId
  1635  	`, map[string]interface{}{"ChannelId": channelId})
  1636  
  1637  	if err != nil {
  1638  		return nil, errors.Wrapf(err, "failed to find user timezones for users in channels with channelId=%s", channelId)
  1639  	}
  1640  
  1641  	return dbMembersTimezone, nil
  1642  }
  1643  
  1644  func (s SqlChannelStore) GetMember(channelId string, userId string) (*model.ChannelMember, error) {
  1645  	var dbMember channelMemberWithSchemeRoles
  1646  
  1647  	if err := s.GetReplica().SelectOne(&dbMember, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil {
  1648  		if err == sql.ErrNoRows {
  1649  			return nil, store.NewErrNotFound("ChannelMember", fmt.Sprintf("channelId=%s, userId=%s", channelId, userId))
  1650  		}
  1651  		return nil, errors.Wrapf(err, "failed to get ChannelMember with channelId=%s and userId=%s", channelId, userId)
  1652  	}
  1653  
  1654  	return dbMember.ToModel(), nil
  1655  }
  1656  
  1657  func (s SqlChannelStore) InvalidateAllChannelMembersForUser(userId string) {
  1658  	allChannelMembersForUserCache.Remove(userId)
  1659  	allChannelMembersForUserCache.Remove(userId + "_deleted")
  1660  	if s.metrics != nil {
  1661  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Remove by UserId")
  1662  	}
  1663  }
  1664  
  1665  func (s SqlChannelStore) IsUserInChannelUseCache(userId string, channelId string) bool {
  1666  	var ids map[string]string
  1667  	if err := allChannelMembersForUserCache.Get(userId, &ids); err == nil {
  1668  		if s.metrics != nil {
  1669  			s.metrics.IncrementMemCacheHitCounter("All Channel Members for User")
  1670  		}
  1671  		if _, ok := ids[channelId]; ok {
  1672  			return true
  1673  		}
  1674  		return false
  1675  	}
  1676  
  1677  	if s.metrics != nil {
  1678  		s.metrics.IncrementMemCacheMissCounter("All Channel Members for User")
  1679  	}
  1680  
  1681  	ids, err := s.GetAllChannelMembersForUser(userId, true, false)
  1682  	if err != nil {
  1683  		mlog.Error("Error getting all channel members for user", mlog.Err(err))
  1684  		return false
  1685  	}
  1686  
  1687  	if _, ok := ids[channelId]; ok {
  1688  		return true
  1689  	}
  1690  
  1691  	return false
  1692  }
  1693  
  1694  func (s SqlChannelStore) GetMemberForPost(postId string, userId string) (*model.ChannelMember, error) {
  1695  	var dbMember channelMemberWithSchemeRoles
  1696  	query := `
  1697  		SELECT
  1698  			ChannelMembers.*,
  1699  			TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole,
  1700  			TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1701  			TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1702  			ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole,
  1703  			ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1704  			ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1705  		FROM
  1706  			ChannelMembers
  1707  		INNER JOIN
  1708  			Posts ON ChannelMembers.ChannelId = Posts.ChannelId
  1709  		INNER JOIN
  1710  			Channels ON ChannelMembers.ChannelId = Channels.Id
  1711  		LEFT JOIN
  1712  			Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1713  		LEFT JOIN
  1714  			Teams ON Channels.TeamId = Teams.Id
  1715  		LEFT JOIN
  1716  			Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1717  		WHERE
  1718  			ChannelMembers.UserId = :UserId
  1719  		AND
  1720  			Posts.Id = :PostId`
  1721  	if err := s.GetReplica().SelectOne(&dbMember, query, map[string]interface{}{"UserId": userId, "PostId": postId}); err != nil {
  1722  		return nil, errors.Wrapf(err, "failed to get ChannelMember with postId=%s and userId=%s", postId, userId)
  1723  	}
  1724  	return dbMember.ToModel(), nil
  1725  }
  1726  
  1727  func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool, includeDeleted bool) (map[string]string, error) {
  1728  	cache_key := userId
  1729  	if includeDeleted {
  1730  		cache_key += "_deleted"
  1731  	}
  1732  	if allowFromCache {
  1733  		var ids map[string]string
  1734  		if err := allChannelMembersForUserCache.Get(cache_key, &ids); err == nil {
  1735  			if s.metrics != nil {
  1736  				s.metrics.IncrementMemCacheHitCounter("All Channel Members for User")
  1737  			}
  1738  			return ids, nil
  1739  		}
  1740  	}
  1741  
  1742  	if s.metrics != nil {
  1743  		s.metrics.IncrementMemCacheMissCounter("All Channel Members for User")
  1744  	}
  1745  
  1746  	query := s.getQueryBuilder().
  1747  		Select(`
  1748  				ChannelMembers.ChannelId, ChannelMembers.Roles, ChannelMembers.SchemeGuest,
  1749  				ChannelMembers.SchemeUser, ChannelMembers.SchemeAdmin,
  1750  				TeamScheme.DefaultChannelGuestRole TeamSchemeDefaultGuestRole,
  1751  				TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1752  				TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1753  				ChannelScheme.DefaultChannelGuestRole ChannelSchemeDefaultGuestRole,
  1754  				ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1755  				ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1756  		`).
  1757  		From("ChannelMembers").
  1758  		Join("Channels ON ChannelMembers.ChannelId = Channels.Id").
  1759  		LeftJoin("Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id").
  1760  		LeftJoin("Teams ON Channels.TeamId = Teams.Id").
  1761  		LeftJoin("Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id").
  1762  		Where(sq.Eq{"ChannelMembers.UserId": userId})
  1763  	if !includeDeleted {
  1764  		query = query.Where(sq.Eq{"Channels.DeleteAt": 0})
  1765  	}
  1766  	queryString, args, err := query.ToSql()
  1767  	if err != nil {
  1768  		return nil, errors.Wrap(err, "channel_tosql")
  1769  	}
  1770  
  1771  	rows, err := s.GetReplica().Db.Query(queryString, args...)
  1772  	if err != nil {
  1773  		return nil, errors.Wrap(err, "failed to find ChannelMembers, TeamScheme and ChannelScheme data")
  1774  	}
  1775  
  1776  	var data allChannelMembers
  1777  	defer rows.Close()
  1778  	for rows.Next() {
  1779  		var cm allChannelMember
  1780  		err = rows.Scan(
  1781  			&cm.ChannelId, &cm.Roles, &cm.SchemeGuest, &cm.SchemeUser,
  1782  			&cm.SchemeAdmin, &cm.TeamSchemeDefaultGuestRole, &cm.TeamSchemeDefaultUserRole,
  1783  			&cm.TeamSchemeDefaultAdminRole, &cm.ChannelSchemeDefaultGuestRole,
  1784  			&cm.ChannelSchemeDefaultUserRole, &cm.ChannelSchemeDefaultAdminRole,
  1785  		)
  1786  		if err != nil {
  1787  			return nil, errors.Wrap(err, "unable to scan columns")
  1788  		}
  1789  		data = append(data, cm)
  1790  	}
  1791  	if err = rows.Err(); err != nil {
  1792  		return nil, errors.Wrap(err, "error while iterating over rows")
  1793  	}
  1794  	ids := data.ToMapStringString()
  1795  
  1796  	if allowFromCache {
  1797  		allChannelMembersForUserCache.SetWithExpiry(cache_key, ids, AllChannelMembersForUserCacheDuration)
  1798  	}
  1799  	return ids, nil
  1800  }
  1801  
  1802  func (s SqlChannelStore) InvalidateCacheForChannelMembersNotifyProps(channelId string) {
  1803  	allChannelMembersNotifyPropsForChannelCache.Remove(channelId)
  1804  	if s.metrics != nil {
  1805  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Remove by ChannelId")
  1806  	}
  1807  }
  1808  
  1809  type allChannelMemberNotifyProps struct {
  1810  	UserId      string
  1811  	NotifyProps model.StringMap
  1812  }
  1813  
  1814  func (s SqlChannelStore) GetAllChannelMembersNotifyPropsForChannel(channelId string, allowFromCache bool) (map[string]model.StringMap, error) {
  1815  	if allowFromCache {
  1816  		var cacheItem map[string]model.StringMap
  1817  		if err := allChannelMembersNotifyPropsForChannelCache.Get(channelId, &cacheItem); err == nil {
  1818  			if s.metrics != nil {
  1819  				s.metrics.IncrementMemCacheHitCounter("All Channel Members Notify Props for Channel")
  1820  			}
  1821  			return cacheItem, nil
  1822  		}
  1823  	}
  1824  
  1825  	if s.metrics != nil {
  1826  		s.metrics.IncrementMemCacheMissCounter("All Channel Members Notify Props for Channel")
  1827  	}
  1828  
  1829  	var data []allChannelMemberNotifyProps
  1830  	_, err := s.GetReplica().Select(&data, `
  1831  		SELECT UserId, NotifyProps
  1832  		FROM ChannelMembers
  1833  		WHERE ChannelId = :ChannelId`, map[string]interface{}{"ChannelId": channelId})
  1834  
  1835  	if err != nil {
  1836  		return nil, errors.Wrapf(err, "failed to find data from ChannelMembers with channelId=%s", channelId)
  1837  	}
  1838  
  1839  	props := make(map[string]model.StringMap)
  1840  	for i := range data {
  1841  		props[data[i].UserId] = data[i].NotifyProps
  1842  	}
  1843  
  1844  	allChannelMembersNotifyPropsForChannelCache.SetWithExpiry(channelId, props, AllChannelMembersNotifyPropsForChannelCacheDuration)
  1845  
  1846  	return props, nil
  1847  }
  1848  
  1849  //nolint:unparam
  1850  func (s SqlChannelStore) InvalidateMemberCount(channelId string) {
  1851  }
  1852  
  1853  func (s SqlChannelStore) GetMemberCountFromCache(channelId string) int64 {
  1854  	count, _ := s.GetMemberCount(channelId, true)
  1855  	return count
  1856  }
  1857  
  1858  //nolint:unparam
  1859  func (s SqlChannelStore) GetMemberCount(channelId string, allowFromCache bool) (int64, error) {
  1860  	count, err := s.GetReplica().SelectInt(`
  1861  		SELECT
  1862  			count(*)
  1863  		FROM
  1864  			ChannelMembers,
  1865  			Users
  1866  		WHERE
  1867  			ChannelMembers.UserId = Users.Id
  1868  			AND ChannelMembers.ChannelId = :ChannelId
  1869  			AND Users.DeleteAt = 0`, map[string]interface{}{"ChannelId": channelId})
  1870  	if err != nil {
  1871  		return 0, errors.Wrapf(err, "failed to count ChanenelMembers with channelId=%s", channelId)
  1872  	}
  1873  
  1874  	return count, nil
  1875  }
  1876  
  1877  // GetMemberCountsByGroup returns a slice of ChannelMemberCountByGroup for a given channel
  1878  // which contains the number of channel members for each group and optionally the number of unique timezones present for each group in the channel
  1879  func (s SqlChannelStore) GetMemberCountsByGroup(channelID string, includeTimezones bool) ([]*model.ChannelMemberCountByGroup, error) {
  1880  	selectStr := "GroupMembers.GroupId, COUNT(ChannelMembers.UserId) AS ChannelMemberCount"
  1881  
  1882  	if includeTimezones {
  1883  		// Length of default timezone (len {"automaticTimezone":"","manualTimezone":"","useAutomaticTimezone":"true"})
  1884  		defaultTimezoneLength := `74`
  1885  
  1886  		// Beginning and end of the value for the automatic and manual timezones respectively
  1887  		autoTimezone := `LOCATE(':', Users.Timezone) + 2`
  1888  		autoTimezoneEnd := `LOCATE(',', Users.Timezone) - LOCATE(':', Users.Timezone) - 3`
  1889  		manualTimezone := `LOCATE(',', Users.Timezone) + 19`
  1890  		manualTimezoneEnd := `LOCATE('useAutomaticTimezone', Users.Timezone) - 22 - LOCATE(',', Users.Timezone)`
  1891  
  1892  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1893  			autoTimezone = `POSITION(':' IN Users.Timezone) + 2`
  1894  			autoTimezoneEnd = `POSITION(',' IN Users.Timezone) - POSITION(':' IN Users.Timezone) - 3`
  1895  			manualTimezone = `POSITION(',' IN Users.Timezone) + 19`
  1896  			manualTimezoneEnd = `POSITION('useAutomaticTimezone' IN Users.Timezone) - 22 - POSITION(',' IN Users.Timezone)`
  1897  		}
  1898  
  1899  		selectStr = `
  1900  			GroupMembers.GroupId,
  1901  			COUNT(ChannelMembers.UserId) AS ChannelMemberCount,
  1902  			COUNT(DISTINCT
  1903  				(
  1904  					CASE WHEN Timezone like '%"useAutomaticTimezone":"true"}' AND LENGTH(Timezone) > ` + defaultTimezoneLength + `
  1905  					THEN
  1906  					SUBSTRING(
  1907  						Timezone
  1908  						FROM ` + autoTimezone + `
  1909  						FOR ` + autoTimezoneEnd + `
  1910  					)
  1911  					WHEN Timezone like '%"useAutomaticTimezone":"false"}' AND LENGTH(Timezone) > ` + defaultTimezoneLength + `
  1912  					THEN
  1913  						SUBSTRING(
  1914  						Timezone
  1915  						FROM ` + manualTimezone + `
  1916  						FOR ` + manualTimezoneEnd + `
  1917  					)
  1918  					END
  1919  				)
  1920  			) AS ChannelMemberTimezonesCount
  1921  		`
  1922  	}
  1923  
  1924  	query := s.getQueryBuilder().
  1925  		Select(selectStr).
  1926  		From("ChannelMembers").
  1927  		Join("GroupMembers ON GroupMembers.UserId = ChannelMembers.UserId")
  1928  
  1929  	if includeTimezones {
  1930  		query = query.Join("Users ON Users.Id = GroupMembers.UserId")
  1931  	}
  1932  
  1933  	query = query.Where(sq.Eq{"ChannelMembers.ChannelId": channelID}).GroupBy("GroupMembers.GroupId")
  1934  
  1935  	queryString, args, err := query.ToSql()
  1936  	if err != nil {
  1937  		return nil, errors.Wrap(err, "channel_tosql")
  1938  	}
  1939  	var data []*model.ChannelMemberCountByGroup
  1940  	if _, err = s.GetReplica().Select(&data, queryString, args...); err != nil {
  1941  		return nil, errors.Wrapf(err, "failed to count ChannelMembers with channelId=%s", channelID)
  1942  	}
  1943  
  1944  	return data, nil
  1945  }
  1946  
  1947  //nolint:unparam
  1948  func (s SqlChannelStore) InvalidatePinnedPostCount(channelId string) {
  1949  }
  1950  
  1951  //nolint:unparam
  1952  func (s SqlChannelStore) GetPinnedPostCount(channelId string, allowFromCache bool) (int64, error) {
  1953  	count, err := s.GetReplica().SelectInt(`
  1954  		SELECT count(*)
  1955  			FROM Posts
  1956  		WHERE
  1957  			IsPinned = true
  1958  			AND ChannelId = :ChannelId
  1959  			AND DeleteAt = 0`, map[string]interface{}{"ChannelId": channelId})
  1960  
  1961  	if err != nil {
  1962  		return 0, errors.Wrapf(err, "failed to count pinned Posts with channelId=%s", channelId)
  1963  	}
  1964  
  1965  	return count, nil
  1966  }
  1967  
  1968  //nolint:unparam
  1969  func (s SqlChannelStore) InvalidateGuestCount(channelId string) {
  1970  }
  1971  
  1972  //nolint:unparam
  1973  func (s SqlChannelStore) GetGuestCount(channelId string, allowFromCache bool) (int64, error) {
  1974  	count, err := s.GetReplica().SelectInt(`
  1975  		SELECT
  1976  			count(*)
  1977  		FROM
  1978  			ChannelMembers,
  1979  			Users
  1980  		WHERE
  1981  			ChannelMembers.UserId = Users.Id
  1982  			AND ChannelMembers.ChannelId = :ChannelId
  1983  			AND ChannelMembers.SchemeGuest = TRUE
  1984  			AND Users.DeleteAt = 0`, map[string]interface{}{"ChannelId": channelId})
  1985  	if err != nil {
  1986  		return 0, errors.Wrapf(err, "failed to count Guests with channelId=%s", channelId)
  1987  	}
  1988  	return count, nil
  1989  }
  1990  
  1991  func (s SqlChannelStore) RemoveMembers(channelId string, userIds []string) error {
  1992  	builder := s.getQueryBuilder().
  1993  		Delete("ChannelMembers").
  1994  		Where(sq.Eq{"ChannelId": channelId}).
  1995  		Where(sq.Eq{"UserId": userIds})
  1996  	query, args, err := builder.ToSql()
  1997  	if err != nil {
  1998  		return errors.Wrap(err, "channel_tosql")
  1999  	}
  2000  	_, err = s.GetMaster().Exec(query, args...)
  2001  	if err != nil {
  2002  		return errors.Wrap(err, "failed to delete ChannelMembers")
  2003  	}
  2004  
  2005  	// cleanup sidebarchannels table if the user is no longer a member of that channel
  2006  	query, args, err = s.getQueryBuilder().
  2007  		Delete("SidebarChannels").
  2008  		Where(sq.And{
  2009  			sq.Eq{"ChannelId": channelId},
  2010  			sq.Eq{"UserId": userIds},
  2011  		}).ToSql()
  2012  	if err != nil {
  2013  		return errors.Wrap(err, "channel_tosql")
  2014  	}
  2015  	_, err = s.GetMaster().Exec(query, args...)
  2016  	if err != nil {
  2017  		return errors.Wrap(err, "failed to delete SidebarChannels")
  2018  	}
  2019  	return nil
  2020  }
  2021  
  2022  func (s SqlChannelStore) RemoveMember(channelId string, userId string) error {
  2023  	return s.RemoveMembers(channelId, []string{userId})
  2024  }
  2025  
  2026  func (s SqlChannelStore) RemoveAllDeactivatedMembers(channelId string) error {
  2027  	query := `
  2028  		DELETE
  2029  		FROM
  2030  			ChannelMembers
  2031  		WHERE
  2032  			UserId IN (
  2033  				SELECT
  2034  					Id
  2035  				FROM
  2036  					Users
  2037  				WHERE
  2038  					Users.DeleteAt != 0
  2039  			)
  2040  		AND
  2041  			ChannelMembers.ChannelId = :ChannelId
  2042  	`
  2043  
  2044  	_, err := s.GetMaster().Exec(query, map[string]interface{}{"ChannelId": channelId})
  2045  	if err != nil {
  2046  		return errors.Wrapf(err, "failed to delete ChannelMembers with channelId=%s", channelId)
  2047  	}
  2048  	return nil
  2049  }
  2050  
  2051  func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) error {
  2052  	if _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
  2053  		return errors.Wrapf(err, "failed to permanent delete ChannelMembers with userId=%s", userId)
  2054  	}
  2055  	return nil
  2056  }
  2057  
  2058  func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string, updateThreads bool) (map[string]int64, error) {
  2059  	var threadsToUpdate []string
  2060  	now := model.GetMillis()
  2061  	if updateThreads {
  2062  		var err error
  2063  		threadsToUpdate, err = s.Thread().CollectThreadsWithNewerReplies(userId, channelIds, now)
  2064  		if err != nil {
  2065  			return nil, err
  2066  		}
  2067  	}
  2068  
  2069  	keys, props := MapStringsToQueryParams(channelIds, "Channel")
  2070  	props["UserId"] = userId
  2071  
  2072  	var lastPostAtTimes []struct {
  2073  		Id            string
  2074  		LastPostAt    int64
  2075  		TotalMsgCount int64
  2076  	}
  2077  
  2078  	query := `SELECT Id, LastPostAt, TotalMsgCount FROM Channels WHERE Id IN ` + keys
  2079  	// TODO: use a CTE for mysql too when version 8 becomes the minimum supported version.
  2080  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2081  		query = `WITH c AS ( ` + query + `),
  2082  	updated AS (
  2083  	UPDATE
  2084  		ChannelMembers cm
  2085  	SET
  2086  		MentionCount = 0,
  2087  		MsgCount = greatest(cm.MsgCount, c.TotalMsgCount),
  2088  		LastViewedAt = greatest(cm.LastViewedAt, c.LastPostAt),
  2089  		LastUpdateAt = greatest(cm.LastViewedAt, c.LastPostAt)
  2090  	FROM c
  2091  		WHERE cm.UserId = :UserId
  2092  		AND c.Id=cm.ChannelId
  2093  )
  2094  	SELECT Id, LastPostAt FROM c`
  2095  	}
  2096  
  2097  	_, err := s.GetMaster().Select(&lastPostAtTimes, query, props)
  2098  	if err != nil {
  2099  		return nil, errors.Wrapf(err, "failed to find ChannelMembers data with userId=%s and channelId in %v", userId, channelIds)
  2100  	}
  2101  
  2102  	if len(lastPostAtTimes) == 0 {
  2103  		return nil, store.NewErrInvalidInput("Channel", "Id", fmt.Sprintf("%v", channelIds))
  2104  	}
  2105  
  2106  	times := map[string]int64{}
  2107  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2108  		for _, t := range lastPostAtTimes {
  2109  			times[t.Id] = t.LastPostAt
  2110  		}
  2111  		if updateThreads {
  2112  			s.Thread().UpdateUnreadsByChannel(userId, threadsToUpdate, now, true)
  2113  		}
  2114  		return times, nil
  2115  	}
  2116  
  2117  	msgCountQuery := ""
  2118  	lastViewedQuery := ""
  2119  
  2120  	for index, t := range lastPostAtTimes {
  2121  		times[t.Id] = t.LastPostAt
  2122  
  2123  		props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount
  2124  		msgCountQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCount, :msgCount%d) ", index, index)
  2125  
  2126  		props["lastViewed"+strconv.Itoa(index)] = t.LastPostAt
  2127  		lastViewedQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(LastViewedAt, :lastViewed%d) ", index, index)
  2128  
  2129  		props["channelId"+strconv.Itoa(index)] = t.Id
  2130  	}
  2131  
  2132  	updateQuery := `UPDATE
  2133  			ChannelMembers
  2134  		SET
  2135  			MentionCount = 0,
  2136  			MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
  2137  			LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
  2138  			LastUpdateAt = LastViewedAt
  2139  		WHERE
  2140  				UserId = :UserId
  2141  				AND ChannelId IN ` + keys
  2142  
  2143  	if _, err := s.GetMaster().Exec(updateQuery, props); err != nil {
  2144  		return nil, errors.Wrapf(err, "failed to update ChannelMembers with userId=%s and channelId in %v", userId, channelIds)
  2145  	}
  2146  
  2147  	if updateThreads {
  2148  		s.Thread().UpdateUnreadsByChannel(userId, threadsToUpdate, now, true)
  2149  	}
  2150  	return times, nil
  2151  }
  2152  
  2153  // CountPostsAfter returns the number of posts in the given channel created after but not including the given timestamp. If given a non-empty user ID, only counts posts made by that user.
  2154  func (s SqlChannelStore) CountPostsAfter(channelId string, timestamp int64, userId string) (int, error) {
  2155  	joinLeavePostTypes, params := MapStringsToQueryParams([]string{
  2156  		// These types correspond to the ones checked by Post.IsJoinLeaveMessage
  2157  		model.POST_JOIN_LEAVE,
  2158  		model.POST_ADD_REMOVE,
  2159  		model.POST_JOIN_CHANNEL,
  2160  		model.POST_LEAVE_CHANNEL,
  2161  		model.POST_JOIN_TEAM,
  2162  		model.POST_LEAVE_TEAM,
  2163  		model.POST_ADD_TO_CHANNEL,
  2164  		model.POST_REMOVE_FROM_CHANNEL,
  2165  		model.POST_ADD_TO_TEAM,
  2166  		model.POST_REMOVE_FROM_TEAM,
  2167  	}, "PostType")
  2168  
  2169  	query := `
  2170  	SELECT count(*)
  2171  	FROM Posts
  2172  	WHERE
  2173  		ChannelId = :ChannelId
  2174  		AND CreateAt > :CreateAt
  2175  		AND Type NOT IN ` + joinLeavePostTypes + `
  2176  		AND DeleteAt = 0
  2177  	`
  2178  
  2179  	params["ChannelId"] = channelId
  2180  	params["CreateAt"] = timestamp
  2181  
  2182  	if userId != "" {
  2183  		query += " AND UserId = :UserId"
  2184  		params["UserId"] = userId
  2185  	}
  2186  
  2187  	unread, err := s.GetReplica().SelectInt(query, params)
  2188  	if err != nil {
  2189  		return 0, errors.Wrap(err, "failed to count Posts")
  2190  	}
  2191  	return int(unread), nil
  2192  }
  2193  
  2194  // UpdateLastViewedAtPost updates a ChannelMember as if the user last read the channel at the time of the given post.
  2195  // If the provided mentionCount is -1, the given post and all posts after it are considered to be mentions. Returns
  2196  // an updated model.ChannelUnreadAt that can be returned to the client.
  2197  func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error) {
  2198  	var threadsToUpdate []string
  2199  	unreadDate := unreadPost.CreateAt - 1
  2200  	if updateThreads {
  2201  		var err error
  2202  		threadsToUpdate, err = s.Thread().CollectThreadsWithNewerReplies(userID, []string{unreadPost.ChannelId}, unreadDate)
  2203  		if err != nil {
  2204  			return nil, err
  2205  		}
  2206  	}
  2207  
  2208  	unread, err := s.CountPostsAfter(unreadPost.ChannelId, unreadDate, "")
  2209  	if err != nil {
  2210  		return nil, err
  2211  	}
  2212  
  2213  	params := map[string]interface{}{
  2214  		"mentions":     mentionCount,
  2215  		"unreadCount":  unread,
  2216  		"lastViewedAt": unreadDate,
  2217  		"userId":       userID,
  2218  		"channelId":    unreadPost.ChannelId,
  2219  		"updatedAt":    model.GetMillis(),
  2220  	}
  2221  
  2222  	// msg count uses the value from channels to prevent counting on older channels where no. of messages can be high.
  2223  	// we only count the unread which will be a lot less in 99% cases
  2224  	setUnreadQuery := `
  2225  	UPDATE
  2226  		ChannelMembers
  2227  	SET
  2228  		MentionCount = :mentions,
  2229  		MsgCount = (SELECT TotalMsgCount FROM Channels WHERE ID = :channelId) - :unreadCount,
  2230  		LastViewedAt = :lastViewedAt,
  2231  		LastUpdateAt = :updatedAt
  2232  	WHERE
  2233  		UserId = :userId
  2234  		AND ChannelId = :channelId
  2235  	`
  2236  	_, err = s.GetMaster().Exec(setUnreadQuery, params)
  2237  	if err != nil {
  2238  		return nil, errors.Wrap(err, "failed to update ChannelMembers")
  2239  	}
  2240  
  2241  	chanUnreadQuery := `
  2242  	SELECT
  2243  		c.TeamId TeamId,
  2244  		cm.UserId UserId,
  2245  		cm.ChannelId ChannelId,
  2246  		cm.MsgCount MsgCount,
  2247  		cm.MentionCount MentionCount,
  2248  		cm.LastViewedAt LastViewedAt,
  2249  		cm.NotifyProps NotifyProps
  2250  	FROM
  2251  		ChannelMembers cm
  2252  	LEFT JOIN Channels c ON c.Id=cm.ChannelId
  2253  	WHERE
  2254  		cm.UserId = :userId
  2255  		AND cm.channelId = :channelId
  2256  		AND c.DeleteAt = 0
  2257  	`
  2258  	result := &model.ChannelUnreadAt{}
  2259  	if err = s.GetMaster().SelectOne(result, chanUnreadQuery, params); err != nil {
  2260  		return nil, errors.Wrapf(err, "failed to get ChannelMember with channelId=%s", unreadPost.ChannelId)
  2261  	}
  2262  
  2263  	if updateThreads {
  2264  		s.Thread().UpdateUnreadsByChannel(userID, threadsToUpdate, unreadDate, true)
  2265  	}
  2266  	return result, nil
  2267  }
  2268  
  2269  func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string, updateThreads bool) error {
  2270  	now := model.GetMillis()
  2271  	var threadsToUpdate []string
  2272  	if updateThreads {
  2273  		var err error
  2274  		threadsToUpdate, err = s.Thread().CollectThreadsWithNewerReplies(userId, []string{channelId}, now)
  2275  		if err != nil {
  2276  			return err
  2277  		}
  2278  	}
  2279  
  2280  	_, err := s.GetMaster().Exec(
  2281  		`UPDATE
  2282  			ChannelMembers
  2283  		SET
  2284  			MentionCount = MentionCount + 1,
  2285  			LastUpdateAt = :LastUpdateAt
  2286  		WHERE
  2287  			UserId = :UserId
  2288  				AND ChannelId = :ChannelId`,
  2289  		map[string]interface{}{"ChannelId": channelId, "UserId": userId, "LastUpdateAt": now})
  2290  	if err != nil {
  2291  		return errors.Wrapf(err, "failed to Update ChannelMembers with channelId=%s and userId=%s", channelId, userId)
  2292  	}
  2293  	if updateThreads {
  2294  		s.Thread().UpdateUnreadsByChannel(userId, threadsToUpdate, now, false)
  2295  	}
  2296  	return nil
  2297  }
  2298  
  2299  func (s SqlChannelStore) GetAll(teamId string) ([]*model.Channel, error) {
  2300  	var data []*model.Channel
  2301  	_, err := s.GetReplica().Select(&data, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Type != 'D' ORDER BY Name", map[string]interface{}{"TeamId": teamId})
  2302  
  2303  	if err != nil {
  2304  		return nil, errors.Wrapf(err, "failed to find Channels with teamId=%s", teamId)
  2305  	}
  2306  
  2307  	return data, nil
  2308  }
  2309  
  2310  func (s SqlChannelStore) GetChannelsByIds(channelIds []string, includeDeleted bool) ([]*model.Channel, error) {
  2311  	keys, params := MapStringsToQueryParams(channelIds, "Channel")
  2312  	query := `SELECT * FROM Channels WHERE Id IN ` + keys + ` ORDER BY Name`
  2313  	if !includeDeleted {
  2314  		query = `SELECT * FROM Channels WHERE DeleteAt=0 AND Id IN ` + keys + ` ORDER BY Name`
  2315  	}
  2316  
  2317  	var channels []*model.Channel
  2318  	_, err := s.GetReplica().Select(&channels, query, params)
  2319  
  2320  	if err != nil {
  2321  		return nil, errors.Wrap(err, "failed to find Channels")
  2322  	}
  2323  	return channels, nil
  2324  }
  2325  
  2326  func (s SqlChannelStore) GetForPost(postId string) (*model.Channel, error) {
  2327  	channel := &model.Channel{}
  2328  	if err := s.GetReplica().SelectOne(
  2329  		channel,
  2330  		`SELECT
  2331  			Channels.*
  2332  		FROM
  2333  			Channels,
  2334  			Posts
  2335  		WHERE
  2336  			Channels.Id = Posts.ChannelId
  2337  			AND Posts.Id = :PostId`, map[string]interface{}{"PostId": postId}); err != nil {
  2338  		return nil, errors.Wrapf(err, "failed to get Channel with postId=%s", postId)
  2339  
  2340  	}
  2341  	return channel, nil
  2342  }
  2343  
  2344  func (s SqlChannelStore) AnalyticsTypeCount(teamId string, channelType string) (int64, error) {
  2345  	query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType"
  2346  
  2347  	if teamId != "" {
  2348  		query += " AND TeamId = :TeamId"
  2349  	}
  2350  
  2351  	value, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType})
  2352  	if err != nil {
  2353  		return int64(0), errors.Wrap(err, "failed to count Channels")
  2354  	}
  2355  	return value, nil
  2356  }
  2357  
  2358  func (s SqlChannelStore) AnalyticsDeletedTypeCount(teamId string, channelType string) (int64, error) {
  2359  	query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType AND DeleteAt > 0"
  2360  
  2361  	if teamId != "" {
  2362  		query += " AND TeamId = :TeamId"
  2363  	}
  2364  
  2365  	v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType})
  2366  	if err != nil {
  2367  		return 0, errors.Wrapf(err, "failed to count Channels with teamId=%s and channelType=%s", teamId, channelType)
  2368  	}
  2369  
  2370  	return v, nil
  2371  }
  2372  
  2373  func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) (*model.ChannelMembers, error) {
  2374  	var dbMembers channelMemberWithSchemeRolesList
  2375  	_, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId AND (Teams.Id = :TeamId OR Teams.Id = '' OR Teams.Id IS NULL)", map[string]interface{}{"TeamId": teamId, "UserId": userId})
  2376  	if err != nil {
  2377  		return nil, errors.Wrapf(err, "failed to find ChannelMembers data with teamId=%s and userId=%s", teamId, userId)
  2378  	}
  2379  
  2380  	return dbMembers.ToModel(), nil
  2381  }
  2382  
  2383  func (s SqlChannelStore) GetMembersForUserWithPagination(teamId, userId string, page, perPage int) (*model.ChannelMembers, error) {
  2384  	var dbMembers channelMemberWithSchemeRolesList
  2385  	offset := page * perPage
  2386  	_, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId Limit :Limit Offset :Offset", map[string]interface{}{"TeamId": teamId, "UserId": userId, "Limit": perPage, "Offset": offset})
  2387  
  2388  	if err != nil {
  2389  		return nil, errors.Wrapf(err, "failed to find ChannelMembers data with teamId=%s and userId=%s", teamId, userId)
  2390  	}
  2391  
  2392  	return dbMembers.ToModel(), nil
  2393  }
  2394  
  2395  func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, error) {
  2396  	deleteFilter := "AND Channels.DeleteAt = 0"
  2397  	if includeDeleted {
  2398  		deleteFilter = ""
  2399  	}
  2400  
  2401  	queryFormat := `
  2402  		SELECT
  2403  			Channels.*
  2404  		FROM
  2405  			Channels
  2406  		JOIN
  2407  			PublicChannels c ON (c.Id = Channels.Id)
  2408  		WHERE
  2409  			Channels.TeamId = :TeamId
  2410  			` + deleteFilter + `
  2411  			%v
  2412  		LIMIT ` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT)
  2413  
  2414  	var channels model.ChannelList
  2415  
  2416  	if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" {
  2417  		if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil {
  2418  			return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2419  		}
  2420  	} else {
  2421  		// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
  2422  		// query you would get using an OR of the LIKE and full-text clauses.
  2423  		fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  2424  		likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
  2425  		fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
  2426  		query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
  2427  
  2428  		if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
  2429  			return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2430  		}
  2431  	}
  2432  
  2433  	sort.Slice(channels, func(a, b int) bool {
  2434  		return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
  2435  	})
  2436  	return &channels, nil
  2437  }
  2438  
  2439  func (s SqlChannelStore) AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) (*model.ChannelList, error) {
  2440  	deleteFilter := "AND DeleteAt = 0"
  2441  	if includeDeleted {
  2442  		deleteFilter = ""
  2443  	}
  2444  
  2445  	queryFormat := `
  2446  		SELECT
  2447  			C.*
  2448  		FROM
  2449  			Channels AS C
  2450  		JOIN
  2451  			ChannelMembers AS CM ON CM.ChannelId = C.Id
  2452  		WHERE
  2453  			(C.TeamId = :TeamId OR (C.TeamId = '' AND C.Type = 'G'))
  2454  			AND CM.UserId = :UserId
  2455  			` + deleteFilter + `
  2456  			%v
  2457  		LIMIT 50`
  2458  
  2459  	var channels model.ChannelList
  2460  
  2461  	if likeClause, likeTerm := s.buildLIKEClause(term, "Name, DisplayName, Purpose"); likeClause == "" {
  2462  		if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId, "UserId": userId}); err != nil {
  2463  			return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2464  		}
  2465  	} else {
  2466  		// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
  2467  		// query you would get using an OR of the LIKE and full-text clauses.
  2468  		fulltextClause, fulltextTerm := s.buildFulltextClause(term, "Name, DisplayName, Purpose")
  2469  		likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
  2470  		fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
  2471  		query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
  2472  
  2473  		if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "UserId": userId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
  2474  			return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2475  		}
  2476  	}
  2477  
  2478  	directChannels, err := s.autocompleteInTeamForSearchDirectMessages(userId, term)
  2479  	if err != nil {
  2480  		return nil, err
  2481  	}
  2482  
  2483  	channels = append(channels, directChannels...)
  2484  
  2485  	sort.Slice(channels, func(a, b int) bool {
  2486  		return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
  2487  	})
  2488  	return &channels, nil
  2489  }
  2490  
  2491  func (s SqlChannelStore) autocompleteInTeamForSearchDirectMessages(userId string, term string) ([]*model.Channel, error) {
  2492  	queryFormat := `
  2493  			SELECT
  2494  				C.*,
  2495  				OtherUsers.Username as DisplayName
  2496  			FROM
  2497  				Channels AS C
  2498  			JOIN
  2499  				ChannelMembers AS CM ON CM.ChannelId = C.Id
  2500  			INNER JOIN (
  2501  				SELECT
  2502  					ICM.ChannelId AS ChannelId, IU.Username AS Username
  2503  				FROM
  2504  					Users as IU
  2505  				JOIN
  2506  					ChannelMembers AS ICM ON ICM.UserId = IU.Id
  2507  				WHERE
  2508  					IU.Id != :UserId
  2509  					%v
  2510  				) AS OtherUsers ON OtherUsers.ChannelId = C.Id
  2511  			WHERE
  2512  			    C.Type = 'D'
  2513  				AND CM.UserId = :UserId
  2514  			LIMIT 50`
  2515  
  2516  	var channels model.ChannelList
  2517  
  2518  	if likeClause, likeTerm := s.buildLIKEClause(term, "IU.Username, IU.Nickname"); likeClause == "" {
  2519  		if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"UserId": userId}); err != nil {
  2520  			return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2521  		}
  2522  	} else {
  2523  		query := fmt.Sprintf(queryFormat, "AND "+likeClause)
  2524  
  2525  		if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"UserId": userId, "LikeTerm": likeTerm}); err != nil {
  2526  			return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2527  		}
  2528  	}
  2529  
  2530  	return channels, nil
  2531  }
  2532  
  2533  func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) (*model.ChannelList, error) {
  2534  	deleteFilter := "AND c.DeleteAt = 0"
  2535  	if includeDeleted {
  2536  		deleteFilter = ""
  2537  	}
  2538  
  2539  	return s.performSearch(`
  2540  		SELECT
  2541  			Channels.*
  2542  		FROM
  2543  			Channels
  2544  		JOIN
  2545  			PublicChannels c ON (c.Id = Channels.Id)
  2546  		WHERE
  2547  			c.TeamId = :TeamId
  2548  			`+deleteFilter+`
  2549  			SEARCH_CLAUSE
  2550  		ORDER BY c.DisplayName
  2551  		LIMIT 100
  2552  		`, term, map[string]interface{}{
  2553  		"TeamId": teamId,
  2554  	})
  2555  }
  2556  
  2557  func (s SqlChannelStore) SearchArchivedInTeam(teamId string, term string, userId string) (*model.ChannelList, error) {
  2558  	publicChannels, publicErr := s.performSearch(`
  2559  		SELECT
  2560  			Channels.*
  2561  		FROM
  2562  			Channels
  2563  		JOIN
  2564  			Channels c ON (c.Id = Channels.Id)
  2565  		WHERE
  2566  			c.TeamId = :TeamId
  2567  			SEARCH_CLAUSE
  2568  			AND c.DeleteAt != 0
  2569  			AND c.Type != 'P'
  2570  		ORDER BY c.DisplayName
  2571  		LIMIT 100
  2572  		`, term, map[string]interface{}{
  2573  		"TeamId": teamId,
  2574  		"UserId": userId,
  2575  	})
  2576  
  2577  	privateChannels, privateErr := s.performSearch(`
  2578  		SELECT
  2579  			Channels.*
  2580  		FROM
  2581  			Channels
  2582  		JOIN
  2583  			Channels c ON (c.Id = Channels.Id)
  2584  		WHERE
  2585  			c.TeamId = :TeamId
  2586  			SEARCH_CLAUSE
  2587  			AND c.DeleteAt != 0
  2588  			AND c.Type = 'P'
  2589  			AND c.Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId)
  2590  		ORDER BY c.DisplayName
  2591  		LIMIT 100
  2592  		`, term, map[string]interface{}{
  2593  		"TeamId": teamId,
  2594  		"UserId": userId,
  2595  	})
  2596  
  2597  	outputErr := publicErr
  2598  	if privateErr != nil {
  2599  		outputErr = privateErr
  2600  	}
  2601  
  2602  	if outputErr != nil {
  2603  		return nil, outputErr
  2604  	}
  2605  
  2606  	output := *publicChannels
  2607  	output = append(output, *privateChannels...)
  2608  
  2609  	return &output, nil
  2610  }
  2611  
  2612  func (s SqlChannelStore) SearchForUserInTeam(userId string, teamId string, term string, includeDeleted bool) (*model.ChannelList, error) {
  2613  	deleteFilter := "AND c.DeleteAt = 0"
  2614  	if includeDeleted {
  2615  		deleteFilter = ""
  2616  	}
  2617  
  2618  	return s.performSearch(`
  2619  		SELECT
  2620  			Channels.*
  2621  		FROM
  2622  			Channels
  2623  		JOIN
  2624  			PublicChannels c ON (c.Id = Channels.Id)
  2625          JOIN
  2626              ChannelMembers cm ON (c.Id = cm.ChannelId)
  2627  		WHERE
  2628  			c.TeamId = :TeamId
  2629          AND
  2630              cm.UserId = :UserId
  2631  			`+deleteFilter+`
  2632  			SEARCH_CLAUSE
  2633  		ORDER BY c.DisplayName
  2634  		LIMIT 100
  2635  		`, term, map[string]interface{}{
  2636  		"TeamId": teamId,
  2637  		"UserId": userId,
  2638  	})
  2639  }
  2640  
  2641  func (s SqlChannelStore) channelSearchQuery(term string, opts store.ChannelSearchOpts, countQuery bool) sq.SelectBuilder {
  2642  	var limit int
  2643  	if opts.PerPage != nil {
  2644  		limit = *opts.PerPage
  2645  	} else {
  2646  		limit = 100
  2647  	}
  2648  
  2649  	var selectStr string
  2650  	if countQuery {
  2651  		selectStr = "count(*)"
  2652  	} else {
  2653  		selectStr = "c.*, t.DisplayName AS TeamDisplayName, t.Name AS TeamName, t.UpdateAt as TeamUpdateAt"
  2654  	}
  2655  
  2656  	query := s.getQueryBuilder().
  2657  		Select(selectStr).
  2658  		From("Channels AS c").
  2659  		Join("Teams AS t ON t.Id = c.TeamId")
  2660  
  2661  	// don't bother ordering or limiting if we're just getting the count
  2662  	if !countQuery {
  2663  		query = query.
  2664  			OrderBy("c.DisplayName, t.DisplayName").
  2665  			Limit(uint64(limit))
  2666  	}
  2667  	if opts.Deleted {
  2668  		query = query.Where(sq.NotEq{"c.DeleteAt": int(0)})
  2669  	} else if !opts.IncludeDeleted {
  2670  		query = query.Where(sq.Eq{"c.DeleteAt": int(0)})
  2671  	}
  2672  
  2673  	if opts.IsPaginated() && !countQuery {
  2674  		query = query.Offset(uint64(*opts.Page * *opts.PerPage))
  2675  	}
  2676  
  2677  	likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
  2678  	if likeTerm != "" {
  2679  		likeClause = strings.ReplaceAll(likeClause, ":LikeTerm", "?")
  2680  		fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  2681  		fulltextClause = strings.ReplaceAll(fulltextClause, ":FulltextTerm", "?")
  2682  		query = query.Where(sq.Or{
  2683  			sq.Expr(likeClause, likeTerm, likeTerm, likeTerm), // Keep the number of likeTerms same as the number
  2684  			// of columns (c.Name, c.DisplayName, c.Purpose)
  2685  			sq.Expr(fulltextClause, fulltextTerm),
  2686  		})
  2687  	}
  2688  
  2689  	if len(opts.ExcludeChannelNames) > 0 {
  2690  		query = query.Where(sq.NotEq{"c.Name": opts.ExcludeChannelNames})
  2691  	}
  2692  
  2693  	if opts.NotAssociatedToGroup != "" {
  2694  		query = query.Where("c.Id NOT IN (SELECT ChannelId FROM GroupChannels WHERE GroupChannels.GroupId = ? AND GroupChannels.DeleteAt = 0)", opts.NotAssociatedToGroup)
  2695  	}
  2696  
  2697  	if len(opts.TeamIds) > 0 {
  2698  		query = query.Where(sq.Eq{"c.TeamId": opts.TeamIds})
  2699  	}
  2700  
  2701  	if opts.GroupConstrained {
  2702  		query = query.Where(sq.Eq{"c.GroupConstrained": true})
  2703  	} else if opts.ExcludeGroupConstrained {
  2704  		query = query.Where(sq.Or{
  2705  			sq.NotEq{"c.GroupConstrained": true},
  2706  			sq.Eq{"c.GroupConstrained": nil},
  2707  		})
  2708  	}
  2709  
  2710  	if opts.Public && !opts.Private {
  2711  		query = query.Where(sq.Eq{"c.Type": model.CHANNEL_OPEN})
  2712  	} else if opts.Private && !opts.Public {
  2713  		query = query.Where(sq.Eq{"c.Type": model.CHANNEL_PRIVATE})
  2714  	} else {
  2715  		query = query.Where(sq.Or{
  2716  			sq.Eq{"c.Type": model.CHANNEL_OPEN},
  2717  			sq.Eq{"c.Type": model.CHANNEL_PRIVATE},
  2718  		})
  2719  	}
  2720  
  2721  	return query
  2722  }
  2723  
  2724  func (s SqlChannelStore) SearchAllChannels(term string, opts store.ChannelSearchOpts) (*model.ChannelListWithTeamData, int64, error) {
  2725  	queryString, args, err := s.channelSearchQuery(term, opts, false).ToSql()
  2726  	if err != nil {
  2727  		return nil, 0, errors.Wrap(err, "channel_tosql")
  2728  	}
  2729  	var channels model.ChannelListWithTeamData
  2730  	if _, err = s.GetReplica().Select(&channels, queryString, args...); err != nil {
  2731  		return nil, 0, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2732  	}
  2733  
  2734  	var totalCount int64
  2735  
  2736  	// only query a 2nd time for the count if the results are being requested paginated.
  2737  	if opts.IsPaginated() {
  2738  		queryString, args, err = s.channelSearchQuery(term, opts, true).ToSql()
  2739  		if err != nil {
  2740  			return nil, 0, errors.Wrap(err, "channel_tosql")
  2741  		}
  2742  		if totalCount, err = s.GetReplica().SelectInt(queryString, args...); err != nil {
  2743  			return nil, 0, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2744  		}
  2745  	} else {
  2746  		totalCount = int64(len(channels))
  2747  	}
  2748  
  2749  	return &channels, totalCount, nil
  2750  }
  2751  
  2752  func (s SqlChannelStore) SearchMore(userId string, teamId string, term string) (*model.ChannelList, error) {
  2753  	return s.performSearch(`
  2754  		SELECT
  2755  			Channels.*
  2756  		FROM
  2757  			Channels
  2758  		JOIN
  2759  			PublicChannels c ON (c.Id = Channels.Id)
  2760  		WHERE
  2761  			c.TeamId = :TeamId
  2762  		AND c.DeleteAt = 0
  2763  		AND c.Id NOT IN (
  2764  			SELECT
  2765  				c.Id
  2766  			FROM
  2767  				PublicChannels c
  2768  			JOIN
  2769  				ChannelMembers cm ON (cm.ChannelId = c.Id)
  2770  			WHERE
  2771  				c.TeamId = :TeamId
  2772  			AND cm.UserId = :UserId
  2773  			AND c.DeleteAt = 0
  2774  			)
  2775  		SEARCH_CLAUSE
  2776  		ORDER BY c.DisplayName
  2777  		LIMIT 100
  2778  		`, term, map[string]interface{}{
  2779  		"TeamId": teamId,
  2780  		"UserId": userId,
  2781  	})
  2782  }
  2783  
  2784  func (s SqlChannelStore) buildLIKEClause(term string, searchColumns string) (likeClause, likeTerm string) {
  2785  	likeTerm = sanitizeSearchTerm(term, "*")
  2786  
  2787  	if likeTerm == "" {
  2788  		return
  2789  	}
  2790  
  2791  	// Prepare the LIKE portion of the query.
  2792  	var searchFields []string
  2793  	for _, field := range strings.Split(searchColumns, ", ") {
  2794  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2795  			searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*'", field, ":LikeTerm"))
  2796  		} else {
  2797  			searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*'", field, ":LikeTerm"))
  2798  		}
  2799  	}
  2800  
  2801  	likeClause = fmt.Sprintf("(%s)", strings.Join(searchFields, " OR "))
  2802  	likeTerm = wildcardSearchTerm(likeTerm)
  2803  	return
  2804  }
  2805  
  2806  func (s SqlChannelStore) buildFulltextClause(term string, searchColumns string) (fulltextClause, fulltextTerm string) {
  2807  	// Copy the terms as we will need to prepare them differently for each search type.
  2808  	fulltextTerm = term
  2809  
  2810  	// These chars must be treated as spaces in the fulltext query.
  2811  	for _, c := range spaceFulltextSearchChar {
  2812  		fulltextTerm = strings.Replace(fulltextTerm, c, " ", -1)
  2813  	}
  2814  
  2815  	// Prepare the FULLTEXT portion of the query.
  2816  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2817  		fulltextTerm = strings.Replace(fulltextTerm, "|", "", -1)
  2818  
  2819  		splitTerm := strings.Fields(fulltextTerm)
  2820  		for i, t := range strings.Fields(fulltextTerm) {
  2821  			if i == len(splitTerm)-1 {
  2822  				splitTerm[i] = t + ":*"
  2823  			} else {
  2824  				splitTerm[i] = t + ":* &"
  2825  			}
  2826  		}
  2827  
  2828  		fulltextTerm = strings.Join(splitTerm, " ")
  2829  
  2830  		fulltextClause = fmt.Sprintf("((to_tsvector('english', %s)) @@ to_tsquery('english', :FulltextTerm))", convertMySQLFullTextColumnsToPostgres(searchColumns))
  2831  	} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  2832  		splitTerm := strings.Fields(fulltextTerm)
  2833  		for i, t := range strings.Fields(fulltextTerm) {
  2834  			splitTerm[i] = "+" + t + "*"
  2835  		}
  2836  
  2837  		fulltextTerm = strings.Join(splitTerm, " ")
  2838  
  2839  		fulltextClause = fmt.Sprintf("MATCH(%s) AGAINST (:FulltextTerm IN BOOLEAN MODE)", searchColumns)
  2840  	}
  2841  
  2842  	return
  2843  }
  2844  
  2845  func (s SqlChannelStore) performSearch(searchQuery string, term string, parameters map[string]interface{}) (*model.ChannelList, error) {
  2846  	likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
  2847  	if likeTerm == "" {
  2848  		// If the likeTerm is empty after preparing, then don't bother searching.
  2849  		searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
  2850  	} else {
  2851  		parameters["LikeTerm"] = likeTerm
  2852  		fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  2853  		parameters["FulltextTerm"] = fulltextTerm
  2854  		searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
  2855  	}
  2856  
  2857  	var channels model.ChannelList
  2858  
  2859  	if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil {
  2860  		return nil, errors.Wrapf(err, "failed to find Channels with term='%s'", term)
  2861  	}
  2862  
  2863  	return &channels, nil
  2864  }
  2865  
  2866  func (s SqlChannelStore) getSearchGroupChannelsQuery(userId, term string, isPostgreSQL bool) (string, map[string]interface{}) {
  2867  	var query, baseLikeClause string
  2868  	if isPostgreSQL {
  2869  		baseLikeClause = "ARRAY_TO_STRING(ARRAY_AGG(u.Username), ', ') LIKE %s"
  2870  		query = `
  2871              SELECT
  2872                  *
  2873              FROM
  2874                  Channels
  2875              WHERE
  2876                  Id IN (
  2877                      SELECT
  2878                          cc.Id
  2879                      FROM (
  2880                          SELECT
  2881                              c.Id
  2882                          FROM
  2883                              Channels c
  2884                          JOIN
  2885                              ChannelMembers cm on c.Id = cm.ChannelId
  2886                          JOIN
  2887                              Users u on u.Id = cm.UserId
  2888                          WHERE
  2889                              c.Type = 'G'
  2890                          AND
  2891                              u.Id = :UserId
  2892                          GROUP BY
  2893                              c.Id
  2894                      ) cc
  2895                      JOIN
  2896                          ChannelMembers cm on cc.Id = cm.ChannelId
  2897                      JOIN
  2898                          Users u on u.Id = cm.UserId
  2899                      GROUP BY
  2900                          cc.Id
  2901                      HAVING
  2902                          %s
  2903                      LIMIT
  2904                          ` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT) + `
  2905                  )`
  2906  	} else {
  2907  		baseLikeClause = "GROUP_CONCAT(u.Username SEPARATOR ', ') LIKE %s"
  2908  		query = `
  2909              SELECT
  2910                  cc.*
  2911              FROM (
  2912                  SELECT
  2913                      c.*
  2914                  FROM
  2915                      Channels c
  2916                  JOIN
  2917                      ChannelMembers cm on c.Id = cm.ChannelId
  2918                  JOIN
  2919                      Users u on u.Id = cm.UserId
  2920                  WHERE
  2921                      c.Type = 'G'
  2922                  AND
  2923                      u.Id = :UserId
  2924                  GROUP BY
  2925                      c.Id
  2926              ) cc
  2927              JOIN
  2928                  ChannelMembers cm on cc.Id = cm.ChannelId
  2929              JOIN
  2930                  Users u on u.Id = cm.UserId
  2931              GROUP BY
  2932                  cc.Id
  2933              HAVING
  2934                  %s
  2935              LIMIT
  2936                  ` + strconv.Itoa(model.CHANNEL_SEARCH_DEFAULT_LIMIT)
  2937  	}
  2938  
  2939  	var likeClauses []string
  2940  	args := map[string]interface{}{"UserId": userId}
  2941  	terms := strings.Split(strings.ToLower(strings.Trim(term, " ")), " ")
  2942  
  2943  	for idx, term := range terms {
  2944  		argName := fmt.Sprintf("Term%v", idx)
  2945  		term = sanitizeSearchTerm(term, "\\")
  2946  		likeClauses = append(likeClauses, fmt.Sprintf(baseLikeClause, ":"+argName))
  2947  		args[argName] = "%" + term + "%"
  2948  	}
  2949  
  2950  	query = fmt.Sprintf(query, strings.Join(likeClauses, " AND "))
  2951  	return query, args
  2952  }
  2953  
  2954  func (s SqlChannelStore) SearchGroupChannels(userId, term string) (*model.ChannelList, error) {
  2955  	isPostgreSQL := s.DriverName() == model.DATABASE_DRIVER_POSTGRES
  2956  	queryString, args := s.getSearchGroupChannelsQuery(userId, term, isPostgreSQL)
  2957  
  2958  	var groupChannels model.ChannelList
  2959  	if _, err := s.GetReplica().Select(&groupChannels, queryString, args); err != nil {
  2960  		return nil, errors.Wrapf(err, "failed to find Channels with term='%s' and userId=%s", term, userId)
  2961  	}
  2962  	return &groupChannels, nil
  2963  }
  2964  
  2965  func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) (*model.ChannelMembers, error) {
  2966  	var dbMembers channelMemberWithSchemeRolesList
  2967  
  2968  	keys, props := MapStringsToQueryParams(userIds, "User")
  2969  	props["ChannelId"] = channelId
  2970  
  2971  	if _, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId IN "+keys, props); err != nil {
  2972  		return nil, errors.Wrapf(err, "failed to find ChannelMembers with channelId=%s and userId in %v", channelId, userIds)
  2973  	}
  2974  
  2975  	return dbMembers.ToModel(), nil
  2976  }
  2977  
  2978  func (s SqlChannelStore) GetMembersByChannelIds(channelIds []string, userId string) (*model.ChannelMembers, error) {
  2979  	var dbMembers channelMemberWithSchemeRolesList
  2980  
  2981  	keys, props := MapStringsToQueryParams(channelIds, "Channel")
  2982  	props["UserId"] = userId
  2983  
  2984  	if _, err := s.GetReplica().Select(&dbMembers, ChannelMembersWithSchemeSelectQuery+"WHERE ChannelMembers.UserId = :UserId AND ChannelMembers.ChannelId IN "+keys, props); err != nil {
  2985  		return nil, errors.Wrapf(err, "failed to find ChannelMembers with userId=%s and channelId in %v", userId, channelIds)
  2986  	}
  2987  
  2988  	return dbMembers.ToModel(), nil
  2989  }
  2990  
  2991  func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) (model.ChannelList, error) {
  2992  	var channels model.ChannelList
  2993  	_, err := s.GetReplica().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = :SchemeId ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"SchemeId": schemeId, "Offset": offset, "Limit": limit})
  2994  	if err != nil {
  2995  		return nil, errors.Wrapf(err, "failed to find Channels with schemeId=%s", schemeId)
  2996  	}
  2997  	return channels, nil
  2998  }
  2999  
  3000  // This function does the Advanced Permissions Phase 2 migration for ChannelMember objects. It performs the migration
  3001  // in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid
  3002  // causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function
  3003  // *after* the new Schemes functionality has been used on an installation will have unintended consequences.
  3004  func (s SqlChannelStore) MigrateChannelMembers(fromChannelId string, fromUserId string) (map[string]string, error) {
  3005  	var transaction *gorp.Transaction
  3006  	var err error
  3007  
  3008  	if transaction, err = s.GetMaster().Begin(); err != nil {
  3009  		return nil, errors.Wrap(err, "begin_transaction")
  3010  	}
  3011  	defer finalizeTransaction(transaction)
  3012  
  3013  	var channelMembers []channelMember
  3014  	if _, err := transaction.Select(&channelMembers, "SELECT * from ChannelMembers WHERE (ChannelId, UserId) > (:FromChannelId, :FromUserId) ORDER BY ChannelId, UserId LIMIT 100", map[string]interface{}{"FromChannelId": fromChannelId, "FromUserId": fromUserId}); err != nil {
  3015  		return nil, errors.Wrap(err, "failed to find ChannelMembers")
  3016  	}
  3017  
  3018  	if len(channelMembers) == 0 {
  3019  		// No more channel members in query result means that the migration has finished.
  3020  		return nil, nil
  3021  	}
  3022  
  3023  	for i := range channelMembers {
  3024  		member := channelMembers[i]
  3025  		roles := strings.Fields(member.Roles)
  3026  		var newRoles []string
  3027  		if !member.SchemeAdmin.Valid {
  3028  			member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true}
  3029  		}
  3030  		if !member.SchemeUser.Valid {
  3031  			member.SchemeUser = sql.NullBool{Bool: false, Valid: true}
  3032  		}
  3033  		if !member.SchemeGuest.Valid {
  3034  			member.SchemeGuest = sql.NullBool{Bool: false, Valid: true}
  3035  		}
  3036  		for _, role := range roles {
  3037  			if role == model.CHANNEL_ADMIN_ROLE_ID {
  3038  				member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true}
  3039  			} else if role == model.CHANNEL_USER_ROLE_ID {
  3040  				member.SchemeUser = sql.NullBool{Bool: true, Valid: true}
  3041  			} else if role == model.CHANNEL_GUEST_ROLE_ID {
  3042  				member.SchemeGuest = sql.NullBool{Bool: true, Valid: true}
  3043  			} else {
  3044  				newRoles = append(newRoles, role)
  3045  			}
  3046  		}
  3047  		member.Roles = strings.Join(newRoles, " ")
  3048  
  3049  		if _, err := transaction.Update(&member); err != nil {
  3050  			return nil, errors.Wrap(err, "failed to update ChannelMember")
  3051  		}
  3052  
  3053  	}
  3054  
  3055  	if err := transaction.Commit(); err != nil {
  3056  		return nil, errors.Wrap(err, "commit_transaction")
  3057  	}
  3058  
  3059  	data := make(map[string]string)
  3060  	data["ChannelId"] = channelMembers[len(channelMembers)-1].ChannelId
  3061  	data["UserId"] = channelMembers[len(channelMembers)-1].UserId
  3062  	return data, nil
  3063  }
  3064  
  3065  func (s SqlChannelStore) ResetAllChannelSchemes() error {
  3066  	transaction, err := s.GetMaster().Begin()
  3067  	if err != nil {
  3068  		return errors.Wrap(err, "begin_transaction")
  3069  	}
  3070  	defer finalizeTransaction(transaction)
  3071  
  3072  	err = s.resetAllChannelSchemesT(transaction)
  3073  	if err != nil {
  3074  		return err
  3075  	}
  3076  
  3077  	if err := transaction.Commit(); err != nil {
  3078  		return errors.Wrap(err, "commit_transaction")
  3079  	}
  3080  
  3081  	return nil
  3082  }
  3083  
  3084  func (s SqlChannelStore) resetAllChannelSchemesT(transaction *gorp.Transaction) error {
  3085  	if _, err := transaction.Exec("UPDATE Channels SET SchemeId=''"); err != nil {
  3086  		return errors.Wrap(err, "failed to update Channels")
  3087  	}
  3088  
  3089  	return nil
  3090  }
  3091  
  3092  func (s SqlChannelStore) ClearAllCustomRoleAssignments() error {
  3093  	builtInRoles := model.MakeDefaultRoles()
  3094  	lastUserId := strings.Repeat("0", 26)
  3095  	lastChannelId := strings.Repeat("0", 26)
  3096  
  3097  	for {
  3098  		var transaction *gorp.Transaction
  3099  		var err error
  3100  
  3101  		if transaction, err = s.GetMaster().Begin(); err != nil {
  3102  			return errors.Wrap(err, "begin_transaction")
  3103  		}
  3104  
  3105  		var channelMembers []*channelMember
  3106  		if _, err := transaction.Select(&channelMembers, "SELECT * from ChannelMembers WHERE (ChannelId, UserId) > (:ChannelId, :UserId) ORDER BY ChannelId, UserId LIMIT 1000", map[string]interface{}{"ChannelId": lastChannelId, "UserId": lastUserId}); err != nil {
  3107  			finalizeTransaction(transaction)
  3108  			return errors.Wrap(err, "failed to find ChannelMembers")
  3109  		}
  3110  
  3111  		if len(channelMembers) == 0 {
  3112  			finalizeTransaction(transaction)
  3113  			break
  3114  		}
  3115  
  3116  		for _, member := range channelMembers {
  3117  			lastUserId = member.UserId
  3118  			lastChannelId = member.ChannelId
  3119  
  3120  			var newRoles []string
  3121  
  3122  			for _, role := range strings.Fields(member.Roles) {
  3123  				for name := range builtInRoles {
  3124  					if name == role {
  3125  						newRoles = append(newRoles, role)
  3126  						break
  3127  					}
  3128  				}
  3129  			}
  3130  
  3131  			newRolesString := strings.Join(newRoles, " ")
  3132  			if newRolesString != member.Roles {
  3133  				if _, err := transaction.Exec("UPDATE ChannelMembers SET Roles = :Roles WHERE UserId = :UserId AND ChannelId = :ChannelId", map[string]interface{}{"Roles": newRolesString, "ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
  3134  					finalizeTransaction(transaction)
  3135  					return errors.Wrap(err, "failed to update ChannelMembers")
  3136  				}
  3137  			}
  3138  		}
  3139  
  3140  		if err := transaction.Commit(); err != nil {
  3141  			finalizeTransaction(transaction)
  3142  			return errors.Wrap(err, "commit_transaction")
  3143  		}
  3144  	}
  3145  
  3146  	return nil
  3147  }
  3148  
  3149  func (s SqlChannelStore) GetAllChannelsForExportAfter(limit int, afterId string) ([]*model.ChannelForExport, error) {
  3150  	var channels []*model.ChannelForExport
  3151  	if _, err := s.GetReplica().Select(&channels, `
  3152  		SELECT
  3153  			Channels.*,
  3154  			Teams.Name as TeamName,
  3155  			Schemes.Name as SchemeName
  3156  		FROM Channels
  3157  		INNER JOIN
  3158  			Teams ON Channels.TeamId = Teams.Id
  3159  		LEFT JOIN
  3160  			Schemes ON Channels.SchemeId = Schemes.Id
  3161  		WHERE
  3162  			Channels.Id > :AfterId
  3163  			AND Channels.Type IN ('O', 'P')
  3164  		ORDER BY
  3165  			Id
  3166  		LIMIT :Limit`,
  3167  		map[string]interface{}{"AfterId": afterId, "Limit": limit}); err != nil {
  3168  		return nil, errors.Wrap(err, "failed to find Channels for export")
  3169  	}
  3170  
  3171  	return channels, nil
  3172  }
  3173  
  3174  func (s SqlChannelStore) GetChannelMembersForExport(userId string, teamId string) ([]*model.ChannelMemberForExport, error) {
  3175  	var members []*model.ChannelMemberForExport
  3176  	_, err := s.GetReplica().Select(&members, `
  3177  		SELECT
  3178  			ChannelMembers.ChannelId,
  3179  			ChannelMembers.UserId,
  3180  			ChannelMembers.Roles,
  3181  			ChannelMembers.LastViewedAt,
  3182  			ChannelMembers.MsgCount,
  3183  			ChannelMembers.MentionCount,
  3184  			ChannelMembers.NotifyProps,
  3185  			ChannelMembers.LastUpdateAt,
  3186  			ChannelMembers.SchemeUser,
  3187  			ChannelMembers.SchemeAdmin,
  3188  			(ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) as SchemeGuest,
  3189  			Channels.Name as ChannelName
  3190  		FROM
  3191  			ChannelMembers
  3192  		INNER JOIN
  3193  			Channels ON ChannelMembers.ChannelId = Channels.Id
  3194  		WHERE
  3195  			ChannelMembers.UserId = :UserId
  3196  			AND Channels.TeamId = :TeamId
  3197  			AND Channels.DeleteAt = 0`,
  3198  		map[string]interface{}{"TeamId": teamId, "UserId": userId})
  3199  
  3200  	if err != nil {
  3201  		return nil, errors.Wrap(err, "failed to find Channels for export")
  3202  	}
  3203  
  3204  	return members, nil
  3205  }
  3206  
  3207  func (s SqlChannelStore) GetAllDirectChannelsForExportAfter(limit int, afterId string) ([]*model.DirectChannelForExport, error) {
  3208  	var directChannelsForExport []*model.DirectChannelForExport
  3209  	query := s.getQueryBuilder().
  3210  		Select("Channels.*").
  3211  		From("Channels").
  3212  		Where(sq.And{
  3213  			sq.Gt{"Channels.Id": afterId},
  3214  			sq.Eq{"Channels.DeleteAt": int(0)},
  3215  			sq.Eq{"Channels.Type": []string{"D", "G"}},
  3216  		}).
  3217  		OrderBy("Channels.Id").
  3218  		Limit(uint64(limit))
  3219  
  3220  	queryString, args, err := query.ToSql()
  3221  	if err != nil {
  3222  		return nil, errors.Wrap(err, "channel_tosql")
  3223  	}
  3224  
  3225  	if _, err = s.GetReplica().Select(&directChannelsForExport, queryString, args...); err != nil {
  3226  		return nil, errors.Wrap(err, "failed to find direct Channels for export")
  3227  	}
  3228  
  3229  	var channelIds []string
  3230  	for _, channel := range directChannelsForExport {
  3231  		channelIds = append(channelIds, channel.Id)
  3232  	}
  3233  	query = s.getQueryBuilder().
  3234  		Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest").
  3235  		From("ChannelMembers cm").
  3236  		Join("Users u ON ( u.Id = cm.UserId )").
  3237  		Where(sq.And{
  3238  			sq.Eq{"cm.ChannelId": channelIds},
  3239  			sq.Eq{"u.DeleteAt": int(0)},
  3240  		})
  3241  
  3242  	queryString, args, err = query.ToSql()
  3243  	if err != nil {
  3244  		return nil, errors.Wrap(err, "channel_tosql")
  3245  	}
  3246  
  3247  	var channelMembers []*model.ChannelMemberForExport
  3248  	if _, err := s.GetReplica().Select(&channelMembers, queryString, args...); err != nil {
  3249  		return nil, errors.Wrap(err, "failed to find ChannelMembers")
  3250  	}
  3251  
  3252  	// Populate each channel with its members
  3253  	dmChannelsMap := make(map[string]*model.DirectChannelForExport)
  3254  	for _, channel := range directChannelsForExport {
  3255  		channel.Members = &[]string{}
  3256  		dmChannelsMap[channel.Id] = channel
  3257  	}
  3258  	for _, member := range channelMembers {
  3259  		members := dmChannelsMap[member.ChannelId].Members
  3260  		*members = append(*members, member.Username)
  3261  	}
  3262  
  3263  	return directChannelsForExport, nil
  3264  }
  3265  
  3266  func (s SqlChannelStore) GetChannelsBatchForIndexing(startTime, endTime int64, limit int) ([]*model.Channel, error) {
  3267  	query :=
  3268  		`SELECT
  3269  			 *
  3270  		 FROM
  3271  			 Channels
  3272  		 WHERE
  3273  			 Type = 'O'
  3274  		 AND
  3275  			 CreateAt >= :StartTime
  3276  		 AND
  3277  			 CreateAt < :EndTime
  3278  		 ORDER BY
  3279  			 CreateAt
  3280  		 LIMIT
  3281  			 :NumChannels`
  3282  
  3283  	var channels []*model.Channel
  3284  	_, err := s.GetSearchReplica().Select(&channels, query, map[string]interface{}{"StartTime": startTime, "EndTime": endTime, "NumChannels": limit})
  3285  	if err != nil {
  3286  		return nil, errors.Wrap(err, "failed to find Channels")
  3287  	}
  3288  
  3289  	return channels, nil
  3290  }
  3291  
  3292  func (s SqlChannelStore) UserBelongsToChannels(userId string, channelIds []string) (bool, error) {
  3293  	query := s.getQueryBuilder().
  3294  		Select("Count(*)").
  3295  		From("ChannelMembers").
  3296  		Where(sq.And{
  3297  			sq.Eq{"UserId": userId},
  3298  			sq.Eq{"ChannelId": channelIds},
  3299  		})
  3300  
  3301  	queryString, args, err := query.ToSql()
  3302  	if err != nil {
  3303  		return false, errors.Wrap(err, "channel_tosql")
  3304  	}
  3305  	c, err := s.GetReplica().SelectInt(queryString, args...)
  3306  	if err != nil {
  3307  		return false, errors.Wrap(err, "failed to count ChannelMembers")
  3308  	}
  3309  	return c > 0, nil
  3310  }
  3311  
  3312  func (s SqlChannelStore) UpdateMembersRole(channelID string, userIDs []string) error {
  3313  	sql := fmt.Sprintf(`
  3314  		UPDATE
  3315  			ChannelMembers
  3316  		SET
  3317  			SchemeAdmin = CASE WHEN UserId IN ('%s') THEN
  3318  				TRUE
  3319  			ELSE
  3320  				FALSE
  3321  			END
  3322  		WHERE
  3323  			ChannelId = :ChannelId
  3324  			AND (SchemeGuest = false OR SchemeGuest IS NULL)
  3325  			`, strings.Join(userIDs, "', '"))
  3326  
  3327  	if _, err := s.GetMaster().Exec(sql, map[string]interface{}{"ChannelId": channelID}); err != nil {
  3328  		return errors.Wrap(err, "failed to update ChannelMembers")
  3329  	}
  3330  
  3331  	return nil
  3332  }
  3333  
  3334  func (s SqlChannelStore) GroupSyncedChannelCount() (int64, error) {
  3335  	query := s.getQueryBuilder().Select("COUNT(*)").From("Channels").Where(sq.Eq{"GroupConstrained": true, "DeleteAt": 0})
  3336  
  3337  	sql, args, err := query.ToSql()
  3338  	if err != nil {
  3339  		return 0, errors.Wrap(err, "channel_tosql")
  3340  	}
  3341  
  3342  	count, err := s.GetReplica().SelectInt(sql, args...)
  3343  	if err != nil {
  3344  		return 0, errors.Wrap(err, "failed to count Channels")
  3345  	}
  3346  
  3347  	return count, nil
  3348  }