github.com/xzl8028/xenia-server@v0.0.0-20190809101854-18450a97da63/store/sqlstore/user_store.go (about)

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