github.com/jfrerich/mattermost-server@v5.8.0-rc2+incompatible/store/sqlstore/channel_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"database/sql"
     8  	"fmt"
     9  	"net/http"
    10  	"sort"
    11  	"strconv"
    12  	"strings"
    13  
    14  	"github.com/mattermost/gorp"
    15  	"github.com/pkg/errors"
    16  
    17  	"github.com/mattermost/mattermost-server/einterfaces"
    18  	"github.com/mattermost/mattermost-server/mlog"
    19  	"github.com/mattermost/mattermost-server/model"
    20  	"github.com/mattermost/mattermost-server/store"
    21  	"github.com/mattermost/mattermost-server/utils"
    22  )
    23  
    24  const (
    25  	ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE = model.SESSION_CACHE_SIZE
    26  	ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SEC  = 900 // 15 mins
    27  
    28  	ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE = model.SESSION_CACHE_SIZE
    29  	ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SEC  = 1800 // 30 mins
    30  
    31  	CHANNEL_MEMBERS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
    32  	CHANNEL_MEMBERS_COUNTS_CACHE_SEC  = 1800 // 30 mins
    33  
    34  	CHANNEL_CACHE_SEC = 900 // 15 mins
    35  )
    36  
    37  type SqlChannelStore struct {
    38  	SqlStore
    39  	metrics einterfaces.MetricsInterface
    40  }
    41  
    42  type channelMember struct {
    43  	ChannelId    string
    44  	UserId       string
    45  	Roles        string
    46  	LastViewedAt int64
    47  	MsgCount     int64
    48  	MentionCount int64
    49  	NotifyProps  model.StringMap
    50  	LastUpdateAt int64
    51  	SchemeUser   sql.NullBool
    52  	SchemeAdmin  sql.NullBool
    53  }
    54  
    55  func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
    56  	return &channelMember{
    57  		ChannelId:    cm.ChannelId,
    58  		UserId:       cm.UserId,
    59  		Roles:        cm.ExplicitRoles,
    60  		LastViewedAt: cm.LastViewedAt,
    61  		MsgCount:     cm.MsgCount,
    62  		MentionCount: cm.MentionCount,
    63  		NotifyProps:  cm.NotifyProps,
    64  		LastUpdateAt: cm.LastUpdateAt,
    65  		SchemeUser:   sql.NullBool{Valid: true, Bool: cm.SchemeUser},
    66  		SchemeAdmin:  sql.NullBool{Valid: true, Bool: cm.SchemeAdmin},
    67  	}
    68  }
    69  
    70  type channelMemberWithSchemeRoles struct {
    71  	ChannelId                     string
    72  	UserId                        string
    73  	Roles                         string
    74  	LastViewedAt                  int64
    75  	MsgCount                      int64
    76  	MentionCount                  int64
    77  	NotifyProps                   model.StringMap
    78  	LastUpdateAt                  int64
    79  	SchemeUser                    sql.NullBool
    80  	SchemeAdmin                   sql.NullBool
    81  	TeamSchemeDefaultUserRole     sql.NullString
    82  	TeamSchemeDefaultAdminRole    sql.NullString
    83  	ChannelSchemeDefaultUserRole  sql.NullString
    84  	ChannelSchemeDefaultAdminRole sql.NullString
    85  }
    86  
    87  type channelMemberWithSchemeRolesList []channelMemberWithSchemeRoles
    88  
    89  func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
    90  	var roles []string
    91  	var explicitRoles []string
    92  
    93  	// Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated,
    94  	// and exclude them from ExplicitRoles field.
    95  	schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool
    96  	schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool
    97  	for _, role := range strings.Fields(db.Roles) {
    98  		isImplicit := false
    99  		if role == model.CHANNEL_USER_ROLE_ID {
   100  			// We have an implicit role via the system scheme. Override the "schemeUser" field to true.
   101  			schemeUser = true
   102  			isImplicit = true
   103  		} else if role == model.CHANNEL_ADMIN_ROLE_ID {
   104  			// We have an implicit role via the system scheme.
   105  			schemeAdmin = true
   106  			isImplicit = true
   107  		}
   108  
   109  		if !isImplicit {
   110  			explicitRoles = append(explicitRoles, role)
   111  		}
   112  		roles = append(roles, role)
   113  	}
   114  
   115  	// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
   116  	// them to the Roles field for backwards compatibility reasons.
   117  	var schemeImpliedRoles []string
   118  	if db.SchemeUser.Valid && db.SchemeUser.Bool {
   119  		if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" {
   120  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String)
   121  		} else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
   122  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
   123  		} else {
   124  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID)
   125  		}
   126  	}
   127  	if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
   128  		if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" {
   129  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String)
   130  		} else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
   131  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
   132  		} else {
   133  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID)
   134  		}
   135  	}
   136  	for _, impliedRole := range schemeImpliedRoles {
   137  		alreadyThere := false
   138  		for _, role := range roles {
   139  			if role == impliedRole {
   140  				alreadyThere = true
   141  			}
   142  		}
   143  		if !alreadyThere {
   144  			roles = append(roles, impliedRole)
   145  		}
   146  	}
   147  
   148  	return &model.ChannelMember{
   149  		ChannelId:     db.ChannelId,
   150  		UserId:        db.UserId,
   151  		Roles:         strings.Join(roles, " "),
   152  		LastViewedAt:  db.LastViewedAt,
   153  		MsgCount:      db.MsgCount,
   154  		MentionCount:  db.MentionCount,
   155  		NotifyProps:   db.NotifyProps,
   156  		LastUpdateAt:  db.LastUpdateAt,
   157  		SchemeAdmin:   schemeAdmin,
   158  		SchemeUser:    schemeUser,
   159  		ExplicitRoles: strings.Join(explicitRoles, " "),
   160  	}
   161  }
   162  
   163  func (db channelMemberWithSchemeRolesList) ToModel() *model.ChannelMembers {
   164  	cms := model.ChannelMembers{}
   165  
   166  	for _, cm := range db {
   167  		cms = append(cms, *cm.ToModel())
   168  	}
   169  
   170  	return &cms
   171  }
   172  
   173  type allChannelMember struct {
   174  	ChannelId                     string
   175  	Roles                         string
   176  	SchemeUser                    sql.NullBool
   177  	SchemeAdmin                   sql.NullBool
   178  	TeamSchemeDefaultUserRole     sql.NullString
   179  	TeamSchemeDefaultAdminRole    sql.NullString
   180  	ChannelSchemeDefaultUserRole  sql.NullString
   181  	ChannelSchemeDefaultAdminRole sql.NullString
   182  }
   183  
   184  type allChannelMembers []allChannelMember
   185  
   186  func (db allChannelMember) Process() (string, string) {
   187  	roles := strings.Fields(db.Roles)
   188  
   189  	// Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add
   190  	// them to the Roles field for backwards compatibility reasons.
   191  	var schemeImpliedRoles []string
   192  	if db.SchemeUser.Valid && db.SchemeUser.Bool {
   193  		if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" {
   194  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String)
   195  		} else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" {
   196  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String)
   197  		} else {
   198  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID)
   199  		}
   200  	}
   201  	if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool {
   202  		if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" {
   203  			schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String)
   204  		} else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" {
   205  			schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String)
   206  		} else {
   207  			schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID)
   208  		}
   209  	}
   210  	for _, impliedRole := range schemeImpliedRoles {
   211  		alreadyThere := false
   212  		for _, role := range roles {
   213  			if role == impliedRole {
   214  				alreadyThere = true
   215  			}
   216  		}
   217  		if !alreadyThere {
   218  			roles = append(roles, impliedRole)
   219  		}
   220  	}
   221  
   222  	return db.ChannelId, strings.Join(roles, " ")
   223  }
   224  
   225  func (db allChannelMembers) ToMapStringString() map[string]string {
   226  	result := make(map[string]string)
   227  
   228  	for _, item := range db {
   229  		key, value := item.Process()
   230  		result[key] = value
   231  	}
   232  
   233  	return result
   234  }
   235  
   236  // publicChannel is a subset of the metadata corresponding to public channels only.
   237  type publicChannel struct {
   238  	Id          string `json:"id"`
   239  	DeleteAt    int64  `json:"delete_at"`
   240  	TeamId      string `json:"team_id"`
   241  	DisplayName string `json:"display_name"`
   242  	Name        string `json:"name"`
   243  	Header      string `json:"header"`
   244  	Purpose     string `json:"purpose"`
   245  }
   246  
   247  var channelMemberCountsCache = utils.NewLru(CHANNEL_MEMBERS_COUNTS_CACHE_SIZE)
   248  var allChannelMembersForUserCache = utils.NewLru(ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE)
   249  var allChannelMembersNotifyPropsForChannelCache = utils.NewLru(ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE)
   250  var channelCache = utils.NewLru(model.CHANNEL_CACHE_SIZE)
   251  var channelByNameCache = utils.NewLru(model.CHANNEL_CACHE_SIZE)
   252  
   253  func (s SqlChannelStore) ClearCaches() {
   254  	channelMemberCountsCache.Purge()
   255  	allChannelMembersForUserCache.Purge()
   256  	allChannelMembersNotifyPropsForChannelCache.Purge()
   257  	channelCache.Purge()
   258  	channelByNameCache.Purge()
   259  
   260  	if s.metrics != nil {
   261  		s.metrics.IncrementMemCacheInvalidationCounter("Channel Member Counts - Purge")
   262  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Purge")
   263  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Purge")
   264  		s.metrics.IncrementMemCacheInvalidationCounter("Channel - Purge")
   265  		s.metrics.IncrementMemCacheInvalidationCounter("Channel By Name - Purge")
   266  	}
   267  }
   268  
   269  func NewSqlChannelStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.ChannelStore {
   270  	s := &SqlChannelStore{
   271  		SqlStore: sqlStore,
   272  		metrics:  metrics,
   273  	}
   274  
   275  	for _, db := range sqlStore.GetAllConns() {
   276  		table := db.AddTableWithName(model.Channel{}, "Channels").SetKeys(false, "Id")
   277  		table.ColMap("Id").SetMaxSize(26)
   278  		table.ColMap("TeamId").SetMaxSize(26)
   279  		table.ColMap("Type").SetMaxSize(1)
   280  		table.ColMap("DisplayName").SetMaxSize(64)
   281  		table.ColMap("Name").SetMaxSize(64)
   282  		table.SetUniqueTogether("Name", "TeamId")
   283  		table.ColMap("Header").SetMaxSize(1024)
   284  		table.ColMap("Purpose").SetMaxSize(250)
   285  		table.ColMap("CreatorId").SetMaxSize(26)
   286  		table.ColMap("SchemeId").SetMaxSize(26)
   287  
   288  		tablem := db.AddTableWithName(channelMember{}, "ChannelMembers").SetKeys(false, "ChannelId", "UserId")
   289  		tablem.ColMap("ChannelId").SetMaxSize(26)
   290  		tablem.ColMap("UserId").SetMaxSize(26)
   291  		tablem.ColMap("Roles").SetMaxSize(64)
   292  		tablem.ColMap("NotifyProps").SetMaxSize(2000)
   293  
   294  		tablePublicChannels := db.AddTableWithName(publicChannel{}, "PublicChannels").SetKeys(false, "Id")
   295  		tablePublicChannels.ColMap("Id").SetMaxSize(26)
   296  		tablePublicChannels.ColMap("TeamId").SetMaxSize(26)
   297  		tablePublicChannels.ColMap("DisplayName").SetMaxSize(64)
   298  		tablePublicChannels.ColMap("Name").SetMaxSize(64)
   299  		tablePublicChannels.SetUniqueTogether("Name", "TeamId")
   300  		tablePublicChannels.ColMap("Header").SetMaxSize(1024)
   301  		tablePublicChannels.ColMap("Purpose").SetMaxSize(250)
   302  	}
   303  
   304  	return s
   305  }
   306  
   307  func (s SqlChannelStore) CreateIndexesIfNotExists() {
   308  	s.CreateIndexIfNotExists("idx_channels_team_id", "Channels", "TeamId")
   309  	s.CreateIndexIfNotExists("idx_channels_name", "Channels", "Name")
   310  	s.CreateIndexIfNotExists("idx_channels_update_at", "Channels", "UpdateAt")
   311  	s.CreateIndexIfNotExists("idx_channels_create_at", "Channels", "CreateAt")
   312  	s.CreateIndexIfNotExists("idx_channels_delete_at", "Channels", "DeleteAt")
   313  
   314  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   315  		s.CreateIndexIfNotExists("idx_channels_name_lower", "Channels", "lower(Name)")
   316  		s.CreateIndexIfNotExists("idx_channels_displayname_lower", "Channels", "lower(DisplayName)")
   317  	}
   318  
   319  	s.CreateIndexIfNotExists("idx_channelmembers_channel_id", "ChannelMembers", "ChannelId")
   320  	s.CreateIndexIfNotExists("idx_channelmembers_user_id", "ChannelMembers", "UserId")
   321  
   322  	s.CreateFullTextIndexIfNotExists("idx_channel_search_txt", "Channels", "Name, DisplayName, Purpose")
   323  
   324  	s.CreateIndexIfNotExists("idx_publicchannels_team_id", "PublicChannels", "TeamId")
   325  	s.CreateIndexIfNotExists("idx_publicchannels_name", "PublicChannels", "Name")
   326  	s.CreateIndexIfNotExists("idx_publicchannels_delete_at", "PublicChannels", "DeleteAt")
   327  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   328  		s.CreateIndexIfNotExists("idx_publicchannels_name_lower", "PublicChannels", "lower(Name)")
   329  		s.CreateIndexIfNotExists("idx_publicchannels_displayname_lower", "PublicChannels", "lower(DisplayName)")
   330  	}
   331  	s.CreateFullTextIndexIfNotExists("idx_publicchannels_search_txt", "PublicChannels", "Name, DisplayName, Purpose")
   332  }
   333  
   334  // MigratePublicChannels initializes the PublicChannels table with data created before this version
   335  // of the Mattermost server kept it up-to-date.
   336  func (s SqlChannelStore) MigratePublicChannels() error {
   337  	transaction, err := s.GetMaster().Begin()
   338  	if err != nil {
   339  		return err
   340  	}
   341  
   342  	if _, err := transaction.Exec(`
   343  		INSERT INTO PublicChannels
   344  		    (Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
   345  		SELECT
   346  		    c.Id, c.DeleteAt, c.TeamId, c.DisplayName, c.Name, c.Header, c.Purpose
   347  		FROM
   348  		    Channels c
   349  		LEFT JOIN
   350  		    PublicChannels pc ON (pc.Id = c.Id)
   351  		WHERE
   352  		    c.Type = 'O'
   353  		AND pc.Id IS NULL
   354  	`); err != nil {
   355  		return err
   356  	}
   357  
   358  	if err := transaction.Commit(); err != nil {
   359  		return err
   360  	}
   361  
   362  	return nil
   363  }
   364  
   365  func (s SqlChannelStore) upsertPublicChannelT(transaction *gorp.Transaction, channel *model.Channel) error {
   366  	publicChannel := &publicChannel{
   367  		Id:          channel.Id,
   368  		DeleteAt:    channel.DeleteAt,
   369  		TeamId:      channel.TeamId,
   370  		DisplayName: channel.DisplayName,
   371  		Name:        channel.Name,
   372  		Header:      channel.Header,
   373  		Purpose:     channel.Purpose,
   374  	}
   375  
   376  	if channel.Type != model.CHANNEL_OPEN {
   377  		if _, err := transaction.Delete(publicChannel); err != nil {
   378  			return errors.Wrap(err, "failed to delete public channel")
   379  		}
   380  
   381  		return nil
   382  	}
   383  
   384  	if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
   385  		// Leverage native upsert for MySQL, since RowsAffected returns 0 if the row exists
   386  		// but no changes were made, breaking the update-then-insert paradigm below when
   387  		// the row already exists. (Postgres 9.4 doesn't support native upsert.)
   388  		if _, err := transaction.Exec(`
   389  			INSERT INTO
   390  			    PublicChannels(Id, DeleteAt, TeamId, DisplayName, Name, Header, Purpose)
   391  			VALUES
   392  			    (:Id, :DeleteAt, :TeamId, :DisplayName, :Name, :Header, :Purpose)
   393  			ON DUPLICATE KEY UPDATE
   394  			    DeleteAt = :DeleteAt,
   395  			    TeamId = :TeamId,
   396  			    DisplayName = :DisplayName,
   397  			    Name = :Name,
   398  			    Header = :Header,
   399  			    Purpose = :Purpose;
   400  		`, map[string]interface{}{
   401  			"Id":          publicChannel.Id,
   402  			"DeleteAt":    publicChannel.DeleteAt,
   403  			"TeamId":      publicChannel.TeamId,
   404  			"DisplayName": publicChannel.DisplayName,
   405  			"Name":        publicChannel.Name,
   406  			"Header":      publicChannel.Header,
   407  			"Purpose":     publicChannel.Purpose,
   408  		}); err != nil {
   409  			return errors.Wrap(err, "failed to insert public channel")
   410  		}
   411  	} else {
   412  		count, err := transaction.Update(publicChannel)
   413  		if err != nil {
   414  			return errors.Wrap(err, "failed to update public channel")
   415  		}
   416  		if count > 0 {
   417  			return nil
   418  		}
   419  
   420  		if err := transaction.Insert(publicChannel); err != nil {
   421  			return errors.Wrap(err, "failed to insert public channel")
   422  		}
   423  	}
   424  
   425  	return nil
   426  }
   427  
   428  // Save writes the (non-direct) channel channel to the database.
   429  func (s SqlChannelStore) Save(channel *model.Channel, maxChannelsPerTeam int64) store.StoreChannel {
   430  	return store.Do(func(result *store.StoreResult) {
   431  		if channel.DeleteAt != 0 {
   432  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
   433  			return
   434  		}
   435  
   436  		if channel.Type == model.CHANNEL_DIRECT {
   437  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest)
   438  			return
   439  		}
   440  
   441  		transaction, err := s.GetMaster().Begin()
   442  		if err != nil {
   443  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   444  			return
   445  		}
   446  
   447  		*result = s.saveChannelT(transaction, channel, maxChannelsPerTeam)
   448  		if result.Err != nil {
   449  			transaction.Rollback()
   450  			return
   451  		}
   452  
   453  		// Additionally propagate the write to the PublicChannels table.
   454  		if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
   455  			transaction.Rollback()
   456  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
   457  			return
   458  		}
   459  
   460  		if err := transaction.Commit(); err != nil {
   461  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   462  			return
   463  		}
   464  	})
   465  }
   466  
   467  func (s SqlChannelStore) CreateDirectChannel(userId string, otherUserId string) store.StoreChannel {
   468  	channel := new(model.Channel)
   469  
   470  	channel.DisplayName = ""
   471  	channel.Name = model.GetDMNameFromIds(otherUserId, userId)
   472  
   473  	channel.Header = ""
   474  	channel.Type = model.CHANNEL_DIRECT
   475  
   476  	cm1 := &model.ChannelMember{
   477  		UserId:      userId,
   478  		NotifyProps: model.GetDefaultChannelNotifyProps(),
   479  		SchemeUser:  true,
   480  	}
   481  	cm2 := &model.ChannelMember{
   482  		UserId:      otherUserId,
   483  		NotifyProps: model.GetDefaultChannelNotifyProps(),
   484  		SchemeUser:  true,
   485  	}
   486  
   487  	return s.SaveDirectChannel(channel, cm1, cm2)
   488  }
   489  
   490  func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) store.StoreChannel {
   491  	return store.Do(func(result *store.StoreResult) {
   492  		if directchannel.DeleteAt != 0 {
   493  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest)
   494  			return
   495  		}
   496  
   497  		if directchannel.Type != model.CHANNEL_DIRECT {
   498  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest)
   499  			return
   500  		}
   501  
   502  		transaction, err := s.GetMaster().Begin()
   503  		if err != nil {
   504  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   505  			return
   506  		}
   507  
   508  		directchannel.TeamId = ""
   509  		channelResult := s.saveChannelT(transaction, directchannel, 0)
   510  
   511  		if channelResult.Err != nil {
   512  			transaction.Rollback()
   513  			result.Err = channelResult.Err
   514  			result.Data = channelResult.Data
   515  			return
   516  		}
   517  
   518  		newChannel := channelResult.Data.(*model.Channel)
   519  		// Members need new channel ID
   520  		member1.ChannelId = newChannel.Id
   521  		member2.ChannelId = newChannel.Id
   522  
   523  		member1Result := s.saveMemberT(transaction, member1, newChannel)
   524  		member2Result := member1Result
   525  		if member1.UserId != member2.UserId {
   526  			member2Result = s.saveMemberT(transaction, member2, newChannel)
   527  		}
   528  
   529  		if member1Result.Err != nil || member2Result.Err != nil {
   530  			transaction.Rollback()
   531  			details := ""
   532  			if member1Result.Err != nil {
   533  				details += "Member1Err: " + member1Result.Err.Message
   534  			}
   535  			if member2Result.Err != nil {
   536  				details += "Member2Err: " + member2Result.Err.Message
   537  			}
   538  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.add_members.app_error", nil, details, http.StatusInternalServerError)
   539  			return
   540  		}
   541  
   542  		if err := transaction.Commit(); err != nil {
   543  			result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.commit.app_error", nil, err.Error(), http.StatusInternalServerError)
   544  			return
   545  		}
   546  
   547  		*result = channelResult
   548  	})
   549  }
   550  
   551  func (s SqlChannelStore) saveChannelT(transaction *gorp.Transaction, channel *model.Channel, maxChannelsPerTeam int64) store.StoreResult {
   552  	result := store.StoreResult{}
   553  
   554  	if len(channel.Id) > 0 {
   555  		result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.existing.app_error", nil, "id="+channel.Id, http.StatusBadRequest)
   556  		return result
   557  	}
   558  
   559  	channel.PreSave()
   560  	if result.Err = channel.IsValid(); result.Err != nil {
   561  		return result
   562  	}
   563  
   564  	if channel.Type != model.CHANNEL_DIRECT && channel.Type != model.CHANNEL_GROUP && maxChannelsPerTeam >= 0 {
   565  		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 {
   566  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.current_count.app_error", nil, "teamId="+channel.TeamId+", "+err.Error(), http.StatusInternalServerError)
   567  			return result
   568  		} else if count >= maxChannelsPerTeam {
   569  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.limit.app_error", nil, "teamId="+channel.TeamId, http.StatusBadRequest)
   570  			return result
   571  		}
   572  	}
   573  
   574  	if err := transaction.Insert(channel); err != nil {
   575  		if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) {
   576  			dupChannel := model.Channel{}
   577  			s.GetMaster().SelectOne(&dupChannel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name = :Name", map[string]interface{}{"TeamId": channel.TeamId, "Name": channel.Name})
   578  			if dupChannel.DeleteAt > 0 {
   579  				result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.previously.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   580  			} else {
   581  				result.Err = model.NewAppError("SqlChannelStore.Save", store.CHANNEL_EXISTS_ERROR, nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   582  				result.Data = &dupChannel
   583  			}
   584  		} else {
   585  			result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.save.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusInternalServerError)
   586  		}
   587  	} else {
   588  		result.Data = channel
   589  	}
   590  
   591  	return result
   592  }
   593  
   594  // Update writes the updated channel to the database.
   595  func (s SqlChannelStore) Update(channel *model.Channel) store.StoreChannel {
   596  	return store.Do(func(result *store.StoreResult) {
   597  		transaction, err := s.GetMaster().Begin()
   598  		if err != nil {
   599  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   600  			return
   601  		}
   602  
   603  		*result = s.updateChannelT(transaction, channel)
   604  		if result.Err != nil {
   605  			transaction.Rollback()
   606  			return
   607  		}
   608  
   609  		// Additionally propagate the write to the PublicChannels table.
   610  		if err := s.upsertPublicChannelT(transaction, result.Data.(*model.Channel)); err != nil {
   611  			transaction.Rollback()
   612  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.upsert_public_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
   613  			return
   614  		}
   615  
   616  		if err := transaction.Commit(); err != nil {
   617  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   618  			return
   619  		}
   620  	})
   621  
   622  }
   623  
   624  func (s SqlChannelStore) updateChannelT(transaction *gorp.Transaction, channel *model.Channel) store.StoreResult {
   625  	result := store.StoreResult{}
   626  
   627  	channel.PreUpdate()
   628  
   629  	if channel.DeleteAt != 0 {
   630  		result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.archived_channel.app_error", nil, "", http.StatusBadRequest)
   631  		return result
   632  	}
   633  
   634  	if result.Err = channel.IsValid(); result.Err != nil {
   635  		return result
   636  	}
   637  
   638  	count, err := transaction.Update(channel)
   639  	if err != nil {
   640  		if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) {
   641  			dupChannel := model.Channel{}
   642  			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})
   643  			if dupChannel.DeleteAt > 0 {
   644  				result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.previously.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   645  				return result
   646  			}
   647  			result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.exists.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest)
   648  			return result
   649  		}
   650  		result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.updating.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusInternalServerError)
   651  		return result
   652  	}
   653  
   654  	if count != 1 {
   655  		result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.app_error", nil, "id="+channel.Id, http.StatusInternalServerError)
   656  		return result
   657  	}
   658  
   659  	result.Data = channel
   660  
   661  	return result
   662  }
   663  
   664  func (s SqlChannelStore) GetChannelUnread(channelId, userId string) store.StoreChannel {
   665  	return store.Do(func(result *store.StoreResult) {
   666  		var unreadChannel model.ChannelUnread
   667  		err := s.GetReplica().SelectOne(&unreadChannel,
   668  			`SELECT
   669  				Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
   670  			FROM
   671  				Channels, ChannelMembers
   672  			WHERE
   673  				Id = ChannelId
   674                  AND Id = :ChannelId
   675                  AND UserId = :UserId
   676                  AND DeleteAt = 0`,
   677  			map[string]interface{}{"ChannelId": channelId, "UserId": userId})
   678  
   679  		if err != nil {
   680  			result.Err = model.NewAppError("SqlChannelStore.GetChannelUnread", "store.sql_channel.get_unread.app_error", nil, "channelId="+channelId+" "+err.Error(), http.StatusInternalServerError)
   681  			if err == sql.ErrNoRows {
   682  				result.Err.StatusCode = http.StatusNotFound
   683  			}
   684  		} else {
   685  			result.Data = &unreadChannel
   686  		}
   687  	})
   688  }
   689  
   690  func (s SqlChannelStore) InvalidateChannel(id string) {
   691  	channelCache.Remove(id)
   692  	if s.metrics != nil {
   693  		s.metrics.IncrementMemCacheInvalidationCounter("Channel - Remove by ChannelId")
   694  	}
   695  }
   696  
   697  func (s SqlChannelStore) InvalidateChannelByName(teamId, name string) {
   698  	channelByNameCache.Remove(teamId + name)
   699  	if s.metrics != nil {
   700  		s.metrics.IncrementMemCacheInvalidationCounter("Channel by Name - Remove by TeamId and Name")
   701  	}
   702  }
   703  
   704  func (s SqlChannelStore) Get(id string, allowFromCache bool) store.StoreChannel {
   705  	return s.get(id, false, allowFromCache)
   706  }
   707  
   708  func (s SqlChannelStore) GetPinnedPosts(channelId string) store.StoreChannel {
   709  	return store.Do(func(result *store.StoreResult) {
   710  		pl := model.NewPostList()
   711  
   712  		var posts []*model.Post
   713  		if _, err := s.GetReplica().Select(&posts, "SELECT * FROM Posts WHERE IsPinned = true AND ChannelId = :ChannelId AND DeleteAt = 0 ORDER BY CreateAt ASC", map[string]interface{}{"ChannelId": channelId}); err != nil {
   714  			result.Err = model.NewAppError("SqlPostStore.GetPinnedPosts", "store.sql_channel.pinned_posts.app_error", nil, err.Error(), http.StatusInternalServerError)
   715  		} else {
   716  			for _, post := range posts {
   717  				pl.AddPost(post)
   718  				pl.AddOrder(post.Id)
   719  			}
   720  		}
   721  
   722  		result.Data = pl
   723  	})
   724  }
   725  
   726  func (s SqlChannelStore) GetFromMaster(id string) store.StoreChannel {
   727  	return s.get(id, true, false)
   728  }
   729  
   730  func (s SqlChannelStore) get(id string, master bool, allowFromCache bool) store.StoreChannel {
   731  	return store.Do(func(result *store.StoreResult) {
   732  		var db *gorp.DbMap
   733  		if master {
   734  			db = s.GetMaster()
   735  		} else {
   736  			db = s.GetReplica()
   737  		}
   738  
   739  		if allowFromCache {
   740  			if cacheItem, ok := channelCache.Get(id); ok {
   741  				if s.metrics != nil {
   742  					s.metrics.IncrementMemCacheHitCounter("Channel")
   743  				}
   744  				result.Data = (cacheItem.(*model.Channel)).DeepCopy()
   745  				return
   746  			}
   747  		}
   748  
   749  		if s.metrics != nil {
   750  			s.metrics.IncrementMemCacheMissCounter("Channel")
   751  		}
   752  
   753  		obj, err := db.Get(model.Channel{}, id)
   754  		if err != nil {
   755  			result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.find.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError)
   756  			return
   757  		}
   758  
   759  		if obj == nil {
   760  			result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.existing.app_error", nil, "id="+id, http.StatusNotFound)
   761  			return
   762  		}
   763  
   764  		result.Data = obj.(*model.Channel)
   765  		channelCache.AddWithExpiresInSecs(id, obj.(*model.Channel), CHANNEL_CACHE_SEC)
   766  	})
   767  }
   768  
   769  // Delete records the given deleted timestamp to the channel in question.
   770  func (s SqlChannelStore) Delete(channelId string, time int64) store.StoreChannel {
   771  	return s.SetDeleteAt(channelId, time, time)
   772  }
   773  
   774  // Restore reverts a previous deleted timestamp from the channel in question.
   775  func (s SqlChannelStore) Restore(channelId string, time int64) store.StoreChannel {
   776  	return s.SetDeleteAt(channelId, 0, time)
   777  }
   778  
   779  // SetDeleteAt records the given deleted and updated timestamp to the channel in question.
   780  func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt, updateAt int64) store.StoreChannel {
   781  	return store.Do(func(result *store.StoreResult) {
   782  		defer s.InvalidateChannel(channelId)
   783  
   784  		transaction, err := s.GetMaster().Begin()
   785  		if err != nil {
   786  			result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   787  			return
   788  		}
   789  
   790  		*result = s.setDeleteAtT(transaction, channelId, deleteAt, updateAt)
   791  		if result.Err != nil {
   792  			transaction.Rollback()
   793  			return
   794  		}
   795  
   796  		// Additionally propagate the write to the PublicChannels table.
   797  		if _, err := transaction.Exec(`
   798  			UPDATE
   799  			    PublicChannels 
   800  			SET 
   801  			    DeleteAt = :DeleteAt
   802  			WHERE 
   803  			    Id = :ChannelId
   804  		`, map[string]interface{}{
   805  			"DeleteAt":  deleteAt,
   806  			"ChannelId": channelId,
   807  		}); err != nil {
   808  			transaction.Rollback()
   809  			result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.update_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
   810  			return
   811  		}
   812  
   813  		if err := transaction.Commit(); err != nil {
   814  			result.Err = model.NewAppError("SqlChannelStore.SetDeleteAt", "store.sql_channel.set_delete_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   815  			return
   816  		}
   817  	})
   818  }
   819  
   820  func (s SqlChannelStore) setDeleteAtT(transaction *gorp.Transaction, channelId string, deleteAt, updateAt int64) store.StoreResult {
   821  	result := store.StoreResult{}
   822  
   823  	_, err := transaction.Exec("Update Channels SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :ChannelId", map[string]interface{}{"DeleteAt": deleteAt, "UpdateAt": updateAt, "ChannelId": channelId})
   824  	if err != nil {
   825  		result.Err = model.NewAppError("SqlChannelStore.Delete", "store.sql_channel.delete.channel.app_error", nil, "id="+channelId+", err="+err.Error(), http.StatusInternalServerError)
   826  		return result
   827  	}
   828  
   829  	return result
   830  }
   831  
   832  // PermanentDeleteByTeam removes all channels for the given team from the database.
   833  func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) store.StoreChannel {
   834  	return store.Do(func(result *store.StoreResult) {
   835  		transaction, err := s.GetMaster().Begin()
   836  		if err != nil {
   837  			result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   838  			return
   839  		}
   840  
   841  		*result = s.permanentDeleteByTeamtT(transaction, teamId)
   842  		if result.Err != nil {
   843  			transaction.Rollback()
   844  			return
   845  		}
   846  
   847  		// Additionally propagate the deletions to the PublicChannels table.
   848  		if _, err := transaction.Exec(`
   849  			DELETE FROM
   850  			    PublicChannels 
   851  			WHERE
   852  			    TeamId = :TeamId
   853  		`, map[string]interface{}{
   854  			"TeamId": teamId,
   855  		}); err != nil {
   856  			transaction.Rollback()
   857  			result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeamt", "store.sql_channel.permanent_delete_by_team.delete_public_channels.app_error", nil, "team_id="+teamId+", "+err.Error(), http.StatusInternalServerError)
   858  			return
   859  		}
   860  
   861  		if err := transaction.Commit(); err != nil {
   862  			result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   863  			return
   864  		}
   865  	})
   866  }
   867  
   868  func (s SqlChannelStore) permanentDeleteByTeamtT(transaction *gorp.Transaction, teamId string) store.StoreResult {
   869  	result := store.StoreResult{}
   870  
   871  	if _, err := transaction.Exec("DELETE FROM Channels WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil {
   872  		result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError)
   873  		return result
   874  	}
   875  
   876  	return result
   877  }
   878  
   879  // PermanentDelete removes the given channel from the database.
   880  func (s SqlChannelStore) PermanentDelete(channelId string) store.StoreChannel {
   881  	return store.Do(func(result *store.StoreResult) {
   882  		transaction, err := s.GetMaster().Begin()
   883  		if err != nil {
   884  			result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   885  			return
   886  		}
   887  
   888  		*result = s.permanentDeleteT(transaction, channelId)
   889  		if result.Err != nil {
   890  			transaction.Rollback()
   891  			return
   892  		}
   893  
   894  		// Additionally propagate the deletion to the PublicChannels table.
   895  		if _, err := transaction.Exec(`
   896  			DELETE FROM
   897  			    PublicChannels 
   898  			WHERE
   899  			    Id = :ChannelId
   900  		`, map[string]interface{}{
   901  			"ChannelId": channelId,
   902  		}); err != nil {
   903  			transaction.Rollback()
   904  			result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.delete_public_channel.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
   905  			return
   906  		}
   907  
   908  		if err := transaction.Commit(); err != nil {
   909  			result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
   910  			return
   911  		}
   912  	})
   913  }
   914  
   915  func (s SqlChannelStore) permanentDeleteT(transaction *gorp.Transaction, channelId string) store.StoreResult {
   916  	result := store.StoreResult{}
   917  
   918  	if _, err := transaction.Exec("DELETE FROM Channels WHERE Id = :ChannelId", map[string]interface{}{"ChannelId": channelId}); err != nil {
   919  		result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
   920  		return result
   921  	}
   922  
   923  	return result
   924  }
   925  
   926  func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) store.StoreChannel {
   927  	return store.Do(func(result *store.StoreResult) {
   928  		_, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelId})
   929  		if err != nil {
   930  			result.Err = model.NewAppError("SqlChannelStore.RemoveAllMembersByChannel", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
   931  		}
   932  	})
   933  }
   934  
   935  func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool) store.StoreChannel {
   936  	return store.Do(func(result *store.StoreResult) {
   937  		query := "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND DeleteAt = 0 AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName"
   938  		if includeDeleted {
   939  			query = "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName"
   940  		}
   941  		data := &model.ChannelList{}
   942  		_, err := s.GetReplica().Select(data, query, map[string]interface{}{"TeamId": teamId, "UserId": userId})
   943  
   944  		if err != nil {
   945  			result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
   946  			return
   947  		}
   948  
   949  		if len(*data) == 0 {
   950  			result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.not_found.app_error", nil, "teamId="+teamId+", userId="+userId, http.StatusBadRequest)
   951  			return
   952  		}
   953  
   954  		result.Data = data
   955  	})
   956  }
   957  
   958  func (s SqlChannelStore) GetAllChannels(offset int, limit int, includeDeleted bool) store.StoreChannel {
   959  	return store.Do(func(result *store.StoreResult) {
   960  		deleteFilter := "AND c.DeleteAt = 0"
   961  		if includeDeleted {
   962  			deleteFilter = ""
   963  		}
   964  
   965  		query := "SELECT c.*, Teams.DisplayName AS TeamDisplayName, Teams.Name AS TeamName, Teams.UpdateAt as TeamUpdateAt FROM Channels AS c JOIN Teams ON Teams.Id = c.TeamId WHERE (c.Type = 'P' OR c.Type = 'O') " + deleteFilter + " ORDER BY c.DisplayName, Teams.DisplayName LIMIT :Limit OFFSET :Offset"
   966  
   967  		data := &model.ChannelListWithTeamData{}
   968  		_, err := s.GetReplica().Select(data, query, map[string]interface{}{"Limit": limit, "Offset": offset})
   969  
   970  		if err != nil {
   971  			result.Err = model.NewAppError("SqlChannelStore.GetAllChannels", "store.sql_channel.get_all_channels.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   972  			return
   973  		}
   974  
   975  		result.Data = data
   976  	})
   977  }
   978  
   979  func (s SqlChannelStore) GetMoreChannels(teamId string, userId string, offset int, limit int) store.StoreChannel {
   980  	return store.Do(func(result *store.StoreResult) {
   981  		data := &model.ChannelList{}
   982  		_, err := s.GetReplica().Select(data, `
   983  			SELECT
   984  			    Channels.*
   985  			FROM
   986  			    Channels
   987  			JOIN
   988  			    PublicChannels c ON (c.Id = Channels.Id)
   989  			WHERE
   990  			    c.TeamId = :TeamId
   991  			AND c.DeleteAt = 0
   992  			AND c.Id NOT IN (
   993  			    SELECT
   994  			        c.Id
   995  			    FROM
   996  			        PublicChannels c
   997  			    JOIN
   998  			        ChannelMembers cm ON (cm.ChannelId = c.Id)
   999  			    WHERE
  1000  			        c.TeamId = :TeamId
  1001  			    AND cm.UserId = :UserId
  1002  			    AND c.DeleteAt = 0
  1003  			)
  1004  			ORDER BY
  1005  				c.DisplayName
  1006  			LIMIT :Limit
  1007  			OFFSET :Offset
  1008  		`, map[string]interface{}{
  1009  			"TeamId": teamId,
  1010  			"UserId": userId,
  1011  			"Limit":  limit,
  1012  			"Offset": offset,
  1013  		})
  1014  
  1015  		if err != nil {
  1016  			result.Err = model.NewAppError("SqlChannelStore.GetMoreChannels", "store.sql_channel.get_more_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1017  			return
  1018  		}
  1019  
  1020  		result.Data = data
  1021  	})
  1022  }
  1023  
  1024  func (s SqlChannelStore) GetPublicChannelsForTeam(teamId string, offset int, limit int) store.StoreChannel {
  1025  	return store.Do(func(result *store.StoreResult) {
  1026  		data := &model.ChannelList{}
  1027  		_, err := s.GetReplica().Select(data, `
  1028  			SELECT
  1029  			    Channels.*
  1030  			FROM
  1031  			    Channels
  1032  			JOIN
  1033  			    PublicChannels pc ON (pc.Id = Channels.Id)
  1034  			WHERE
  1035  			    pc.TeamId = :TeamId
  1036  			AND pc.DeleteAt = 0
  1037  			ORDER BY pc.DisplayName
  1038  			LIMIT :Limit
  1039  			OFFSET :Offset
  1040  		`, map[string]interface{}{
  1041  			"TeamId": teamId,
  1042  			"Limit":  limit,
  1043  			"Offset": offset,
  1044  		})
  1045  
  1046  		if err != nil {
  1047  			result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsForTeam", "store.sql_channel.get_public_channels.get.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError)
  1048  			return
  1049  		}
  1050  
  1051  		result.Data = data
  1052  	})
  1053  }
  1054  
  1055  func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) store.StoreChannel {
  1056  	return store.Do(func(result *store.StoreResult) {
  1057  		props := make(map[string]interface{})
  1058  		props["teamId"] = teamId
  1059  
  1060  		idQuery := ""
  1061  
  1062  		for index, channelId := range channelIds {
  1063  			if len(idQuery) > 0 {
  1064  				idQuery += ", "
  1065  			}
  1066  
  1067  			props["channelId"+strconv.Itoa(index)] = channelId
  1068  			idQuery += ":channelId" + strconv.Itoa(index)
  1069  		}
  1070  
  1071  		data := &model.ChannelList{}
  1072  		_, err := s.GetReplica().Select(data, `
  1073  			SELECT
  1074  			    Channels.*
  1075  			FROM
  1076  			    Channels
  1077  			JOIN
  1078  			    PublicChannels pc ON (pc.Id = Channels.Id)
  1079  			WHERE
  1080  			    pc.TeamId = :teamId
  1081  			AND pc.DeleteAt = 0
  1082  			AND pc.Id IN (`+idQuery+`)
  1083  			ORDER BY pc.DisplayName
  1084  		`, props)
  1085  
  1086  		if err != nil {
  1087  			result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.get.app_error", nil, err.Error(), http.StatusInternalServerError)
  1088  		}
  1089  
  1090  		if len(*data) == 0 {
  1091  			result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.not_found.app_error", nil, "", http.StatusNotFound)
  1092  		}
  1093  
  1094  		result.Data = data
  1095  	})
  1096  }
  1097  
  1098  type channelIdWithCountAndUpdateAt struct {
  1099  	Id            string
  1100  	TotalMsgCount int64
  1101  	UpdateAt      int64
  1102  }
  1103  
  1104  func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) store.StoreChannel {
  1105  	return store.Do(func(result *store.StoreResult) {
  1106  		var data []channelIdWithCountAndUpdateAt
  1107  		_, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND (TeamId = :TeamId OR TeamId = '') AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
  1108  
  1109  		if err != nil {
  1110  			result.Err = model.NewAppError("SqlChannelStore.GetChannelCounts", "store.sql_channel.get_channel_counts.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1111  			return
  1112  		}
  1113  
  1114  		counts := &model.ChannelCounts{Counts: make(map[string]int64), UpdateTimes: make(map[string]int64)}
  1115  		for i := range data {
  1116  			v := data[i]
  1117  			counts.Counts[v.Id] = v.TotalMsgCount
  1118  			counts.UpdateTimes[v.Id] = v.UpdateAt
  1119  		}
  1120  
  1121  		result.Data = counts
  1122  	})
  1123  }
  1124  
  1125  func (s SqlChannelStore) GetTeamChannels(teamId string) store.StoreChannel {
  1126  	return store.Do(func(result *store.StoreResult) {
  1127  		data := &model.ChannelList{}
  1128  		_, err := s.GetReplica().Select(data, "SELECT * FROM Channels WHERE TeamId = :TeamId And Type != 'D' ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId})
  1129  
  1130  		if err != nil {
  1131  			result.Err = model.NewAppError("SqlChannelStore.GetTeamChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+",  err="+err.Error(), http.StatusInternalServerError)
  1132  			return
  1133  		}
  1134  
  1135  		if len(*data) == 0 {
  1136  			result.Err = model.NewAppError("SqlChannelStore.GetTeamChannels", "store.sql_channel.get_channels.not_found.app_error", nil, "teamId="+teamId, http.StatusNotFound)
  1137  			return
  1138  		}
  1139  
  1140  		result.Data = data
  1141  	})
  1142  }
  1143  
  1144  func (s SqlChannelStore) GetByName(teamId string, name string, allowFromCache bool) store.StoreChannel {
  1145  	return s.getByName(teamId, name, false, allowFromCache)
  1146  }
  1147  
  1148  func (s SqlChannelStore) GetByNames(teamId string, names []string, allowFromCache bool) store.StoreChannel {
  1149  	return store.Do(func(result *store.StoreResult) {
  1150  		var channels []*model.Channel
  1151  
  1152  		if allowFromCache {
  1153  			var misses []string
  1154  			visited := make(map[string]struct{})
  1155  			for _, name := range names {
  1156  				if _, ok := visited[name]; ok {
  1157  					continue
  1158  				}
  1159  				visited[name] = struct{}{}
  1160  				if cacheItem, ok := channelByNameCache.Get(teamId + name); ok {
  1161  					if s.metrics != nil {
  1162  						s.metrics.IncrementMemCacheHitCounter("Channel By Name")
  1163  					}
  1164  					channels = append(channels, cacheItem.(*model.Channel))
  1165  				} else {
  1166  					if s.metrics != nil {
  1167  						s.metrics.IncrementMemCacheMissCounter("Channel By Name")
  1168  					}
  1169  					misses = append(misses, name)
  1170  				}
  1171  			}
  1172  			names = misses
  1173  		}
  1174  
  1175  		if len(names) > 0 {
  1176  			props := map[string]interface{}{}
  1177  			var namePlaceholders []string
  1178  			for _, name := range names {
  1179  				key := fmt.Sprintf("Name%v", len(namePlaceholders))
  1180  				props[key] = name
  1181  				namePlaceholders = append(namePlaceholders, ":"+key)
  1182  			}
  1183  
  1184  			var query string
  1185  			if teamId == "" {
  1186  				query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND DeleteAt = 0`
  1187  			} else {
  1188  				props["TeamId"] = teamId
  1189  				query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND TeamId = :TeamId AND DeleteAt = 0`
  1190  			}
  1191  
  1192  			var dbChannels []*model.Channel
  1193  			if _, err := s.GetReplica().Select(&dbChannels, query, props); err != nil && err != sql.ErrNoRows {
  1194  				result.Err = model.NewAppError("SqlChannelStore.GetByName", "store.sql_channel.get_by_name.existing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError)
  1195  				return
  1196  			}
  1197  			for _, channel := range dbChannels {
  1198  				channelByNameCache.AddWithExpiresInSecs(teamId+channel.Name, channel, CHANNEL_CACHE_SEC)
  1199  				channels = append(channels, channel)
  1200  			}
  1201  		}
  1202  
  1203  		result.Data = channels
  1204  	})
  1205  }
  1206  
  1207  func (s SqlChannelStore) GetByNameIncludeDeleted(teamId string, name string, allowFromCache bool) store.StoreChannel {
  1208  	return s.getByName(teamId, name, true, allowFromCache)
  1209  }
  1210  
  1211  func (s SqlChannelStore) getByName(teamId string, name string, includeDeleted bool, allowFromCache bool) store.StoreChannel {
  1212  	var query string
  1213  	if includeDeleted {
  1214  		query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name"
  1215  	} else {
  1216  		query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt = 0"
  1217  	}
  1218  	return store.Do(func(result *store.StoreResult) {
  1219  		channel := model.Channel{}
  1220  
  1221  		if allowFromCache {
  1222  			if cacheItem, ok := channelByNameCache.Get(teamId + name); ok {
  1223  				if s.metrics != nil {
  1224  					s.metrics.IncrementMemCacheHitCounter("Channel By Name")
  1225  				}
  1226  				result.Data = cacheItem.(*model.Channel)
  1227  				return
  1228  			}
  1229  			if s.metrics != nil {
  1230  				s.metrics.IncrementMemCacheMissCounter("Channel By Name")
  1231  			}
  1232  		}
  1233  
  1234  		if err := s.GetReplica().SelectOne(&channel, query, map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil {
  1235  			if err == sql.ErrNoRows {
  1236  				result.Err = model.NewAppError("SqlChannelStore.GetByName", store.MISSING_CHANNEL_ERROR, nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusNotFound)
  1237  				return
  1238  			}
  1239  			result.Err = model.NewAppError("SqlChannelStore.GetByName", "store.sql_channel.get_by_name.existing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusInternalServerError)
  1240  			return
  1241  		}
  1242  
  1243  		result.Data = &channel
  1244  		channelByNameCache.AddWithExpiresInSecs(teamId+name, &channel, CHANNEL_CACHE_SEC)
  1245  	})
  1246  }
  1247  
  1248  func (s SqlChannelStore) GetDeletedByName(teamId string, name string) store.StoreChannel {
  1249  	return store.Do(func(result *store.StoreResult) {
  1250  		channel := model.Channel{}
  1251  
  1252  		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 {
  1253  			if err == sql.ErrNoRows {
  1254  				result.Err = model.NewAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.missing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusNotFound)
  1255  				return
  1256  			}
  1257  			result.Err = model.NewAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.existing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusInternalServerError)
  1258  			return
  1259  		}
  1260  
  1261  		result.Data = &channel
  1262  	})
  1263  }
  1264  
  1265  func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int) store.StoreChannel {
  1266  	return store.Do(func(result *store.StoreResult) {
  1267  		channels := &model.ChannelList{}
  1268  
  1269  		if _, err := s.GetReplica().Select(channels, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND DeleteAt != 0 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset}); err != nil {
  1270  			if err == sql.ErrNoRows {
  1271  				result.Err = model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.missing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusNotFound)
  1272  				return
  1273  			}
  1274  			result.Err = model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.existing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError)
  1275  			return
  1276  		}
  1277  
  1278  		result.Data = channels
  1279  	})
  1280  }
  1281  
  1282  var CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY = `
  1283  	SELECT
  1284  		ChannelMembers.*,
  1285  		TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1286  		TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1287  		ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1288  		ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1289  	FROM
  1290  		ChannelMembers
  1291  	INNER JOIN
  1292  		Channels ON ChannelMembers.ChannelId = Channels.Id
  1293  	LEFT JOIN
  1294  		Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1295  	LEFT JOIN
  1296  		Teams ON Channels.TeamId = Teams.Id
  1297  	LEFT JOIN
  1298  		Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1299  `
  1300  
  1301  func (s SqlChannelStore) SaveMember(member *model.ChannelMember) store.StoreChannel {
  1302  	return store.Do(func(result *store.StoreResult) {
  1303  		defer s.InvalidateAllChannelMembersForUser(member.UserId)
  1304  
  1305  		// Grab the channel we are saving this member to
  1306  		cr := <-s.GetFromMaster(member.ChannelId)
  1307  		if cr.Err != nil {
  1308  			result.Err = cr.Err
  1309  			return
  1310  		}
  1311  
  1312  		channel := cr.Data.(*model.Channel)
  1313  
  1314  		transaction, err := s.GetMaster().Begin()
  1315  		if err != nil {
  1316  			result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  1317  			return
  1318  		}
  1319  
  1320  		*result = s.saveMemberT(transaction, member, channel)
  1321  		if result.Err != nil {
  1322  			transaction.Rollback()
  1323  			return
  1324  		}
  1325  
  1326  		if err := transaction.Commit(); err != nil {
  1327  			result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  1328  			return
  1329  		}
  1330  	})
  1331  }
  1332  
  1333  func (s SqlChannelStore) saveMemberT(transaction *gorp.Transaction, member *model.ChannelMember, channel *model.Channel) store.StoreResult {
  1334  	result := store.StoreResult{}
  1335  
  1336  	member.PreSave()
  1337  	if result.Err = member.IsValid(); result.Err != nil {
  1338  		return result
  1339  	}
  1340  
  1341  	dbMember := NewChannelMemberFromModel(member)
  1342  
  1343  	if err := transaction.Insert(dbMember); err != nil {
  1344  		if IsUniqueConstraintError(err, []string{"ChannelId", "channelmembers_pkey"}) {
  1345  			result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.exists.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest)
  1346  			return result
  1347  		}
  1348  		result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.save.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
  1349  		return result
  1350  	}
  1351  
  1352  	var retrievedMember channelMemberWithSchemeRoles
  1353  	if err := transaction.SelectOne(&retrievedMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": dbMember.ChannelId, "UserId": dbMember.UserId}); err != nil {
  1354  		if err == sql.ErrNoRows {
  1355  			result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound)
  1356  			return result
  1357  		}
  1358  		result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusInternalServerError)
  1359  		return result
  1360  	}
  1361  
  1362  	result.Data = retrievedMember.ToModel()
  1363  	return result
  1364  }
  1365  
  1366  func (s SqlChannelStore) UpdateMember(member *model.ChannelMember) store.StoreChannel {
  1367  	return store.Do(func(result *store.StoreResult) {
  1368  		member.PreUpdate()
  1369  
  1370  		if result.Err = member.IsValid(); result.Err != nil {
  1371  			return
  1372  		}
  1373  
  1374  		if _, err := s.GetMaster().Update(NewChannelMemberFromModel(member)); err != nil {
  1375  			result.Err = model.NewAppError("SqlChannelStore.UpdateMember", "store.sql_channel.update_member.app_error", nil, "channel_id="+member.ChannelId+", "+"user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError)
  1376  			return
  1377  		}
  1378  
  1379  		var dbMember channelMemberWithSchemeRoles
  1380  
  1381  		if err := s.GetReplica().SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil {
  1382  			if err == sql.ErrNoRows {
  1383  				result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound)
  1384  				return
  1385  			}
  1386  			result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError)
  1387  			return
  1388  		}
  1389  		result.Data = dbMember.ToModel()
  1390  	})
  1391  }
  1392  
  1393  func (s SqlChannelStore) GetMembers(channelId string, offset, limit int) store.StoreChannel {
  1394  	return store.Do(func(result *store.StoreResult) {
  1395  		var dbMembers channelMemberWithSchemeRolesList
  1396  		_, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelId = :ChannelId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"ChannelId": channelId, "Limit": limit, "Offset": offset})
  1397  		if err != nil {
  1398  			result.Err = model.NewAppError("SqlChannelStore.GetMembers", "store.sql_channel.get_members.app_error", nil, "channel_id="+channelId+","+err.Error(), http.StatusInternalServerError)
  1399  			return
  1400  		}
  1401  
  1402  		result.Data = dbMembers.ToModel()
  1403  	})
  1404  }
  1405  
  1406  func (s SqlChannelStore) GetChannelMembersTimezones(channelId string) store.StoreChannel {
  1407  	return store.Do(func(result *store.StoreResult) {
  1408  		var dbMembersTimezone []map[string]string
  1409  		_, err := s.GetReplica().Select(&dbMembersTimezone, `
  1410  					SELECT
  1411  						Users.Timezone
  1412  					FROM
  1413  						ChannelMembers
  1414  					LEFT JOIN
  1415  						Users  ON ChannelMembers.UserId = Id
  1416  					WHERE ChannelId = :ChannelId
  1417  		`, map[string]interface{}{
  1418  			"ChannelId": channelId})
  1419  		if err != nil {
  1420  			result.Err = model.NewAppError("SqlChannelStore.GetChannelMembersTimezones", "store.sql_channel.get_members.app_error", nil, "channel_id="+channelId+","+err.Error(), http.StatusInternalServerError)
  1421  			return
  1422  		}
  1423  		result.Data = dbMembersTimezone
  1424  	})
  1425  }
  1426  
  1427  func (s SqlChannelStore) GetMember(channelId string, userId string) store.StoreChannel {
  1428  	return store.Do(func(result *store.StoreResult) {
  1429  		var dbMember channelMemberWithSchemeRoles
  1430  
  1431  		if err := s.GetReplica().SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil {
  1432  			if err == sql.ErrNoRows {
  1433  				result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+channelId+"user_id="+userId+","+err.Error(), http.StatusNotFound)
  1434  				return
  1435  			}
  1436  			result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+channelId+"user_id="+userId+","+err.Error(), http.StatusInternalServerError)
  1437  			return
  1438  		}
  1439  
  1440  		result.Data = dbMember.ToModel()
  1441  	})
  1442  }
  1443  
  1444  func (s SqlChannelStore) InvalidateAllChannelMembersForUser(userId string) {
  1445  	allChannelMembersForUserCache.Remove(userId)
  1446  	allChannelMembersForUserCache.Remove(userId + "_deleted")
  1447  	if s.metrics != nil {
  1448  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Remove by UserId")
  1449  	}
  1450  }
  1451  
  1452  func (s SqlChannelStore) IsUserInChannelUseCache(userId string, channelId string) bool {
  1453  	if cacheItem, ok := allChannelMembersForUserCache.Get(userId); ok {
  1454  		if s.metrics != nil {
  1455  			s.metrics.IncrementMemCacheHitCounter("All Channel Members for User")
  1456  		}
  1457  		ids := cacheItem.(map[string]string)
  1458  		if _, ok := ids[channelId]; ok {
  1459  			return true
  1460  		}
  1461  		return false
  1462  	}
  1463  
  1464  	if s.metrics != nil {
  1465  		s.metrics.IncrementMemCacheMissCounter("All Channel Members for User")
  1466  	}
  1467  
  1468  	result := <-s.GetAllChannelMembersForUser(userId, true, false)
  1469  	if result.Err != nil {
  1470  		mlog.Error("SqlChannelStore.IsUserInChannelUseCache: " + result.Err.Error())
  1471  		return false
  1472  	}
  1473  
  1474  	ids := result.Data.(map[string]string)
  1475  	if _, ok := ids[channelId]; ok {
  1476  		return true
  1477  	}
  1478  
  1479  	return false
  1480  }
  1481  
  1482  func (s SqlChannelStore) GetMemberForPost(postId string, userId string) store.StoreChannel {
  1483  	return store.Do(func(result *store.StoreResult) {
  1484  		var dbMember channelMemberWithSchemeRoles
  1485  		if err := s.GetReplica().SelectOne(&dbMember,
  1486  			`
  1487  			SELECT
  1488  				ChannelMembers.*,
  1489  				TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1490  				TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1491  				ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1492  				ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1493  			FROM
  1494  				ChannelMembers
  1495  			INNER JOIN
  1496  				Posts ON ChannelMembers.ChannelId = Posts.ChannelId
  1497  			INNER JOIN
  1498  				Channels ON ChannelMembers.ChannelId = Channels.Id
  1499  			LEFT JOIN
  1500  				Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1501  			LEFT JOIN
  1502  				Teams ON Channels.TeamId = Teams.Id
  1503  			LEFT JOIN
  1504  				Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1505  			WHERE
  1506  				ChannelMembers.UserId = :UserId
  1507  				AND Posts.Id = :PostId`, map[string]interface{}{"UserId": userId, "PostId": postId}); err != nil {
  1508  			result.Err = model.NewAppError("SqlChannelStore.GetMemberForPost", "store.sql_channel.get_member_for_post.app_error", nil, "postId="+postId+", err="+err.Error(), http.StatusInternalServerError)
  1509  			return
  1510  		}
  1511  		result.Data = dbMember.ToModel()
  1512  	})
  1513  }
  1514  
  1515  func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool, includeDeleted bool) store.StoreChannel {
  1516  	return store.Do(func(result *store.StoreResult) {
  1517  		cache_key := userId
  1518  		if includeDeleted {
  1519  			cache_key += "_deleted"
  1520  		}
  1521  		if allowFromCache {
  1522  			if cacheItem, ok := allChannelMembersForUserCache.Get(cache_key); ok {
  1523  				if s.metrics != nil {
  1524  					s.metrics.IncrementMemCacheHitCounter("All Channel Members for User")
  1525  				}
  1526  				result.Data = cacheItem.(map[string]string)
  1527  				return
  1528  			}
  1529  		}
  1530  
  1531  		if s.metrics != nil {
  1532  			s.metrics.IncrementMemCacheMissCounter("All Channel Members for User")
  1533  		}
  1534  
  1535  		var deletedClause string
  1536  		if !includeDeleted {
  1537  			deletedClause = "Channels.DeleteAt = 0 AND"
  1538  		}
  1539  
  1540  		var data allChannelMembers
  1541  		_, err := s.GetReplica().Select(&data, `
  1542  			SELECT
  1543  				ChannelMembers.ChannelId, ChannelMembers.Roles, ChannelMembers.SchemeUser, ChannelMembers.SchemeAdmin,
  1544  				TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole,
  1545  				TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole,
  1546  				ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole,
  1547  				ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole
  1548  			FROM
  1549  				ChannelMembers
  1550  			INNER JOIN
  1551  				Channels ON ChannelMembers.ChannelId = Channels.Id
  1552  			LEFT JOIN
  1553  				Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id
  1554  			LEFT JOIN
  1555  				Teams ON Channels.TeamId = Teams.Id
  1556  			LEFT JOIN
  1557  				Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id
  1558  			WHERE
  1559  				`+deletedClause+`
  1560  				ChannelMembers.UserId = :UserId`, map[string]interface{}{"UserId": userId})
  1561  
  1562  		if err != nil {
  1563  			result.Err = model.NewAppError("SqlChannelStore.GetAllChannelMembersForUser", "store.sql_channel.get_channels.get.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1564  			return
  1565  		}
  1566  
  1567  		ids := data.ToMapStringString()
  1568  		result.Data = ids
  1569  
  1570  		if allowFromCache {
  1571  			allChannelMembersForUserCache.AddWithExpiresInSecs(cache_key, ids, ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SEC)
  1572  		}
  1573  	})
  1574  }
  1575  
  1576  func (s SqlChannelStore) InvalidateCacheForChannelMembersNotifyProps(channelId string) {
  1577  	allChannelMembersNotifyPropsForChannelCache.Remove(channelId)
  1578  	if s.metrics != nil {
  1579  		s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Remove by ChannelId")
  1580  	}
  1581  }
  1582  
  1583  type allChannelMemberNotifyProps struct {
  1584  	UserId      string
  1585  	NotifyProps model.StringMap
  1586  }
  1587  
  1588  func (s SqlChannelStore) GetAllChannelMembersNotifyPropsForChannel(channelId string, allowFromCache bool) store.StoreChannel {
  1589  	return store.Do(func(result *store.StoreResult) {
  1590  		if allowFromCache {
  1591  			if cacheItem, ok := allChannelMembersNotifyPropsForChannelCache.Get(channelId); ok {
  1592  				if s.metrics != nil {
  1593  					s.metrics.IncrementMemCacheHitCounter("All Channel Members Notify Props for Channel")
  1594  				}
  1595  				result.Data = cacheItem.(map[string]model.StringMap)
  1596  				return
  1597  			}
  1598  		}
  1599  
  1600  		if s.metrics != nil {
  1601  			s.metrics.IncrementMemCacheMissCounter("All Channel Members Notify Props for Channel")
  1602  		}
  1603  
  1604  		var data []allChannelMemberNotifyProps
  1605  		_, err := s.GetReplica().Select(&data, `
  1606  			SELECT UserId, NotifyProps
  1607  			FROM ChannelMembers
  1608  			WHERE ChannelId = :ChannelId`, map[string]interface{}{"ChannelId": channelId})
  1609  
  1610  		if err != nil {
  1611  			result.Err = model.NewAppError("SqlChannelStore.GetAllChannelMembersPropsForChannel", "store.sql_channel.get_members.app_error", nil, "channelId="+channelId+", err="+err.Error(), http.StatusInternalServerError)
  1612  			return
  1613  		}
  1614  
  1615  		props := make(map[string]model.StringMap)
  1616  		for i := range data {
  1617  			props[data[i].UserId] = data[i].NotifyProps
  1618  		}
  1619  
  1620  		result.Data = props
  1621  
  1622  		allChannelMembersNotifyPropsForChannelCache.AddWithExpiresInSecs(channelId, props, ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SEC)
  1623  	})
  1624  }
  1625  
  1626  func (s SqlChannelStore) InvalidateMemberCount(channelId string) {
  1627  	channelMemberCountsCache.Remove(channelId)
  1628  	if s.metrics != nil {
  1629  		s.metrics.IncrementMemCacheInvalidationCounter("Channel Member Counts - Remove by ChannelId")
  1630  	}
  1631  }
  1632  
  1633  func (s SqlChannelStore) GetMemberCountFromCache(channelId string) int64 {
  1634  	if cacheItem, ok := channelMemberCountsCache.Get(channelId); ok {
  1635  		if s.metrics != nil {
  1636  			s.metrics.IncrementMemCacheHitCounter("Channel Member Counts")
  1637  		}
  1638  		return cacheItem.(int64)
  1639  	}
  1640  
  1641  	if s.metrics != nil {
  1642  		s.metrics.IncrementMemCacheMissCounter("Channel Member Counts")
  1643  	}
  1644  
  1645  	result := <-s.GetMemberCount(channelId, true)
  1646  	if result.Err != nil {
  1647  		return 0
  1648  	}
  1649  
  1650  	return result.Data.(int64)
  1651  }
  1652  
  1653  func (s SqlChannelStore) GetMemberCount(channelId string, allowFromCache bool) store.StoreChannel {
  1654  	return store.Do(func(result *store.StoreResult) {
  1655  		if allowFromCache {
  1656  			if cacheItem, ok := channelMemberCountsCache.Get(channelId); ok {
  1657  				if s.metrics != nil {
  1658  					s.metrics.IncrementMemCacheHitCounter("Channel Member Counts")
  1659  				}
  1660  				result.Data = cacheItem.(int64)
  1661  				return
  1662  			}
  1663  		}
  1664  
  1665  		if s.metrics != nil {
  1666  			s.metrics.IncrementMemCacheMissCounter("Channel Member Counts")
  1667  		}
  1668  
  1669  		count, err := s.GetReplica().SelectInt(`
  1670  			SELECT
  1671  				count(*)
  1672  			FROM
  1673  				ChannelMembers,
  1674  				Users
  1675  			WHERE
  1676  				ChannelMembers.UserId = Users.Id
  1677  				AND ChannelMembers.ChannelId = :ChannelId
  1678  				AND Users.DeleteAt = 0`, map[string]interface{}{"ChannelId": channelId})
  1679  		if err != nil {
  1680  			result.Err = model.NewAppError("SqlChannelStore.GetMemberCount", "store.sql_channel.get_member_count.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
  1681  			return
  1682  		}
  1683  		result.Data = count
  1684  
  1685  		if allowFromCache {
  1686  			channelMemberCountsCache.AddWithExpiresInSecs(channelId, count, CHANNEL_MEMBERS_COUNTS_CACHE_SEC)
  1687  		}
  1688  	})
  1689  }
  1690  
  1691  func (s SqlChannelStore) RemoveMember(channelId string, userId string) store.StoreChannel {
  1692  	return store.Do(func(result *store.StoreResult) {
  1693  		_, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId AND UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId})
  1694  		if err != nil {
  1695  			result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1696  		}
  1697  	})
  1698  }
  1699  
  1700  func (s SqlChannelStore) RemoveAllDeactivatedMembers(channelId string) store.StoreChannel {
  1701  	return store.Do(func(result *store.StoreResult) {
  1702  		query := `
  1703  			DELETE
  1704  			FROM
  1705  				ChannelMembers
  1706  			WHERE 
  1707  				UserId IN (
  1708  					SELECT
  1709  						Id
  1710  					FROM
  1711  						Users
  1712  					WHERE
  1713  						Users.DeleteAt != 0
  1714  				)
  1715  			AND
  1716  				ChannelMembers.ChannelId = :ChannelId
  1717  		`
  1718  
  1719  		_, err := s.GetMaster().Exec(query, map[string]interface{}{"ChannelId": channelId})
  1720  		if err != nil {
  1721  			result.Err = model.NewAppError("SqlChannelStore.RemoveAllDeactivatedMembers", "store.sql_channel.remove_all_deactivated_members.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError)
  1722  		}
  1723  	})
  1724  }
  1725  
  1726  func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) store.StoreChannel {
  1727  	return store.Do(func(result *store.StoreResult) {
  1728  		if _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
  1729  			result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.permanent_delete_members_by_user.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1730  		}
  1731  	})
  1732  }
  1733  
  1734  func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string) store.StoreChannel {
  1735  	return store.Do(func(result *store.StoreResult) {
  1736  		props := make(map[string]interface{})
  1737  
  1738  		updateIdQuery := ""
  1739  		for index, channelId := range channelIds {
  1740  			if len(updateIdQuery) > 0 {
  1741  				updateIdQuery += " OR "
  1742  			}
  1743  
  1744  			props["channelId"+strconv.Itoa(index)] = channelId
  1745  			updateIdQuery += "ChannelId = :channelId" + strconv.Itoa(index)
  1746  		}
  1747  
  1748  		selectIdQuery := strings.Replace(updateIdQuery, "ChannelId", "Id", -1)
  1749  
  1750  		var lastPostAtTimes []struct {
  1751  			Id            string
  1752  			LastPostAt    int64
  1753  			TotalMsgCount int64
  1754  		}
  1755  
  1756  		selectQuery := "SELECT Id, LastPostAt, TotalMsgCount FROM Channels WHERE (" + selectIdQuery + ")"
  1757  
  1758  		if _, err := s.GetMaster().Select(&lastPostAtTimes, selectQuery, props); err != nil || len(lastPostAtTimes) <= 0 {
  1759  			var extra string
  1760  			status := http.StatusInternalServerError
  1761  			if err == nil {
  1762  				status = http.StatusBadRequest
  1763  				extra = "No channels found"
  1764  			} else {
  1765  				extra = err.Error()
  1766  			}
  1767  			result.Err = model.NewAppError("SqlChannelStore.UpdateLastViewedAt", "store.sql_channel.update_last_viewed_at.app_error", nil, "channel_ids="+strings.Join(channelIds, ",")+", user_id="+userId+", "+extra, status)
  1768  			return
  1769  		}
  1770  
  1771  		times := map[string]int64{}
  1772  		msgCountQuery := ""
  1773  		lastViewedQuery := ""
  1774  		for index, t := range lastPostAtTimes {
  1775  			times[t.Id] = t.LastPostAt
  1776  
  1777  			props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount
  1778  			msgCountQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCount, :msgCount%d) ", index, index)
  1779  
  1780  			props["lastViewed"+strconv.Itoa(index)] = t.LastPostAt
  1781  			lastViewedQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(LastViewedAt, :lastViewed%d) ", index, index)
  1782  
  1783  			props["channelId"+strconv.Itoa(index)] = t.Id
  1784  		}
  1785  
  1786  		var updateQuery string
  1787  
  1788  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1789  			updateQuery = `UPDATE
  1790  				ChannelMembers
  1791  			SET
  1792  			    MentionCount = 0,
  1793  			    MsgCount = CAST(CASE ChannelId ` + msgCountQuery + ` END AS BIGINT),
  1794  			    LastViewedAt = CAST(CASE ChannelId ` + lastViewedQuery + ` END AS BIGINT),
  1795  			    LastUpdateAt = CAST(CASE ChannelId ` + lastViewedQuery + ` END AS BIGINT)
  1796  			WHERE
  1797  			        UserId = :UserId
  1798  			        AND (` + updateIdQuery + `)`
  1799  		} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  1800  			updateQuery = `UPDATE
  1801  				ChannelMembers
  1802  			SET
  1803  			    MentionCount = 0,
  1804  			    MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
  1805  			    LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
  1806  			    LastUpdateAt = CASE ChannelId ` + lastViewedQuery + ` END
  1807  			WHERE
  1808  			        UserId = :UserId
  1809  			        AND (` + updateIdQuery + `)`
  1810  		}
  1811  
  1812  		props["UserId"] = userId
  1813  
  1814  		if _, err := s.GetMaster().Exec(updateQuery, props); err != nil {
  1815  			result.Err = model.NewAppError("SqlChannelStore.UpdateLastViewedAt", "store.sql_channel.update_last_viewed_at.app_error", nil, "channel_ids="+strings.Join(channelIds, ",")+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1816  			return
  1817  		}
  1818  
  1819  		result.Data = times
  1820  	})
  1821  }
  1822  
  1823  func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string) store.StoreChannel {
  1824  	return store.Do(func(result *store.StoreResult) {
  1825  		_, err := s.GetMaster().Exec(
  1826  			`UPDATE
  1827  				ChannelMembers
  1828  			SET
  1829  				MentionCount = MentionCount + 1,
  1830  				LastUpdateAt = :LastUpdateAt
  1831  			WHERE
  1832  				UserId = :UserId
  1833  					AND ChannelId = :ChannelId`,
  1834  			map[string]interface{}{"ChannelId": channelId, "UserId": userId, "LastUpdateAt": model.GetMillis()})
  1835  		if err != nil {
  1836  			result.Err = model.NewAppError("SqlChannelStore.IncrementMentionCount", "store.sql_channel.increment_mention_count.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
  1837  		}
  1838  	})
  1839  }
  1840  
  1841  func (s SqlChannelStore) GetAll(teamId string) store.StoreChannel {
  1842  	return store.Do(func(result *store.StoreResult) {
  1843  		var data []*model.Channel
  1844  		_, err := s.GetReplica().Select(&data, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Type != 'D' ORDER BY Name", map[string]interface{}{"TeamId": teamId})
  1845  
  1846  		if err != nil {
  1847  			result.Err = model.NewAppError("SqlChannelStore.GetAll", "store.sql_channel.get_all.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError)
  1848  			return
  1849  		}
  1850  
  1851  		result.Data = data
  1852  	})
  1853  }
  1854  
  1855  func (s SqlChannelStore) GetForPost(postId string) store.StoreChannel {
  1856  	return store.Do(func(result *store.StoreResult) {
  1857  		channel := &model.Channel{}
  1858  		if err := s.GetReplica().SelectOne(
  1859  			channel,
  1860  			`SELECT
  1861  				Channels.*
  1862  			FROM
  1863  				Channels,
  1864  				Posts
  1865  			WHERE
  1866  				Channels.Id = Posts.ChannelId
  1867  				AND Posts.Id = :PostId`, map[string]interface{}{"PostId": postId}); err != nil {
  1868  			result.Err = model.NewAppError("SqlChannelStore.GetForPost", "store.sql_channel.get_for_post.app_error", nil, "postId="+postId+", err="+err.Error(), http.StatusInternalServerError)
  1869  			return
  1870  		}
  1871  
  1872  		result.Data = channel
  1873  	})
  1874  }
  1875  
  1876  func (s SqlChannelStore) AnalyticsTypeCount(teamId string, channelType string) store.StoreChannel {
  1877  	return store.Do(func(result *store.StoreResult) {
  1878  		query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType"
  1879  
  1880  		if len(teamId) > 0 {
  1881  			query += " AND TeamId = :TeamId"
  1882  		}
  1883  
  1884  		v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType})
  1885  		if err != nil {
  1886  			result.Err = model.NewAppError("SqlChannelStore.AnalyticsTypeCount", "store.sql_channel.analytics_type_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1887  			return
  1888  		}
  1889  
  1890  		result.Data = v
  1891  	})
  1892  }
  1893  
  1894  func (s SqlChannelStore) AnalyticsDeletedTypeCount(teamId string, channelType string) store.StoreChannel {
  1895  	return store.Do(func(result *store.StoreResult) {
  1896  		query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType AND DeleteAt > 0"
  1897  
  1898  		if len(teamId) > 0 {
  1899  			query += " AND TeamId = :TeamId"
  1900  		}
  1901  
  1902  		v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType})
  1903  		if err != nil {
  1904  			result.Err = model.NewAppError("SqlChannelStore.AnalyticsDeletedTypeCount", "store.sql_channel.analytics_deleted_type_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1905  			return
  1906  		}
  1907  
  1908  		result.Data = v
  1909  	})
  1910  }
  1911  
  1912  func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) store.StoreChannel {
  1913  	return store.Do(func(result *store.StoreResult) {
  1914  		var dbMembers channelMemberWithSchemeRolesList
  1915  		_, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId})
  1916  
  1917  		if err != nil {
  1918  			result.Err = model.NewAppError("SqlChannelStore.GetMembersForUser", "store.sql_channel.get_members.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  1919  			return
  1920  		}
  1921  
  1922  		result.Data = dbMembers.ToModel()
  1923  	})
  1924  }
  1925  
  1926  func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
  1927  	return store.Do(func(result *store.StoreResult) {
  1928  		deleteFilter := "AND c.DeleteAt = 0"
  1929  		if includeDeleted {
  1930  			deleteFilter = ""
  1931  		}
  1932  
  1933  		queryFormat := `
  1934  			SELECT
  1935  			    Channels.*
  1936  			FROM
  1937  			    Channels
  1938  			JOIN
  1939  			    PublicChannels c ON (c.Id = Channels.Id)
  1940  			WHERE
  1941  			    c.TeamId = :TeamId
  1942  			    ` + deleteFilter + `
  1943  			    %v
  1944  			LIMIT 50
  1945  		`
  1946  
  1947  		var channels model.ChannelList
  1948  
  1949  		if likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose"); likeClause == "" {
  1950  			if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil {
  1951  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  1952  			}
  1953  		} else {
  1954  			// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
  1955  			// query you would get using an OR of the LIKE and full-text clauses.
  1956  			fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  1957  			likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
  1958  			fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
  1959  			query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
  1960  
  1961  			if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
  1962  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  1963  			}
  1964  		}
  1965  
  1966  		sort.Slice(channels, func(a, b int) bool {
  1967  			return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
  1968  		})
  1969  		result.Data = &channels
  1970  	})
  1971  }
  1972  
  1973  func (s SqlChannelStore) AutocompleteInTeamForSearch(teamId string, userId string, term string, includeDeleted bool) store.StoreChannel {
  1974  	return store.Do(func(result *store.StoreResult) {
  1975  		deleteFilter := "AND DeleteAt = 0"
  1976  		if includeDeleted {
  1977  			deleteFilter = ""
  1978  		}
  1979  
  1980  		queryFormat := `
  1981  			SELECT
  1982  				C.*
  1983  			FROM
  1984  				Channels AS C
  1985  			JOIN
  1986  				ChannelMembers AS CM ON CM.ChannelId = C.Id
  1987  			WHERE
  1988  			    (C.TeamId = :TeamId OR (C.TeamId = '' AND C.Type = 'G'))
  1989  				AND CM.UserId = :UserId
  1990  				` + deleteFilter + `
  1991  				%v
  1992  			LIMIT 50`
  1993  
  1994  		var channels model.ChannelList
  1995  
  1996  		if likeClause, likeTerm := s.buildLIKEClause(term, "Name, DisplayName, Purpose"); likeClause == "" {
  1997  			if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId, "UserId": userId}); err != nil {
  1998  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  1999  			}
  2000  		} else {
  2001  			// Using a UNION results in index_merge and fulltext queries and is much faster than the ref
  2002  			// query you would get using an OR of the LIKE and full-text clauses.
  2003  			fulltextClause, fulltextTerm := s.buildFulltextClause(term, "Name, DisplayName, Purpose")
  2004  			likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause)
  2005  			fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause)
  2006  			query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery)
  2007  
  2008  			if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "UserId": userId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil {
  2009  				result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2010  			}
  2011  		}
  2012  
  2013  		directChannels, err := s.autocompleteInTeamForSearchDirectMessages(userId, term)
  2014  		if err != nil {
  2015  			result.Err = err
  2016  			return
  2017  		}
  2018  
  2019  		channels = append(channels, directChannels...)
  2020  
  2021  		sort.Slice(channels, func(a, b int) bool {
  2022  			return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName)
  2023  		})
  2024  		result.Data = &channels
  2025  	})
  2026  }
  2027  
  2028  func (s SqlChannelStore) autocompleteInTeamForSearchDirectMessages(userId string, term string) ([]*model.Channel, *model.AppError) {
  2029  	queryFormat := `
  2030  			SELECT
  2031  				C.*,
  2032  				OtherUsers.Username as DisplayName
  2033  			FROM
  2034  				Channels AS C
  2035  			JOIN
  2036  				ChannelMembers AS CM ON CM.ChannelId = C.Id
  2037  			INNER JOIN (
  2038  				SELECT
  2039  					ICM.ChannelId AS ChannelId, IU.Username AS Username
  2040  				FROM
  2041  					Users as IU
  2042  				JOIN
  2043  					ChannelMembers AS ICM ON ICM.UserId = IU.Id
  2044  				WHERE
  2045  					IU.Id != :UserId
  2046  					%v
  2047  				) AS OtherUsers ON OtherUsers.ChannelId = C.Id
  2048  			WHERE
  2049  			    C.Type = 'D'
  2050  				AND CM.UserId = :UserId
  2051  			LIMIT 50`
  2052  
  2053  	var channels model.ChannelList
  2054  
  2055  	if likeClause, likeTerm := s.buildLIKEClause(term, "IU.Username, IU.Nickname"); likeClause == "" {
  2056  		if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"UserId": userId}); err != nil {
  2057  			return nil, model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2058  		}
  2059  	} else {
  2060  		query := fmt.Sprintf(queryFormat, "AND "+likeClause)
  2061  
  2062  		if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"UserId": userId, "LikeTerm": likeTerm}); err != nil {
  2063  			return nil, model.NewAppError("SqlChannelStore.AutocompleteInTeamForSearch", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2064  		}
  2065  	}
  2066  
  2067  	return channels, nil
  2068  }
  2069  
  2070  func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel {
  2071  	return store.Do(func(result *store.StoreResult) {
  2072  		deleteFilter := "AND c.DeleteAt = 0"
  2073  		if includeDeleted {
  2074  			deleteFilter = ""
  2075  		}
  2076  
  2077  		*result = s.performSearch(`
  2078  			SELECT
  2079  			    Channels.*
  2080  			FROM
  2081  			    Channels
  2082  			JOIN
  2083  			    PublicChannels c ON (c.Id = Channels.Id)
  2084  			WHERE
  2085  			    c.TeamId = :TeamId
  2086  			    `+deleteFilter+`
  2087  			    SEARCH_CLAUSE
  2088  			ORDER BY c.DisplayName
  2089  			LIMIT 100
  2090  		`, term, map[string]interface{}{
  2091  			"TeamId": teamId,
  2092  		})
  2093  	})
  2094  }
  2095  
  2096  func (s SqlChannelStore) SearchAllChannels(term string, includeDeleted bool) store.StoreChannel {
  2097  	return store.Do(func(result *store.StoreResult) {
  2098  		parameters := map[string]interface{}{}
  2099  		deleteFilter := "AND c.DeleteAt = 0"
  2100  		if includeDeleted {
  2101  			deleteFilter = ""
  2102  		}
  2103  		searchQuery := `SELECT c.*, t.DisplayName AS TeamDisplayName, t.Name AS TeamName, t.UpdateAt as TeamUpdateAt FROM Channels AS c JOIN Teams AS t ON t.Id = c.TeamId WHERE (c.Type = 'P' OR c.Type = 'O') ` + deleteFilter + ` SEARCH_CLAUSE ORDER BY c.DisplayName, t.DisplayName LIMIT 100`
  2104  
  2105  		likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
  2106  		if likeTerm == "" {
  2107  			// If the likeTerm is empty after preparing, then don't bother searching.
  2108  			searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
  2109  		} else {
  2110  			parameters["LikeTerm"] = likeTerm
  2111  			fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  2112  			parameters["FulltextTerm"] = fulltextTerm
  2113  			searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
  2114  		}
  2115  
  2116  		var channels model.ChannelListWithTeamData
  2117  
  2118  		if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil {
  2119  			result.Err = model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2120  		}
  2121  
  2122  		result.Data = &channels
  2123  	})
  2124  }
  2125  
  2126  func (s SqlChannelStore) SearchMore(userId string, teamId string, term string) store.StoreChannel {
  2127  	return store.Do(func(result *store.StoreResult) {
  2128  		*result = s.performSearch(`
  2129  			SELECT
  2130  			    Channels.*
  2131  			FROM
  2132  			    Channels
  2133  			JOIN
  2134  			    PublicChannels c ON (c.Id = Channels.Id)
  2135  			WHERE
  2136  			    c.TeamId = :TeamId
  2137  			AND c.DeleteAt = 0
  2138  			AND c.Id NOT IN (
  2139  			    SELECT
  2140  			        c.Id
  2141  			    FROM
  2142  			        PublicChannels c
  2143  			    JOIN
  2144  			        ChannelMembers cm ON (cm.ChannelId = c.Id)
  2145  			    WHERE
  2146  			        c.TeamId = :TeamId
  2147  			    AND cm.UserId = :UserId
  2148  			    AND c.DeleteAt = 0
  2149  		        )
  2150  			SEARCH_CLAUSE
  2151  			ORDER BY c.DisplayName
  2152  			LIMIT 100
  2153  		`, term, map[string]interface{}{
  2154  			"TeamId": teamId,
  2155  			"UserId": userId,
  2156  		})
  2157  	})
  2158  }
  2159  
  2160  func (s SqlChannelStore) buildLIKEClause(term string, searchColumns string) (likeClause, likeTerm string) {
  2161  	likeTerm = term
  2162  
  2163  	// These chars must be removed from the like query.
  2164  	for _, c := range ignoreLikeSearchChar {
  2165  		likeTerm = strings.Replace(likeTerm, c, "", -1)
  2166  	}
  2167  
  2168  	// These chars must be escaped in the like query.
  2169  	for _, c := range escapeLikeSearchChar {
  2170  		likeTerm = strings.Replace(likeTerm, c, "*"+c, -1)
  2171  	}
  2172  
  2173  	if likeTerm == "" {
  2174  		return
  2175  	}
  2176  
  2177  	// Prepare the LIKE portion of the query.
  2178  	var searchFields []string
  2179  	for _, field := range strings.Split(searchColumns, ", ") {
  2180  		if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2181  			searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*'", field, ":LikeTerm"))
  2182  		} else {
  2183  			searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*'", field, ":LikeTerm"))
  2184  		}
  2185  	}
  2186  
  2187  	likeClause = fmt.Sprintf("(%s)", strings.Join(searchFields, " OR "))
  2188  	likeTerm += "%"
  2189  	return
  2190  }
  2191  
  2192  func (s SqlChannelStore) buildFulltextClause(term string, searchColumns string) (fulltextClause, fulltextTerm string) {
  2193  	// Copy the terms as we will need to prepare them differently for each search type.
  2194  	fulltextTerm = term
  2195  
  2196  	// These chars must be treated as spaces in the fulltext query.
  2197  	for _, c := range spaceFulltextSearchChar {
  2198  		fulltextTerm = strings.Replace(fulltextTerm, c, " ", -1)
  2199  	}
  2200  
  2201  	// Prepare the FULLTEXT portion of the query.
  2202  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2203  		fulltextTerm = strings.Replace(fulltextTerm, "|", "", -1)
  2204  
  2205  		splitTerm := strings.Fields(fulltextTerm)
  2206  		for i, t := range strings.Fields(fulltextTerm) {
  2207  			if i == len(splitTerm)-1 {
  2208  				splitTerm[i] = t + ":*"
  2209  			} else {
  2210  				splitTerm[i] = t + ":* &"
  2211  			}
  2212  		}
  2213  
  2214  		fulltextTerm = strings.Join(splitTerm, " ")
  2215  
  2216  		fulltextClause = fmt.Sprintf("((%s) @@ to_tsquery(:FulltextTerm))", convertMySQLFullTextColumnsToPostgres(searchColumns))
  2217  	} else if s.DriverName() == model.DATABASE_DRIVER_MYSQL {
  2218  		splitTerm := strings.Fields(fulltextTerm)
  2219  		for i, t := range strings.Fields(fulltextTerm) {
  2220  			splitTerm[i] = "+" + t + "*"
  2221  		}
  2222  
  2223  		fulltextTerm = strings.Join(splitTerm, " ")
  2224  
  2225  		fulltextClause = fmt.Sprintf("MATCH(%s) AGAINST (:FulltextTerm IN BOOLEAN MODE)", searchColumns)
  2226  	}
  2227  
  2228  	return
  2229  }
  2230  
  2231  func (s SqlChannelStore) performSearch(searchQuery string, term string, parameters map[string]interface{}) store.StoreResult {
  2232  	result := store.StoreResult{}
  2233  
  2234  	likeClause, likeTerm := s.buildLIKEClause(term, "c.Name, c.DisplayName, c.Purpose")
  2235  	if likeTerm == "" {
  2236  		// If the likeTerm is empty after preparing, then don't bother searching.
  2237  		searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1)
  2238  	} else {
  2239  		parameters["LikeTerm"] = likeTerm
  2240  		fulltextClause, fulltextTerm := s.buildFulltextClause(term, "c.Name, c.DisplayName, c.Purpose")
  2241  		parameters["FulltextTerm"] = fulltextTerm
  2242  		searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1)
  2243  	}
  2244  
  2245  	var channels model.ChannelList
  2246  
  2247  	if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil {
  2248  		result.Err = model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError)
  2249  		return result
  2250  	}
  2251  
  2252  	result.Data = &channels
  2253  	return result
  2254  }
  2255  
  2256  func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) store.StoreChannel {
  2257  	return store.Do(func(result *store.StoreResult) {
  2258  		var dbMembers channelMemberWithSchemeRolesList
  2259  		props := make(map[string]interface{})
  2260  		idQuery := ""
  2261  
  2262  		for index, userId := range userIds {
  2263  			if len(idQuery) > 0 {
  2264  				idQuery += ", "
  2265  			}
  2266  
  2267  			props["userId"+strconv.Itoa(index)] = userId
  2268  			idQuery += ":userId" + strconv.Itoa(index)
  2269  		}
  2270  
  2271  		props["ChannelId"] = channelId
  2272  
  2273  		if _, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId IN ("+idQuery+")", props); err != nil {
  2274  			result.Err = model.NewAppError("SqlChannelStore.GetMembersByIds", "store.sql_channel.get_members_by_ids.app_error", nil, "channelId="+channelId+" "+err.Error(), http.StatusInternalServerError)
  2275  			return
  2276  		}
  2277  
  2278  		result.Data = dbMembers.ToModel()
  2279  	})
  2280  }
  2281  
  2282  func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) store.StoreChannel {
  2283  	return store.Do(func(result *store.StoreResult) {
  2284  		var channels model.ChannelList
  2285  		_, 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})
  2286  		if err != nil {
  2287  			result.Err = model.NewAppError("SqlChannelStore.GetChannelsByScheme", "store.sql_channel.get_by_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError)
  2288  			return
  2289  		}
  2290  		result.Data = channels
  2291  	})
  2292  }
  2293  
  2294  // This function does the Advanced Permissions Phase 2 migration for ChannelMember objects. It performs the migration
  2295  // in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid
  2296  // causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function
  2297  // *after* the new Schemes functionality has been used on an installation will have unintended consequences.
  2298  func (s SqlChannelStore) MigrateChannelMembers(fromChannelId string, fromUserId string) store.StoreChannel {
  2299  	return store.Do(func(result *store.StoreResult) {
  2300  		var transaction *gorp.Transaction
  2301  		var err error
  2302  
  2303  		if transaction, err = s.GetMaster().Begin(); err != nil {
  2304  			result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2305  			return
  2306  		}
  2307  
  2308  		var channelMembers []channelMember
  2309  		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 {
  2310  			result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.select.app_error", nil, err.Error(), http.StatusInternalServerError)
  2311  			return
  2312  		}
  2313  
  2314  		if len(channelMembers) == 0 {
  2315  			// No more channel members in query result means that the migration has finished.
  2316  			return
  2317  		}
  2318  
  2319  		for _, member := range channelMembers {
  2320  			roles := strings.Fields(member.Roles)
  2321  			var newRoles []string
  2322  			if !member.SchemeAdmin.Valid {
  2323  				member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true}
  2324  			}
  2325  			if !member.SchemeUser.Valid {
  2326  				member.SchemeUser = sql.NullBool{Bool: false, Valid: true}
  2327  			}
  2328  			for _, role := range roles {
  2329  				if role == model.CHANNEL_ADMIN_ROLE_ID {
  2330  					member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true}
  2331  				} else if role == model.CHANNEL_USER_ROLE_ID {
  2332  					member.SchemeUser = sql.NullBool{Bool: true, Valid: true}
  2333  				} else {
  2334  					newRoles = append(newRoles, role)
  2335  				}
  2336  			}
  2337  			member.Roles = strings.Join(newRoles, " ")
  2338  
  2339  			if _, err := transaction.Update(&member); err != nil {
  2340  				if err2 := transaction.Rollback(); err2 != nil {
  2341  					result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError)
  2342  					return
  2343  				}
  2344  				result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.update.app_error", nil, err.Error(), http.StatusInternalServerError)
  2345  				return
  2346  			}
  2347  
  2348  		}
  2349  
  2350  		if err := transaction.Commit(); err != nil {
  2351  			if err2 := transaction.Rollback(); err2 != nil {
  2352  				result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError)
  2353  				return
  2354  			}
  2355  			result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2356  			return
  2357  		}
  2358  
  2359  		data := make(map[string]string)
  2360  		data["ChannelId"] = channelMembers[len(channelMembers)-1].ChannelId
  2361  		data["UserId"] = channelMembers[len(channelMembers)-1].UserId
  2362  		result.Data = data
  2363  	})
  2364  }
  2365  
  2366  func (s SqlChannelStore) ResetAllChannelSchemes() store.StoreChannel {
  2367  	return store.Do(func(result *store.StoreResult) {
  2368  		transaction, err := s.GetMaster().Begin()
  2369  		if err != nil {
  2370  			result.Err = model.NewAppError("SqlChannelStore.ResetAllChannelSchemes", "store.sql_channel.reset_all_channel_schemes.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2371  			return
  2372  		}
  2373  
  2374  		*result = s.resetAllChannelSchemesT(transaction)
  2375  		if result.Err != nil {
  2376  			transaction.Rollback()
  2377  			return
  2378  		}
  2379  
  2380  		if err := transaction.Commit(); err != nil {
  2381  			result.Err = model.NewAppError("SqlChannelStore.ResetAllChannelSchemes", "store.sql_channel.reset_all_channel_schemes.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2382  			return
  2383  		}
  2384  	})
  2385  }
  2386  
  2387  func (s SqlChannelStore) resetAllChannelSchemesT(transaction *gorp.Transaction) store.StoreResult {
  2388  	result := store.StoreResult{}
  2389  
  2390  	if _, err := transaction.Exec("UPDATE Channels SET SchemeId=''"); err != nil {
  2391  		result.Err = model.NewAppError("SqlChannelStore.ResetAllChannelSchemes", "store.sql_channel.reset_all_channel_schemes.app_error", nil, err.Error(), http.StatusInternalServerError)
  2392  		return result
  2393  	}
  2394  
  2395  	return result
  2396  }
  2397  
  2398  func (s SqlChannelStore) ClearAllCustomRoleAssignments() store.StoreChannel {
  2399  	return store.Do(func(result *store.StoreResult) {
  2400  		builtInRoles := model.MakeDefaultRoles()
  2401  		lastUserId := strings.Repeat("0", 26)
  2402  		lastChannelId := strings.Repeat("0", 26)
  2403  
  2404  		for {
  2405  			var transaction *gorp.Transaction
  2406  			var err error
  2407  
  2408  			if transaction, err = s.GetMaster().Begin(); err != nil {
  2409  				result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2410  				return
  2411  			}
  2412  
  2413  			var channelMembers []*channelMember
  2414  			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 {
  2415  				if err2 := transaction.Rollback(); err2 != nil {
  2416  					result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError)
  2417  					return
  2418  				}
  2419  				result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.select.app_error", nil, err.Error(), http.StatusInternalServerError)
  2420  				return
  2421  			}
  2422  
  2423  			if len(channelMembers) == 0 {
  2424  				break
  2425  			}
  2426  
  2427  			for _, member := range channelMembers {
  2428  				lastUserId = member.UserId
  2429  				lastChannelId = member.ChannelId
  2430  
  2431  				var newRoles []string
  2432  
  2433  				for _, role := range strings.Fields(member.Roles) {
  2434  					for name := range builtInRoles {
  2435  						if name == role {
  2436  							newRoles = append(newRoles, role)
  2437  							break
  2438  						}
  2439  					}
  2440  				}
  2441  
  2442  				newRolesString := strings.Join(newRoles, " ")
  2443  				if newRolesString != member.Roles {
  2444  					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 {
  2445  						if err2 := transaction.Rollback(); err2 != nil {
  2446  							result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError)
  2447  							return
  2448  						}
  2449  						result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.update.app_error", nil, err.Error(), http.StatusInternalServerError)
  2450  						return
  2451  					}
  2452  				}
  2453  			}
  2454  
  2455  			if err := transaction.Commit(); err != nil {
  2456  				if err2 := transaction.Rollback(); err2 != nil {
  2457  					result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError)
  2458  					return
  2459  				}
  2460  				result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2461  				return
  2462  			}
  2463  		}
  2464  	})
  2465  }
  2466  
  2467  func (s SqlChannelStore) ResetLastPostAt() store.StoreChannel {
  2468  	return store.Do(func(result *store.StoreResult) {
  2469  		transaction, err := s.GetMaster().Begin()
  2470  		if err != nil {
  2471  			result.Err = model.NewAppError("SqlChannelStore.ResetLastPostAt", "store.sql_channel.reset_last_post_at.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2472  			return
  2473  		}
  2474  
  2475  		*result = s.resetLastPostAtT(transaction)
  2476  		if result.Err != nil {
  2477  			transaction.Rollback()
  2478  			return
  2479  		}
  2480  
  2481  		if err := transaction.Commit(); err != nil {
  2482  			result.Err = model.NewAppError("SqlChannelStore.ResetLastPostAt", "store.sql_channel.reset_last_post_at.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  2483  			return
  2484  		}
  2485  	})
  2486  }
  2487  
  2488  func (s SqlChannelStore) resetLastPostAtT(transaction *gorp.Transaction) store.StoreResult {
  2489  	result := store.StoreResult{}
  2490  
  2491  	var query string
  2492  	if s.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  2493  		query = "UPDATE Channels SET LastPostAt = COALESCE((SELECT UpdateAt FROM Posts WHERE ChannelId = Channels.Id ORDER BY UpdateAt DESC LIMIT 1), Channels.CreateAt);"
  2494  	} else {
  2495  		query = "UPDATE Channels SET LastPostAt = IFNULL((SELECT UpdateAt FROM Posts WHERE ChannelId = Channels.Id ORDER BY UpdateAt DESC LIMIT 1), Channels.CreateAt);"
  2496  	}
  2497  
  2498  	if _, err := transaction.Exec(query); err != nil {
  2499  		result.Err = model.NewAppError("SqlChannelStore.ResetLastPostAt", "store.sql_channel.reset_last_post_at.app_error", nil, err.Error(), http.StatusInternalServerError)
  2500  		return result
  2501  	}
  2502  
  2503  	return result
  2504  }
  2505  
  2506  func (s SqlChannelStore) GetAllChannelsForExportAfter(limit int, afterId string) store.StoreChannel {
  2507  	return store.Do(func(result *store.StoreResult) {
  2508  		var data []*model.ChannelForExport
  2509  		if _, err := s.GetReplica().Select(&data, `
  2510  			SELECT
  2511  				Channels.*,
  2512  				Teams.Name as TeamName,
  2513  				Schemes.Name as SchemeName
  2514  			FROM Channels
  2515  			INNER JOIN
  2516  				Teams ON Channels.TeamId = Teams.Id
  2517  			LEFT JOIN
  2518  				Schemes ON Channels.SchemeId = Schemes.Id
  2519  			WHERE
  2520  				Channels.Id > :AfterId
  2521  				AND Channels.Type IN ('O', 'P')
  2522  			ORDER BY
  2523  				Id
  2524  			LIMIT :Limit`,
  2525  			map[string]interface{}{"AfterId": afterId, "Limit": limit}); err != nil {
  2526  			result.Err = model.NewAppError("SqlTeamStore.GetAllChannelsForExportAfter", "store.sql_channel.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
  2527  			return
  2528  		}
  2529  
  2530  		result.Data = data
  2531  	})
  2532  }
  2533  
  2534  func (s SqlChannelStore) GetChannelMembersForExport(userId string, teamId string) store.StoreChannel {
  2535  	return store.Do(func(result *store.StoreResult) {
  2536  		var members []*model.ChannelMemberForExport
  2537  		_, err := s.GetReplica().Select(&members, `
  2538              SELECT
  2539                  ChannelMembers.*,
  2540                  Channels.Name as ChannelName
  2541              FROM
  2542                  ChannelMembers
  2543              INNER JOIN
  2544                  Channels ON ChannelMembers.ChannelId = Channels.Id
  2545              WHERE
  2546                  ChannelMembers.UserId = :UserId
  2547  				AND Channels.TeamId = :TeamId
  2548  				AND Channels.DeleteAt = 0`,
  2549  			map[string]interface{}{"TeamId": teamId, "UserId": userId})
  2550  
  2551  		if err != nil {
  2552  			result.Err = model.NewAppError("SqlChannelStore.GetChannelMembersForExport", "store.sql_channel.get_members.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError)
  2553  			return
  2554  		}
  2555  
  2556  		result.Data = members
  2557  	})
  2558  }