github.com/mattermost/mattermost-server/v5@v5.39.3/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  	"context"
     8  	"database/sql"
     9  	"encoding/json"
    10  	"fmt"
    11  	"sort"
    12  	"strings"
    13  
    14  	sq "github.com/Masterminds/squirrel"
    15  	"github.com/mattermost/gorp"
    16  	"github.com/pkg/errors"
    17  	"golang.org/x/sync/errgroup"
    18  
    19  	"github.com/mattermost/mattermost-server/v5/einterfaces"
    20  	"github.com/mattermost/mattermost-server/v5/model"
    21  	"github.com/mattermost/mattermost-server/v5/store"
    22  )
    23  
    24  const (
    25  	MaxGroupChannelsForProfiles = 50
    26  )
    27  
    28  var (
    29  	UserSearchTypeNames_NO_FULL_NAME = []string{"Username", "Nickname"}
    30  	UserSearchTypeNames              = []string{"Username", "FirstName", "LastName", "Nickname"}
    31  	UserSearchTypeAll_NO_FULL_NAME   = []string{"Username", "Nickname", "Email"}
    32  	UserSearchTypeAll                = []string{"Username", "FirstName", "LastName", "Nickname", "Email"}
    33  )
    34  
    35  type SqlUserStore struct {
    36  	*SqlStore
    37  	metrics einterfaces.MetricsInterface
    38  
    39  	// usersQuery is a starting point for all queries that return one or more Users.
    40  	usersQuery sq.SelectBuilder
    41  }
    42  
    43  func (us *SqlUserStore) ClearCaches() {}
    44  
    45  func (us SqlUserStore) InvalidateProfileCacheForUser(userId string) {}
    46  
    47  func newSqlUserStore(sqlStore *SqlStore, metrics einterfaces.MetricsInterface) store.UserStore {
    48  	us := &SqlUserStore{
    49  		SqlStore: sqlStore,
    50  		metrics:  metrics,
    51  	}
    52  
    53  	// note: we are providing field names explicitly here to maintain order of columns (needed when using raw queries)
    54  	us.usersQuery = us.getQueryBuilder().
    55  		Select("u.Id", "u.CreateAt", "u.UpdateAt", "u.DeleteAt", "u.Username", "u.Password", "u.AuthData", "u.AuthService", "u.Email", "u.EmailVerified", "u.Nickname", "u.FirstName", "u.LastName", "u.Position", "u.Roles", "u.AllowMarketing", "u.Props", "u.NotifyProps", "u.LastPasswordUpdate", "u.LastPictureUpdate", "u.FailedAttempts", "u.Locale", "u.Timezone", "u.MfaActive", "u.MfaSecret",
    56  			"b.UserId IS NOT NULL AS IsBot", "COALESCE(b.Description, '') AS BotDescription", "COALESCE(b.LastIconUpdate, 0) AS BotLastIconUpdate", "u.RemoteId").
    57  		From("Users u").
    58  		LeftJoin("Bots b ON ( b.UserId = u.Id )")
    59  
    60  	for _, db := range sqlStore.GetAllConns() {
    61  		table := db.AddTableWithName(model.User{}, "Users").SetKeys(false, "Id")
    62  		table.ColMap("Id").SetMaxSize(26)
    63  		table.ColMap("Username").SetMaxSize(64).SetUnique(true)
    64  		table.ColMap("Password").SetMaxSize(128)
    65  		table.ColMap("AuthData").SetMaxSize(128).SetUnique(true)
    66  		table.ColMap("AuthService").SetMaxSize(32)
    67  		table.ColMap("Email").SetMaxSize(128).SetUnique(true)
    68  		table.ColMap("Nickname").SetMaxSize(64)
    69  		table.ColMap("FirstName").SetMaxSize(64)
    70  		table.ColMap("LastName").SetMaxSize(64)
    71  		table.ColMap("Roles").SetMaxSize(256)
    72  		table.ColMap("Props").SetMaxSize(4000)
    73  		table.ColMap("NotifyProps").SetMaxSize(2000)
    74  		table.ColMap("Locale").SetMaxSize(5)
    75  		table.ColMap("MfaSecret").SetMaxSize(128)
    76  		table.ColMap("RemoteId").SetMaxSize(26)
    77  		table.ColMap("Position").SetMaxSize(128)
    78  		table.ColMap("Timezone").SetMaxSize(256)
    79  	}
    80  
    81  	return us
    82  }
    83  
    84  func (us SqlUserStore) createIndexesIfNotExists() {
    85  	us.CreateIndexIfNotExists("idx_users_update_at", "Users", "UpdateAt")
    86  	us.CreateIndexIfNotExists("idx_users_create_at", "Users", "CreateAt")
    87  	us.CreateIndexIfNotExists("idx_users_delete_at", "Users", "DeleteAt")
    88  
    89  	if us.DriverName() == model.DATABASE_DRIVER_POSTGRES {
    90  		us.CreateIndexIfNotExists("idx_users_email_lower_textpattern", "Users", "lower(Email) text_pattern_ops")
    91  		us.CreateIndexIfNotExists("idx_users_username_lower_textpattern", "Users", "lower(Username) text_pattern_ops")
    92  		us.CreateIndexIfNotExists("idx_users_nickname_lower_textpattern", "Users", "lower(Nickname) text_pattern_ops")
    93  		us.CreateIndexIfNotExists("idx_users_firstname_lower_textpattern", "Users", "lower(FirstName) text_pattern_ops")
    94  		us.CreateIndexIfNotExists("idx_users_lastname_lower_textpattern", "Users", "lower(LastName) text_pattern_ops")
    95  	}
    96  
    97  	us.CreateFullTextIndexIfNotExists("idx_users_all_txt", "Users", strings.Join(UserSearchTypeAll, ", "))
    98  	us.CreateFullTextIndexIfNotExists("idx_users_all_no_full_name_txt", "Users", strings.Join(UserSearchTypeAll_NO_FULL_NAME, ", "))
    99  	us.CreateFullTextIndexIfNotExists("idx_users_names_txt", "Users", strings.Join(UserSearchTypeNames, ", "))
   100  	us.CreateFullTextIndexIfNotExists("idx_users_names_no_full_name_txt", "Users", strings.Join(UserSearchTypeNames_NO_FULL_NAME, ", "))
   101  }
   102  
   103  func (us SqlUserStore) Save(user *model.User) (*model.User, error) {
   104  	if user.Id != "" && !user.IsRemote() {
   105  		return nil, store.NewErrInvalidInput("User", "id", user.Id)
   106  	}
   107  
   108  	user.PreSave()
   109  	if err := user.IsValid(); err != nil {
   110  		return nil, err
   111  	}
   112  
   113  	if err := us.GetMaster().Insert(user); err != nil {
   114  		if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique"}) {
   115  			return nil, store.NewErrInvalidInput("User", "email", user.Email)
   116  		}
   117  		if IsUniqueConstraintError(err, []string{"Username", "users_username_key", "idx_users_username_unique"}) {
   118  			return nil, store.NewErrInvalidInput("User", "username", user.Username)
   119  		}
   120  		return nil, errors.Wrapf(err, "failed to save User with userId=%s", user.Id)
   121  	}
   122  
   123  	return user, nil
   124  }
   125  
   126  func (us SqlUserStore) DeactivateGuests() ([]string, error) {
   127  	curTime := model.GetMillis()
   128  	updateQuery := us.getQueryBuilder().Update("Users").
   129  		Set("UpdateAt", curTime).
   130  		Set("DeleteAt", curTime).
   131  		Where(sq.Eq{"Roles": "system_guest"}).
   132  		Where(sq.Eq{"DeleteAt": 0})
   133  
   134  	queryString, args, err := updateQuery.ToSql()
   135  	if err != nil {
   136  		return nil, errors.Wrap(err, "deactivate_guests_tosql")
   137  	}
   138  
   139  	_, err = us.GetMaster().Exec(queryString, args...)
   140  	if err != nil {
   141  		return nil, errors.Wrap(err, "failed to update Users with roles=system_guest")
   142  	}
   143  
   144  	selectQuery := us.getQueryBuilder().Select("Id").From("Users").Where(sq.Eq{"DeleteAt": curTime})
   145  
   146  	queryString, args, err = selectQuery.ToSql()
   147  	if err != nil {
   148  		return nil, errors.Wrap(err, "deactivate_guests_tosql")
   149  	}
   150  
   151  	userIds := []string{}
   152  	_, err = us.GetMaster().Select(&userIds, queryString, args...)
   153  	if err != nil {
   154  		return nil, errors.Wrap(err, "failed to find Users")
   155  	}
   156  
   157  	return userIds, nil
   158  }
   159  
   160  func (us SqlUserStore) Update(user *model.User, trustedUpdateData bool) (*model.UserUpdate, error) {
   161  	user.PreUpdate()
   162  
   163  	if err := user.IsValid(); err != nil {
   164  		return nil, err
   165  	}
   166  
   167  	oldUserResult, err := us.GetMaster().Get(model.User{}, user.Id)
   168  	if err != nil {
   169  		return nil, errors.Wrapf(err, "failed to get User with userId=%s", user.Id)
   170  	}
   171  
   172  	if oldUserResult == nil {
   173  		return nil, store.NewErrInvalidInput("User", "id", user.Id)
   174  	}
   175  
   176  	oldUser := oldUserResult.(*model.User)
   177  	user.CreateAt = oldUser.CreateAt
   178  	user.AuthData = oldUser.AuthData
   179  	user.AuthService = oldUser.AuthService
   180  	user.Password = oldUser.Password
   181  	user.LastPasswordUpdate = oldUser.LastPasswordUpdate
   182  	user.LastPictureUpdate = oldUser.LastPictureUpdate
   183  	user.EmailVerified = oldUser.EmailVerified
   184  	user.FailedAttempts = oldUser.FailedAttempts
   185  	user.MfaSecret = oldUser.MfaSecret
   186  	user.MfaActive = oldUser.MfaActive
   187  
   188  	if !trustedUpdateData {
   189  		user.Roles = oldUser.Roles
   190  		user.DeleteAt = oldUser.DeleteAt
   191  	}
   192  
   193  	if user.IsOAuthUser() {
   194  		if !trustedUpdateData {
   195  			user.Email = oldUser.Email
   196  		}
   197  	} else if user.IsLDAPUser() && !trustedUpdateData {
   198  		if user.Username != oldUser.Username || user.Email != oldUser.Email {
   199  			return nil, store.NewErrInvalidInput("User", "id", user.Id)
   200  		}
   201  	} else if user.Email != oldUser.Email {
   202  		user.EmailVerified = false
   203  	}
   204  
   205  	if user.Username != oldUser.Username {
   206  		user.UpdateMentionKeysFromUsername(oldUser.Username)
   207  	}
   208  
   209  	count, err := us.GetMaster().Update(user)
   210  	if err != nil {
   211  		if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique"}) {
   212  			return nil, store.NewErrConflict("Email", err, user.Email)
   213  		}
   214  		if IsUniqueConstraintError(err, []string{"Username", "users_username_key", "idx_users_username_unique"}) {
   215  			return nil, store.NewErrConflict("Username", err, user.Username)
   216  		}
   217  		return nil, errors.Wrapf(err, "failed to update User with userId=%s", user.Id)
   218  	}
   219  
   220  	if count > 1 {
   221  		return nil, fmt.Errorf("multiple users were update: userId=%s, count=%d", user.Id, count)
   222  	}
   223  
   224  	user.Sanitize(map[string]bool{})
   225  	oldUser.Sanitize(map[string]bool{})
   226  	return &model.UserUpdate{New: user, Old: oldUser}, nil
   227  }
   228  
   229  func (us SqlUserStore) UpdateLastPictureUpdate(userId string) error {
   230  	curTime := model.GetMillis()
   231  
   232  	if _, err := us.GetMaster().Exec("UPDATE Users SET LastPictureUpdate = :Time, UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"Time": curTime, "UserId": userId}); err != nil {
   233  		return errors.Wrapf(err, "failed to update User with userId=%s", userId)
   234  	}
   235  
   236  	return nil
   237  }
   238  
   239  func (us SqlUserStore) ResetLastPictureUpdate(userId string) error {
   240  	curTime := model.GetMillis()
   241  
   242  	if _, err := us.GetMaster().Exec("UPDATE Users SET LastPictureUpdate = :PictureUpdateTime, UpdateAt = :UpdateTime WHERE Id = :UserId", map[string]interface{}{"PictureUpdateTime": 0, "UpdateTime": curTime, "UserId": userId}); err != nil {
   243  		return errors.Wrapf(err, "failed to update User with userId=%s", userId)
   244  	}
   245  
   246  	return nil
   247  }
   248  
   249  func (us SqlUserStore) UpdateUpdateAt(userId string) (int64, error) {
   250  	curTime := model.GetMillis()
   251  
   252  	if _, err := us.GetMaster().Exec("UPDATE Users SET UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"Time": curTime, "UserId": userId}); err != nil {
   253  		return curTime, errors.Wrapf(err, "failed to update User with userId=%s", userId)
   254  	}
   255  
   256  	return curTime, nil
   257  }
   258  
   259  func (us SqlUserStore) UpdatePassword(userId, hashedPassword string) error {
   260  	updateAt := model.GetMillis()
   261  
   262  	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 {
   263  		return errors.Wrapf(err, "failed to update User with userId=%s", userId)
   264  	}
   265  
   266  	return nil
   267  }
   268  
   269  func (us SqlUserStore) UpdateFailedPasswordAttempts(userId string, attempts int) error {
   270  	if _, err := us.GetMaster().Exec("UPDATE Users SET FailedAttempts = :FailedAttempts WHERE Id = :UserId", map[string]interface{}{"FailedAttempts": attempts, "UserId": userId}); err != nil {
   271  		return errors.Wrapf(err, "failed to update User with userId=%s", userId)
   272  	}
   273  
   274  	return nil
   275  }
   276  
   277  func (us SqlUserStore) UpdateAuthData(userId string, service string, authData *string, email string, resetMfa bool) (string, error) {
   278  	updateAt := model.GetMillis()
   279  
   280  	query := `
   281  			UPDATE
   282  			     Users
   283  			SET
   284  			     Password = '',
   285  			     LastPasswordUpdate = :LastPasswordUpdate,
   286  			     UpdateAt = :UpdateAt,
   287  			     FailedAttempts = 0,
   288  			     AuthService = :AuthService,
   289  			     AuthData = :AuthData`
   290  
   291  	if email != "" {
   292  		query += ", Email = lower(:Email)"
   293  	}
   294  
   295  	if resetMfa {
   296  		query += ", MfaActive = false, MfaSecret = ''"
   297  	}
   298  
   299  	query += " WHERE Id = :UserId"
   300  
   301  	if _, err := us.GetMaster().Exec(query, map[string]interface{}{"LastPasswordUpdate": updateAt, "UpdateAt": updateAt, "UserId": userId, "AuthService": service, "AuthData": authData, "Email": email}); err != nil {
   302  		if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique", "AuthData", "users_authdata_key"}) {
   303  			return "", store.NewErrInvalidInput("User", "id", userId)
   304  		}
   305  		return "", errors.Wrapf(err, "failed to update User with userId=%s", userId)
   306  	}
   307  	return userId, nil
   308  }
   309  
   310  // ResetAuthDataToEmailForUsers resets the AuthData of users whose AuthService
   311  // is |service| to their Email. If userIDs is non-empty, only the users whose
   312  // IDs are in userIDs will be affected. If dryRun is true, only the number
   313  // of users who *would* be affected is returned; otherwise, the number of
   314  // users who actually were affected is returned.
   315  func (us SqlUserStore) ResetAuthDataToEmailForUsers(service string, userIDs []string, includeDeleted bool, dryRun bool) (int, error) {
   316  	whereEquals := sq.Eq{"AuthService": service}
   317  	if len(userIDs) > 0 {
   318  		whereEquals["Id"] = userIDs
   319  	}
   320  	if !includeDeleted {
   321  		whereEquals["DeleteAt"] = 0
   322  	}
   323  
   324  	if dryRun {
   325  		builder := us.getQueryBuilder().
   326  			Select("COUNT(*)").
   327  			From("Users").
   328  			Where(whereEquals)
   329  		query, args, err := builder.ToSql()
   330  		if err != nil {
   331  			return 0, errors.Wrap(err, "select_count_users_tosql")
   332  		}
   333  		numAffected, err := us.GetReplica().SelectInt(query, args...)
   334  		return int(numAffected), err
   335  	}
   336  	builder := us.getQueryBuilder().
   337  		Update("Users").
   338  		Set("AuthData", sq.Expr("Email")).
   339  		Where(whereEquals)
   340  	query, args, err := builder.ToSql()
   341  	if err != nil {
   342  		return 0, errors.Wrap(err, "update_users_tosql")
   343  	}
   344  	result, err := us.GetMaster().Exec(query, args...)
   345  	if err != nil {
   346  		return 0, errors.Wrap(err, "failed to update users' AuthData")
   347  	}
   348  	numAffected, err := result.RowsAffected()
   349  	return int(numAffected), err
   350  }
   351  
   352  func (us SqlUserStore) UpdateMfaSecret(userId, secret string) error {
   353  	updateAt := model.GetMillis()
   354  
   355  	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 {
   356  		return errors.Wrapf(err, "failed to update User with userId=%s", userId)
   357  	}
   358  
   359  	return nil
   360  }
   361  
   362  func (us SqlUserStore) UpdateMfaActive(userId string, active bool) error {
   363  	updateAt := model.GetMillis()
   364  
   365  	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 {
   366  		return errors.Wrapf(err, "failed to update User with userId=%s", userId)
   367  	}
   368  
   369  	return nil
   370  }
   371  
   372  // GetMany returns a list of users for the provided list of ids
   373  func (us SqlUserStore) GetMany(ctx context.Context, ids []string) ([]*model.User, error) {
   374  	query := us.usersQuery.Where(sq.Eq{"Id": ids})
   375  	queryString, args, err := query.ToSql()
   376  	if err != nil {
   377  		return nil, errors.Wrap(err, "users_get_many_tosql")
   378  	}
   379  
   380  	var users []*model.User
   381  	if _, err := us.SqlStore.DBFromContext(ctx).Select(&users, queryString, args...); err != nil {
   382  		return nil, errors.Wrap(err, "users_get_many_select")
   383  	}
   384  
   385  	return users, nil
   386  }
   387  
   388  func (us SqlUserStore) Get(ctx context.Context, id string) (*model.User, error) {
   389  	query := us.usersQuery.Where("Id = ?", id)
   390  	queryString, args, err := query.ToSql()
   391  	if err != nil {
   392  		return nil, errors.Wrap(err, "users_get_tosql")
   393  	}
   394  	row := us.SqlStore.DBFromContext(ctx).Db.QueryRow(queryString, args...)
   395  
   396  	var user model.User
   397  	var props, notifyProps, timezone []byte
   398  	err = row.Scan(&user.Id, &user.CreateAt, &user.UpdateAt, &user.DeleteAt, &user.Username,
   399  		&user.Password, &user.AuthData, &user.AuthService, &user.Email, &user.EmailVerified,
   400  		&user.Nickname, &user.FirstName, &user.LastName, &user.Position, &user.Roles,
   401  		&user.AllowMarketing, &props, &notifyProps, &user.LastPasswordUpdate, &user.LastPictureUpdate,
   402  		&user.FailedAttempts, &user.Locale, &timezone, &user.MfaActive, &user.MfaSecret,
   403  		&user.IsBot, &user.BotDescription, &user.BotLastIconUpdate, &user.RemoteId)
   404  	if err != nil {
   405  		if err == sql.ErrNoRows {
   406  			return nil, store.NewErrNotFound("User", id)
   407  		}
   408  		return nil, errors.Wrapf(err, "failed to get User with userId=%s", id)
   409  
   410  	}
   411  	if err = json.Unmarshal(props, &user.Props); err != nil {
   412  		return nil, errors.Wrap(err, "failed to unmarshal user props")
   413  	}
   414  	if err = json.Unmarshal(notifyProps, &user.NotifyProps); err != nil {
   415  		return nil, errors.Wrap(err, "failed to unmarshal user notify props")
   416  	}
   417  	if err = json.Unmarshal(timezone, &user.Timezone); err != nil {
   418  		return nil, errors.Wrap(err, "failed to unmarshal user timezone")
   419  	}
   420  
   421  	return &user, nil
   422  }
   423  
   424  func (us SqlUserStore) GetAll() ([]*model.User, error) {
   425  	query := us.usersQuery.OrderBy("Username ASC")
   426  
   427  	queryString, args, err := query.ToSql()
   428  	if err != nil {
   429  		return nil, errors.Wrap(err, "get_all_users_tosql")
   430  	}
   431  
   432  	var data []*model.User
   433  	if _, err := us.GetReplica().Select(&data, queryString, args...); err != nil {
   434  		return nil, errors.Wrap(err, "failed to find Users")
   435  	}
   436  	return data, nil
   437  }
   438  
   439  func (us SqlUserStore) GetAllAfter(limit int, afterId string) ([]*model.User, error) {
   440  	query := us.usersQuery.
   441  		Where("Id > ?", afterId).
   442  		OrderBy("Id ASC").
   443  		Limit(uint64(limit))
   444  
   445  	queryString, args, err := query.ToSql()
   446  	if err != nil {
   447  		return nil, errors.Wrap(err, "get_all_after_tosql")
   448  	}
   449  
   450  	var users []*model.User
   451  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   452  		return nil, errors.Wrap(err, "failed to find Users")
   453  	}
   454  
   455  	return users, nil
   456  }
   457  
   458  func (us SqlUserStore) GetEtagForAllProfiles() string {
   459  	updateAt, err := us.GetReplica().SelectInt("SELECT UpdateAt FROM Users ORDER BY UpdateAt DESC LIMIT 1")
   460  	if err != nil {
   461  		return fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis())
   462  	}
   463  	return fmt.Sprintf("%v.%v", model.CurrentVersion, updateAt)
   464  }
   465  
   466  func (us SqlUserStore) GetAllProfiles(options *model.UserGetOptions) ([]*model.User, error) {
   467  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
   468  	query := us.usersQuery.
   469  		OrderBy("u.Username ASC").
   470  		Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
   471  
   472  	query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
   473  
   474  	query = applyRoleFilter(query, options.Role, isPostgreSQL)
   475  	query = applyMultiRoleFilters(query, options.Roles, []string{}, []string{}, isPostgreSQL)
   476  
   477  	if options.Inactive {
   478  		query = query.Where("u.DeleteAt != 0")
   479  	} else if options.Active {
   480  		query = query.Where("u.DeleteAt = 0")
   481  	}
   482  
   483  	queryString, args, err := query.ToSql()
   484  	if err != nil {
   485  		return nil, errors.Wrap(err, "get_all_profiles_tosql")
   486  	}
   487  
   488  	var users []*model.User
   489  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   490  		return nil, errors.Wrap(err, "failed to get User profiles")
   491  	}
   492  
   493  	for _, u := range users {
   494  		u.Sanitize(map[string]bool{})
   495  	}
   496  
   497  	return users, nil
   498  }
   499  
   500  func applyRoleFilter(query sq.SelectBuilder, role string, isPostgreSQL bool) sq.SelectBuilder {
   501  	if role == "" {
   502  		return query
   503  	}
   504  
   505  	if isPostgreSQL {
   506  		roleParam := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(role, "\\"))
   507  		return query.Where("u.Roles LIKE LOWER(?)", roleParam)
   508  	}
   509  
   510  	roleParam := fmt.Sprintf("%%%s%%", sanitizeSearchTerm(role, "*"))
   511  
   512  	return query.Where("u.Roles LIKE ? ESCAPE '*'", roleParam)
   513  }
   514  
   515  func applyMultiRoleFilters(query sq.SelectBuilder, systemRoles []string, teamRoles []string, channelRoles []string, isPostgreSQL bool) sq.SelectBuilder {
   516  	sqOr := sq.Or{}
   517  
   518  	if len(systemRoles) > 0 && systemRoles[0] != "" {
   519  		for _, role := range systemRoles {
   520  			queryRole := wildcardSearchTerm(role)
   521  			switch role {
   522  			case model.SYSTEM_USER_ROLE_ID:
   523  				// If querying for a `system_user` ensure that the user is only a system_user.
   524  				sqOr = append(sqOr, sq.Eq{"u.Roles": role})
   525  			case model.SYSTEM_GUEST_ROLE_ID, model.SYSTEM_ADMIN_ROLE_ID, model.SYSTEM_USER_MANAGER_ROLE_ID, model.SYSTEM_READ_ONLY_ADMIN_ROLE_ID, model.SYSTEM_MANAGER_ROLE_ID:
   526  				// If querying for any other roles search using a wildcard.
   527  				if isPostgreSQL {
   528  					sqOr = append(sqOr, sq.ILike{"u.Roles": queryRole})
   529  				} else {
   530  					sqOr = append(sqOr, sq.Like{"u.Roles": queryRole})
   531  				}
   532  			}
   533  
   534  		}
   535  	}
   536  
   537  	if len(channelRoles) > 0 && channelRoles[0] != "" {
   538  		for _, channelRole := range channelRoles {
   539  			switch channelRole {
   540  			case model.CHANNEL_ADMIN_ROLE_ID:
   541  				if isPostgreSQL {
   542  					sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeAdmin": true}, sq.NotILike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   543  				} else {
   544  					sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeAdmin": true}, sq.NotLike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   545  				}
   546  			case model.CHANNEL_USER_ROLE_ID:
   547  				if isPostgreSQL {
   548  					sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeUser": true}, sq.Eq{"cm.SchemeAdmin": false}, sq.NotILike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   549  				} else {
   550  					sqOr = append(sqOr, sq.And{sq.Eq{"cm.SchemeUser": true}, sq.Eq{"cm.SchemeAdmin": false}, sq.NotLike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   551  				}
   552  			case model.CHANNEL_GUEST_ROLE_ID:
   553  				sqOr = append(sqOr, sq.Eq{"cm.SchemeGuest": true})
   554  			}
   555  		}
   556  	}
   557  
   558  	if len(teamRoles) > 0 && teamRoles[0] != "" {
   559  		for _, teamRole := range teamRoles {
   560  			switch teamRole {
   561  			case model.TEAM_ADMIN_ROLE_ID:
   562  				if isPostgreSQL {
   563  					sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeAdmin": true}, sq.NotILike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   564  				} else {
   565  					sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeAdmin": true}, sq.NotLike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   566  				}
   567  			case model.TEAM_USER_ROLE_ID:
   568  				if isPostgreSQL {
   569  					sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeUser": true}, sq.Eq{"tm.SchemeAdmin": false}, sq.NotILike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   570  				} else {
   571  					sqOr = append(sqOr, sq.And{sq.Eq{"tm.SchemeUser": true}, sq.Eq{"tm.SchemeAdmin": false}, sq.NotLike{"u.Roles": wildcardSearchTerm(model.SYSTEM_ADMIN_ROLE_ID)}})
   572  				}
   573  			case model.TEAM_GUEST_ROLE_ID:
   574  				sqOr = append(sqOr, sq.Eq{"tm.SchemeGuest": true})
   575  			}
   576  		}
   577  	}
   578  
   579  	if len(sqOr) > 0 {
   580  		return query.Where(sqOr)
   581  	}
   582  	return query
   583  }
   584  
   585  func applyChannelGroupConstrainedFilter(query sq.SelectBuilder, channelId string) sq.SelectBuilder {
   586  	if channelId == "" {
   587  		return query
   588  	}
   589  
   590  	return query.
   591  		Where(`u.Id IN (
   592  				SELECT
   593  					GroupMembers.UserId
   594  				FROM
   595  					Channels
   596  					JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id
   597  					JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId
   598  					JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
   599  				WHERE
   600  					Channels.Id = ?
   601  					AND GroupChannels.DeleteAt = 0
   602  					AND UserGroups.DeleteAt = 0
   603  					AND GroupMembers.DeleteAt = 0
   604  				GROUP BY
   605  					GroupMembers.UserId
   606  			)`, channelId)
   607  }
   608  
   609  func applyTeamGroupConstrainedFilter(query sq.SelectBuilder, teamId string) sq.SelectBuilder {
   610  	if teamId == "" {
   611  		return query
   612  	}
   613  
   614  	return query.
   615  		Where(`u.Id IN (
   616  				SELECT
   617  					GroupMembers.UserId
   618  				FROM
   619  					Teams
   620  					JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id
   621  					JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId
   622  					JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
   623  				WHERE
   624  					Teams.Id = ?
   625  					AND GroupTeams.DeleteAt = 0
   626  					AND UserGroups.DeleteAt = 0
   627  					AND GroupMembers.DeleteAt = 0
   628  				GROUP BY
   629  					GroupMembers.UserId
   630  			)`, teamId)
   631  }
   632  
   633  func (us SqlUserStore) GetEtagForProfiles(teamId string) string {
   634  	updateAt, err := us.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})
   635  	if err != nil {
   636  		return fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis())
   637  	}
   638  	return fmt.Sprintf("%v.%v", model.CurrentVersion, updateAt)
   639  }
   640  
   641  func (us SqlUserStore) GetProfiles(options *model.UserGetOptions) ([]*model.User, error) {
   642  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
   643  	query := us.usersQuery.
   644  		Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 )").
   645  		Where("tm.TeamId = ?", options.InTeamId).
   646  		OrderBy("u.Username ASC").
   647  		Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
   648  
   649  	query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
   650  
   651  	query = applyRoleFilter(query, options.Role, isPostgreSQL)
   652  	query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles, isPostgreSQL)
   653  
   654  	if options.Inactive {
   655  		query = query.Where("u.DeleteAt != 0")
   656  	} else if options.Active {
   657  		query = query.Where("u.DeleteAt = 0")
   658  	}
   659  
   660  	queryString, args, err := query.ToSql()
   661  	if err != nil {
   662  		return nil, errors.Wrap(err, "get_etag_for_profiles_tosql")
   663  	}
   664  
   665  	var users []*model.User
   666  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   667  		return nil, errors.Wrap(err, "failed to find Users")
   668  	}
   669  
   670  	for _, u := range users {
   671  		u.Sanitize(map[string]bool{})
   672  	}
   673  
   674  	return users, nil
   675  }
   676  
   677  func (us SqlUserStore) InvalidateProfilesInChannelCacheByUser(userId string) {}
   678  
   679  func (us SqlUserStore) InvalidateProfilesInChannelCache(channelId string) {}
   680  
   681  func (us SqlUserStore) GetProfilesInChannel(options *model.UserGetOptions) ([]*model.User, error) {
   682  	query := us.usersQuery.
   683  		Join("ChannelMembers cm ON ( cm.UserId = u.Id )").
   684  		Where("cm.ChannelId = ?", options.InChannelId).
   685  		OrderBy("u.Username ASC").
   686  		Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
   687  
   688  	if options.Inactive {
   689  		query = query.Where("u.DeleteAt != 0")
   690  	} else if options.Active {
   691  		query = query.Where("u.DeleteAt = 0")
   692  	}
   693  
   694  	queryString, args, err := query.ToSql()
   695  	if err != nil {
   696  		return nil, errors.Wrap(err, "get_profiles_in_channel_tosql")
   697  	}
   698  
   699  	var users []*model.User
   700  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   701  		return nil, errors.Wrap(err, "failed to find Users")
   702  	}
   703  
   704  	for _, u := range users {
   705  		u.Sanitize(map[string]bool{})
   706  	}
   707  
   708  	return users, nil
   709  }
   710  
   711  func (us SqlUserStore) GetProfilesInChannelByStatus(options *model.UserGetOptions) ([]*model.User, error) {
   712  	query := us.usersQuery.
   713  		Join("ChannelMembers cm ON ( cm.UserId = u.Id )").
   714  		LeftJoin("Status s ON ( s.UserId = u.Id )").
   715  		Where("cm.ChannelId = ?", options.InChannelId).
   716  		OrderBy(`
   717  			CASE s.Status
   718  				WHEN 'online' THEN 1
   719  				WHEN 'away' THEN 2
   720  				WHEN 'dnd' THEN 3
   721  				ELSE 4
   722  			END
   723  			`).
   724  		OrderBy("u.Username ASC").
   725  		Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
   726  
   727  	if options.Inactive && !options.Active {
   728  		query = query.Where("u.DeleteAt != 0")
   729  	} else if options.Active && !options.Inactive {
   730  		query = query.Where("u.DeleteAt = 0")
   731  	}
   732  
   733  	queryString, args, err := query.ToSql()
   734  	if err != nil {
   735  		return nil, errors.Wrap(err, "get_profiles_in_channel_by_status_tosql")
   736  	}
   737  
   738  	var users []*model.User
   739  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   740  		return nil, errors.Wrap(err, "failed to find Users")
   741  	}
   742  
   743  	for _, u := range users {
   744  		u.Sanitize(map[string]bool{})
   745  	}
   746  
   747  	return users, nil
   748  }
   749  
   750  func (us SqlUserStore) GetAllProfilesInChannel(ctx context.Context, channelID string, allowFromCache bool) (map[string]*model.User, error) {
   751  	query := us.usersQuery.
   752  		Join("ChannelMembers cm ON ( cm.UserId = u.Id )").
   753  		Where("cm.ChannelId = ?", channelID).
   754  		Where("u.DeleteAt = 0").
   755  		OrderBy("u.Username ASC")
   756  
   757  	queryString, args, err := query.ToSql()
   758  	if err != nil {
   759  		return nil, errors.Wrap(err, "get_all_profiles_in_channel_tosql")
   760  	}
   761  
   762  	var users []*model.User
   763  	rows, err := us.SqlStore.DBFromContext(ctx).Db.Query(queryString, args...)
   764  	if err != nil {
   765  		return nil, errors.Wrap(err, "failed to find Users")
   766  	}
   767  
   768  	defer rows.Close()
   769  	for rows.Next() {
   770  		var user model.User
   771  		var props, notifyProps, timezone []byte
   772  		if err = rows.Scan(&user.Id, &user.CreateAt, &user.UpdateAt, &user.DeleteAt, &user.Username, &user.Password, &user.AuthData, &user.AuthService, &user.Email, &user.EmailVerified, &user.Nickname, &user.FirstName, &user.LastName, &user.Position, &user.Roles, &user.AllowMarketing, &props, &notifyProps, &user.LastPasswordUpdate, &user.LastPictureUpdate, &user.FailedAttempts, &user.Locale, &timezone, &user.MfaActive, &user.MfaSecret, &user.IsBot, &user.BotDescription, &user.BotLastIconUpdate, &user.RemoteId); err != nil {
   773  			return nil, errors.Wrap(err, "failed to scan values from rows into User entity")
   774  		}
   775  		if err = json.Unmarshal(props, &user.Props); err != nil {
   776  			return nil, errors.Wrap(err, "failed to unmarshal user props")
   777  		}
   778  		if err = json.Unmarshal(notifyProps, &user.NotifyProps); err != nil {
   779  			return nil, errors.Wrap(err, "failed to unmarshal user notify props")
   780  		}
   781  		if err = json.Unmarshal(timezone, &user.Timezone); err != nil {
   782  			return nil, errors.Wrap(err, "failed to unmarshal user timezone")
   783  		}
   784  		users = append(users, &user)
   785  	}
   786  	err = rows.Err()
   787  	if err != nil {
   788  		return nil, errors.Wrap(err, "error while iterating over rows")
   789  	}
   790  
   791  	userMap := make(map[string]*model.User)
   792  
   793  	for _, u := range users {
   794  		u.Sanitize(map[string]bool{})
   795  		userMap[u.Id] = u
   796  	}
   797  
   798  	return userMap, nil
   799  }
   800  
   801  func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) {
   802  	query := us.usersQuery.
   803  		Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
   804  		LeftJoin("ChannelMembers cm ON ( cm.UserId = u.Id AND cm.ChannelId = ? )", channelId).
   805  		Where("cm.UserId IS NULL").
   806  		OrderBy("u.Username ASC").
   807  		Offset(uint64(offset)).Limit(uint64(limit))
   808  
   809  	query = applyViewRestrictionsFilter(query, viewRestrictions, true)
   810  
   811  	if groupConstrained {
   812  		query = applyChannelGroupConstrainedFilter(query, channelId)
   813  	}
   814  
   815  	queryString, args, err := query.ToSql()
   816  	if err != nil {
   817  		return nil, errors.Wrap(err, "get_profiles_not_in_channel_tosql")
   818  	}
   819  
   820  	var users []*model.User
   821  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   822  		return nil, errors.Wrap(err, "failed to find Users")
   823  	}
   824  
   825  	for _, u := range users {
   826  		u.Sanitize(map[string]bool{})
   827  	}
   828  
   829  	return users, nil
   830  }
   831  
   832  func (us SqlUserStore) GetProfilesWithoutTeam(options *model.UserGetOptions) ([]*model.User, error) {
   833  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
   834  	query := us.usersQuery.
   835  		Where(`(
   836  			SELECT
   837  				COUNT(0)
   838  			FROM
   839  				TeamMembers
   840  			WHERE
   841  				TeamMembers.UserId = u.Id
   842  				AND TeamMembers.DeleteAt = 0
   843  		) = 0`).
   844  		OrderBy("u.Username ASC").
   845  		Offset(uint64(options.Page * options.PerPage)).Limit(uint64(options.PerPage))
   846  
   847  	query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
   848  
   849  	query = applyRoleFilter(query, options.Role, isPostgreSQL)
   850  
   851  	if options.Inactive {
   852  		query = query.Where("u.DeleteAt != 0")
   853  	} else if options.Active {
   854  		query = query.Where("u.DeleteAt = 0")
   855  	}
   856  
   857  	queryString, args, err := query.ToSql()
   858  	if err != nil {
   859  		return nil, errors.Wrap(err, "get_profiles_without_team_tosql")
   860  	}
   861  
   862  	var users []*model.User
   863  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   864  		return nil, errors.Wrap(err, "failed to find Users")
   865  	}
   866  
   867  	for _, u := range users {
   868  		u.Sanitize(map[string]bool{})
   869  	}
   870  
   871  	return users, nil
   872  }
   873  
   874  func (us SqlUserStore) GetProfilesByUsernames(usernames []string, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) {
   875  	query := us.usersQuery
   876  
   877  	query = applyViewRestrictionsFilter(query, viewRestrictions, true)
   878  
   879  	query = query.
   880  		Where(map[string]interface{}{
   881  			"Username": usernames,
   882  		}).
   883  		OrderBy("u.Username ASC")
   884  
   885  	queryString, args, err := query.ToSql()
   886  	if err != nil {
   887  		return nil, errors.Wrap(err, "get_profiles_by_usernames")
   888  	}
   889  
   890  	var users []*model.User
   891  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   892  		return nil, errors.Wrap(err, "failed to find Users")
   893  	}
   894  
   895  	return users, nil
   896  }
   897  
   898  type UserWithLastActivityAt struct {
   899  	model.User
   900  	LastActivityAt int64
   901  }
   902  
   903  func (us SqlUserStore) GetRecentlyActiveUsersForTeam(teamId string, offset, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) {
   904  	query := us.usersQuery.
   905  		Column("s.LastActivityAt").
   906  		Join("TeamMembers tm ON (tm.UserId = u.Id AND tm.TeamId = ?)", teamId).
   907  		Join("Status s ON (s.UserId = u.Id)").
   908  		OrderBy("s.LastActivityAt DESC").
   909  		OrderBy("u.Username ASC").
   910  		Offset(uint64(offset)).Limit(uint64(limit))
   911  
   912  	query = applyViewRestrictionsFilter(query, viewRestrictions, true)
   913  
   914  	queryString, args, err := query.ToSql()
   915  	if err != nil {
   916  		return nil, errors.Wrap(err, "get_recently_active_users_for_team_tosql")
   917  	}
   918  
   919  	var users []*UserWithLastActivityAt
   920  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   921  		return nil, errors.Wrap(err, "failed to find Users")
   922  	}
   923  
   924  	userList := []*model.User{}
   925  
   926  	for _, userWithLastActivityAt := range users {
   927  		u := userWithLastActivityAt.User
   928  		u.Sanitize(map[string]bool{})
   929  		u.LastActivityAt = userWithLastActivityAt.LastActivityAt
   930  		userList = append(userList, &u)
   931  	}
   932  
   933  	return userList, nil
   934  }
   935  
   936  func (us SqlUserStore) GetNewUsersForTeam(teamId string, offset, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) {
   937  	query := us.usersQuery.
   938  		Join("TeamMembers tm ON (tm.UserId = u.Id AND tm.TeamId = ?)", teamId).
   939  		OrderBy("u.CreateAt DESC").
   940  		OrderBy("u.Username ASC").
   941  		Offset(uint64(offset)).Limit(uint64(limit))
   942  
   943  	query = applyViewRestrictionsFilter(query, viewRestrictions, true)
   944  
   945  	queryString, args, err := query.ToSql()
   946  	if err != nil {
   947  		return nil, errors.Wrap(err, "get_new_users_for_team_tosql")
   948  	}
   949  
   950  	var users []*model.User
   951  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
   952  		return nil, errors.Wrap(err, "failed to find Users")
   953  	}
   954  
   955  	for _, u := range users {
   956  		u.Sanitize(map[string]bool{})
   957  	}
   958  
   959  	return users, nil
   960  }
   961  
   962  func (us SqlUserStore) GetProfileByIds(ctx context.Context, userIds []string, options *store.UserGetByIdsOpts, allowFromCache bool) ([]*model.User, error) {
   963  	if options == nil {
   964  		options = &store.UserGetByIdsOpts{}
   965  	}
   966  
   967  	users := []*model.User{}
   968  	query := us.usersQuery.
   969  		Where(map[string]interface{}{
   970  			"u.Id": userIds,
   971  		}).
   972  		OrderBy("u.Username ASC")
   973  
   974  	if options.Since > 0 {
   975  		query = query.Where(sq.Gt(map[string]interface{}{
   976  			"u.UpdateAt": options.Since,
   977  		}))
   978  	}
   979  
   980  	query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
   981  
   982  	queryString, args, err := query.ToSql()
   983  	if err != nil {
   984  		return nil, errors.Wrap(err, "get_profile_by_ids_tosql")
   985  	}
   986  
   987  	if _, err := us.SqlStore.DBFromContext(ctx).Select(&users, queryString, args...); err != nil {
   988  		return nil, errors.Wrap(err, "failed to find Users")
   989  	}
   990  
   991  	return users, nil
   992  }
   993  
   994  type UserWithChannel struct {
   995  	model.User
   996  	ChannelId string
   997  }
   998  
   999  func (us SqlUserStore) GetProfileByGroupChannelIdsForUser(userId string, channelIds []string) (map[string][]*model.User, error) {
  1000  	if len(channelIds) > MaxGroupChannelsForProfiles {
  1001  		channelIds = channelIds[0:MaxGroupChannelsForProfiles]
  1002  	}
  1003  
  1004  	isMemberQuery := fmt.Sprintf(`
  1005        EXISTS(
  1006          SELECT
  1007            1
  1008          FROM
  1009            ChannelMembers
  1010          WHERE
  1011            UserId = '%s'
  1012          AND
  1013            ChannelId = cm.ChannelId
  1014          )`, userId)
  1015  
  1016  	query := us.getQueryBuilder().
  1017  		Select("u.*, cm.ChannelId").
  1018  		From("Users u").
  1019  		Join("ChannelMembers cm ON u.Id = cm.UserId").
  1020  		Join("Channels c ON cm.ChannelId = c.Id").
  1021  		Where(sq.Eq{"c.Type": model.CHANNEL_GROUP, "cm.ChannelId": channelIds}).
  1022  		Where(isMemberQuery).
  1023  		Where(sq.NotEq{"u.Id": userId}).
  1024  		OrderBy("u.Username ASC")
  1025  
  1026  	queryString, args, err := query.ToSql()
  1027  	if err != nil {
  1028  		return nil, errors.Wrap(err, "get_profiles_by_group_channel_ids_for_user_tosql")
  1029  	}
  1030  
  1031  	usersWithChannel := []*UserWithChannel{}
  1032  	if _, err := us.GetReplica().Select(&usersWithChannel, queryString, args...); err != nil {
  1033  		return nil, errors.Wrap(err, "failed to find Users")
  1034  	}
  1035  
  1036  	usersByChannelId := map[string][]*model.User{}
  1037  	for _, user := range usersWithChannel {
  1038  		if val, ok := usersByChannelId[user.ChannelId]; ok {
  1039  			usersByChannelId[user.ChannelId] = append(val, &user.User)
  1040  		} else {
  1041  			usersByChannelId[user.ChannelId] = []*model.User{&user.User}
  1042  		}
  1043  	}
  1044  
  1045  	return usersByChannelId, nil
  1046  }
  1047  
  1048  func (us SqlUserStore) GetSystemAdminProfiles() (map[string]*model.User, error) {
  1049  	query := us.usersQuery.
  1050  		Where("Roles LIKE ?", "%system_admin%").
  1051  		OrderBy("u.Username ASC")
  1052  
  1053  	queryString, args, err := query.ToSql()
  1054  	if err != nil {
  1055  		return nil, errors.Wrap(err, "get_system_admin_profiles_tosql")
  1056  	}
  1057  
  1058  	var users []*model.User
  1059  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1060  		return nil, errors.Wrap(err, "failed to find Users")
  1061  	}
  1062  
  1063  	userMap := make(map[string]*model.User)
  1064  
  1065  	for _, u := range users {
  1066  		u.Sanitize(map[string]bool{})
  1067  		userMap[u.Id] = u
  1068  	}
  1069  
  1070  	return userMap, nil
  1071  }
  1072  
  1073  func (us SqlUserStore) GetByEmail(email string) (*model.User, error) {
  1074  	query := us.usersQuery.Where("Email = lower(?)", email)
  1075  
  1076  	queryString, args, err := query.ToSql()
  1077  	if err != nil {
  1078  		return nil, errors.Wrap(err, "get_by_email_tosql")
  1079  	}
  1080  
  1081  	user := model.User{}
  1082  	if err := us.GetReplica().SelectOne(&user, queryString, args...); err != nil {
  1083  		if err == sql.ErrNoRows {
  1084  			return nil, errors.Wrap(store.NewErrNotFound("User", fmt.Sprintf("email=%s", email)), "failed to find User")
  1085  		}
  1086  
  1087  		return nil, errors.Wrapf(err, "failed to get User with email=%s", email)
  1088  	}
  1089  
  1090  	return &user, nil
  1091  }
  1092  
  1093  func (us SqlUserStore) GetByAuth(authData *string, authService string) (*model.User, error) {
  1094  	if authData == nil || *authData == "" {
  1095  		return nil, store.NewErrInvalidInput("User", "<authData>", "empty or nil")
  1096  	}
  1097  
  1098  	query := us.usersQuery.
  1099  		Where("u.AuthData = ?", authData).
  1100  		Where("u.AuthService = ?", authService)
  1101  
  1102  	queryString, args, err := query.ToSql()
  1103  	if err != nil {
  1104  		return nil, errors.Wrap(err, "get_by_auth_tosql")
  1105  	}
  1106  
  1107  	user := model.User{}
  1108  	if err := us.GetReplica().SelectOne(&user, queryString, args...); err == sql.ErrNoRows {
  1109  		return nil, store.NewErrNotFound("User", fmt.Sprintf("authData=%s, authService=%s", *authData, authService))
  1110  	} else if err != nil {
  1111  		return nil, errors.Wrapf(err, "failed to find User with authData=%s and authService=%s", *authData, authService)
  1112  	}
  1113  	return &user, nil
  1114  }
  1115  
  1116  func (us SqlUserStore) GetAllUsingAuthService(authService string) ([]*model.User, error) {
  1117  	query := us.usersQuery.
  1118  		Where("u.AuthService = ?", authService).
  1119  		OrderBy("u.Username ASC")
  1120  
  1121  	queryString, args, err := query.ToSql()
  1122  	if err != nil {
  1123  		return nil, errors.Wrap(err, "get_all_using_auth_service_tosql")
  1124  	}
  1125  
  1126  	var users []*model.User
  1127  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1128  		return nil, errors.Wrapf(err, "failed to find Users with authService=%s", authService)
  1129  	}
  1130  
  1131  	return users, nil
  1132  }
  1133  
  1134  func (us SqlUserStore) GetAllNotInAuthService(authServices []string) ([]*model.User, error) {
  1135  	query := us.usersQuery.
  1136  		Where(sq.NotEq{"u.AuthService": authServices}).
  1137  		OrderBy("u.Username ASC")
  1138  
  1139  	queryString, args, err := query.ToSql()
  1140  	if err != nil {
  1141  		return nil, errors.Wrap(err, "get_all_not_in_auth_service_tosql")
  1142  	}
  1143  
  1144  	var users []*model.User
  1145  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1146  		return nil, errors.Wrapf(err, "failed to find Users with authServices in %v", authServices)
  1147  	}
  1148  
  1149  	return users, nil
  1150  }
  1151  
  1152  func (us SqlUserStore) GetByUsername(username string) (*model.User, error) {
  1153  	query := us.usersQuery.Where("u.Username = lower(?)", username)
  1154  
  1155  	queryString, args, err := query.ToSql()
  1156  	if err != nil {
  1157  		return nil, errors.Wrap(err, "get_by_username_tosql")
  1158  	}
  1159  
  1160  	var user *model.User
  1161  	if err := us.GetReplica().SelectOne(&user, queryString, args...); err != nil {
  1162  		if err == sql.ErrNoRows {
  1163  			return nil, errors.Wrap(store.NewErrNotFound("User", fmt.Sprintf("username=%s", username)), "failed to find User")
  1164  		}
  1165  
  1166  		return nil, errors.Wrapf(err, "failed to find User with username=%s", username)
  1167  	}
  1168  
  1169  	return user, nil
  1170  }
  1171  
  1172  func (us SqlUserStore) GetForLogin(loginId string, allowSignInWithUsername, allowSignInWithEmail bool) (*model.User, error) {
  1173  	query := us.usersQuery
  1174  	if allowSignInWithUsername && allowSignInWithEmail {
  1175  		query = query.Where("Username = lower(?) OR Email = lower(?)", loginId, loginId)
  1176  	} else if allowSignInWithUsername {
  1177  		query = query.Where("Username = lower(?)", loginId)
  1178  	} else if allowSignInWithEmail {
  1179  		query = query.Where("Email = lower(?)", loginId)
  1180  	} else {
  1181  		return nil, errors.New("sign in with username and email are disabled")
  1182  	}
  1183  
  1184  	queryString, args, err := query.ToSql()
  1185  	if err != nil {
  1186  		return nil, errors.Wrap(err, "get_for_login_tosql")
  1187  	}
  1188  
  1189  	users := []*model.User{}
  1190  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1191  		return nil, errors.Wrap(err, "failed to find Users")
  1192  	}
  1193  
  1194  	if len(users) == 0 {
  1195  		return nil, errors.New("user not found")
  1196  	}
  1197  
  1198  	if len(users) > 1 {
  1199  		return nil, errors.New("multiple users found")
  1200  	}
  1201  
  1202  	return users[0], nil
  1203  
  1204  }
  1205  
  1206  func (us SqlUserStore) VerifyEmail(userId, email string) (string, error) {
  1207  	curTime := model.GetMillis()
  1208  	if _, err := us.GetMaster().Exec("UPDATE Users SET Email = lower(:email), EmailVerified = true, UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"email": email, "Time": curTime, "UserId": userId}); err != nil {
  1209  		return "", errors.Wrapf(err, "failed to update Users with userId=%s and email=%s", userId, email)
  1210  	}
  1211  
  1212  	return userId, nil
  1213  }
  1214  
  1215  func (us SqlUserStore) PermanentDelete(userId string) error {
  1216  	if _, err := us.GetMaster().Exec("DELETE FROM Users WHERE Id = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
  1217  		return errors.Wrapf(err, "failed to delete User with userId=%s", userId)
  1218  	}
  1219  	return nil
  1220  }
  1221  
  1222  func (us SqlUserStore) Count(options model.UserCountOptions) (int64, error) {
  1223  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
  1224  	query := us.getQueryBuilder().Select("COUNT(DISTINCT u.Id)").From("Users AS u")
  1225  
  1226  	if !options.IncludeDeleted {
  1227  		query = query.Where("u.DeleteAt = 0")
  1228  	}
  1229  
  1230  	if options.IncludeBotAccounts {
  1231  		if options.ExcludeRegularUsers {
  1232  			query = query.Join("Bots ON u.Id = Bots.UserId")
  1233  		}
  1234  	} else {
  1235  		query = query.LeftJoin("Bots ON u.Id = Bots.UserId").Where("Bots.UserId IS NULL")
  1236  		if options.ExcludeRegularUsers {
  1237  			// Currently this doesn't make sense because it will always return 0
  1238  			return int64(0), errors.New("query with IncludeBotAccounts=false and excludeRegularUsers=true always return 0")
  1239  		}
  1240  	}
  1241  
  1242  	if options.TeamId != "" {
  1243  		query = query.LeftJoin("TeamMembers AS tm ON u.Id = tm.UserId").Where("tm.TeamId = ? AND tm.DeleteAt = 0", options.TeamId)
  1244  	} else if options.ChannelId != "" {
  1245  		query = query.LeftJoin("ChannelMembers AS cm ON u.Id = cm.UserId").Where("cm.ChannelId = ?", options.ChannelId)
  1246  	}
  1247  	query = applyViewRestrictionsFilter(query, options.ViewRestrictions, false)
  1248  	query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles, isPostgreSQL)
  1249  
  1250  	if isPostgreSQL {
  1251  		query = query.PlaceholderFormat(sq.Dollar)
  1252  	}
  1253  
  1254  	queryString, args, err := query.ToSql()
  1255  	if err != nil {
  1256  		return int64(0), errors.Wrap(err, "count_tosql")
  1257  	}
  1258  
  1259  	count, err := us.GetReplica().SelectInt(queryString, args...)
  1260  	if err != nil {
  1261  		return int64(0), errors.Wrap(err, "failed to count Users")
  1262  	}
  1263  	return count, nil
  1264  }
  1265  
  1266  func (us SqlUserStore) AnalyticsActiveCount(timePeriod int64, options model.UserCountOptions) (int64, error) {
  1267  
  1268  	time := model.GetMillis() - timePeriod
  1269  	query := us.getQueryBuilder().Select("COUNT(*)").From("Status AS s").Where("LastActivityAt > :Time", map[string]interface{}{"Time": time})
  1270  
  1271  	if !options.IncludeBotAccounts {
  1272  		query = query.LeftJoin("Bots ON s.UserId = Bots.UserId").Where("Bots.UserId IS NULL")
  1273  	}
  1274  
  1275  	if !options.IncludeDeleted {
  1276  		query = query.LeftJoin("Users ON s.UserId = Users.Id").Where("Users.DeleteAt = 0")
  1277  	}
  1278  
  1279  	queryStr, args, err := query.ToSql()
  1280  
  1281  	if err != nil {
  1282  		return 0, errors.Wrap(err, "analytics_active_count_tosql")
  1283  	}
  1284  
  1285  	v, err := us.GetReplica().SelectInt(queryStr, args...)
  1286  	if err != nil {
  1287  		return 0, errors.Wrap(err, "failed to count Users")
  1288  	}
  1289  	return v, nil
  1290  }
  1291  
  1292  func (us SqlUserStore) AnalyticsActiveCountForPeriod(startTime int64, endTime int64, options model.UserCountOptions) (int64, error) {
  1293  	query := us.getQueryBuilder().Select("COUNT(*)").From("Status AS s").Where("LastActivityAt > :StartTime AND LastActivityAt <= :EndTime", map[string]interface{}{"StartTime": startTime, "EndTime": endTime})
  1294  
  1295  	if !options.IncludeBotAccounts {
  1296  		query = query.LeftJoin("Bots ON s.UserId = Bots.UserId").Where("Bots.UserId IS NULL")
  1297  	}
  1298  
  1299  	if !options.IncludeDeleted {
  1300  		query = query.LeftJoin("Users ON s.UserId = Users.Id").Where("Users.DeleteAt = 0")
  1301  	}
  1302  
  1303  	queryStr, args, err := query.ToSql()
  1304  
  1305  	if err != nil {
  1306  		return 0, errors.Wrap(err, "Failed to build query.")
  1307  	}
  1308  
  1309  	v, err := us.GetReplica().SelectInt(queryStr, args...)
  1310  	if err != nil {
  1311  		return 0, errors.Wrap(err, "Unable to get the active users during the requested period.")
  1312  	}
  1313  	return v, nil
  1314  }
  1315  
  1316  func (us SqlUserStore) GetUnreadCount(userId string) (int64, error) {
  1317  	query := `
  1318  		SELECT SUM(CASE WHEN c.Type = 'D' THEN (c.TotalMsgCount - cm.MsgCount) ELSE cm.MentionCount END)
  1319  		FROM Channels c
  1320  		INNER JOIN ChannelMembers cm
  1321  			ON cm.ChannelId = c.Id
  1322  			AND cm.UserId = :UserId
  1323  			AND c.DeleteAt = 0
  1324  	`
  1325  	count, err := us.GetReplica().SelectInt(query, map[string]interface{}{"UserId": userId})
  1326  	if err != nil {
  1327  		return count, errors.Wrapf(err, "failed to count unread Channels for userId=%s", userId)
  1328  	}
  1329  
  1330  	return count, nil
  1331  }
  1332  
  1333  func (us SqlUserStore) GetUnreadCountForChannel(userId string, channelId string) (int64, error) {
  1334  	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})
  1335  	if err != nil {
  1336  		return 0, errors.Wrapf(err, "failed to get unread count for channelId=%s and userId=%s", channelId, userId)
  1337  	}
  1338  	return count, nil
  1339  }
  1340  
  1341  func (us SqlUserStore) GetAnyUnreadPostCountForChannel(userId string, channelId string) (int64, error) {
  1342  	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})
  1343  	if err != nil {
  1344  		return count, errors.Wrapf(err, "failed to get any unread count for channelId=%s and userId=%s", channelId, userId)
  1345  	}
  1346  	return count, nil
  1347  }
  1348  
  1349  func (us SqlUserStore) Search(teamId string, term string, options *model.UserSearchOptions) ([]*model.User, error) {
  1350  	query := us.usersQuery.
  1351  		OrderBy("Username ASC").
  1352  		Limit(uint64(options.Limit))
  1353  
  1354  	if teamId != "" {
  1355  		query = query.Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId)
  1356  	}
  1357  	return us.performSearch(query, term, options)
  1358  }
  1359  
  1360  func (us SqlUserStore) SearchWithoutTeam(term string, options *model.UserSearchOptions) ([]*model.User, error) {
  1361  	query := us.usersQuery.
  1362  		Where(`(
  1363  				SELECT
  1364  					COUNT(0)
  1365  				FROM
  1366  					TeamMembers
  1367  				WHERE
  1368  					TeamMembers.UserId = u.Id
  1369  					AND TeamMembers.DeleteAt = 0
  1370  			) = 0`).
  1371  		OrderBy("u.Username ASC").
  1372  		Limit(uint64(options.Limit))
  1373  
  1374  	return us.performSearch(query, term, options)
  1375  }
  1376  
  1377  func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options *model.UserSearchOptions) ([]*model.User, error) {
  1378  	query := us.usersQuery.
  1379  		LeftJoin("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", notInTeamId).
  1380  		Where("tm.UserId IS NULL").
  1381  		OrderBy("u.Username ASC").
  1382  		Limit(uint64(options.Limit))
  1383  
  1384  	if options.GroupConstrained {
  1385  		query = applyTeamGroupConstrainedFilter(query, notInTeamId)
  1386  	}
  1387  
  1388  	return us.performSearch(query, term, options)
  1389  }
  1390  
  1391  func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term string, options *model.UserSearchOptions) ([]*model.User, error) {
  1392  	query := us.usersQuery.
  1393  		LeftJoin("ChannelMembers cm ON ( cm.UserId = u.Id AND cm.ChannelId = ? )", channelId).
  1394  		Where("cm.UserId IS NULL").
  1395  		OrderBy("Username ASC").
  1396  		Limit(uint64(options.Limit))
  1397  
  1398  	if teamId != "" {
  1399  		query = query.Join("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId)
  1400  	}
  1401  
  1402  	if options.GroupConstrained {
  1403  		query = applyChannelGroupConstrainedFilter(query, channelId)
  1404  	}
  1405  
  1406  	return us.performSearch(query, term, options)
  1407  }
  1408  
  1409  func (us SqlUserStore) SearchInChannel(channelId string, term string, options *model.UserSearchOptions) ([]*model.User, error) {
  1410  	query := us.usersQuery.
  1411  		Join("ChannelMembers cm ON ( cm.UserId = u.Id AND cm.ChannelId = ? )", channelId).
  1412  		OrderBy("Username ASC").
  1413  		Limit(uint64(options.Limit))
  1414  
  1415  	return us.performSearch(query, term, options)
  1416  }
  1417  
  1418  func (us SqlUserStore) SearchInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, error) {
  1419  	query := us.usersQuery.
  1420  		Join("GroupMembers gm ON ( gm.UserId = u.Id AND gm.GroupId = ? )", groupID).
  1421  		OrderBy("Username ASC").
  1422  		Limit(uint64(options.Limit))
  1423  
  1424  	return us.performSearch(query, term, options)
  1425  }
  1426  
  1427  var spaceFulltextSearchChar = []string{
  1428  	"<",
  1429  	">",
  1430  	"+",
  1431  	"-",
  1432  	"(",
  1433  	")",
  1434  	"~",
  1435  	":",
  1436  	"*",
  1437  	"\"",
  1438  	"!",
  1439  	"@",
  1440  }
  1441  
  1442  func generateSearchQuery(query sq.SelectBuilder, terms []string, fields []string, isPostgreSQL bool) sq.SelectBuilder {
  1443  	for _, term := range terms {
  1444  		searchFields := []string{}
  1445  		termArgs := []interface{}{}
  1446  		for _, field := range fields {
  1447  			if isPostgreSQL {
  1448  				searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(?) escape '*' ", field))
  1449  			} else {
  1450  				searchFields = append(searchFields, fmt.Sprintf("%s LIKE ? escape '*' ", field))
  1451  			}
  1452  			termArgs = append(termArgs, fmt.Sprintf("%s%%", strings.TrimLeft(term, "@")))
  1453  		}
  1454  		query = query.Where(fmt.Sprintf("(%s)", strings.Join(searchFields, " OR ")), termArgs...)
  1455  	}
  1456  
  1457  	return query
  1458  }
  1459  
  1460  func (us SqlUserStore) performSearch(query sq.SelectBuilder, term string, options *model.UserSearchOptions) ([]*model.User, error) {
  1461  	term = sanitizeSearchTerm(term, "*")
  1462  
  1463  	var searchType []string
  1464  	if options.AllowEmails {
  1465  		if options.AllowFullNames {
  1466  			searchType = UserSearchTypeAll
  1467  		} else {
  1468  			searchType = UserSearchTypeAll_NO_FULL_NAME
  1469  		}
  1470  	} else {
  1471  		if options.AllowFullNames {
  1472  			searchType = UserSearchTypeNames
  1473  		} else {
  1474  			searchType = UserSearchTypeNames_NO_FULL_NAME
  1475  		}
  1476  	}
  1477  
  1478  	isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES
  1479  
  1480  	query = applyRoleFilter(query, options.Role, isPostgreSQL)
  1481  	query = applyMultiRoleFilters(query, options.Roles, options.TeamRoles, options.ChannelRoles, isPostgreSQL)
  1482  
  1483  	if !options.AllowInactive {
  1484  		query = query.Where("u.DeleteAt = 0")
  1485  	}
  1486  
  1487  	if strings.TrimSpace(term) != "" {
  1488  		query = generateSearchQuery(query, strings.Fields(term), searchType, isPostgreSQL)
  1489  	}
  1490  
  1491  	query = applyViewRestrictionsFilter(query, options.ViewRestrictions, true)
  1492  
  1493  	queryString, args, err := query.ToSql()
  1494  	if err != nil {
  1495  		return nil, errors.Wrap(err, "perform_search_tosql")
  1496  	}
  1497  
  1498  	var users []*model.User
  1499  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1500  		return nil, errors.Wrapf(err, "failed to find Users with term=%s and searchType=%v", term, searchType)
  1501  	}
  1502  	for _, u := range users {
  1503  		u.Sanitize(map[string]bool{})
  1504  	}
  1505  
  1506  	return users, nil
  1507  }
  1508  
  1509  func (us SqlUserStore) AnalyticsGetInactiveUsersCount() (int64, error) {
  1510  	count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users WHERE DeleteAt > 0")
  1511  	if err != nil {
  1512  		return int64(0), errors.Wrap(err, "failed to count inactive Users")
  1513  	}
  1514  	return count, nil
  1515  }
  1516  
  1517  func (us SqlUserStore) AnalyticsGetExternalUsers(hostDomain string) (bool, error) {
  1518  	count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users WHERE LOWER(Email) NOT LIKE :HostDomain", map[string]interface{}{"HostDomain": "%@" + strings.ToLower(hostDomain)})
  1519  	if err != nil {
  1520  		return false, errors.Wrap(err, "failed to count inactive Users")
  1521  	}
  1522  	return count > 0, nil
  1523  }
  1524  
  1525  func (us SqlUserStore) AnalyticsGetGuestCount() (int64, error) {
  1526  	count, err := us.GetReplica().SelectInt("SELECT count(*) FROM Users WHERE Roles LIKE :Roles and DeleteAt = 0", map[string]interface{}{"Roles": "%system_guest%"})
  1527  	if err != nil {
  1528  		return int64(0), errors.Wrap(err, "failed to count guest Users")
  1529  	}
  1530  	return count, nil
  1531  }
  1532  
  1533  func (us SqlUserStore) AnalyticsGetSystemAdminCount() (int64, error) {
  1534  	count, err := us.GetReplica().SelectInt("SELECT count(*) FROM Users WHERE Roles LIKE :Roles and DeleteAt = 0", map[string]interface{}{"Roles": "%system_admin%"})
  1535  	if err != nil {
  1536  		return int64(0), errors.Wrap(err, "failed to count system admin Users")
  1537  	}
  1538  	return count, nil
  1539  }
  1540  
  1541  func (us SqlUserStore) GetProfilesNotInTeam(teamId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, error) {
  1542  	var users []*model.User
  1543  	query := us.usersQuery.
  1544  		LeftJoin("TeamMembers tm ON ( tm.UserId = u.Id AND tm.DeleteAt = 0 AND tm.TeamId = ? )", teamId).
  1545  		Where("tm.UserId IS NULL").
  1546  		OrderBy("u.Username ASC").
  1547  		Offset(uint64(offset)).Limit(uint64(limit))
  1548  
  1549  	query = applyViewRestrictionsFilter(query, viewRestrictions, true)
  1550  
  1551  	if groupConstrained {
  1552  		query = applyTeamGroupConstrainedFilter(query, teamId)
  1553  	}
  1554  
  1555  	queryString, args, err := query.ToSql()
  1556  	if err != nil {
  1557  		return nil, errors.Wrap(err, "get_profiles_not_in_team_tosql")
  1558  	}
  1559  
  1560  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1561  		return nil, errors.Wrap(err, "failed to find Users")
  1562  	}
  1563  
  1564  	for _, u := range users {
  1565  		u.Sanitize(map[string]bool{})
  1566  	}
  1567  	return users, nil
  1568  }
  1569  
  1570  func (us SqlUserStore) GetEtagForProfilesNotInTeam(teamId string) string {
  1571  	querystr := `
  1572  		SELECT
  1573  			CONCAT(MAX(UpdateAt), '.', COUNT(Id)) as etag
  1574  		FROM
  1575  			Users as u
  1576  		LEFT JOIN TeamMembers tm
  1577  			ON tm.UserId = u.Id
  1578  			AND tm.TeamId = :TeamId
  1579  			AND tm.DeleteAt = 0
  1580  		WHERE
  1581  			tm.UserId IS NULL
  1582  	`
  1583  	etag, err := us.GetReplica().SelectStr(querystr, map[string]interface{}{"TeamId": teamId})
  1584  	if err != nil {
  1585  		return fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis())
  1586  	}
  1587  
  1588  	return fmt.Sprintf("%v.%v", model.CurrentVersion, etag)
  1589  }
  1590  
  1591  func (us SqlUserStore) ClearAllCustomRoleAssignments() error {
  1592  	builtInRoles := model.MakeDefaultRoles()
  1593  	lastUserId := strings.Repeat("0", 26)
  1594  
  1595  	for {
  1596  		var transaction *gorp.Transaction
  1597  		var err error
  1598  
  1599  		if transaction, err = us.GetMaster().Begin(); err != nil {
  1600  			return errors.Wrap(err, "begin_transaction")
  1601  		}
  1602  		defer finalizeTransaction(transaction)
  1603  
  1604  		var users []*model.User
  1605  		if _, err := transaction.Select(&users, "SELECT * from Users WHERE Id > :Id ORDER BY Id LIMIT 1000", map[string]interface{}{"Id": lastUserId}); err != nil {
  1606  			return errors.Wrapf(err, "failed to find Users with id > %s", lastUserId)
  1607  		}
  1608  
  1609  		if len(users) == 0 {
  1610  			break
  1611  		}
  1612  
  1613  		for _, user := range users {
  1614  			lastUserId = user.Id
  1615  
  1616  			var newRoles []string
  1617  
  1618  			for _, role := range strings.Fields(user.Roles) {
  1619  				for name := range builtInRoles {
  1620  					if name == role {
  1621  						newRoles = append(newRoles, role)
  1622  						break
  1623  					}
  1624  				}
  1625  			}
  1626  
  1627  			newRolesString := strings.Join(newRoles, " ")
  1628  			if newRolesString != user.Roles {
  1629  				if _, err := transaction.Exec("UPDATE Users SET Roles = :Roles WHERE Id = :Id", map[string]interface{}{"Roles": newRolesString, "Id": user.Id}); err != nil {
  1630  					return errors.Wrap(err, "failed to update Users")
  1631  				}
  1632  			}
  1633  		}
  1634  
  1635  		if err := transaction.Commit(); err != nil {
  1636  			return errors.Wrap(err, "commit_transaction")
  1637  		}
  1638  	}
  1639  
  1640  	return nil
  1641  }
  1642  
  1643  func (us SqlUserStore) InferSystemInstallDate() (int64, error) {
  1644  	createAt, err := us.GetReplica().SelectInt("SELECT CreateAt FROM Users WHERE CreateAt IS NOT NULL ORDER BY CreateAt ASC LIMIT 1")
  1645  	if err != nil {
  1646  		return 0, errors.Wrap(err, "failed to infer system install date")
  1647  	}
  1648  
  1649  	return createAt, nil
  1650  }
  1651  
  1652  func (us SqlUserStore) GetUsersBatchForIndexing(startTime, endTime int64, limit int) ([]*model.UserForIndexing, error) {
  1653  	var users []*model.User
  1654  	usersQuery, args, _ := us.usersQuery.
  1655  		Where(sq.GtOrEq{"u.CreateAt": startTime}).
  1656  		Where(sq.Lt{"u.CreateAt": endTime}).
  1657  		OrderBy("u.CreateAt").
  1658  		Limit(uint64(limit)).
  1659  		ToSql()
  1660  	_, err := us.GetSearchReplica().Select(&users, usersQuery, args...)
  1661  	if err != nil {
  1662  		return nil, errors.Wrap(err, "failed to find Users")
  1663  	}
  1664  
  1665  	userIds := []string{}
  1666  	for _, user := range users {
  1667  		userIds = append(userIds, user.Id)
  1668  	}
  1669  
  1670  	var channelMembers []*model.ChannelMember
  1671  	channelMembersQuery, args, _ := us.getQueryBuilder().
  1672  		Select(`
  1673  				cm.ChannelId,
  1674  				cm.UserId,
  1675  				cm.Roles,
  1676  				cm.LastViewedAt,
  1677  				cm.MsgCount,
  1678  				cm.MentionCount,
  1679  				cm.MentionCountRoot,
  1680  				cm.NotifyProps,
  1681  				cm.LastUpdateAt,
  1682  				cm.SchemeUser,
  1683  				cm.SchemeAdmin,
  1684  				(cm.SchemeGuest IS NOT NULL AND cm.SchemeGuest) as SchemeGuest
  1685  			`).
  1686  		From("ChannelMembers cm").
  1687  		Join("Channels c ON cm.ChannelId = c.Id").
  1688  		Where(sq.Eq{"c.Type": "O", "cm.UserId": userIds}).
  1689  		ToSql()
  1690  	_, err = us.GetSearchReplica().Select(&channelMembers, channelMembersQuery, args...)
  1691  	if err != nil {
  1692  		return nil, errors.Wrap(err, "failed to find ChannelMembers")
  1693  	}
  1694  
  1695  	var teamMembers []*model.TeamMember
  1696  	teamMembersQuery, args, _ := us.getQueryBuilder().
  1697  		Select("TeamId, UserId, Roles, DeleteAt, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest, SchemeUser, SchemeAdmin").
  1698  		From("TeamMembers").
  1699  		Where(sq.Eq{"UserId": userIds, "DeleteAt": 0}).
  1700  		ToSql()
  1701  	_, err = us.GetSearchReplica().Select(&teamMembers, teamMembersQuery, args...)
  1702  	if err != nil {
  1703  		return nil, errors.Wrap(err, "failed to find TeamMembers")
  1704  	}
  1705  
  1706  	userMap := map[string]*model.UserForIndexing{}
  1707  	for _, user := range users {
  1708  		userMap[user.Id] = &model.UserForIndexing{
  1709  			Id:          user.Id,
  1710  			Username:    user.Username,
  1711  			Nickname:    user.Nickname,
  1712  			FirstName:   user.FirstName,
  1713  			LastName:    user.LastName,
  1714  			Roles:       user.Roles,
  1715  			CreateAt:    user.CreateAt,
  1716  			DeleteAt:    user.DeleteAt,
  1717  			TeamsIds:    []string{},
  1718  			ChannelsIds: []string{},
  1719  		}
  1720  	}
  1721  
  1722  	for _, c := range channelMembers {
  1723  		if userMap[c.UserId] != nil {
  1724  			userMap[c.UserId].ChannelsIds = append(userMap[c.UserId].ChannelsIds, c.ChannelId)
  1725  		}
  1726  	}
  1727  	for _, t := range teamMembers {
  1728  		if userMap[t.UserId] != nil {
  1729  			userMap[t.UserId].TeamsIds = append(userMap[t.UserId].TeamsIds, t.TeamId)
  1730  		}
  1731  	}
  1732  
  1733  	usersForIndexing := []*model.UserForIndexing{}
  1734  	for _, user := range userMap {
  1735  		usersForIndexing = append(usersForIndexing, user)
  1736  	}
  1737  	sort.Slice(usersForIndexing, func(i, j int) bool {
  1738  		return usersForIndexing[i].CreateAt < usersForIndexing[j].CreateAt
  1739  	})
  1740  
  1741  	return usersForIndexing, nil
  1742  }
  1743  
  1744  func (us SqlUserStore) GetTeamGroupUsers(teamID string) ([]*model.User, error) {
  1745  	query := applyTeamGroupConstrainedFilter(us.usersQuery, teamID)
  1746  
  1747  	queryString, args, err := query.ToSql()
  1748  	if err != nil {
  1749  		return nil, errors.Wrap(err, "get_team_group_users_tosql")
  1750  	}
  1751  
  1752  	var users []*model.User
  1753  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1754  		return nil, errors.Wrap(err, "failed to find Users")
  1755  	}
  1756  
  1757  	for _, u := range users {
  1758  		u.Sanitize(map[string]bool{})
  1759  	}
  1760  
  1761  	return users, nil
  1762  }
  1763  
  1764  func (us SqlUserStore) GetChannelGroupUsers(channelID string) ([]*model.User, error) {
  1765  	query := applyChannelGroupConstrainedFilter(us.usersQuery, channelID)
  1766  
  1767  	queryString, args, err := query.ToSql()
  1768  	if err != nil {
  1769  		return nil, errors.Wrap(err, "get_channel_group_users_tosql")
  1770  	}
  1771  
  1772  	var users []*model.User
  1773  	if _, err := us.GetReplica().Select(&users, queryString, args...); err != nil {
  1774  		return nil, errors.Wrap(err, "failed to find Users")
  1775  	}
  1776  
  1777  	for _, u := range users {
  1778  		u.Sanitize(map[string]bool{})
  1779  	}
  1780  
  1781  	return users, nil
  1782  }
  1783  
  1784  func applyViewRestrictionsFilter(query sq.SelectBuilder, restrictions *model.ViewUsersRestrictions, distinct bool) sq.SelectBuilder {
  1785  	if restrictions == nil {
  1786  		return query
  1787  	}
  1788  
  1789  	// If you have no access to teams or channels, return and empty result.
  1790  	if restrictions.Teams != nil && len(restrictions.Teams) == 0 && restrictions.Channels != nil && len(restrictions.Channels) == 0 {
  1791  		return query.Where("1 = 0")
  1792  	}
  1793  
  1794  	teams := make([]interface{}, len(restrictions.Teams))
  1795  	for i, v := range restrictions.Teams {
  1796  		teams[i] = v
  1797  	}
  1798  	channels := make([]interface{}, len(restrictions.Channels))
  1799  	for i, v := range restrictions.Channels {
  1800  		channels[i] = v
  1801  	}
  1802  	resultQuery := query
  1803  	if restrictions.Teams != nil && len(restrictions.Teams) > 0 {
  1804  		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...)
  1805  	}
  1806  	if restrictions.Channels != nil && len(restrictions.Channels) > 0 {
  1807  		resultQuery = resultQuery.Join(fmt.Sprintf("ChannelMembers rcm ON ( rcm.UserId = u.Id AND rcm.ChannelId IN (%s))", sq.Placeholders(len(channels))), channels...)
  1808  	}
  1809  
  1810  	if distinct {
  1811  		return resultQuery.Distinct()
  1812  	}
  1813  
  1814  	return resultQuery
  1815  }
  1816  
  1817  func (us SqlUserStore) PromoteGuestToUser(userId string) error {
  1818  	transaction, err := us.GetMaster().Begin()
  1819  	if err != nil {
  1820  		return errors.Wrap(err, "begin_transaction")
  1821  	}
  1822  	defer finalizeTransaction(transaction)
  1823  
  1824  	user, err := us.Get(context.Background(), userId)
  1825  	if err != nil {
  1826  		return err
  1827  	}
  1828  
  1829  	roles := user.GetRoles()
  1830  
  1831  	for idx, role := range roles {
  1832  		if role == "system_guest" {
  1833  			roles[idx] = "system_user"
  1834  		}
  1835  	}
  1836  
  1837  	curTime := model.GetMillis()
  1838  	query := us.getQueryBuilder().Update("Users").
  1839  		Set("Roles", strings.Join(roles, " ")).
  1840  		Set("UpdateAt", curTime).
  1841  		Where(sq.Eq{"Id": userId})
  1842  
  1843  	queryString, args, err := query.ToSql()
  1844  	if err != nil {
  1845  		return errors.Wrap(err, "promote_guest_to_user_tosql")
  1846  	}
  1847  
  1848  	if _, err = transaction.Exec(queryString, args...); err != nil {
  1849  		return errors.Wrapf(err, "failed to update User with userId=%s", userId)
  1850  	}
  1851  
  1852  	query = us.getQueryBuilder().Update("ChannelMembers").
  1853  		Set("SchemeUser", true).
  1854  		Set("SchemeGuest", false).
  1855  		Where(sq.Eq{"UserId": userId})
  1856  
  1857  	queryString, args, err = query.ToSql()
  1858  	if err != nil {
  1859  		return errors.Wrap(err, "promote_guest_to_user_tosql")
  1860  	}
  1861  
  1862  	if _, err = transaction.Exec(queryString, args...); err != nil {
  1863  		return errors.Wrapf(err, "failed to update ChannelMembers with userId=%s", userId)
  1864  	}
  1865  
  1866  	query = us.getQueryBuilder().Update("TeamMembers").
  1867  		Set("SchemeUser", true).
  1868  		Set("SchemeGuest", false).
  1869  		Where(sq.Eq{"UserId": userId})
  1870  
  1871  	queryString, args, err = query.ToSql()
  1872  	if err != nil {
  1873  		return errors.Wrap(err, "promote_guest_to_user_tosql")
  1874  	}
  1875  
  1876  	if _, err := transaction.Exec(queryString, args...); err != nil {
  1877  		return errors.Wrapf(err, "failed to update TeamMembers with userId=%s", userId)
  1878  	}
  1879  
  1880  	if err := transaction.Commit(); err != nil {
  1881  		return errors.Wrap(err, "commit_transaction")
  1882  	}
  1883  	return nil
  1884  }
  1885  
  1886  func (us SqlUserStore) DemoteUserToGuest(userID string) (*model.User, error) {
  1887  	transaction, err := us.GetMaster().Begin()
  1888  	if err != nil {
  1889  		return nil, errors.Wrap(err, "begin_transaction")
  1890  	}
  1891  	defer finalizeTransaction(transaction)
  1892  
  1893  	user, err := us.Get(context.Background(), userID)
  1894  	if err != nil {
  1895  		return nil, err
  1896  	}
  1897  
  1898  	roles := user.GetRoles()
  1899  
  1900  	newRoles := []string{}
  1901  	for _, role := range roles {
  1902  		if role == model.SYSTEM_USER_ROLE_ID {
  1903  			newRoles = append(newRoles, model.SYSTEM_GUEST_ROLE_ID)
  1904  		} else if role != model.SYSTEM_ADMIN_ROLE_ID {
  1905  			newRoles = append(newRoles, role)
  1906  		}
  1907  	}
  1908  
  1909  	curTime := model.GetMillis()
  1910  	newRolesDBStr := strings.Join(newRoles, " ")
  1911  	query := us.getQueryBuilder().Update("Users").
  1912  		Set("Roles", newRolesDBStr).
  1913  		Set("UpdateAt", curTime).
  1914  		Where(sq.Eq{"Id": userID})
  1915  
  1916  	queryString, args, err := query.ToSql()
  1917  	if err != nil {
  1918  		return nil, errors.Wrap(err, "demote_user_to_guest_tosql")
  1919  	}
  1920  
  1921  	if _, err = transaction.Exec(queryString, args...); err != nil {
  1922  		return nil, errors.Wrapf(err, "failed to update User with userId=%s", userID)
  1923  	}
  1924  
  1925  	user.Roles = newRolesDBStr
  1926  	user.UpdateAt = curTime
  1927  
  1928  	query = us.getQueryBuilder().Update("ChannelMembers").
  1929  		Set("SchemeUser", false).
  1930  		Set("SchemeAdmin", false).
  1931  		Set("SchemeGuest", true).
  1932  		Where(sq.Eq{"UserId": userID})
  1933  
  1934  	queryString, args, err = query.ToSql()
  1935  	if err != nil {
  1936  		return nil, errors.Wrap(err, "demote_user_to_guest_tosql")
  1937  	}
  1938  
  1939  	if _, err = transaction.Exec(queryString, args...); err != nil {
  1940  		return nil, errors.Wrapf(err, "failed to update ChannelMembers with userId=%s", userID)
  1941  	}
  1942  
  1943  	query = us.getQueryBuilder().Update("TeamMembers").
  1944  		Set("SchemeUser", false).
  1945  		Set("SchemeAdmin", false).
  1946  		Set("SchemeGuest", true).
  1947  		Where(sq.Eq{"UserId": userID})
  1948  
  1949  	queryString, args, err = query.ToSql()
  1950  	if err != nil {
  1951  		return nil, errors.Wrap(err, "demote_user_to_guest_tosql")
  1952  	}
  1953  
  1954  	if _, err := transaction.Exec(queryString, args...); err != nil {
  1955  		return nil, errors.Wrapf(err, "failed to update TeamMembers with userId=%s", userID)
  1956  	}
  1957  
  1958  	if err := transaction.Commit(); err != nil {
  1959  		return nil, errors.Wrap(err, "commit_transaction")
  1960  	}
  1961  	return user, nil
  1962  }
  1963  
  1964  func (us SqlUserStore) AutocompleteUsersInChannel(teamId, channelId, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, error) {
  1965  	var usersInChannel, usersNotInChannel []*model.User
  1966  	g := errgroup.Group{}
  1967  	g.Go(func() (err error) {
  1968  		usersInChannel, err = us.SearchInChannel(channelId, term, options)
  1969  		return err
  1970  	})
  1971  	g.Go(func() (err error) {
  1972  		usersNotInChannel, err = us.SearchNotInChannel(teamId, channelId, term, options)
  1973  		return err
  1974  	})
  1975  	err := g.Wait()
  1976  	if err != nil {
  1977  		return nil, err
  1978  	}
  1979  
  1980  	return &model.UserAutocompleteInChannel{
  1981  		InChannel:    usersInChannel,
  1982  		OutOfChannel: usersNotInChannel,
  1983  	}, nil
  1984  }
  1985  
  1986  // GetKnownUsers returns the list of user ids of users with any direct
  1987  // relationship with a user. That means any user sharing any channel, including
  1988  // direct and group channels.
  1989  func (us SqlUserStore) GetKnownUsers(userId string) ([]string, error) {
  1990  	var userIds []string
  1991  	usersQuery, args, _ := us.getQueryBuilder().
  1992  		Select("DISTINCT ocm.UserId").
  1993  		From("ChannelMembers AS cm").
  1994  		Join("ChannelMembers AS ocm ON ocm.ChannelId = cm.ChannelId").
  1995  		Where(sq.NotEq{"ocm.UserId": userId}).
  1996  		Where(sq.Eq{"cm.UserId": userId}).
  1997  		ToSql()
  1998  	_, err := us.GetSearchReplica().Select(&userIds, usersQuery, args...)
  1999  	if err != nil {
  2000  		return nil, errors.Wrap(err, "failed to find ChannelMembers")
  2001  	}
  2002  
  2003  	return userIds, nil
  2004  }