github.com/mad-app/mattermost-server@v5.11.1+incompatible/store/sqlstore/user_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  	"strings"
    12  
    13  	sq "github.com/Masterminds/squirrel"
    14  	"github.com/mattermost/gorp"
    15  
    16  	"github.com/mattermost/mattermost-server/einterfaces"
    17  	"github.com/mattermost/mattermost-server/model"
    18  	"github.com/mattermost/mattermost-server/store"
    19  	"github.com/mattermost/mattermost-server/utils"
    20  )
    21  
    22  const (
    23  	PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE
    24  	PROFILES_IN_CHANNEL_CACHE_SEC  = 900 // 15 mins
    25  	PROFILE_BY_IDS_CACHE_SIZE      = model.SESSION_CACHE_SIZE
    26  	PROFILE_BY_IDS_CACHE_SEC       = 900 // 15 mins
    27  )
    28  
    29  var (
    30  	USER_SEARCH_TYPE_NAMES_NO_FULL_NAME = []string{"Username", "Nickname"}
    31  	USER_SEARCH_TYPE_NAMES              = []string{"Username", "FirstName", "LastName", "Nickname"}
    32  	USER_SEARCH_TYPE_ALL_NO_FULL_NAME   = []string{"Username", "Nickname", "Email"}
    33  	USER_SEARCH_TYPE_ALL                = []string{"Username", "FirstName", "LastName", "Nickname", "Email"}
    34  )
    35  
    36  type SqlUserStore struct {
    37  	SqlStore
    38  	metrics einterfaces.MetricsInterface
    39  
    40  	// usersQuery is a starting point for all queries that return one or more Users.
    41  	usersQuery sq.SelectBuilder
    42  }
    43  
    44  var profilesInChannelCache *utils.Cache = utils.NewLru(PROFILES_IN_CHANNEL_CACHE_SIZE)
    45  var profileByIdsCache *utils.Cache = utils.NewLru(PROFILE_BY_IDS_CACHE_SIZE)
    46  
    47  func (us SqlUserStore) ClearCaches() {
    48  	profilesInChannelCache.Purge()
    49  	profileByIdsCache.Purge()
    50  
    51  	if us.metrics != nil {
    52  		us.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Purge")
    53  		us.metrics.IncrementMemCacheInvalidationCounter("Profile By Ids - Purge")
    54  	}
    55  }
    56  
    57  func (us SqlUserStore) InvalidatProfileCacheForUser(userId string) {
    58  	profileByIdsCache.Remove(userId)
    59  
    60  	if us.metrics != nil {
    61  		us.metrics.IncrementMemCacheInvalidationCounter("Profile By Ids - Remove")
    62  	}
    63  }
    64  
    65  func NewSqlUserStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.UserStore {
    66  	us := &SqlUserStore{
    67  		SqlStore: sqlStore,
    68  		metrics:  metrics,
    69  	}
    70  
    71  	us.usersQuery = us.getQueryBuilder().
    72  		Select("u.*", "b.UserId IS NOT NULL AS IsBot").
    73  		From("Users u").
    74  		LeftJoin("Bots b ON ( b.UserId = u.Id )")
    75  
    76  	for _, db := range sqlStore.GetAllConns() {
    77  		table := db.AddTableWithName(model.User{}, "Users").SetKeys(false, "Id")
    78  		table.ColMap("Id").SetMaxSize(26)
    79  		table.ColMap("Username").SetMaxSize(64).SetUnique(true)
    80  		table.ColMap("Password").SetMaxSize(128)
    81  		table.ColMap("AuthData").SetMaxSize(128).SetUnique(true)
    82  		table.ColMap("AuthService").SetMaxSize(32)
    83  		table.ColMap("Email").SetMaxSize(128).SetUnique(true)
    84  		table.ColMap("Nickname").SetMaxSize(64)
    85  		table.ColMap("FirstName").SetMaxSize(64)
    86  		table.ColMap("LastName").SetMaxSize(64)
    87  		table.ColMap("Roles").SetMaxSize(256)
    88  		table.ColMap("Props").SetMaxSize(4000)
    89  		table.ColMap("NotifyProps").SetMaxSize(2000)
    90  		table.ColMap("Locale").SetMaxSize(5)
    91  		table.ColMap("MfaSecret").SetMaxSize(128)
    92  		table.ColMap("Position").SetMaxSize(128)
    93  		table.ColMap("Timezone").SetMaxSize(256)
    94  	}
    95  
    96  	return us
    97  }
    98  
    99  func (us SqlUserStore) CreateIndexesIfNotExists() {
   100  	us.CreateIndexIfNotExists("idx_users_email", "Users", "Email")
   101  	us.CreateIndexIfNotExists("idx_users_update_at", "Users", "UpdateAt")
   102  	us.CreateIndexIfNotExists("idx_users_create_at", "Users", "CreateAt")
   103  	us.CreateIndexIfNotExists("idx_users_delete_at", "Users", "DeleteAt")
   104  
   105  	if us.DriverName() == model.DATABASE_DRIVER_POSTGRES {
   106  		us.CreateIndexIfNotExists("idx_users_email_lower_textpattern", "Users", "lower(Email) text_pattern_ops")
   107  		us.CreateIndexIfNotExists("idx_users_username_lower_textpattern", "Users", "lower(Username) text_pattern_ops")
   108  		us.CreateIndexIfNotExists("idx_users_nickname_lower_textpattern", "Users", "lower(Nickname) text_pattern_ops")
   109  		us.CreateIndexIfNotExists("idx_users_firstname_lower_textpattern", "Users", "lower(FirstName) text_pattern_ops")
   110  		us.CreateIndexIfNotExists("idx_users_lastname_lower_textpattern", "Users", "lower(LastName) text_pattern_ops")
   111  	}
   112  
   113  	us.CreateFullTextIndexIfNotExists("idx_users_all_txt", "Users", strings.Join(USER_SEARCH_TYPE_ALL, ", "))
   114  	us.CreateFullTextIndexIfNotExists("idx_users_all_no_full_name_txt", "Users", strings.Join(USER_SEARCH_TYPE_ALL_NO_FULL_NAME, ", "))
   115  	us.CreateFullTextIndexIfNotExists("idx_users_names_txt", "Users", strings.Join(USER_SEARCH_TYPE_NAMES, ", "))
   116  	us.CreateFullTextIndexIfNotExists("idx_users_names_no_full_name_txt", "Users", strings.Join(USER_SEARCH_TYPE_NAMES_NO_FULL_NAME, ", "))
   117  }
   118  
   119  func (us SqlUserStore) Save(user *model.User) store.StoreChannel {
   120  	return store.Do(func(result *store.StoreResult) {
   121  		if len(user.Id) > 0 {
   122  			result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.existing.app_error", nil, "user_id="+user.Id, http.StatusBadRequest)
   123  			return
   124  		}
   125  
   126  		user.PreSave()
   127  		if result.Err = user.IsValid(); result.Err != nil {
   128  			return
   129  		}
   130  
   131  		if err := us.GetMaster().Insert(user); err != nil {
   132  			if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique"}) {
   133  				result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.email_exists.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest)
   134  			} else if IsUniqueConstraintError(err, []string{"Username", "users_username_key", "idx_users_username_unique"}) {
   135  				result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.username_exists.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest)
   136  			} else {
   137  				result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusInternalServerError)
   138  			}
   139  		} else {
   140  			result.Data = user
   141  		}
   142  	})
   143  }
   144  
   145  func (us SqlUserStore) Update(user *model.User, trustedUpdateData bool) store.StoreChannel {
   146  	return store.Do(func(result *store.StoreResult) {
   147  		user.PreUpdate()
   148  
   149  		if result.Err = user.IsValid(); result.Err != nil {
   150  			return
   151  		}
   152  
   153  		if oldUserResult, err := us.GetMaster().Get(model.User{}, user.Id); err != nil {
   154  			result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.finding.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusInternalServerError)
   155  		} else if oldUserResult == nil {
   156  			result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.find.app_error", nil, "user_id="+user.Id, http.StatusBadRequest)
   157  		} else {
   158  			oldUser := oldUserResult.(*model.User)
   159  			user.CreateAt = oldUser.CreateAt
   160  			user.AuthData = oldUser.AuthData
   161  			user.AuthService = oldUser.AuthService
   162  			user.Password = oldUser.Password
   163  			user.LastPasswordUpdate = oldUser.LastPasswordUpdate
   164  			user.LastPictureUpdate = oldUser.LastPictureUpdate
   165  			user.EmailVerified = oldUser.EmailVerified
   166  			user.FailedAttempts = oldUser.FailedAttempts
   167  			user.MfaSecret = oldUser.MfaSecret
   168  			user.MfaActive = oldUser.MfaActive
   169  
   170  			if !trustedUpdateData {
   171  				user.Roles = oldUser.Roles
   172  				user.DeleteAt = oldUser.DeleteAt
   173  			}
   174  
   175  			if user.IsOAuthUser() {
   176  				if !trustedUpdateData {
   177  					user.Email = oldUser.Email
   178  				}
   179  			} else if user.IsLDAPUser() && !trustedUpdateData {
   180  				if user.Username != oldUser.Username ||
   181  					user.Email != oldUser.Email {
   182  					result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.can_not_change_ldap.app_error", nil, "user_id="+user.Id, http.StatusBadRequest)
   183  					return
   184  				}
   185  			} else if user.Email != oldUser.Email {
   186  				user.EmailVerified = false
   187  			}
   188  
   189  			if user.Username != oldUser.Username {
   190  				user.UpdateMentionKeysFromUsername(oldUser.Username)
   191  			}
   192  
   193  			if count, err := us.GetMaster().Update(user); err != nil {
   194  				if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique"}) {
   195  					result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.email_taken.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest)
   196  				} else if IsUniqueConstraintError(err, []string{"Username", "users_username_key", "idx_users_username_unique"}) {
   197  					result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.username_taken.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest)
   198  				} else {
   199  					result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.updating.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusInternalServerError)
   200  				}
   201  			} else if count != 1 {
   202  				result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.app_error", nil, fmt.Sprintf("user_id=%v, count=%v", user.Id, count), http.StatusInternalServerError)
   203  			} else {
   204  				user.Sanitize(map[string]bool{})
   205  				oldUser.Sanitize(map[string]bool{})
   206  				result.Data = [2]*model.User{user, oldUser}
   207  			}
   208  		}
   209  	})
   210  }
   211  
   212  func (us SqlUserStore) UpdateLastPictureUpdate(userId string) store.StoreChannel {
   213  	return store.Do(func(result *store.StoreResult) {
   214  		curTime := model.GetMillis()
   215  
   216  		if _, err := us.GetMaster().Exec("UPDATE Users SET LastPictureUpdate = :Time, UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"Time": curTime, "UserId": userId}); err != nil {
   217  			result.Err = model.NewAppError("SqlUserStore.UpdateLastPictureUpdate", "store.sql_user.update_last_picture_update.app_error", nil, "user_id="+userId, http.StatusInternalServerError)
   218  		} else {
   219  			result.Data = userId
   220  		}
   221  	})
   222  }
   223  
   224  func (us SqlUserStore) ResetLastPictureUpdate(userId string) store.StoreChannel {
   225  	return store.Do(func(result *store.StoreResult) {
   226  		if _, err := us.GetMaster().Exec("UPDATE Users SET LastPictureUpdate = :Time, UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"Time": 0, "UserId": userId}); err != nil {
   227  			result.Err = model.NewAppError("SqlUserStore.ResetLastPictureUpdate", "store.sql_user.update_last_picture_update.app_error", nil, "user_id="+userId, http.StatusInternalServerError)
   228  		} else {
   229  			result.Data = userId
   230  		}
   231  	})
   232  }
   233  
   234  func (us SqlUserStore) UpdateUpdateAt(userId string) store.StoreChannel {
   235  	return store.Do(func(result *store.StoreResult) {
   236  		curTime := model.GetMillis()
   237  
   238  		if _, err := us.GetMaster().Exec("UPDATE Users SET UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"Time": curTime, "UserId": userId}); err != nil {
   239  			result.Err = model.NewAppError("SqlUserStore.UpdateUpdateAt", "store.sql_user.update_update.app_error", nil, "user_id="+userId, http.StatusInternalServerError)
   240  			return
   241  		}
   242  
   243  		result.Data = curTime
   244  	})
   245  }
   246  
   247  func (us SqlUserStore) UpdatePassword(userId, hashedPassword string) store.StoreChannel {
   248  	return store.Do(func(result *store.StoreResult) {
   249  		updateAt := model.GetMillis()
   250  
   251  		if _, err := us.GetMaster().Exec("UPDATE Users SET Password = :Password, LastPasswordUpdate = :LastPasswordUpdate, UpdateAt = :UpdateAt, AuthData = NULL, AuthService = '', FailedAttempts = 0 WHERE Id = :UserId", map[string]interface{}{"Password": hashedPassword, "LastPasswordUpdate": updateAt, "UpdateAt": updateAt, "UserId": userId}); err != nil {
   252  			result.Err = model.NewAppError("SqlUserStore.UpdatePassword", "store.sql_user.update_password.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError)
   253  		} else {
   254  			result.Data = userId
   255  		}
   256  	})
   257  }
   258  
   259  func (us SqlUserStore) UpdateFailedPasswordAttempts(userId string, attempts int) store.StoreChannel {
   260  	return store.Do(func(result *store.StoreResult) {
   261  		if _, err := us.GetMaster().Exec("UPDATE Users SET FailedAttempts = :FailedAttempts WHERE Id = :UserId", map[string]interface{}{"FailedAttempts": attempts, "UserId": userId}); err != nil {
   262  			result.Err = model.NewAppError("SqlUserStore.UpdateFailedPasswordAttempts", "store.sql_user.update_failed_pwd_attempts.app_error", nil, "user_id="+userId, http.StatusInternalServerError)
   263  		} else {
   264  			result.Data = userId
   265  		}
   266  	})
   267  }
   268  
   269  func (us SqlUserStore) UpdateAuthData(userId string, service string, authData *string, email string, resetMfa bool) store.StoreChannel {
   270  	return store.Do(func(result *store.StoreResult) {
   271  		email = strings.ToLower(email)
   272  
   273  		updateAt := model.GetMillis()
   274  
   275  		query := `
   276  			UPDATE
   277  			     Users
   278  			SET
   279  			     Password = '',
   280  			     LastPasswordUpdate = :LastPasswordUpdate,
   281  			     UpdateAt = :UpdateAt,
   282  			     FailedAttempts = 0,
   283  			     AuthService = :AuthService,
   284  			     AuthData = :AuthData`
   285  
   286  		if len(email) != 0 {
   287  			query += ", Email = :Email"
   288  		}
   289  
   290  		if resetMfa {
   291  			query += ", MfaActive = false, MfaSecret = ''"
   292  		}
   293  
   294  		query += " WHERE Id = :UserId"
   295  
   296  		if _, err := us.GetMaster().Exec(query, map[string]interface{}{"LastPasswordUpdate": updateAt, "UpdateAt": updateAt, "UserId": userId, "AuthService": service, "AuthData": authData, "Email": email}); err != nil {
   297  			if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique", "AuthData", "users_authdata_key"}) {
   298  				result.Err = model.NewAppError("SqlUserStore.UpdateAuthData", "store.sql_user.update_auth_data.email_exists.app_error", map[string]interface{}{"Service": service, "Email": email}, "user_id="+userId+", "+err.Error(), http.StatusBadRequest)
   299  			} else {
   300  				result.Err = model.NewAppError("SqlUserStore.UpdateAuthData", "store.sql_user.update_auth_data.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError)
   301  			}
   302  		} else {
   303  			result.Data = userId
   304  		}
   305  	})
   306  }
   307  
   308  func (us SqlUserStore) UpdateMfaSecret(userId, secret string) store.StoreChannel {
   309  	return store.Do(func(result *store.StoreResult) {
   310  		updateAt := model.GetMillis()
   311  
   312  		if _, err := us.GetMaster().Exec("UPDATE Users SET MfaSecret = :Secret, UpdateAt = :UpdateAt WHERE Id = :UserId", map[string]interface{}{"Secret": secret, "UpdateAt": updateAt, "UserId": userId}); err != nil {
   313  			result.Err = model.NewAppError("SqlUserStore.UpdateMfaSecret", "store.sql_user.update_mfa_secret.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError)
   314  		} else {
   315  			result.Data = userId
   316  		}
   317  	})
   318  }
   319  
   320  func (us SqlUserStore) UpdateMfaActive(userId string, active bool) store.StoreChannel {
   321  	return store.Do(func(result *store.StoreResult) {
   322  		updateAt := model.GetMillis()
   323  
   324  		if _, err := us.GetMaster().Exec("UPDATE Users SET MfaActive = :Active, UpdateAt = :UpdateAt WHERE Id = :UserId", map[string]interface{}{"Active": active, "UpdateAt": updateAt, "UserId": userId}); err != nil {
   325  			result.Err = model.NewAppError("SqlUserStore.UpdateMfaActive", "store.sql_user.update_mfa_active.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError)
   326  		} else {
   327  			result.Data = userId
   328  		}
   329  	})
   330  }
   331  
   332  func (us SqlUserStore) Get(id string) store.StoreChannel {
   333  	return store.Do(func(result *store.StoreResult) {
   334  		query := us.usersQuery.Where("Id = ?", id)
   335  
   336  		queryString, args, err := query.ToSql()
   337  		if err != nil {
   338  			result.Err = model.NewAppError("SqlUserStore.Get", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   339  			return
   340  		}
   341  
   342  		user := &model.User{}
   343  		if err := us.GetReplica().SelectOne(user, queryString, args...); err == sql.ErrNoRows {
   344  			result.Err = model.NewAppError("SqlUserStore.Get", store.MISSING_ACCOUNT_ERROR, nil, "user_id="+id, http.StatusNotFound)
   345  			return
   346  		} else if err != nil {
   347  			result.Err = model.NewAppError("SqlUserStore.Get", "store.sql_user.get.app_error", nil, "user_id="+id+", "+err.Error(), http.StatusInternalServerError)
   348  			return
   349  		}
   350  
   351  		result.Data = user
   352  	})
   353  }
   354  
   355  func (us SqlUserStore) GetAll() store.StoreChannel {
   356  	return store.Do(func(result *store.StoreResult) {
   357  		query := us.usersQuery.OrderBy("Username ASC")
   358  
   359  		queryString, args, err := query.ToSql()
   360  		if err != nil {
   361  			result.Err = model.NewAppError("SqlUserStore.GetAll", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   362  			return
   363  		}
   364  
   365  		var data []*model.User
   366  		if _, err := us.GetReplica().Select(&data, queryString, args...); err != nil {
   367  			result.Err = model.NewAppError("SqlUserStore.GetAll", "store.sql_user.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   368  			return
   369  		}
   370  
   371  		result.Data = data
   372  	})
   373  }
   374  
   375  func (us SqlUserStore) GetAllAfter(limit int, afterId string) store.StoreChannel {
   376  	return store.Do(func(result *store.StoreResult) {
   377  		query := us.usersQuery.
   378  			Where("Id > ?", afterId).
   379  			OrderBy("Id ASC").
   380  			Limit(uint64(limit))
   381  
   382  		queryString, args, err := query.ToSql()
   383  		if err != nil {
   384  			result.Err = model.NewAppError("SqlUserStore.GetAllAfter", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   385  			return
   386  		}
   387  
   388  		var data []*model.User
   389  		if _, err := us.GetReplica().Select(&data, queryString, args...); err != nil {
   390  			result.Err = model.NewAppError("SqlUserStore.GetAllAfter", "store.sql_user.get.app_error", nil, err.Error(), http.StatusInternalServerError)
   391  		}
   392  
   393  		result.Data = data
   394  	})
   395  }
   396  
   397  func (s SqlUserStore) GetEtagForAllProfiles() store.StoreChannel {
   398  	return store.Do(func(result *store.StoreResult) {
   399  		updateAt, err := s.GetReplica().SelectInt("SELECT UpdateAt FROM Users ORDER BY UpdateAt DESC LIMIT 1")
   400  		if err != nil {
   401  			result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis())
   402  		} else {
   403  			result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, updateAt)
   404  		}
   405  	})
   406  }
   407  
   408  func (us SqlUserStore) GetAllProfiles(options *model.UserGetOptions) store.StoreChannel {
   409  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
   410  	return store.Do(func(result *store.StoreResult) {
   411  		query := us.usersQuery.
   412  			OrderBy("u.Username ASC").
   413  			Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
   414  
   415  		query = applyRoleFilter(query, options.Role, isPostgreSQL)
   416  
   417  		if options.Inactive {
   418  			query = query.Where("u.DeleteAt != 0")
   419  		}
   420  
   421  		queryString, args, err := query.ToSql()
   422  		if err != nil {
   423  			result.Err = model.NewAppError("SqlUserStore.GetAllProfiles", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   424  			return
   425  		}
   426  
   427  		var users []*model.User
   428  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   429  			result.Err = model.NewAppError("SqlUserStore.GetAllProfiles", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   430  			return
   431  		}
   432  
   433  		for _, u := range users {
   434  			u.Sanitize(map[string]bool{})
   435  		}
   436  
   437  		result.Data = users
   438  	})
   439  }
   440  
   441  func applyRoleFilter(query sq.SelectBuilder, role string, isPostgreSQL bool) sq.SelectBuilder {
   442  	if role == "" {
   443  		return query
   444  	}
   445  
   446  	roleParam := fmt.Sprintf("%%%s%%", role)
   447  	if isPostgreSQL {
   448  		return query.Where("u.Roles LIKE LOWER(?)", roleParam)
   449  	}
   450  
   451  	return query.Where("u.Roles LIKE ? ESCAPE '*'", roleParam)
   452  }
   453  
   454  func (s SqlUserStore) GetEtagForProfiles(teamId string) store.StoreChannel {
   455  	return store.Do(func(result *store.StoreResult) {
   456  		updateAt, err := s.GetReplica().SelectInt("SELECT UpdateAt FROM Users, TeamMembers WHERE TeamMembers.TeamId = :TeamId AND Users.Id = TeamMembers.UserId ORDER BY UpdateAt DESC LIMIT 1", map[string]interface{}{"TeamId": teamId})
   457  		if err != nil {
   458  			result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis())
   459  		} else {
   460  			result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, updateAt)
   461  		}
   462  	})
   463  }
   464  
   465  func (us SqlUserStore) GetProfiles(options *model.UserGetOptions) store.StoreChannel {
   466  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
   467  	return store.Do(func(result *store.StoreResult) {
   468  		query := us.usersQuery.
   469  			Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 )").
   470  			Where("tm.TeamId = ?", options.InTeamId).
   471  			OrderBy("u.Username ASC").
   472  			Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
   473  
   474  		query = applyRoleFilter(query, options.Role, isPostgreSQL)
   475  
   476  		if options.Inactive {
   477  			query = query.Where("u.DeleteAt != 0")
   478  		}
   479  
   480  		queryString, args, err := query.ToSql()
   481  		if err != nil {
   482  			result.Err = model.NewAppError("SqlUserStore.GetProfiles", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   483  			return
   484  		}
   485  
   486  		var users []*model.User
   487  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   488  			result.Err = model.NewAppError("SqlUserStore.GetProfiles", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   489  			return
   490  		}
   491  
   492  		for _, u := range users {
   493  			u.Sanitize(map[string]bool{})
   494  		}
   495  		result.Data = users
   496  	})
   497  }
   498  
   499  func (us SqlUserStore) InvalidateProfilesInChannelCacheByUser(userId string) {
   500  	keys := profilesInChannelCache.Keys()
   501  
   502  	for _, key := range keys {
   503  		if cacheItem, ok := profilesInChannelCache.Get(key); ok {
   504  			userMap := cacheItem.(map[string]*model.User)
   505  			if _, userInCache := userMap[userId]; userInCache {
   506  				profilesInChannelCache.Remove(key)
   507  				if us.metrics != nil {
   508  					us.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by User")
   509  				}
   510  			}
   511  		}
   512  	}
   513  }
   514  
   515  func (us SqlUserStore) InvalidateProfilesInChannelCache(channelId string) {
   516  	profilesInChannelCache.Remove(channelId)
   517  	if us.metrics != nil {
   518  		us.metrics.IncrementMemCacheInvalidationCounter("Profiles in Channel - Remove by Channel")
   519  	}
   520  }
   521  
   522  func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit int) store.StoreChannel {
   523  	return store.Do(func(result *store.StoreResult) {
   524  		query := us.usersQuery.
   525  			Join("ChannelMembers cm ON ( cm.UserId = u.Id )").
   526  			Where("cm.ChannelId = ?", channelId).
   527  			OrderBy("u.Username ASC").
   528  			Offset(uint64(offset)).Limit(uint64(limit))
   529  
   530  		queryString, args, err := query.ToSql()
   531  		if err != nil {
   532  			result.Err = model.NewAppError("SqlUserStore.GetProfilesInChannel", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   533  			return
   534  		}
   535  
   536  		var users []*model.User
   537  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   538  			result.Err = model.NewAppError("SqlUserStore.GetProfilesInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   539  			return
   540  		}
   541  
   542  		for _, u := range users {
   543  			u.Sanitize(map[string]bool{})
   544  		}
   545  
   546  		result.Data = users
   547  	})
   548  }
   549  
   550  func (us SqlUserStore) GetProfilesInChannelByStatus(channelId string, offset int, limit int) store.StoreChannel {
   551  	return store.Do(func(result *store.StoreResult) {
   552  		query := us.usersQuery.
   553  			Join("ChannelMembers cm ON ( cm.UserId = u.Id )").
   554  			LeftJoin("Status s ON ( s.UserId = u.Id )").
   555  			Where("cm.ChannelId = ?", channelId).
   556  			OrderBy(`
   557  				CASE s.Status
   558  					WHEN 'online' THEN 1
   559  					WHEN 'away' THEN 2
   560  					WHEN 'dnd' THEN 3
   561  					ELSE 4
   562  				END
   563  			`).
   564  			OrderBy("u.Username ASC").
   565  			Offset(uint64(offset)).Limit(uint64(limit))
   566  
   567  		queryString, args, err := query.ToSql()
   568  		if err != nil {
   569  			result.Err = model.NewAppError("SqlUserStore.GetProfilesInChannelByStatus", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   570  			return
   571  		}
   572  
   573  		var users []*model.User
   574  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   575  			result.Err = model.NewAppError("SqlUserStore.GetProfilesInChannelByStatus", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   576  			return
   577  		}
   578  
   579  		for _, u := range users {
   580  			u.Sanitize(map[string]bool{})
   581  		}
   582  
   583  		result.Data = users
   584  	})
   585  }
   586  
   587  func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) store.StoreChannel {
   588  	return store.Do(func(result *store.StoreResult) {
   589  		if allowFromCache {
   590  			if cacheItem, ok := profilesInChannelCache.Get(channelId); ok {
   591  				if us.metrics != nil {
   592  					us.metrics.IncrementMemCacheHitCounter("Profiles in Channel")
   593  				}
   594  				result.Data = cacheItem.(map[string]*model.User)
   595  				return
   596  			} else {
   597  				if us.metrics != nil {
   598  					us.metrics.IncrementMemCacheMissCounter("Profiles in Channel")
   599  				}
   600  			}
   601  		} else {
   602  			if us.metrics != nil {
   603  				us.metrics.IncrementMemCacheMissCounter("Profiles in Channel")
   604  			}
   605  		}
   606  
   607  		query := us.usersQuery.
   608  			Join("ChannelMembers cm ON ( cm.UserId = u.Id )").
   609  			Where("cm.ChannelId = ?", channelId).
   610  			Where("u.DeleteAt = 0").
   611  			OrderBy("u.Username ASC")
   612  
   613  		queryString, args, err := query.ToSql()
   614  		if err != nil {
   615  			result.Err = model.NewAppError("SqlUserStore.GetAllProfilesInChannel", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   616  			return
   617  		}
   618  
   619  		var users []*model.User
   620  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   621  			result.Err = model.NewAppError("SqlUserStore.GetAllProfilesInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   622  			return
   623  		}
   624  
   625  		userMap := make(map[string]*model.User)
   626  
   627  		for _, u := range users {
   628  			u.Sanitize(map[string]bool{})
   629  			userMap[u.Id] = u
   630  		}
   631  
   632  		result.Data = userMap
   633  
   634  		if allowFromCache {
   635  			profilesInChannelCache.AddWithExpiresInSecs(channelId, userMap, PROFILES_IN_CHANNEL_CACHE_SEC)
   636  		}
   637  	})
   638  }
   639  
   640  func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int) store.StoreChannel {
   641  	return store.Do(func(result *store.StoreResult) {
   642  		query := us.usersQuery.
   643  			Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
   644  			LeftJoin("ChannelMembers cm ON ( cm.UserId = u.Id AND cm.ChannelId = ? )", channelId).
   645  			Where("cm.UserId IS NULL").
   646  			OrderBy("u.Username ASC").
   647  			Offset(uint64(offset)).Limit(uint64(limit))
   648  
   649  		queryString, args, err := query.ToSql()
   650  		if err != nil {
   651  			result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInChannel", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   652  			return
   653  		}
   654  
   655  		var users []*model.User
   656  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   657  			result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   658  			return
   659  		}
   660  
   661  		for _, u := range users {
   662  			u.Sanitize(map[string]bool{})
   663  		}
   664  
   665  		result.Data = users
   666  	})
   667  }
   668  
   669  func (us SqlUserStore) GetProfilesWithoutTeam(offset int, limit int) store.StoreChannel {
   670  	return store.Do(func(result *store.StoreResult) {
   671  		query := us.usersQuery.
   672  			Where(`(
   673  				SELECT
   674  					COUNT(0)
   675  				FROM
   676  					TeamMembers
   677  				WHERE
   678  					TeamMembers.UserId = u.Id
   679  					AND TeamMembers.DeleteAt = 0
   680  			) = 0`).
   681  			OrderBy("u.Username ASC").
   682  			Offset(uint64(offset)).Limit(uint64(limit))
   683  
   684  		queryString, args, err := query.ToSql()
   685  		if err != nil {
   686  			result.Err = model.NewAppError("SqlUserStore.GetProfilesWithoutTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   687  			return
   688  		}
   689  
   690  		var users []*model.User
   691  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   692  			result.Err = model.NewAppError("SqlUserStore.GetProfilesWithoutTeam", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   693  			return
   694  		}
   695  
   696  		for _, u := range users {
   697  			u.Sanitize(map[string]bool{})
   698  		}
   699  
   700  		result.Data = users
   701  	})
   702  }
   703  
   704  func (us SqlUserStore) GetProfilesByUsernames(usernames []string, teamId string) store.StoreChannel {
   705  	return store.Do(func(result *store.StoreResult) {
   706  		query := us.usersQuery
   707  
   708  		if teamId != "" {
   709  			query = query.Join("TeamMembers tm ON (tm.UserId = u.Id AND tm.TeamId = ?)", teamId)
   710  		}
   711  
   712  		query = query.
   713  			Where(map[string]interface{}{
   714  				"Username": usernames,
   715  			}).
   716  			OrderBy("u.Username ASC")
   717  
   718  		queryString, args, err := query.ToSql()
   719  		if err != nil {
   720  			result.Err = model.NewAppError("SqlUserStore.GetProfilesByUsernames", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   721  			return
   722  		}
   723  
   724  		var users []*model.User
   725  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   726  			result.Err = model.NewAppError("SqlUserStore.GetProfilesByUsernames", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   727  			return
   728  		}
   729  
   730  		result.Data = users
   731  	})
   732  }
   733  
   734  type UserWithLastActivityAt struct {
   735  	model.User
   736  	LastActivityAt int64
   737  }
   738  
   739  func (us SqlUserStore) GetRecentlyActiveUsersForTeam(teamId string, offset, limit int) store.StoreChannel {
   740  	return store.Do(func(result *store.StoreResult) {
   741  		query := us.usersQuery.
   742  			Column("s.LastActivityAt").
   743  			Join("TeamMembers tm ON (tm.UserId = u.Id AND tm.TeamId = ?)", teamId).
   744  			Join("Status s ON (s.UserId = u.Id)").
   745  			OrderBy("s.LastActivityAt DESC").
   746  			OrderBy("u.Username ASC").
   747  			Offset(uint64(offset)).Limit(uint64(limit))
   748  
   749  		queryString, args, err := query.ToSql()
   750  		if err != nil {
   751  			result.Err = model.NewAppError("SqlUserStore.GetRecentlyActiveUsers", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   752  			return
   753  		}
   754  
   755  		var users []*UserWithLastActivityAt
   756  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   757  			result.Err = model.NewAppError("SqlUserStore.GetRecentlyActiveUsers", "store.sql_user.get_recently_active_users.app_error", nil, err.Error(), http.StatusInternalServerError)
   758  			return
   759  		}
   760  
   761  		userList := []*model.User{}
   762  
   763  		for _, userWithLastActivityAt := range users {
   764  			u := userWithLastActivityAt.User
   765  			u.Sanitize(map[string]bool{})
   766  			u.LastActivityAt = userWithLastActivityAt.LastActivityAt
   767  			userList = append(userList, &u)
   768  		}
   769  
   770  		result.Data = userList
   771  	})
   772  }
   773  
   774  func (us SqlUserStore) GetNewUsersForTeam(teamId string, offset, limit int) store.StoreChannel {
   775  	return store.Do(func(result *store.StoreResult) {
   776  		query := us.usersQuery.
   777  			Join("TeamMembers tm ON (tm.UserId = u.Id AND tm.TeamId = ?)", teamId).
   778  			OrderBy("u.CreateAt DESC").
   779  			OrderBy("u.Username ASC").
   780  			Offset(uint64(offset)).Limit(uint64(limit))
   781  
   782  		queryString, args, err := query.ToSql()
   783  		if err != nil {
   784  			result.Err = model.NewAppError("SqlUserStore.GetNewUsersForTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   785  			return
   786  		}
   787  
   788  		var users []*model.User
   789  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   790  			result.Err = model.NewAppError("SqlUserStore.GetNewUsersForTeam", "store.sql_user.get_new_users.app_error", nil, err.Error(), http.StatusInternalServerError)
   791  			return
   792  		}
   793  
   794  		for _, u := range users {
   795  			u.Sanitize(map[string]bool{})
   796  		}
   797  
   798  		result.Data = users
   799  	})
   800  }
   801  
   802  func (us SqlUserStore) GetProfileByIds(userIds []string, allowFromCache bool) store.StoreChannel {
   803  	return store.Do(func(result *store.StoreResult) {
   804  		users := []*model.User{}
   805  		remainingUserIds := make([]string, 0)
   806  
   807  		if allowFromCache {
   808  			for _, userId := range userIds {
   809  				if cacheItem, ok := profileByIdsCache.Get(userId); ok {
   810  					u := &model.User{}
   811  					*u = *cacheItem.(*model.User)
   812  					users = append(users, u)
   813  				} else {
   814  					remainingUserIds = append(remainingUserIds, userId)
   815  				}
   816  			}
   817  			if us.metrics != nil {
   818  				us.metrics.AddMemCacheHitCounter("Profile By Ids", float64(len(users)))
   819  				us.metrics.AddMemCacheMissCounter("Profile By Ids", float64(len(remainingUserIds)))
   820  			}
   821  		} else {
   822  			remainingUserIds = userIds
   823  			if us.metrics != nil {
   824  				us.metrics.AddMemCacheMissCounter("Profile By Ids", float64(len(remainingUserIds)))
   825  			}
   826  		}
   827  
   828  		// If everything came from the cache then just return
   829  		if len(remainingUserIds) == 0 {
   830  			result.Data = users
   831  			return
   832  		}
   833  
   834  		query := us.usersQuery.
   835  			Where(map[string]interface{}{
   836  				"u.Id": remainingUserIds,
   837  			}).
   838  			OrderBy("u.Username ASC")
   839  
   840  		queryString, args, err := query.ToSql()
   841  		if err != nil {
   842  			result.Err = model.NewAppError("SqlUserStore.GetProfileByIds", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   843  			return
   844  		}
   845  
   846  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   847  			result.Err = model.NewAppError("SqlUserStore.GetProfileByIds", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   848  			return
   849  		}
   850  
   851  		for _, u := range users {
   852  			u.Sanitize(map[string]bool{})
   853  
   854  			cpy := &model.User{}
   855  			*cpy = *u
   856  			profileByIdsCache.AddWithExpiresInSecs(cpy.Id, cpy, PROFILE_BY_IDS_CACHE_SEC)
   857  		}
   858  
   859  		result.Data = users
   860  	})
   861  }
   862  
   863  func (us SqlUserStore) GetSystemAdminProfiles() store.StoreChannel {
   864  	return store.Do(func(result *store.StoreResult) {
   865  		query := us.usersQuery.
   866  			Where("Roles LIKE ?", "%system_admin%").
   867  			OrderBy("u.Username ASC")
   868  
   869  		queryString, args, err := query.ToSql()
   870  		if err != nil {
   871  			result.Err = model.NewAppError("SqlUserStore.GetSystemAdminProfiles", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   872  			return
   873  		}
   874  
   875  		var users []*model.User
   876  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   877  			result.Err = model.NewAppError("SqlUserStore.GetSystemAdminProfiles", "store.sql_user.get_sysadmin_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
   878  			return
   879  		}
   880  
   881  		userMap := make(map[string]*model.User)
   882  
   883  		for _, u := range users {
   884  			u.Sanitize(map[string]bool{})
   885  			userMap[u.Id] = u
   886  		}
   887  
   888  		result.Data = userMap
   889  	})
   890  }
   891  
   892  func (us SqlUserStore) GetByEmail(email string) store.StoreChannel {
   893  	return store.Do(func(result *store.StoreResult) {
   894  		email = strings.ToLower(email)
   895  
   896  		query := us.usersQuery.Where("Email = ?", email)
   897  
   898  		queryString, args, err := query.ToSql()
   899  		if err != nil {
   900  			result.Err = model.NewAppError("SqlUserStore.GetByEmail", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   901  			return
   902  		}
   903  
   904  		user := model.User{}
   905  		if err := us.GetReplica().SelectOne(&user, queryString, args...); err != nil {
   906  			result.Err = model.NewAppError("SqlUserStore.GetByEmail", store.MISSING_ACCOUNT_ERROR, nil, "email="+email+", "+err.Error(), http.StatusInternalServerError)
   907  		}
   908  
   909  		result.Data = &user
   910  	})
   911  }
   912  
   913  func (us SqlUserStore) GetByAuth(authData *string, authService string) store.StoreChannel {
   914  	return store.Do(func(result *store.StoreResult) {
   915  		if authData == nil || *authData == "" {
   916  			result.Err = model.NewAppError("SqlUserStore.GetByAuth", store.MISSING_AUTH_ACCOUNT_ERROR, nil, "authData='', authService="+authService, http.StatusBadRequest)
   917  			return
   918  		}
   919  
   920  		query := us.usersQuery.
   921  			Where("u.AuthData = ?", authData).
   922  			Where("u.AuthService = ?", authService)
   923  
   924  		queryString, args, err := query.ToSql()
   925  		if err != nil {
   926  			result.Err = model.NewAppError("SqlUserStore.GetByAuth", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   927  			return
   928  		}
   929  
   930  		user := model.User{}
   931  		if err := us.GetReplica().SelectOne(&user, queryString, args...); err == sql.ErrNoRows {
   932  			result.Err = model.NewAppError("SqlUserStore.GetByAuth", store.MISSING_AUTH_ACCOUNT_ERROR, nil, "authData="+*authData+", authService="+authService+", "+err.Error(), http.StatusInternalServerError)
   933  			return
   934  		} else if err != nil {
   935  			result.Err = model.NewAppError("SqlUserStore.GetByAuth", "store.sql_user.get_by_auth.other.app_error", nil, "authData="+*authData+", authService="+authService+", "+err.Error(), http.StatusInternalServerError)
   936  			return
   937  		}
   938  
   939  		result.Data = &user
   940  	})
   941  }
   942  
   943  func (us SqlUserStore) GetAllUsingAuthService(authService string) store.StoreChannel {
   944  	return store.Do(func(result *store.StoreResult) {
   945  		query := us.usersQuery.
   946  			Where("u.AuthService = ?", authService).
   947  			OrderBy("u.Username ASC")
   948  
   949  		queryString, args, err := query.ToSql()
   950  		if err != nil {
   951  			result.Err = model.NewAppError("SqlUserStore.GetAllUsingAuthService", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   952  			return
   953  		}
   954  
   955  		var data []*model.User
   956  		if _, err := us.GetReplica().Select(&data, queryString, args...); err != nil {
   957  			result.Err = model.NewAppError("SqlUserStore.GetAllUsingAuthService", "store.sql_user.get_by_auth.other.app_error", nil, "authService="+authService+", "+err.Error(), http.StatusInternalServerError)
   958  			return
   959  		}
   960  
   961  		result.Data = data
   962  	})
   963  }
   964  
   965  func (us SqlUserStore) GetByUsername(username string) store.StoreChannel {
   966  	return store.Do(func(result *store.StoreResult) {
   967  		query := us.usersQuery.Where("u.Username = ?", username)
   968  
   969  		queryString, args, err := query.ToSql()
   970  		if err != nil {
   971  			result.Err = model.NewAppError("SqlUserStore.GetByUsername", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
   972  			return
   973  		}
   974  
   975  		user := model.User{}
   976  		if err := us.GetReplica().SelectOne(&user, queryString, args...); err != nil {
   977  			result.Err = model.NewAppError("SqlUserStore.GetByUsername", "store.sql_user.get_by_username.app_error", nil, err.Error()+" -- "+queryString, http.StatusInternalServerError)
   978  			return
   979  		}
   980  
   981  		result.Data = &user
   982  	})
   983  }
   984  
   985  func (us SqlUserStore) GetForLogin(loginId string, allowSignInWithUsername, allowSignInWithEmail bool) store.StoreChannel {
   986  	return store.Do(func(result *store.StoreResult) {
   987  		query := us.usersQuery
   988  
   989  		if allowSignInWithUsername && allowSignInWithEmail {
   990  			query = query.Where("Username = ? OR Email = ?", loginId, loginId)
   991  		} else if allowSignInWithUsername {
   992  			query = query.Where("Username = ?", loginId)
   993  		} else if allowSignInWithEmail {
   994  			query = query.Where("Email = ?", loginId)
   995  		} else {
   996  			result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.get_for_login.app_error", nil, "", http.StatusInternalServerError)
   997  			return
   998  		}
   999  
  1000  		queryString, args, err := query.ToSql()
  1001  		if err != nil {
  1002  			result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
  1003  			return
  1004  		}
  1005  
  1006  		users := []*model.User{}
  1007  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1008  			result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.get_for_login.app_error", nil, err.Error(), http.StatusInternalServerError)
  1009  			return
  1010  		}
  1011  
  1012  		if len(users) == 0 {
  1013  			result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.get_for_login.app_error", nil, "", http.StatusInternalServerError)
  1014  			return
  1015  		}
  1016  
  1017  		if len(users) > 1 {
  1018  			result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.get_for_login.multiple_users", nil, "", http.StatusInternalServerError)
  1019  			return
  1020  		}
  1021  
  1022  		result.Data = users[0]
  1023  	})
  1024  }
  1025  
  1026  func (us SqlUserStore) VerifyEmail(userId, email string) store.StoreChannel {
  1027  	return store.Do(func(result *store.StoreResult) {
  1028  		curTime := model.GetMillis()
  1029  		if _, err := us.GetMaster().Exec("UPDATE Users SET Email = :email, EmailVerified = true, UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"email": email, "Time": curTime, "UserId": userId}); err != nil {
  1030  			result.Err = model.NewAppError("SqlUserStore.VerifyEmail", "store.sql_user.verify_email.app_error", nil, "userId="+userId+", "+err.Error(), http.StatusInternalServerError)
  1031  		}
  1032  
  1033  		result.Data = userId
  1034  	})
  1035  }
  1036  
  1037  func (us SqlUserStore) PermanentDelete(userId string) store.StoreChannel {
  1038  	return store.Do(func(result *store.StoreResult) {
  1039  		if _, err := us.GetMaster().Exec("DELETE FROM Users WHERE Id = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
  1040  			result.Err = model.NewAppError("SqlUserStore.PermanentDelete", "store.sql_user.permanent_delete.app_error", nil, "userId="+userId+", "+err.Error(), http.StatusInternalServerError)
  1041  		}
  1042  	})
  1043  }
  1044  
  1045  func (us SqlUserStore) Count(options model.UserCountOptions) store.StoreChannel {
  1046  	return store.Do(func(result *store.StoreResult) {
  1047  		query := sq.Select("COUNT(Users.Id)").From("Users")
  1048  
  1049  		if !options.IncludeDeleted {
  1050  			query = query.Where("Users.DeleteAt = 0")
  1051  		}
  1052  
  1053  		if options.IncludeBotAccounts {
  1054  			if options.ExcludeRegularUsers {
  1055  				query = query.Join("Bots ON Users.Id = Bots.UserId")
  1056  			}
  1057  		} else {
  1058  			query = query.LeftJoin("Bots ON Users.Id = Bots.UserId").Where("Bots.UserId IS NULL")
  1059  			if options.ExcludeRegularUsers {
  1060  				// Currenty this doesn't make sense because it will always return 0
  1061  				result.Err = model.NewAppError("SqlUserStore.Count", "UserCountOptions don't make sense", nil, "", http.StatusInternalServerError)
  1062  				return
  1063  			}
  1064  		}
  1065  
  1066  		if options.TeamId != "" {
  1067  			query = query.LeftJoin("TeamMembers ON Users.Id = TeamMembers.UserId").Where("TeamMembers.TeamId = ? AND TeamMembers.DeleteAt = 0", options.TeamId)
  1068  		}
  1069  
  1070  		if us.DriverName() == model.DATABASE_DRIVER_POSTGRES {
  1071  			query = query.PlaceholderFormat(sq.Dollar)
  1072  		}
  1073  
  1074  		queryString, args, err := query.ToSql()
  1075  		if err != nil {
  1076  			result.Err = model.NewAppError("SqlUserStore.Get", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
  1077  			return
  1078  		}
  1079  
  1080  		if count, err := us.GetReplica().SelectInt(queryString, args...); err != nil {
  1081  			result.Err = model.NewAppError("SqlUserStore.Count", "store.sql_user.get_total_users_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1082  		} else {
  1083  			result.Data = count
  1084  		}
  1085  	})
  1086  }
  1087  
  1088  func (us SqlUserStore) AnalyticsActiveCount(timePeriod int64) store.StoreChannel {
  1089  	return store.Do(func(result *store.StoreResult) {
  1090  		time := model.GetMillis() - timePeriod
  1091  
  1092  		query := "SELECT COUNT(*) FROM Status WHERE LastActivityAt > :Time"
  1093  
  1094  		v, err := us.GetReplica().SelectInt(query, map[string]interface{}{"Time": time})
  1095  		if err != nil {
  1096  			result.Err = model.NewAppError("SqlUserStore.AnalyticsDailyActiveUsers", "store.sql_user.analytics_daily_active_users.app_error", nil, err.Error(), http.StatusInternalServerError)
  1097  		} else {
  1098  			result.Data = v
  1099  		}
  1100  	})
  1101  }
  1102  
  1103  func (us SqlUserStore) GetUnreadCount(userId string) store.StoreChannel {
  1104  	return store.Do(func(result *store.StoreResult) {
  1105  		if count, err := us.GetReplica().SelectInt(`
  1106  		SELECT SUM(CASE WHEN c.Type = 'D' THEN (c.TotalMsgCount - cm.MsgCount) ELSE cm.MentionCount END)
  1107  		FROM Channels c
  1108  		INNER JOIN ChannelMembers cm
  1109  		      ON cm.ChannelId = c.Id
  1110  		      AND cm.UserId = :UserId
  1111  		      AND c.DeleteAt = 0`, map[string]interface{}{"UserId": userId}); err != nil {
  1112  			result.Err = model.NewAppError("SqlUserStore.GetMentionCount", "store.sql_user.get_unread_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1113  		} else {
  1114  			result.Data = count
  1115  		}
  1116  	})
  1117  }
  1118  
  1119  func (us SqlUserStore) GetUnreadCountForChannel(userId string, channelId string) store.StoreChannel {
  1120  	return store.Do(func(result *store.StoreResult) {
  1121  		if count, err := us.GetReplica().SelectInt("SELECT SUM(CASE WHEN c.Type = 'D' THEN (c.TotalMsgCount - cm.MsgCount) ELSE cm.MentionCount END) FROM Channels c INNER JOIN ChannelMembers cm ON c.Id = cm.ChannelId AND cm.ChannelId = :ChannelId AND cm.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil {
  1122  			result.Err = model.NewAppError("SqlUserStore.GetMentionCountForChannel", "store.sql_user.get_unread_count_for_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
  1123  		} else {
  1124  			result.Data = count
  1125  		}
  1126  	})
  1127  }
  1128  
  1129  func (us SqlUserStore) GetAnyUnreadPostCountForChannel(userId string, channelId string) store.StoreChannel {
  1130  	return store.Do(func(result *store.StoreResult) {
  1131  		if count, err := us.GetReplica().SelectInt("SELECT SUM(c.TotalMsgCount - cm.MsgCount) FROM Channels c INNER JOIN ChannelMembers cm ON c.Id = cm.ChannelId AND cm.ChannelId = :ChannelId AND cm.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil {
  1132  			result.Err = model.NewAppError("SqlUserStore.GetMentionCountForChannel", "store.sql_user.get_unread_count_for_channel.app_error", nil, err.Error(), http.StatusInternalServerError)
  1133  		} else {
  1134  			result.Data = count
  1135  		}
  1136  	})
  1137  }
  1138  
  1139  func (us SqlUserStore) Search(teamId string, term string, options *model.UserSearchOptions) store.StoreChannel {
  1140  	return store.Do(func(result *store.StoreResult) {
  1141  		query := us.usersQuery.
  1142  			OrderBy("Username ASC").
  1143  			Limit(uint64(options.Limit))
  1144  
  1145  		if teamId != "" {
  1146  			query = query.Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId)
  1147  		}
  1148  
  1149  		*result = us.performSearch(query, term, options)
  1150  	})
  1151  }
  1152  
  1153  func (us SqlUserStore) SearchWithoutTeam(term string, options *model.UserSearchOptions) store.StoreChannel {
  1154  	return store.Do(func(result *store.StoreResult) {
  1155  		query := us.usersQuery.
  1156  			Where(`(
  1157  				SELECT
  1158  					COUNT(0)
  1159  				FROM
  1160  					TeamMembers
  1161  				WHERE
  1162  					TeamMembers.UserId = u.Id
  1163  					AND TeamMembers.DeleteAt = 0
  1164  			) = 0`).
  1165  			OrderBy("u.Username ASC").
  1166  			Limit(uint64(options.Limit))
  1167  
  1168  		*result = us.performSearch(query, term, options)
  1169  	})
  1170  }
  1171  
  1172  func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) store.StoreChannel {
  1173  	return store.Do(func(result *store.StoreResult) {
  1174  		query := us.usersQuery.
  1175  			LeftJoin("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", notInTeamId).
  1176  			Where("tm.UserId IS NULL").
  1177  			OrderBy("u.Username ASC").
  1178  			Limit(uint64(options.Limit))
  1179  
  1180  		*result = us.performSearch(query, term, options)
  1181  	})
  1182  }
  1183  
  1184  func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) store.StoreChannel {
  1185  	return store.Do(func(result *store.StoreResult) {
  1186  		query := us.usersQuery.
  1187  			LeftJoin("ChannelMembers cm ON ( cm.UserId = u.Id AND cm.ChannelId = ? )", channelId).
  1188  			Where("cm.UserId IS NULL").
  1189  			OrderBy("Username ASC").
  1190  			Limit(uint64(options.Limit))
  1191  
  1192  		if teamId != "" {
  1193  			query = query.Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId)
  1194  		}
  1195  
  1196  		*result = us.performSearch(query, term, options)
  1197  	})
  1198  }
  1199  
  1200  func (us SqlUserStore) SearchInChannel(channelId string, term string, options *model.UserSearchOptions) store.StoreChannel {
  1201  	return store.Do(func(result *store.StoreResult) {
  1202  		query := us.usersQuery.
  1203  			Join("ChannelMembers cm ON ( cm.UserId = u.Id AND cm.ChannelId = ? )", channelId).
  1204  			OrderBy("Username ASC").
  1205  			Limit(uint64(options.Limit))
  1206  
  1207  		*result = us.performSearch(query, term, options)
  1208  	})
  1209  }
  1210  
  1211  var escapeLikeSearchChar = []string{
  1212  	"%",
  1213  	"_",
  1214  }
  1215  
  1216  var ignoreLikeSearchChar = []string{
  1217  	"*",
  1218  }
  1219  
  1220  var spaceFulltextSearchChar = []string{
  1221  	"<",
  1222  	">",
  1223  	"+",
  1224  	"-",
  1225  	"(",
  1226  	")",
  1227  	"~",
  1228  	":",
  1229  	"*",
  1230  	"\"",
  1231  	"!",
  1232  	"@",
  1233  }
  1234  
  1235  func generateSearchQuery(query sq.SelectBuilder, terms []string, fields []string, isPostgreSQL bool) sq.SelectBuilder {
  1236  	for _, term := range terms {
  1237  		searchFields := []string{}
  1238  		termArgs := []interface{}{}
  1239  		for _, field := range fields {
  1240  			if isPostgreSQL {
  1241  				searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(?) escape '*' ", field))
  1242  			} else {
  1243  				searchFields = append(searchFields, fmt.Sprintf("%s LIKE ? escape '*' ", field))
  1244  			}
  1245  			termArgs = append(termArgs, fmt.Sprintf("%s%%", strings.TrimLeft(term, "@")))
  1246  		}
  1247  		query = query.Where(fmt.Sprintf("(%s)", strings.Join(searchFields, " OR ")), termArgs...)
  1248  	}
  1249  
  1250  	return query
  1251  }
  1252  
  1253  func (us SqlUserStore) performSearch(query sq.SelectBuilder, term string, options *model.UserSearchOptions) store.StoreResult {
  1254  	result := store.StoreResult{}
  1255  
  1256  	// These chars must be removed from the like query.
  1257  	for _, c := range ignoreLikeSearchChar {
  1258  		term = strings.Replace(term, c, "", -1)
  1259  	}
  1260  
  1261  	// These chars must be escaped in the like query.
  1262  	for _, c := range escapeLikeSearchChar {
  1263  		term = strings.Replace(term, c, "*"+c, -1)
  1264  	}
  1265  
  1266  	searchType := USER_SEARCH_TYPE_NAMES_NO_FULL_NAME
  1267  	if options.AllowEmails {
  1268  		if options.AllowFullNames {
  1269  			searchType = USER_SEARCH_TYPE_ALL
  1270  		} else {
  1271  			searchType = USER_SEARCH_TYPE_ALL_NO_FULL_NAME
  1272  		}
  1273  	} else {
  1274  		if options.AllowFullNames {
  1275  			searchType = USER_SEARCH_TYPE_NAMES
  1276  		} else {
  1277  			searchType = USER_SEARCH_TYPE_NAMES_NO_FULL_NAME
  1278  		}
  1279  	}
  1280  
  1281  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
  1282  
  1283  	query = applyRoleFilter(query, options.Role, isPostgreSQL)
  1284  
  1285  	if !options.AllowInactive {
  1286  		query = query.Where("u.DeleteAt = 0")
  1287  	}
  1288  
  1289  	if strings.TrimSpace(term) != "" {
  1290  		query = generateSearchQuery(query, strings.Fields(term), searchType, isPostgreSQL)
  1291  	}
  1292  
  1293  	queryString, args, err := query.ToSql()
  1294  	if err != nil {
  1295  		result.Err = model.NewAppError("SqlUserStore.Search", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
  1296  		return result
  1297  	}
  1298  
  1299  	var users []*model.User
  1300  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1301  		result.Err = model.NewAppError("SqlUserStore.Search", "store.sql_user.search.app_error", nil,
  1302  			fmt.Sprintf("term=%v, search_type=%v, %v", term, searchType, err.Error()), http.StatusInternalServerError)
  1303  	} else {
  1304  		for _, u := range users {
  1305  			u.Sanitize(map[string]bool{})
  1306  		}
  1307  
  1308  		result.Data = users
  1309  	}
  1310  
  1311  	return result
  1312  }
  1313  
  1314  func (us SqlUserStore) AnalyticsGetInactiveUsersCount() store.StoreChannel {
  1315  	return store.Do(func(result *store.StoreResult) {
  1316  		if count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users WHERE DeleteAt > 0"); err != nil {
  1317  			result.Err = model.NewAppError("SqlUserStore.AnalyticsGetInactiveUsersCount", "store.sql_user.analytics_get_inactive_users_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1318  		} else {
  1319  			result.Data = count
  1320  		}
  1321  	})
  1322  }
  1323  
  1324  func (us SqlUserStore) AnalyticsGetSystemAdminCount() store.StoreChannel {
  1325  	return store.Do(func(result *store.StoreResult) {
  1326  		if count, err := us.GetReplica().SelectInt("SELECT count(*) FROM Users WHERE Roles LIKE :Roles and DeleteAt = 0", map[string]interface{}{"Roles": "%system_admin%"}); err != nil {
  1327  			result.Err = model.NewAppError("SqlUserStore.AnalyticsGetSystemAdminCount", "store.sql_user.analytics_get_system_admin_count.app_error", nil, err.Error(), http.StatusInternalServerError)
  1328  		} else {
  1329  			result.Data = count
  1330  		}
  1331  	})
  1332  }
  1333  
  1334  func (us SqlUserStore) GetProfilesNotInTeam(teamId string, offset int, limit int) store.StoreChannel {
  1335  	return store.Do(func(result *store.StoreResult) {
  1336  		query := us.usersQuery.
  1337  			LeftJoin("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
  1338  			Where("tm.UserId IS NULL").
  1339  			OrderBy("u.Username ASC").
  1340  			Offset(uint64(offset)).Limit(uint64(limit))
  1341  
  1342  		queryString, args, err := query.ToSql()
  1343  		if err != nil {
  1344  			result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInTeam", "store.sql_user.app_error", nil, err.Error(), http.StatusInternalServerError)
  1345  			return
  1346  		}
  1347  
  1348  		var users []*model.User
  1349  		if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1350  			result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInTeam", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError)
  1351  			return
  1352  		}
  1353  
  1354  		for _, u := range users {
  1355  			u.Sanitize(map[string]bool{})
  1356  		}
  1357  
  1358  		result.Data = users
  1359  	})
  1360  }
  1361  
  1362  func (us SqlUserStore) GetEtagForProfilesNotInTeam(teamId string) store.StoreChannel {
  1363  	return store.Do(func(result *store.StoreResult) {
  1364  
  1365  		var querystr string
  1366  		querystr = `
  1367  			SELECT
  1368  				CONCAT(MAX(UpdateAt), '.', COUNT(Id)) as etag
  1369  			FROM
  1370  				Users as u
  1371  			LEFT JOIN TeamMembers tm
  1372  				ON tm.UserId = u.Id
  1373  				AND tm.TeamId = :TeamId
  1374  				AND tm.DeleteAt = 0
  1375  			WHERE
  1376  				tm.UserId IS NULL
  1377  		`
  1378  		etag, err := us.GetReplica().SelectStr(querystr, map[string]interface{}{"TeamId": teamId})
  1379  		if err != nil {
  1380  			result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis())
  1381  		} else {
  1382  			result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, etag)
  1383  		}
  1384  	})
  1385  }
  1386  
  1387  func (us SqlUserStore) ClearAllCustomRoleAssignments() store.StoreChannel {
  1388  	return store.Do(func(result *store.StoreResult) {
  1389  		builtInRoles := model.MakeDefaultRoles()
  1390  		lastUserId := strings.Repeat("0", 26)
  1391  
  1392  		for {
  1393  			var transaction *gorp.Transaction
  1394  			var err error
  1395  
  1396  			if transaction, err = us.GetMaster().Begin(); err != nil {
  1397  				result.Err = model.NewAppError("SqlUserStore.ClearAllCustomRoleAssignments", "store.sql_user.clear_all_custom_role_assignments.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  1398  				return
  1399  			}
  1400  			defer finalizeTransaction(transaction)
  1401  
  1402  			var users []*model.User
  1403  			if _, err := transaction.Select(&users, "SELECT * from Users WHERE Id > :Id ORDER BY Id LIMIT 1000", map[string]interface{}{"Id": lastUserId}); err != nil {
  1404  				result.Err = model.NewAppError("SqlUserStore.ClearAllCustomRoleAssignments", "store.sql_user.clear_all_custom_role_assignments.select.app_error", nil, err.Error(), http.StatusInternalServerError)
  1405  				return
  1406  			}
  1407  
  1408  			if len(users) == 0 {
  1409  				break
  1410  			}
  1411  
  1412  			for _, user := range users {
  1413  				lastUserId = user.Id
  1414  
  1415  				var newRoles []string
  1416  
  1417  				for _, role := range strings.Fields(user.Roles) {
  1418  					for name := range builtInRoles {
  1419  						if name == role {
  1420  							newRoles = append(newRoles, role)
  1421  							break
  1422  						}
  1423  					}
  1424  				}
  1425  
  1426  				newRolesString := strings.Join(newRoles, " ")
  1427  				if newRolesString != user.Roles {
  1428  					if _, err := transaction.Exec("UPDATE Users SET Roles = :Roles WHERE Id = :Id", map[string]interface{}{"Roles": newRolesString, "Id": user.Id}); err != nil {
  1429  						result.Err = model.NewAppError("SqlUserStore.ClearAllCustomRoleAssignments", "store.sql_user.clear_all_custom_role_assignments.update.app_error", nil, err.Error(), http.StatusInternalServerError)
  1430  						return
  1431  					}
  1432  				}
  1433  			}
  1434  
  1435  			if err := transaction.Commit(); err != nil {
  1436  				result.Err = model.NewAppError("SqlUserStore.ClearAllCustomRoleAssignments", "store.sql_user.clear_all_custom_role_assignments.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
  1437  				return
  1438  			}
  1439  		}
  1440  	})
  1441  }
  1442  
  1443  func (us SqlUserStore) InferSystemInstallDate() store.StoreChannel {
  1444  	return store.Do(func(result *store.StoreResult) {
  1445  		createAt, err := us.GetReplica().SelectInt("SELECT CreateAt FROM Users WHERE CreateAt IS NOT NULL ORDER BY CreateAt ASC LIMIT 1")
  1446  		if err != nil {
  1447  			result.Err = model.NewAppError("SqlUserStore.GetSystemInstallDate", "store.sql_user.get_system_install_date.app_error", nil, err.Error(), http.StatusInternalServerError)
  1448  			return
  1449  		}
  1450  		result.Data = createAt
  1451  	})
  1452  }
  1453  
  1454  func (us SqlUserStore) GetUsersBatchForIndexing(startTime, endTime int64, limit int) store.StoreChannel {
  1455  	return store.Do(func(result *store.StoreResult) {
  1456  		var users []*model.User
  1457  		usersQuery, args, _ := us.usersQuery.
  1458  			Where(sq.GtOrEq{"u.CreateAt": startTime}).
  1459  			Where(sq.Lt{"u.CreateAt": endTime}).
  1460  			OrderBy("u.CreateAt").
  1461  			Limit(uint64(limit)).
  1462  			ToSql()
  1463  		_, err1 := us.GetSearchReplica().Select(&users, usersQuery, args...)
  1464  
  1465  		if err1 != nil {
  1466  			result.Err = model.NewAppError("SqlUserStore.GetUsersBatchForIndexing", "store.sql_user.get_users_batch_for_indexing.get_users.app_error", nil, err1.Error(), http.StatusInternalServerError)
  1467  			return
  1468  		}
  1469  
  1470  		userIds := []string{}
  1471  		for _, user := range users {
  1472  			userIds = append(userIds, user.Id)
  1473  		}
  1474  
  1475  		var channelMembers []*model.ChannelMember
  1476  		channelMembersQuery, args, _ := us.getQueryBuilder().
  1477  			Select("cm.*").
  1478  			From("ChannelMembers cm").
  1479  			Join("Channels c ON cm.ChannelId = c.Id").
  1480  			Where(sq.Eq{"c.Type": "O", "cm.UserId": userIds}).
  1481  			ToSql()
  1482  		_, err2 := us.GetSearchReplica().Select(&channelMembers, channelMembersQuery, args...)
  1483  
  1484  		if err2 != nil {
  1485  			result.Err = model.NewAppError("SqlUserStore.GetUsersBatchForIndexing", "store.sql_user.get_users_batch_for_indexing.get_channel_members.app_error", nil, err2.Error(), http.StatusInternalServerError)
  1486  			return
  1487  		}
  1488  
  1489  		var teamMembers []*model.TeamMember
  1490  		teamMembersQuery, args, _ := us.getQueryBuilder().
  1491  			Select("*").
  1492  			From("TeamMembers").
  1493  			Where(sq.Eq{"UserId": userIds, "DeleteAt": 0}).
  1494  			ToSql()
  1495  		_, err3 := us.GetSearchReplica().Select(&teamMembers, teamMembersQuery, args...)
  1496  
  1497  		if err3 != nil {
  1498  			result.Err = model.NewAppError("SqlUserStore.GetUsersBatchForIndexing", "store.sql_user.get_users_batch_for_indexing.get_team_members.app_error", nil, err3.Error(), http.StatusInternalServerError)
  1499  			return
  1500  		}
  1501  
  1502  		userMap := map[string]*model.UserForIndexing{}
  1503  		for _, user := range users {
  1504  			userMap[user.Id] = &model.UserForIndexing{
  1505  				Id:          user.Id,
  1506  				Username:    user.Username,
  1507  				Nickname:    user.Nickname,
  1508  				FirstName:   user.FirstName,
  1509  				LastName:    user.LastName,
  1510  				CreateAt:    user.CreateAt,
  1511  				DeleteAt:    user.DeleteAt,
  1512  				TeamsIds:    []string{},
  1513  				ChannelsIds: []string{},
  1514  			}
  1515  		}
  1516  
  1517  		for _, c := range channelMembers {
  1518  			if userMap[c.UserId] != nil {
  1519  				userMap[c.UserId].ChannelsIds = append(userMap[c.UserId].ChannelsIds, c.ChannelId)
  1520  			}
  1521  		}
  1522  		for _, t := range teamMembers {
  1523  			if userMap[t.UserId] != nil {
  1524  				userMap[t.UserId].TeamsIds = append(userMap[t.UserId].TeamsIds, t.TeamId)
  1525  			}
  1526  		}
  1527  
  1528  		usersForIndexing := []*model.UserForIndexing{}
  1529  		for _, user := range userMap {
  1530  			usersForIndexing = append(usersForIndexing, user)
  1531  		}
  1532  		sort.Slice(usersForIndexing, func(i, j int) bool {
  1533  			return usersForIndexing[i].CreateAt < usersForIndexing[j].CreateAt
  1534  		})
  1535  
  1536  		result.Data = usersForIndexing
  1537  	})
  1538  }