github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/store/sqlstore/channel_store.go (about)

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