github.com/wgh-/mattermost-server@v4.8.0-rc2+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 "strconv" 11 "strings" 12 13 "github.com/mattermost/mattermost-server/einterfaces" 14 "github.com/mattermost/mattermost-server/model" 15 "github.com/mattermost/mattermost-server/store" 16 "github.com/mattermost/mattermost-server/utils" 17 ) 18 19 const ( 20 PROFILES_IN_CHANNEL_CACHE_SIZE = model.CHANNEL_CACHE_SIZE 21 PROFILES_IN_CHANNEL_CACHE_SEC = 900 // 15 mins 22 PROFILE_BY_IDS_CACHE_SIZE = model.SESSION_CACHE_SIZE 23 PROFILE_BY_IDS_CACHE_SEC = 900 // 15 mins 24 ) 25 26 var ( 27 USER_SEARCH_TYPE_NAMES_NO_FULL_NAME = []string{"Username", "Nickname"} 28 USER_SEARCH_TYPE_NAMES = []string{"Username", "FirstName", "LastName", "Nickname"} 29 USER_SEARCH_TYPE_ALL_NO_FULL_NAME = []string{"Username", "Nickname", "Email"} 30 USER_SEARCH_TYPE_ALL = []string{"Username", "FirstName", "LastName", "Nickname", "Email"} 31 ) 32 33 type SqlUserStore struct { 34 SqlStore 35 metrics einterfaces.MetricsInterface 36 } 37 38 var profilesInChannelCache *utils.Cache = utils.NewLru(PROFILES_IN_CHANNEL_CACHE_SIZE) 39 var profileByIdsCache *utils.Cache = utils.NewLru(PROFILE_BY_IDS_CACHE_SIZE) 40 41 func ClearUserCaches() { 42 profilesInChannelCache.Purge() 43 profileByIdsCache.Purge() 44 } 45 46 func (us SqlUserStore) InvalidatProfileCacheForUser(userId string) { 47 profileByIdsCache.Remove(userId) 48 } 49 50 func NewSqlUserStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.UserStore { 51 us := &SqlUserStore{ 52 SqlStore: sqlStore, 53 metrics: metrics, 54 } 55 56 for _, db := range sqlStore.GetAllConns() { 57 table := db.AddTableWithName(model.User{}, "Users").SetKeys(false, "Id") 58 table.ColMap("Id").SetMaxSize(26) 59 table.ColMap("Username").SetMaxSize(64).SetUnique(true) 60 table.ColMap("Password").SetMaxSize(128) 61 table.ColMap("AuthData").SetMaxSize(128).SetUnique(true) 62 table.ColMap("AuthService").SetMaxSize(32) 63 table.ColMap("Email").SetMaxSize(128).SetUnique(true) 64 table.ColMap("Nickname").SetMaxSize(64) 65 table.ColMap("FirstName").SetMaxSize(64) 66 table.ColMap("LastName").SetMaxSize(64) 67 table.ColMap("Roles").SetMaxSize(256) 68 table.ColMap("Props").SetMaxSize(4000) 69 table.ColMap("NotifyProps").SetMaxSize(2000) 70 table.ColMap("Locale").SetMaxSize(5) 71 table.ColMap("MfaSecret").SetMaxSize(128) 72 table.ColMap("Position").SetMaxSize(128) 73 } 74 75 return us 76 } 77 78 func (us SqlUserStore) CreateIndexesIfNotExists() { 79 us.CreateIndexIfNotExists("idx_users_email", "Users", "Email") 80 us.CreateIndexIfNotExists("idx_users_update_at", "Users", "UpdateAt") 81 us.CreateIndexIfNotExists("idx_users_create_at", "Users", "CreateAt") 82 us.CreateIndexIfNotExists("idx_users_delete_at", "Users", "DeleteAt") 83 84 if us.DriverName() == model.DATABASE_DRIVER_POSTGRES { 85 us.CreateIndexIfNotExists("idx_users_email_lower", "Users", "lower(Email)") 86 us.CreateIndexIfNotExists("idx_users_username_lower", "Users", "lower(Username)") 87 us.CreateIndexIfNotExists("idx_users_nickname_lower", "Users", "lower(Nickname)") 88 us.CreateIndexIfNotExists("idx_users_firstname_lower", "Users", "lower(FirstName)") 89 us.CreateIndexIfNotExists("idx_users_lastname_lower", "Users", "lower(LastName)") 90 } 91 92 us.CreateFullTextIndexIfNotExists("idx_users_all_txt", "Users", strings.Join(USER_SEARCH_TYPE_ALL, ", ")) 93 us.CreateFullTextIndexIfNotExists("idx_users_all_no_full_name_txt", "Users", strings.Join(USER_SEARCH_TYPE_ALL_NO_FULL_NAME, ", ")) 94 us.CreateFullTextIndexIfNotExists("idx_users_names_txt", "Users", strings.Join(USER_SEARCH_TYPE_NAMES, ", ")) 95 us.CreateFullTextIndexIfNotExists("idx_users_names_no_full_name_txt", "Users", strings.Join(USER_SEARCH_TYPE_NAMES_NO_FULL_NAME, ", ")) 96 } 97 98 func (us SqlUserStore) Save(user *model.User) store.StoreChannel { 99 return store.Do(func(result *store.StoreResult) { 100 if len(user.Id) > 0 { 101 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.existing.app_error", nil, "user_id="+user.Id, http.StatusBadRequest) 102 return 103 } 104 105 user.PreSave() 106 if result.Err = user.IsValid(); result.Err != nil { 107 return 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 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.email_exists.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest) 113 } else if IsUniqueConstraintError(err, []string{"Username", "users_username_key", "idx_users_username_unique"}) { 114 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.username_exists.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest) 115 } else { 116 result.Err = model.NewAppError("SqlUserStore.Save", "store.sql_user.save.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusInternalServerError) 117 } 118 } else { 119 result.Data = user 120 } 121 }) 122 } 123 124 func (us SqlUserStore) Update(user *model.User, trustedUpdateData bool) store.StoreChannel { 125 return store.Do(func(result *store.StoreResult) { 126 user.PreUpdate() 127 128 if result.Err = user.IsValid(); result.Err != nil { 129 return 130 } 131 132 if oldUserResult, err := us.GetMaster().Get(model.User{}, user.Id); err != nil { 133 result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.finding.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusInternalServerError) 134 } else if oldUserResult == nil { 135 result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.find.app_error", nil, "user_id="+user.Id, http.StatusBadRequest) 136 } else { 137 oldUser := oldUserResult.(*model.User) 138 user.CreateAt = oldUser.CreateAt 139 user.AuthData = oldUser.AuthData 140 user.AuthService = oldUser.AuthService 141 user.Password = oldUser.Password 142 user.LastPasswordUpdate = oldUser.LastPasswordUpdate 143 user.LastPictureUpdate = oldUser.LastPictureUpdate 144 user.EmailVerified = oldUser.EmailVerified 145 user.FailedAttempts = oldUser.FailedAttempts 146 user.MfaSecret = oldUser.MfaSecret 147 user.MfaActive = oldUser.MfaActive 148 149 if !trustedUpdateData { 150 user.Roles = oldUser.Roles 151 user.DeleteAt = oldUser.DeleteAt 152 } 153 154 if user.IsOAuthUser() { 155 if !trustedUpdateData { 156 user.Email = oldUser.Email 157 } 158 } else if user.IsLDAPUser() && !trustedUpdateData { 159 if user.Username != oldUser.Username || 160 user.Email != oldUser.Email { 161 result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.can_not_change_ldap.app_error", nil, "user_id="+user.Id, http.StatusBadRequest) 162 return 163 } 164 } else if user.Email != oldUser.Email { 165 user.EmailVerified = false 166 } 167 168 if user.Username != oldUser.Username { 169 user.UpdateMentionKeysFromUsername(oldUser.Username) 170 } 171 172 if count, err := us.GetMaster().Update(user); err != nil { 173 if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique"}) { 174 result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.email_taken.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest) 175 } else if IsUniqueConstraintError(err, []string{"Username", "users_username_key", "idx_users_username_unique"}) { 176 result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.username_taken.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusBadRequest) 177 } else { 178 result.Err = model.NewAppError("SqlUserStore.Update", "store.sql_user.update.updating.app_error", nil, "user_id="+user.Id+", "+err.Error(), http.StatusInternalServerError) 179 } 180 } else if count != 1 { 181 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) 182 } else { 183 user.Sanitize(map[string]bool{}) 184 oldUser.Sanitize(map[string]bool{}) 185 result.Data = [2]*model.User{user, oldUser} 186 } 187 } 188 }) 189 } 190 191 func (us SqlUserStore) UpdateLastPictureUpdate(userId string) store.StoreChannel { 192 return store.Do(func(result *store.StoreResult) { 193 curTime := model.GetMillis() 194 195 if _, err := us.GetMaster().Exec("UPDATE Users SET LastPictureUpdate = :Time, UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"Time": curTime, "UserId": userId}); err != nil { 196 result.Err = model.NewAppError("SqlUserStore.UpdateUpdateAt", "store.sql_user.update_last_picture_update.app_error", nil, "user_id="+userId, http.StatusInternalServerError) 197 } else { 198 result.Data = userId 199 } 200 }) 201 } 202 203 func (us SqlUserStore) UpdateUpdateAt(userId string) store.StoreChannel { 204 return store.Do(func(result *store.StoreResult) { 205 curTime := model.GetMillis() 206 207 if _, err := us.GetMaster().Exec("UPDATE Users SET UpdateAt = :Time WHERE Id = :UserId", map[string]interface{}{"Time": curTime, "UserId": userId}); err != nil { 208 result.Err = model.NewAppError("SqlUserStore.UpdateUpdateAt", "store.sql_user.update_update.app_error", nil, "user_id="+userId, http.StatusInternalServerError) 209 } else { 210 result.Data = userId 211 } 212 }) 213 } 214 215 func (us SqlUserStore) UpdatePassword(userId, hashedPassword string) store.StoreChannel { 216 return store.Do(func(result *store.StoreResult) { 217 updateAt := model.GetMillis() 218 219 if _, err := us.GetMaster().Exec("UPDATE Users SET Password = :Password, LastPasswordUpdate = :LastPasswordUpdate, UpdateAt = :UpdateAt, AuthData = NULL, AuthService = '', EmailVerified = true, FailedAttempts = 0 WHERE Id = :UserId", map[string]interface{}{"Password": hashedPassword, "LastPasswordUpdate": updateAt, "UpdateAt": updateAt, "UserId": userId}); err != nil { 220 result.Err = model.NewAppError("SqlUserStore.UpdatePassword", "store.sql_user.update_password.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError) 221 } else { 222 result.Data = userId 223 } 224 }) 225 } 226 227 func (us SqlUserStore) UpdateFailedPasswordAttempts(userId string, attempts int) store.StoreChannel { 228 return store.Do(func(result *store.StoreResult) { 229 if _, err := us.GetMaster().Exec("UPDATE Users SET FailedAttempts = :FailedAttempts WHERE Id = :UserId", map[string]interface{}{"FailedAttempts": attempts, "UserId": userId}); err != nil { 230 result.Err = model.NewAppError("SqlUserStore.UpdateFailedPasswordAttempts", "store.sql_user.update_failed_pwd_attempts.app_error", nil, "user_id="+userId, http.StatusInternalServerError) 231 } else { 232 result.Data = userId 233 } 234 }) 235 } 236 237 func (us SqlUserStore) UpdateAuthData(userId string, service string, authData *string, email string, resetMfa bool) store.StoreChannel { 238 return store.Do(func(result *store.StoreResult) { 239 email = strings.ToLower(email) 240 241 updateAt := model.GetMillis() 242 243 query := ` 244 UPDATE 245 Users 246 SET 247 Password = '', 248 LastPasswordUpdate = :LastPasswordUpdate, 249 UpdateAt = :UpdateAt, 250 FailedAttempts = 0, 251 AuthService = :AuthService, 252 AuthData = :AuthData` 253 254 if len(email) != 0 { 255 query += ", Email = :Email" 256 } 257 258 if resetMfa { 259 query += ", MfaActive = false, MfaSecret = ''" 260 } 261 262 query += " WHERE Id = :UserId" 263 264 if _, err := us.GetMaster().Exec(query, map[string]interface{}{"LastPasswordUpdate": updateAt, "UpdateAt": updateAt, "UserId": userId, "AuthService": service, "AuthData": authData, "Email": email}); err != nil { 265 if IsUniqueConstraintError(err, []string{"Email", "users_email_key", "idx_users_email_unique", "AuthData", "users_authdata_key"}) { 266 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) 267 } else { 268 result.Err = model.NewAppError("SqlUserStore.UpdateAuthData", "store.sql_user.update_auth_data.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError) 269 } 270 } else { 271 result.Data = userId 272 } 273 }) 274 } 275 276 func (us SqlUserStore) UpdateMfaSecret(userId, secret string) store.StoreChannel { 277 return store.Do(func(result *store.StoreResult) { 278 updateAt := model.GetMillis() 279 280 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 { 281 result.Err = model.NewAppError("SqlUserStore.UpdateMfaSecret", "store.sql_user.update_mfa_secret.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError) 282 } else { 283 result.Data = userId 284 } 285 }) 286 } 287 288 func (us SqlUserStore) UpdateMfaActive(userId string, active bool) store.StoreChannel { 289 return store.Do(func(result *store.StoreResult) { 290 updateAt := model.GetMillis() 291 292 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 { 293 result.Err = model.NewAppError("SqlUserStore.UpdateMfaActive", "store.sql_user.update_mfa_active.app_error", nil, "id="+userId+", "+err.Error(), http.StatusInternalServerError) 294 } else { 295 result.Data = userId 296 } 297 }) 298 } 299 300 func (us SqlUserStore) Get(id string) store.StoreChannel { 301 return store.Do(func(result *store.StoreResult) { 302 if obj, err := us.GetReplica().Get(model.User{}, id); err != nil { 303 result.Err = model.NewAppError("SqlUserStore.Get", "store.sql_user.get.app_error", nil, "user_id="+id+", "+err.Error(), http.StatusInternalServerError) 304 } else if obj == nil { 305 result.Err = model.NewAppError("SqlUserStore.Get", store.MISSING_ACCOUNT_ERROR, nil, "user_id="+id, http.StatusNotFound) 306 } else { 307 result.Data = obj.(*model.User) 308 } 309 }) 310 } 311 312 func (us SqlUserStore) GetAll() store.StoreChannel { 313 return store.Do(func(result *store.StoreResult) { 314 var data []*model.User 315 if _, err := us.GetReplica().Select(&data, "SELECT * FROM Users"); err != nil { 316 result.Err = model.NewAppError("SqlUserStore.GetAll", "store.sql_user.get.app_error", nil, err.Error(), http.StatusInternalServerError) 317 } 318 319 result.Data = data 320 }) 321 } 322 323 func (s SqlUserStore) GetEtagForAllProfiles() store.StoreChannel { 324 return store.Do(func(result *store.StoreResult) { 325 updateAt, err := s.GetReplica().SelectInt("SELECT UpdateAt FROM Users ORDER BY UpdateAt DESC LIMIT 1") 326 if err != nil { 327 result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis()) 328 } else { 329 result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, updateAt) 330 } 331 }) 332 } 333 334 func (us SqlUserStore) GetAllProfiles(offset int, limit int) store.StoreChannel { 335 return store.Do(func(result *store.StoreResult) { 336 var users []*model.User 337 338 if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users ORDER BY Username ASC LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil { 339 result.Err = model.NewAppError("SqlUserStore.GetAllProfiles", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 340 } else { 341 342 for _, u := range users { 343 u.Sanitize(map[string]bool{}) 344 } 345 346 result.Data = users 347 } 348 }) 349 } 350 351 func (s SqlUserStore) GetEtagForProfiles(teamId string) store.StoreChannel { 352 return store.Do(func(result *store.StoreResult) { 353 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}) 354 if err != nil { 355 result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis()) 356 } else { 357 result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, updateAt) 358 } 359 }) 360 } 361 362 func (us SqlUserStore) GetProfiles(teamId string, offset int, limit int) store.StoreChannel { 363 return store.Do(func(result *store.StoreResult) { 364 var users []*model.User 365 366 if _, err := us.GetReplica().Select(&users, "SELECT Users.* FROM Users, TeamMembers WHERE TeamMembers.TeamId = :TeamId AND Users.Id = TeamMembers.UserId AND TeamMembers.DeleteAt = 0 ORDER BY Users.Username ASC LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Offset": offset, "Limit": limit}); err != nil { 367 result.Err = model.NewAppError("SqlUserStore.GetProfiles", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 368 } else { 369 370 for _, u := range users { 371 u.Sanitize(map[string]bool{}) 372 } 373 374 result.Data = users 375 } 376 }) 377 } 378 379 func (us SqlUserStore) InvalidateProfilesInChannelCacheByUser(userId string) { 380 keys := profilesInChannelCache.Keys() 381 382 for _, key := range keys { 383 if cacheItem, ok := profilesInChannelCache.Get(key); ok { 384 userMap := cacheItem.(map[string]*model.User) 385 if _, userInCache := userMap[userId]; userInCache { 386 profilesInChannelCache.Remove(key) 387 } 388 } 389 } 390 } 391 392 func (us SqlUserStore) InvalidateProfilesInChannelCache(channelId string) { 393 profilesInChannelCache.Remove(channelId) 394 } 395 396 func (us SqlUserStore) GetProfilesInChannel(channelId string, offset int, limit int) store.StoreChannel { 397 return store.Do(func(result *store.StoreResult) { 398 var users []*model.User 399 400 query := "SELECT Users.* FROM Users, ChannelMembers WHERE ChannelMembers.ChannelId = :ChannelId AND Users.Id = ChannelMembers.UserId ORDER BY Users.Username ASC LIMIT :Limit OFFSET :Offset" 401 402 if _, err := us.GetReplica().Select(&users, query, map[string]interface{}{"ChannelId": channelId, "Offset": offset, "Limit": limit}); err != nil { 403 result.Err = model.NewAppError("SqlUserStore.GetProfilesInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 404 } else { 405 406 for _, u := range users { 407 u.Sanitize(map[string]bool{}) 408 } 409 410 result.Data = users 411 } 412 }) 413 } 414 415 func (us SqlUserStore) GetAllProfilesInChannel(channelId string, allowFromCache bool) store.StoreChannel { 416 return store.Do(func(result *store.StoreResult) { 417 if allowFromCache { 418 if cacheItem, ok := profilesInChannelCache.Get(channelId); ok { 419 if us.metrics != nil { 420 us.metrics.IncrementMemCacheHitCounter("Profiles in Channel") 421 } 422 result.Data = cacheItem.(map[string]*model.User) 423 return 424 } else { 425 if us.metrics != nil { 426 us.metrics.IncrementMemCacheMissCounter("Profiles in Channel") 427 } 428 } 429 } else { 430 if us.metrics != nil { 431 us.metrics.IncrementMemCacheMissCounter("Profiles in Channel") 432 } 433 } 434 435 var users []*model.User 436 437 query := "SELECT Users.* FROM Users, ChannelMembers WHERE ChannelMembers.ChannelId = :ChannelId AND Users.Id = ChannelMembers.UserId AND Users.DeleteAt = 0" 438 439 if _, err := us.GetReplica().Select(&users, query, map[string]interface{}{"ChannelId": channelId}); err != nil { 440 result.Err = model.NewAppError("SqlUserStore.GetAllProfilesInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 441 } else { 442 443 userMap := make(map[string]*model.User) 444 445 for _, u := range users { 446 u.Sanitize(map[string]bool{}) 447 userMap[u.Id] = u 448 } 449 450 result.Data = userMap 451 452 if allowFromCache { 453 profilesInChannelCache.AddWithExpiresInSecs(channelId, userMap, PROFILES_IN_CHANNEL_CACHE_SEC) 454 } 455 } 456 }) 457 } 458 459 func (us SqlUserStore) GetProfilesNotInChannel(teamId string, channelId string, offset int, limit int) store.StoreChannel { 460 return store.Do(func(result *store.StoreResult) { 461 var users []*model.User 462 463 if _, err := us.GetReplica().Select(&users, ` 464 SELECT 465 u.* 466 FROM Users u 467 INNER JOIN TeamMembers tm 468 ON tm.UserId = u.Id 469 AND tm.TeamId = :TeamId 470 AND tm.DeleteAt = 0 471 LEFT JOIN ChannelMembers cm 472 ON cm.UserId = u.Id 473 AND cm.ChannelId = :ChannelId 474 WHERE cm.UserId IS NULL 475 ORDER BY u.Username ASC 476 LIMIT :Limit OFFSET :Offset 477 `, map[string]interface{}{"TeamId": teamId, "ChannelId": channelId, "Offset": offset, "Limit": limit}); err != nil { 478 result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInChannel", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 479 } else { 480 481 for _, u := range users { 482 u.Sanitize(map[string]bool{}) 483 } 484 485 result.Data = users 486 } 487 }) 488 } 489 490 func (us SqlUserStore) GetProfilesWithoutTeam(offset int, limit int) store.StoreChannel { 491 return store.Do(func(result *store.StoreResult) { 492 var users []*model.User 493 494 query := ` 495 SELECT 496 * 497 FROM 498 Users 499 WHERE 500 (SELECT 501 COUNT(0) 502 FROM 503 TeamMembers 504 WHERE 505 TeamMembers.UserId = Users.Id 506 AND TeamMembers.DeleteAt = 0) = 0 507 ORDER BY 508 Username ASC 509 LIMIT 510 :Limit 511 OFFSET 512 :Offset` 513 514 if _, err := us.GetReplica().Select(&users, query, map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil { 515 result.Err = model.NewAppError("SqlUserStore.GetProfilesWithoutTeam", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 516 } else { 517 518 for _, u := range users { 519 u.Sanitize(map[string]bool{}) 520 } 521 522 result.Data = users 523 } 524 }) 525 } 526 527 func (us SqlUserStore) GetProfilesByUsernames(usernames []string, teamId string) store.StoreChannel { 528 return store.Do(func(result *store.StoreResult) { 529 var users []*model.User 530 props := make(map[string]interface{}) 531 idQuery := "" 532 533 for index, usernames := range usernames { 534 if len(idQuery) > 0 { 535 idQuery += ", " 536 } 537 538 props["username"+strconv.Itoa(index)] = usernames 539 idQuery += ":username" + strconv.Itoa(index) 540 } 541 542 var query string 543 if teamId == "" { 544 query = `SELECT * FROM Users WHERE Username IN (` + idQuery + `)` 545 } else { 546 query = `SELECT Users.* FROM Users INNER JOIN TeamMembers ON 547 Users.Id = TeamMembers.UserId AND Users.Username IN (` + idQuery + `) AND TeamMembers.TeamId = :TeamId ` 548 props["TeamId"] = teamId 549 } 550 551 if _, err := us.GetReplica().Select(&users, query, props); err != nil { 552 result.Err = model.NewAppError("SqlUserStore.GetProfilesByUsernames", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 553 } else { 554 result.Data = users 555 } 556 }) 557 } 558 559 type UserWithLastActivityAt struct { 560 model.User 561 LastActivityAt int64 562 } 563 564 func (us SqlUserStore) GetRecentlyActiveUsersForTeam(teamId string, offset, limit int) store.StoreChannel { 565 return store.Do(func(result *store.StoreResult) { 566 var users []*UserWithLastActivityAt 567 568 if _, err := us.GetReplica().Select(&users, ` 569 SELECT 570 u.*, 571 s.LastActivityAt 572 FROM Users AS u 573 INNER JOIN TeamMembers AS t ON u.Id = t.UserId 574 INNER JOIN Status AS s ON s.UserId = t.UserId 575 WHERE t.TeamId = :TeamId 576 ORDER BY s.LastActivityAt DESC 577 LIMIT :Limit OFFSET :Offset 578 `, map[string]interface{}{"TeamId": teamId, "Offset": offset, "Limit": limit}); err != nil { 579 result.Err = model.NewAppError("SqlUserStore.GetRecentlyActiveUsers", "store.sql_user.get_recently_active_users.app_error", nil, err.Error(), http.StatusInternalServerError) 580 } else { 581 582 userList := []*model.User{} 583 584 for _, userWithLastActivityAt := range users { 585 u := userWithLastActivityAt.User 586 u.Sanitize(map[string]bool{}) 587 u.LastActivityAt = userWithLastActivityAt.LastActivityAt 588 userList = append(userList, &u) 589 } 590 591 result.Data = userList 592 } 593 }) 594 } 595 596 func (us SqlUserStore) GetNewUsersForTeam(teamId string, offset, limit int) store.StoreChannel { 597 return store.Do(func(result *store.StoreResult) { 598 var users []*model.User 599 600 if _, err := us.GetReplica().Select(&users, ` 601 SELECT 602 u.* 603 FROM Users AS u 604 INNER JOIN TeamMembers AS t ON u.Id = t.UserId 605 WHERE t.TeamId = :TeamId 606 ORDER BY u.CreateAt DESC 607 LIMIT :Limit OFFSET :Offset 608 `, map[string]interface{}{"TeamId": teamId, "Offset": offset, "Limit": limit}); err != nil { 609 result.Err = model.NewAppError("SqlUserStore.GetNewUsersForTeam", "store.sql_user.get_new_users.app_error", nil, err.Error(), http.StatusInternalServerError) 610 } else { 611 for _, u := range users { 612 u.Sanitize(map[string]bool{}) 613 } 614 615 result.Data = users 616 } 617 }) 618 } 619 620 func (us SqlUserStore) GetProfileByIds(userIds []string, allowFromCache bool) store.StoreChannel { 621 return store.Do(func(result *store.StoreResult) { 622 users := []*model.User{} 623 props := make(map[string]interface{}) 624 idQuery := "" 625 remainingUserIds := make([]string, 0) 626 627 if allowFromCache { 628 for _, userId := range userIds { 629 if cacheItem, ok := profileByIdsCache.Get(userId); ok { 630 u := &model.User{} 631 *u = *cacheItem.(*model.User) 632 users = append(users, u) 633 } else { 634 remainingUserIds = append(remainingUserIds, userId) 635 } 636 } 637 if us.metrics != nil { 638 us.metrics.AddMemCacheHitCounter("Profile By Ids", float64(len(users))) 639 us.metrics.AddMemCacheMissCounter("Profile By Ids", float64(len(remainingUserIds))) 640 } 641 } else { 642 remainingUserIds = userIds 643 if us.metrics != nil { 644 us.metrics.AddMemCacheMissCounter("Profile By Ids", float64(len(remainingUserIds))) 645 } 646 } 647 648 // If everything came from the cache then just return 649 if len(remainingUserIds) == 0 { 650 result.Data = users 651 return 652 } 653 654 for index, userId := range remainingUserIds { 655 if len(idQuery) > 0 { 656 idQuery += ", " 657 } 658 659 props["userId"+strconv.Itoa(index)] = userId 660 idQuery += ":userId" + strconv.Itoa(index) 661 } 662 663 if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users WHERE Users.Id IN ("+idQuery+")", props); err != nil { 664 result.Err = model.NewAppError("SqlUserStore.GetProfileByIds", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 665 } else { 666 667 for _, u := range users { 668 u.Sanitize(map[string]bool{}) 669 670 cpy := &model.User{} 671 *cpy = *u 672 profileByIdsCache.AddWithExpiresInSecs(cpy.Id, cpy, PROFILE_BY_IDS_CACHE_SEC) 673 } 674 675 result.Data = users 676 } 677 }) 678 } 679 680 func (us SqlUserStore) GetSystemAdminProfiles() store.StoreChannel { 681 return store.Do(func(result *store.StoreResult) { 682 var users []*model.User 683 684 if _, err := us.GetReplica().Select(&users, "SELECT * FROM Users WHERE Roles LIKE :Roles", map[string]interface{}{"Roles": "%system_admin%"}); err != nil { 685 result.Err = model.NewAppError("SqlUserStore.GetSystemAdminProfiles", "store.sql_user.get_sysadmin_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 686 } else { 687 688 userMap := make(map[string]*model.User) 689 690 for _, u := range users { 691 u.Sanitize(map[string]bool{}) 692 userMap[u.Id] = u 693 } 694 695 result.Data = userMap 696 } 697 }) 698 } 699 700 func (us SqlUserStore) GetByEmail(email string) store.StoreChannel { 701 return store.Do(func(result *store.StoreResult) { 702 email = strings.ToLower(email) 703 704 user := model.User{} 705 706 if err := us.GetReplica().SelectOne(&user, "SELECT * FROM Users WHERE Email = :Email", map[string]interface{}{"Email": email}); err != nil { 707 result.Err = model.NewAppError("SqlUserStore.GetByEmail", store.MISSING_ACCOUNT_ERROR, nil, "email="+email+", "+err.Error(), http.StatusInternalServerError) 708 } 709 710 result.Data = &user 711 }) 712 } 713 714 func (us SqlUserStore) GetByAuth(authData *string, authService string) store.StoreChannel { 715 return store.Do(func(result *store.StoreResult) { 716 if authData == nil || *authData == "" { 717 result.Err = model.NewAppError("SqlUserStore.GetByAuth", store.MISSING_AUTH_ACCOUNT_ERROR, nil, "authData='', authService="+authService, http.StatusBadRequest) 718 return 719 } 720 721 user := model.User{} 722 723 if err := us.GetReplica().SelectOne(&user, "SELECT * FROM Users WHERE AuthData = :AuthData AND AuthService = :AuthService", map[string]interface{}{"AuthData": authData, "AuthService": authService}); err != nil { 724 if err == sql.ErrNoRows { 725 result.Err = model.NewAppError("SqlUserStore.GetByAuth", store.MISSING_AUTH_ACCOUNT_ERROR, nil, "authData="+*authData+", authService="+authService+", "+err.Error(), http.StatusInternalServerError) 726 } else { 727 result.Err = model.NewAppError("SqlUserStore.GetByAuth", "store.sql_user.get_by_auth.other.app_error", nil, "authData="+*authData+", authService="+authService+", "+err.Error(), http.StatusInternalServerError) 728 } 729 } 730 731 result.Data = &user 732 }) 733 } 734 735 func (us SqlUserStore) GetAllUsingAuthService(authService string) store.StoreChannel { 736 return store.Do(func(result *store.StoreResult) { 737 var data []*model.User 738 739 if _, err := us.GetReplica().Select(&data, "SELECT * FROM Users WHERE AuthService = :AuthService", map[string]interface{}{"AuthService": authService}); err != nil { 740 result.Err = model.NewAppError("SqlUserStore.GetByAuth", "store.sql_user.get_by_auth.other.app_error", nil, "authService="+authService+", "+err.Error(), http.StatusInternalServerError) 741 } 742 743 result.Data = data 744 }) 745 } 746 747 func (us SqlUserStore) GetByUsername(username string) store.StoreChannel { 748 return store.Do(func(result *store.StoreResult) { 749 user := model.User{} 750 751 if err := us.GetReplica().SelectOne(&user, "SELECT * FROM Users WHERE Username = :Username", map[string]interface{}{"Username": username}); err != nil { 752 result.Err = model.NewAppError("SqlUserStore.GetByUsername", "store.sql_user.get_by_username.app_error", nil, err.Error(), http.StatusInternalServerError) 753 } 754 755 result.Data = &user 756 }) 757 } 758 759 func (us SqlUserStore) GetForLogin(loginId string, allowSignInWithUsername, allowSignInWithEmail, ldapEnabled bool) store.StoreChannel { 760 return store.Do(func(result *store.StoreResult) { 761 params := map[string]interface{}{ 762 "LoginId": loginId, 763 "AllowSignInWithUsername": allowSignInWithUsername, 764 "AllowSignInWithEmail": allowSignInWithEmail, 765 "LdapEnabled": ldapEnabled, 766 } 767 768 users := []*model.User{} 769 if _, err := us.GetReplica().Select( 770 &users, 771 `SELECT 772 * 773 FROM 774 Users 775 WHERE 776 (:AllowSignInWithUsername AND Username = :LoginId) 777 OR (:AllowSignInWithEmail AND Email = :LoginId) 778 OR (:LdapEnabled AND AuthService = '`+model.USER_AUTH_SERVICE_LDAP+`' AND AuthData = :LoginId)`, 779 params); err != nil { 780 result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.get_for_login.app_error", nil, err.Error(), http.StatusInternalServerError) 781 } else if len(users) == 1 { 782 result.Data = users[0] 783 } else if len(users) > 1 { 784 result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.get_for_login.multiple_users", nil, "", http.StatusInternalServerError) 785 } else { 786 result.Err = model.NewAppError("SqlUserStore.GetForLogin", "store.sql_user.get_for_login.app_error", nil, "", http.StatusInternalServerError) 787 } 788 }) 789 } 790 791 func (us SqlUserStore) VerifyEmail(userId string) store.StoreChannel { 792 return store.Do(func(result *store.StoreResult) { 793 if _, err := us.GetMaster().Exec("UPDATE Users SET EmailVerified = true WHERE Id = :UserId", map[string]interface{}{"UserId": userId}); err != nil { 794 result.Err = model.NewAppError("SqlUserStore.VerifyEmail", "store.sql_user.verify_email.app_error", nil, "userId="+userId+", "+err.Error(), http.StatusInternalServerError) 795 } 796 797 result.Data = userId 798 }) 799 } 800 801 func (us SqlUserStore) GetTotalUsersCount() store.StoreChannel { 802 return store.Do(func(result *store.StoreResult) { 803 if count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users"); err != nil { 804 result.Err = model.NewAppError("SqlUserStore.GetTotalUsersCount", "store.sql_user.get_total_users_count.app_error", nil, err.Error(), http.StatusInternalServerError) 805 } else { 806 result.Data = count 807 } 808 }) 809 } 810 811 func (us SqlUserStore) PermanentDelete(userId string) store.StoreChannel { 812 return store.Do(func(result *store.StoreResult) { 813 if _, err := us.GetMaster().Exec("DELETE FROM Users WHERE Id = :UserId", map[string]interface{}{"UserId": userId}); err != nil { 814 result.Err = model.NewAppError("SqlUserStore.PermanentDelete", "store.sql_user.permanent_delete.app_error", nil, "userId="+userId+", "+err.Error(), http.StatusInternalServerError) 815 } 816 }) 817 } 818 819 func (us SqlUserStore) AnalyticsUniqueUserCount(teamId string) store.StoreChannel { 820 return store.Do(func(result *store.StoreResult) { 821 query := "" 822 if len(teamId) > 0 { 823 query = "SELECT COUNT(DISTINCT Users.Email) From Users, TeamMembers WHERE TeamMembers.TeamId = :TeamId AND Users.Id = TeamMembers.UserId AND TeamMembers.DeleteAt = 0 AND Users.DeleteAt = 0" 824 } else { 825 query = "SELECT COUNT(DISTINCT Email) FROM Users WHERE DeleteAt = 0" 826 } 827 828 v, err := us.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId}) 829 if err != nil { 830 result.Err = model.NewAppError("SqlUserStore.AnalyticsUniqueUserCount", "store.sql_user.analytics_unique_user_count.app_error", nil, err.Error(), http.StatusInternalServerError) 831 } else { 832 result.Data = v 833 } 834 }) 835 } 836 837 func (us SqlUserStore) AnalyticsActiveCount(timePeriod int64) store.StoreChannel { 838 return store.Do(func(result *store.StoreResult) { 839 time := model.GetMillis() - timePeriod 840 841 query := "SELECT COUNT(*) FROM Status WHERE LastActivityAt > :Time" 842 843 v, err := us.GetReplica().SelectInt(query, map[string]interface{}{"Time": time}) 844 if err != nil { 845 result.Err = model.NewAppError("SqlUserStore.AnalyticsDailyActiveUsers", "store.sql_user.analytics_daily_active_users.app_error", nil, err.Error(), http.StatusInternalServerError) 846 } else { 847 result.Data = v 848 } 849 }) 850 } 851 852 func (us SqlUserStore) GetUnreadCount(userId string) store.StoreChannel { 853 return store.Do(func(result *store.StoreResult) { 854 if count, err := us.GetReplica().SelectInt(` 855 SELECT SUM(CASE WHEN c.Type = 'D' THEN (c.TotalMsgCount - cm.MsgCount) ELSE cm.MentionCount END) 856 FROM Channels c 857 INNER JOIN ChannelMembers cm 858 ON cm.ChannelId = c.Id 859 AND cm.UserId = :UserId 860 AND c.DeleteAt = 0`, map[string]interface{}{"UserId": userId}); err != nil { 861 result.Err = model.NewAppError("SqlUserStore.GetMentionCount", "store.sql_user.get_unread_count.app_error", nil, err.Error(), http.StatusInternalServerError) 862 } else { 863 result.Data = count 864 } 865 }) 866 } 867 868 func (us SqlUserStore) GetUnreadCountForChannel(userId string, channelId string) store.StoreChannel { 869 return store.Do(func(result *store.StoreResult) { 870 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 = :ChannelId AND cm.ChannelId = :ChannelId AND cm.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil { 871 result.Err = model.NewAppError("SqlUserStore.GetMentionCountForChannel", "store.sql_user.get_unread_count_for_channel.app_error", nil, err.Error(), http.StatusInternalServerError) 872 } else { 873 result.Data = count 874 } 875 }) 876 } 877 878 func (us SqlUserStore) Search(teamId string, term string, options map[string]bool) store.StoreChannel { 879 return store.Do(func(result *store.StoreResult) { 880 searchQuery := "" 881 882 if teamId == "" { 883 884 // Id != '' is added because both SEARCH_CLAUSE and INACTIVE_CLAUSE start with an AND 885 searchQuery = ` 886 SELECT 887 * 888 FROM 889 Users 890 WHERE 891 Id != '' 892 SEARCH_CLAUSE 893 INACTIVE_CLAUSE 894 ORDER BY Username ASC 895 LIMIT 100` 896 } else { 897 searchQuery = ` 898 SELECT 899 Users.* 900 FROM 901 Users, TeamMembers 902 WHERE 903 TeamMembers.TeamId = :TeamId 904 AND Users.Id = TeamMembers.UserId 905 AND TeamMembers.DeleteAt = 0 906 SEARCH_CLAUSE 907 INACTIVE_CLAUSE 908 ORDER BY Users.Username ASC 909 LIMIT 100` 910 } 911 912 *result = us.performSearch(searchQuery, term, options, map[string]interface{}{"TeamId": teamId}) 913 914 }) 915 } 916 917 func (us SqlUserStore) SearchWithoutTeam(term string, options map[string]bool) store.StoreChannel { 918 return store.Do(func(result *store.StoreResult) { 919 searchQuery := ` 920 SELECT 921 * 922 FROM 923 Users 924 WHERE 925 (SELECT 926 COUNT(0) 927 FROM 928 TeamMembers 929 WHERE 930 TeamMembers.UserId = Users.Id 931 AND TeamMembers.DeleteAt = 0) = 0 932 SEARCH_CLAUSE 933 INACTIVE_CLAUSE 934 ORDER BY Username ASC 935 LIMIT 100` 936 937 *result = us.performSearch(searchQuery, term, options, map[string]interface{}{}) 938 939 }) 940 } 941 942 func (us SqlUserStore) SearchNotInTeam(notInTeamId string, term string, options map[string]bool) store.StoreChannel { 943 return store.Do(func(result *store.StoreResult) { 944 searchQuery := ` 945 SELECT 946 Users.* 947 FROM Users 948 LEFT JOIN TeamMembers tm 949 ON tm.UserId = Users.Id 950 AND tm.TeamId = :NotInTeamId 951 WHERE 952 (tm.UserId IS NULL OR tm.DeleteAt != 0) 953 SEARCH_CLAUSE 954 INACTIVE_CLAUSE 955 ORDER BY Users.Username ASC 956 LIMIT 100` 957 958 *result = us.performSearch(searchQuery, term, options, map[string]interface{}{"NotInTeamId": notInTeamId}) 959 960 }) 961 } 962 963 func (us SqlUserStore) SearchNotInChannel(teamId string, channelId string, term string, options map[string]bool) store.StoreChannel { 964 return store.Do(func(result *store.StoreResult) { 965 searchQuery := "" 966 if teamId == "" { 967 searchQuery = ` 968 SELECT 969 Users.* 970 FROM Users 971 LEFT JOIN ChannelMembers cm 972 ON cm.UserId = Users.Id 973 AND cm.ChannelId = :ChannelId 974 WHERE 975 cm.UserId IS NULL 976 SEARCH_CLAUSE 977 INACTIVE_CLAUSE 978 ORDER BY Users.Username ASC 979 LIMIT 100` 980 } else { 981 searchQuery = ` 982 SELECT 983 Users.* 984 FROM Users 985 INNER JOIN TeamMembers tm 986 ON tm.UserId = Users.Id 987 AND tm.TeamId = :TeamId 988 AND tm.DeleteAt = 0 989 LEFT JOIN ChannelMembers cm 990 ON cm.UserId = Users.Id 991 AND cm.ChannelId = :ChannelId 992 WHERE 993 cm.UserId IS NULL 994 SEARCH_CLAUSE 995 INACTIVE_CLAUSE 996 ORDER BY Users.Username ASC 997 LIMIT 100` 998 } 999 1000 *result = us.performSearch(searchQuery, term, options, map[string]interface{}{"TeamId": teamId, "ChannelId": channelId}) 1001 1002 }) 1003 } 1004 1005 func (us SqlUserStore) SearchInChannel(channelId string, term string, options map[string]bool) store.StoreChannel { 1006 return store.Do(func(result *store.StoreResult) { 1007 searchQuery := ` 1008 SELECT 1009 Users.* 1010 FROM 1011 Users, ChannelMembers 1012 WHERE 1013 ChannelMembers.ChannelId = :ChannelId 1014 AND ChannelMembers.UserId = Users.Id 1015 SEARCH_CLAUSE 1016 INACTIVE_CLAUSE 1017 ORDER BY Users.Username ASC 1018 LIMIT 100` 1019 1020 *result = us.performSearch(searchQuery, term, options, map[string]interface{}{"ChannelId": channelId}) 1021 1022 }) 1023 } 1024 1025 var escapeLikeSearchChar = []string{ 1026 "%", 1027 "_", 1028 } 1029 1030 var ignoreLikeSearchChar = []string{ 1031 "*", 1032 } 1033 1034 var spaceFulltextSearchChar = []string{ 1035 "<", 1036 ">", 1037 "+", 1038 "-", 1039 "(", 1040 ")", 1041 "~", 1042 ":", 1043 "*", 1044 "\"", 1045 "!", 1046 "@", 1047 } 1048 1049 func generateSearchQuery(searchQuery string, terms []string, fields []string, parameters map[string]interface{}, isPostgreSQL bool) string { 1050 searchTerms := []string{} 1051 for i, term := range terms { 1052 searchFields := []string{} 1053 for _, field := range fields { 1054 if isPostgreSQL { 1055 searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*' ", field, fmt.Sprintf(":Term%d", i))) 1056 } else { 1057 searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*' ", field, fmt.Sprintf(":Term%d", i))) 1058 } 1059 } 1060 searchTerms = append(searchTerms, fmt.Sprintf("(%s)", strings.Join(searchFields, " OR "))) 1061 parameters[fmt.Sprintf("Term%d", i)] = fmt.Sprintf("%s%%", term) 1062 } 1063 1064 searchClause := strings.Join(searchTerms, " AND ") 1065 return strings.Replace(searchQuery, "SEARCH_CLAUSE", fmt.Sprintf(" AND %s ", searchClause), 1) 1066 } 1067 1068 func (us SqlUserStore) performSearch(searchQuery string, term string, options map[string]bool, parameters map[string]interface{}) store.StoreResult { 1069 result := store.StoreResult{} 1070 1071 // These chars must be removed from the like query. 1072 for _, c := range ignoreLikeSearchChar { 1073 term = strings.Replace(term, c, "", -1) 1074 } 1075 1076 // These chars must be escaped in the like query. 1077 for _, c := range escapeLikeSearchChar { 1078 term = strings.Replace(term, c, "*"+c, -1) 1079 } 1080 1081 searchType := USER_SEARCH_TYPE_ALL 1082 if ok := options[store.USER_SEARCH_OPTION_NAMES_ONLY]; ok { 1083 searchType = USER_SEARCH_TYPE_NAMES 1084 } else if ok = options[store.USER_SEARCH_OPTION_NAMES_ONLY_NO_FULL_NAME]; ok { 1085 searchType = USER_SEARCH_TYPE_NAMES_NO_FULL_NAME 1086 } else if ok = options[store.USER_SEARCH_OPTION_ALL_NO_FULL_NAME]; ok { 1087 searchType = USER_SEARCH_TYPE_ALL_NO_FULL_NAME 1088 } 1089 1090 if ok := options[store.USER_SEARCH_OPTION_ALLOW_INACTIVE]; ok { 1091 searchQuery = strings.Replace(searchQuery, "INACTIVE_CLAUSE", "", 1) 1092 } else { 1093 searchQuery = strings.Replace(searchQuery, "INACTIVE_CLAUSE", "AND Users.DeleteAt = 0", 1) 1094 } 1095 1096 if strings.TrimSpace(term) == "" { 1097 searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1) 1098 } else { 1099 isPostgreSQL := us.DriverName() == model.DATABASE_DRIVER_POSTGRES 1100 searchQuery = generateSearchQuery(searchQuery, strings.Fields(term), searchType, parameters, isPostgreSQL) 1101 } 1102 1103 var users []*model.User 1104 1105 if _, err := us.GetReplica().Select(&users, searchQuery, parameters); err != nil { 1106 result.Err = model.NewAppError("SqlUserStore.Search", "store.sql_user.search.app_error", nil, 1107 fmt.Sprintf("term=%v, search_type=%v, %v", term, searchType, err.Error()), http.StatusInternalServerError) 1108 } else { 1109 for _, u := range users { 1110 u.Sanitize(map[string]bool{}) 1111 } 1112 1113 result.Data = users 1114 } 1115 1116 return result 1117 } 1118 1119 func (us SqlUserStore) AnalyticsGetInactiveUsersCount() store.StoreChannel { 1120 return store.Do(func(result *store.StoreResult) { 1121 if count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users WHERE DeleteAt > 0"); err != nil { 1122 result.Err = model.NewAppError("SqlUserStore.AnalyticsGetInactiveUsersCount", "store.sql_user.analytics_get_inactive_users_count.app_error", nil, err.Error(), http.StatusInternalServerError) 1123 } else { 1124 result.Data = count 1125 } 1126 }) 1127 } 1128 1129 func (us SqlUserStore) AnalyticsGetSystemAdminCount() store.StoreChannel { 1130 return store.Do(func(result *store.StoreResult) { 1131 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 { 1132 result.Err = model.NewAppError("SqlUserStore.AnalyticsGetSystemAdminCount", "store.sql_user.analytics_get_system_admin_count.app_error", nil, err.Error(), http.StatusInternalServerError) 1133 } else { 1134 result.Data = count 1135 } 1136 }) 1137 } 1138 1139 func (us SqlUserStore) GetProfilesNotInTeam(teamId string, offset int, limit int) store.StoreChannel { 1140 return store.Do(func(result *store.StoreResult) { 1141 var users []*model.User 1142 1143 if _, err := us.GetReplica().Select(&users, ` 1144 SELECT 1145 u.* 1146 FROM Users u 1147 LEFT JOIN TeamMembers tm 1148 ON tm.UserId = u.Id 1149 AND tm.TeamId = :TeamId 1150 AND tm.DeleteAt = 0 1151 WHERE tm.UserId IS NULL 1152 ORDER BY u.Username ASC 1153 LIMIT :Limit OFFSET :Offset 1154 `, map[string]interface{}{"TeamId": teamId, "Offset": offset, "Limit": limit}); err != nil { 1155 result.Err = model.NewAppError("SqlUserStore.GetProfilesNotInTeam", "store.sql_user.get_profiles.app_error", nil, err.Error(), http.StatusInternalServerError) 1156 } else { 1157 1158 for _, u := range users { 1159 u.Sanitize(map[string]bool{}) 1160 } 1161 1162 result.Data = users 1163 } 1164 }) 1165 } 1166 1167 func (us SqlUserStore) GetEtagForProfilesNotInTeam(teamId string) store.StoreChannel { 1168 return store.Do(func(result *store.StoreResult) { 1169 updateAt, err := us.GetReplica().SelectInt(` 1170 SELECT 1171 u.UpdateAt 1172 FROM Users u 1173 LEFT JOIN TeamMembers tm 1174 ON tm.UserId = u.Id 1175 AND tm.TeamId = :TeamId 1176 AND tm.DeleteAt = 0 1177 WHERE tm.UserId IS NULL 1178 ORDER BY u.UpdateAt DESC 1179 LIMIT 1 1180 `, map[string]interface{}{"TeamId": teamId}) 1181 1182 if err != nil { 1183 result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, model.GetMillis()) 1184 } else { 1185 result.Data = fmt.Sprintf("%v.%v", model.CurrentVersion, updateAt) 1186 } 1187 }) 1188 }