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

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