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