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