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