github.com/levb/mattermost-server@v5.3.1+incompatible/store/sqlstore/channel_store.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package sqlstore 5 6 import ( 7 "database/sql" 8 "fmt" 9 "net/http" 10 "sort" 11 "strconv" 12 "strings" 13 14 "github.com/mattermost/gorp" 15 16 "github.com/mattermost/mattermost-server/einterfaces" 17 "github.com/mattermost/mattermost-server/mlog" 18 "github.com/mattermost/mattermost-server/model" 19 "github.com/mattermost/mattermost-server/store" 20 "github.com/mattermost/mattermost-server/utils" 21 ) 22 23 const ( 24 ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE = model.SESSION_CACHE_SIZE 25 ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SEC = 900 // 15 mins 26 27 ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE = model.SESSION_CACHE_SIZE 28 ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SEC = 1800 // 30 mins 29 30 CHANNEL_MEMBERS_COUNTS_CACHE_SIZE = model.CHANNEL_CACHE_SIZE 31 CHANNEL_MEMBERS_COUNTS_CACHE_SEC = 1800 // 30 mins 32 33 CHANNEL_CACHE_SEC = 900 // 15 mins 34 ) 35 36 type SqlChannelStore struct { 37 SqlStore 38 metrics einterfaces.MetricsInterface 39 } 40 41 type channelMember struct { 42 ChannelId string 43 UserId string 44 Roles string 45 LastViewedAt int64 46 MsgCount int64 47 MentionCount int64 48 NotifyProps model.StringMap 49 LastUpdateAt int64 50 SchemeUser sql.NullBool 51 SchemeAdmin sql.NullBool 52 } 53 54 func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember { 55 return &channelMember{ 56 ChannelId: cm.ChannelId, 57 UserId: cm.UserId, 58 Roles: cm.ExplicitRoles, 59 LastViewedAt: cm.LastViewedAt, 60 MsgCount: cm.MsgCount, 61 MentionCount: cm.MentionCount, 62 NotifyProps: cm.NotifyProps, 63 LastUpdateAt: cm.LastUpdateAt, 64 SchemeUser: sql.NullBool{Valid: true, Bool: cm.SchemeUser}, 65 SchemeAdmin: sql.NullBool{Valid: true, Bool: cm.SchemeAdmin}, 66 } 67 } 68 69 type channelMemberWithSchemeRoles struct { 70 ChannelId string 71 UserId string 72 Roles string 73 LastViewedAt int64 74 MsgCount int64 75 MentionCount int64 76 NotifyProps model.StringMap 77 LastUpdateAt int64 78 SchemeUser sql.NullBool 79 SchemeAdmin sql.NullBool 80 TeamSchemeDefaultUserRole sql.NullString 81 TeamSchemeDefaultAdminRole sql.NullString 82 ChannelSchemeDefaultUserRole sql.NullString 83 ChannelSchemeDefaultAdminRole sql.NullString 84 } 85 86 type channelMemberWithSchemeRolesList []channelMemberWithSchemeRoles 87 88 func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember { 89 var roles []string 90 var explicitRoles []string 91 92 // Identify any system-wide scheme derived roles that are in "Roles" field due to not yet being migrated, 93 // and exclude them from ExplicitRoles field. 94 schemeUser := db.SchemeUser.Valid && db.SchemeUser.Bool 95 schemeAdmin := db.SchemeAdmin.Valid && db.SchemeAdmin.Bool 96 for _, role := range strings.Fields(db.Roles) { 97 isImplicit := false 98 if role == model.CHANNEL_USER_ROLE_ID { 99 // We have an implicit role via the system scheme. Override the "schemeUser" field to true. 100 schemeUser = true 101 isImplicit = true 102 } else if role == model.CHANNEL_ADMIN_ROLE_ID { 103 // We have an implicit role via the system scheme. 104 schemeAdmin = true 105 isImplicit = true 106 } 107 108 if !isImplicit { 109 explicitRoles = append(explicitRoles, role) 110 } 111 roles = append(roles, role) 112 } 113 114 // Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add 115 // them to the Roles field for backwards compatibility reasons. 116 var schemeImpliedRoles []string 117 if db.SchemeUser.Valid && db.SchemeUser.Bool { 118 if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" { 119 schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String) 120 } else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" { 121 schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String) 122 } else { 123 schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID) 124 } 125 } 126 if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool { 127 if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" { 128 schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String) 129 } else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" { 130 schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String) 131 } else { 132 schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID) 133 } 134 } 135 for _, impliedRole := range schemeImpliedRoles { 136 alreadyThere := false 137 for _, role := range roles { 138 if role == impliedRole { 139 alreadyThere = true 140 } 141 } 142 if !alreadyThere { 143 roles = append(roles, impliedRole) 144 } 145 } 146 147 return &model.ChannelMember{ 148 ChannelId: db.ChannelId, 149 UserId: db.UserId, 150 Roles: strings.Join(roles, " "), 151 LastViewedAt: db.LastViewedAt, 152 MsgCount: db.MsgCount, 153 MentionCount: db.MentionCount, 154 NotifyProps: db.NotifyProps, 155 LastUpdateAt: db.LastUpdateAt, 156 SchemeAdmin: schemeAdmin, 157 SchemeUser: schemeUser, 158 ExplicitRoles: strings.Join(explicitRoles, " "), 159 } 160 } 161 162 func (db channelMemberWithSchemeRolesList) ToModel() *model.ChannelMembers { 163 cms := model.ChannelMembers{} 164 165 for _, cm := range db { 166 cms = append(cms, *cm.ToModel()) 167 } 168 169 return &cms 170 } 171 172 type allChannelMember struct { 173 ChannelId string 174 Roles string 175 SchemeUser sql.NullBool 176 SchemeAdmin sql.NullBool 177 TeamSchemeDefaultUserRole sql.NullString 178 TeamSchemeDefaultAdminRole sql.NullString 179 ChannelSchemeDefaultUserRole sql.NullString 180 ChannelSchemeDefaultAdminRole sql.NullString 181 } 182 183 type allChannelMembers []allChannelMember 184 185 func (db allChannelMember) Process() (string, string) { 186 roles := strings.Fields(db.Roles) 187 188 // Add any scheme derived roles that are not in the Roles field due to being Implicit from the Scheme, and add 189 // them to the Roles field for backwards compatibility reasons. 190 var schemeImpliedRoles []string 191 if db.SchemeUser.Valid && db.SchemeUser.Bool { 192 if db.ChannelSchemeDefaultUserRole.Valid && db.ChannelSchemeDefaultUserRole.String != "" { 193 schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultUserRole.String) 194 } else if db.TeamSchemeDefaultUserRole.Valid && db.TeamSchemeDefaultUserRole.String != "" { 195 schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultUserRole.String) 196 } else { 197 schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_USER_ROLE_ID) 198 } 199 } 200 if db.SchemeAdmin.Valid && db.SchemeAdmin.Bool { 201 if db.ChannelSchemeDefaultAdminRole.Valid && db.ChannelSchemeDefaultAdminRole.String != "" { 202 schemeImpliedRoles = append(schemeImpliedRoles, db.ChannelSchemeDefaultAdminRole.String) 203 } else if db.TeamSchemeDefaultAdminRole.Valid && db.TeamSchemeDefaultAdminRole.String != "" { 204 schemeImpliedRoles = append(schemeImpliedRoles, db.TeamSchemeDefaultAdminRole.String) 205 } else { 206 schemeImpliedRoles = append(schemeImpliedRoles, model.CHANNEL_ADMIN_ROLE_ID) 207 } 208 } 209 for _, impliedRole := range schemeImpliedRoles { 210 alreadyThere := false 211 for _, role := range roles { 212 if role == impliedRole { 213 alreadyThere = true 214 } 215 } 216 if !alreadyThere { 217 roles = append(roles, impliedRole) 218 } 219 } 220 221 return db.ChannelId, strings.Join(roles, " ") 222 } 223 224 func (db allChannelMembers) ToMapStringString() map[string]string { 225 result := make(map[string]string) 226 227 for _, item := range db { 228 key, value := item.Process() 229 result[key] = value 230 } 231 232 return result 233 } 234 235 var channelMemberCountsCache = utils.NewLru(CHANNEL_MEMBERS_COUNTS_CACHE_SIZE) 236 var allChannelMembersForUserCache = utils.NewLru(ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SIZE) 237 var allChannelMembersNotifyPropsForChannelCache = utils.NewLru(ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SIZE) 238 var channelCache = utils.NewLru(model.CHANNEL_CACHE_SIZE) 239 var channelByNameCache = utils.NewLru(model.CHANNEL_CACHE_SIZE) 240 241 func (s SqlChannelStore) ClearCaches() { 242 channelMemberCountsCache.Purge() 243 allChannelMembersForUserCache.Purge() 244 allChannelMembersNotifyPropsForChannelCache.Purge() 245 channelCache.Purge() 246 channelByNameCache.Purge() 247 248 if s.metrics != nil { 249 s.metrics.IncrementMemCacheInvalidationCounter("Channel Member Counts - Purge") 250 s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Purge") 251 s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Purge") 252 s.metrics.IncrementMemCacheInvalidationCounter("Channel - Purge") 253 s.metrics.IncrementMemCacheInvalidationCounter("Channel By Name - Purge") 254 } 255 } 256 257 func NewSqlChannelStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.ChannelStore { 258 s := &SqlChannelStore{ 259 SqlStore: sqlStore, 260 metrics: metrics, 261 } 262 263 for _, db := range sqlStore.GetAllConns() { 264 table := db.AddTableWithName(model.Channel{}, "Channels").SetKeys(false, "Id") 265 table.ColMap("Id").SetMaxSize(26) 266 table.ColMap("TeamId").SetMaxSize(26) 267 table.ColMap("Type").SetMaxSize(1) 268 table.ColMap("DisplayName").SetMaxSize(64) 269 table.ColMap("Name").SetMaxSize(64) 270 table.SetUniqueTogether("Name", "TeamId") 271 table.ColMap("Header").SetMaxSize(1024) 272 table.ColMap("Purpose").SetMaxSize(250) 273 table.ColMap("CreatorId").SetMaxSize(26) 274 table.ColMap("SchemeId").SetMaxSize(26) 275 276 tablem := db.AddTableWithName(channelMember{}, "ChannelMembers").SetKeys(false, "ChannelId", "UserId") 277 tablem.ColMap("ChannelId").SetMaxSize(26) 278 tablem.ColMap("UserId").SetMaxSize(26) 279 tablem.ColMap("Roles").SetMaxSize(64) 280 tablem.ColMap("NotifyProps").SetMaxSize(2000) 281 } 282 283 return s 284 } 285 286 func (s SqlChannelStore) CreateIndexesIfNotExists() { 287 s.CreateIndexIfNotExists("idx_channels_team_id", "Channels", "TeamId") 288 s.CreateIndexIfNotExists("idx_channels_name", "Channels", "Name") 289 s.CreateIndexIfNotExists("idx_channels_update_at", "Channels", "UpdateAt") 290 s.CreateIndexIfNotExists("idx_channels_create_at", "Channels", "CreateAt") 291 s.CreateIndexIfNotExists("idx_channels_delete_at", "Channels", "DeleteAt") 292 293 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 294 s.CreateIndexIfNotExists("idx_channels_name_lower", "Channels", "lower(Name)") 295 s.CreateIndexIfNotExists("idx_channels_displayname_lower", "Channels", "lower(DisplayName)") 296 } 297 298 s.CreateIndexIfNotExists("idx_channelmembers_channel_id", "ChannelMembers", "ChannelId") 299 s.CreateIndexIfNotExists("idx_channelmembers_user_id", "ChannelMembers", "UserId") 300 301 s.CreateFullTextIndexIfNotExists("idx_channel_search_txt", "Channels", "Name, DisplayName, Purpose") 302 } 303 304 func (s SqlChannelStore) Save(channel *model.Channel, maxChannelsPerTeam int64) store.StoreChannel { 305 return store.Do(func(result *store.StoreResult) { 306 if channel.DeleteAt != 0 { 307 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) 308 return 309 } 310 311 if channel.Type == model.CHANNEL_DIRECT { 312 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.direct_channel.app_error", nil, "", http.StatusBadRequest) 313 return 314 } 315 316 transaction, err := s.GetMaster().Begin() 317 if err != nil { 318 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 319 return 320 } 321 322 *result = s.saveChannelT(transaction, channel, maxChannelsPerTeam) 323 if result.Err != nil { 324 transaction.Rollback() 325 return 326 } 327 328 if err := transaction.Commit(); err != nil { 329 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 330 return 331 } 332 }) 333 } 334 335 func (s SqlChannelStore) CreateDirectChannel(userId string, otherUserId string) store.StoreChannel { 336 channel := new(model.Channel) 337 338 channel.DisplayName = "" 339 channel.Name = model.GetDMNameFromIds(otherUserId, userId) 340 341 channel.Header = "" 342 channel.Type = model.CHANNEL_DIRECT 343 344 cm1 := &model.ChannelMember{ 345 UserId: userId, 346 NotifyProps: model.GetDefaultChannelNotifyProps(), 347 SchemeUser: true, 348 } 349 cm2 := &model.ChannelMember{ 350 UserId: otherUserId, 351 NotifyProps: model.GetDefaultChannelNotifyProps(), 352 SchemeUser: true, 353 } 354 355 return s.SaveDirectChannel(channel, cm1, cm2) 356 } 357 358 func (s SqlChannelStore) SaveDirectChannel(directchannel *model.Channel, member1 *model.ChannelMember, member2 *model.ChannelMember) store.StoreChannel { 359 return store.Do(func(result *store.StoreResult) { 360 if directchannel.DeleteAt != 0 { 361 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save.archived_channel.app_error", nil, "", http.StatusBadRequest) 362 return 363 } 364 365 if directchannel.Type != model.CHANNEL_DIRECT { 366 result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.not_direct.app_error", nil, "", http.StatusBadRequest) 367 return 368 } 369 370 transaction, err := s.GetMaster().Begin() 371 if err != nil { 372 result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 373 return 374 } 375 376 directchannel.TeamId = "" 377 channelResult := s.saveChannelT(transaction, directchannel, 0) 378 379 if channelResult.Err != nil { 380 transaction.Rollback() 381 result.Err = channelResult.Err 382 result.Data = channelResult.Data 383 return 384 } 385 386 newChannel := channelResult.Data.(*model.Channel) 387 // Members need new channel ID 388 member1.ChannelId = newChannel.Id 389 member2.ChannelId = newChannel.Id 390 391 member1Result := s.saveMemberT(transaction, member1, newChannel) 392 member2Result := member1Result 393 if member1.UserId != member2.UserId { 394 member2Result = s.saveMemberT(transaction, member2, newChannel) 395 } 396 397 if member1Result.Err != nil || member2Result.Err != nil { 398 transaction.Rollback() 399 details := "" 400 if member1Result.Err != nil { 401 details += "Member1Err: " + member1Result.Err.Message 402 } 403 if member2Result.Err != nil { 404 details += "Member2Err: " + member2Result.Err.Message 405 } 406 result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.add_members.app_error", nil, details, http.StatusInternalServerError) 407 return 408 } 409 410 if err := transaction.Commit(); err != nil { 411 result.Err = model.NewAppError("SqlChannelStore.SaveDirectChannel", "store.sql_channel.save_direct_channel.commit.app_error", nil, err.Error(), http.StatusInternalServerError) 412 return 413 } 414 415 *result = channelResult 416 }) 417 } 418 419 func (s SqlChannelStore) saveChannelT(transaction *gorp.Transaction, channel *model.Channel, maxChannelsPerTeam int64) store.StoreResult { 420 result := store.StoreResult{} 421 422 if len(channel.Id) > 0 { 423 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.existing.app_error", nil, "id="+channel.Id, http.StatusBadRequest) 424 return result 425 } 426 427 channel.PreSave() 428 if result.Err = channel.IsValid(); result.Err != nil { 429 return result 430 } 431 432 if channel.Type != model.CHANNEL_DIRECT && channel.Type != model.CHANNEL_GROUP && maxChannelsPerTeam >= 0 { 433 if count, err := transaction.SelectInt("SELECT COUNT(0) FROM Channels WHERE TeamId = :TeamId AND DeleteAt = 0 AND (Type = 'O' OR Type = 'P')", map[string]interface{}{"TeamId": channel.TeamId}); err != nil { 434 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.current_count.app_error", nil, "teamId="+channel.TeamId+", "+err.Error(), http.StatusInternalServerError) 435 return result 436 } else if count >= maxChannelsPerTeam { 437 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.limit.app_error", nil, "teamId="+channel.TeamId, http.StatusBadRequest) 438 return result 439 } 440 } 441 442 if err := transaction.Insert(channel); err != nil { 443 if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) { 444 dupChannel := model.Channel{} 445 s.GetMaster().SelectOne(&dupChannel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name = :Name", map[string]interface{}{"TeamId": channel.TeamId, "Name": channel.Name}) 446 if dupChannel.DeleteAt > 0 { 447 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.previously.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest) 448 } else { 449 result.Err = model.NewAppError("SqlChannelStore.Save", store.CHANNEL_EXISTS_ERROR, nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest) 450 result.Data = &dupChannel 451 } 452 } else { 453 result.Err = model.NewAppError("SqlChannelStore.Save", "store.sql_channel.save_channel.save.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusInternalServerError) 454 } 455 } else { 456 result.Data = channel 457 } 458 459 return result 460 } 461 462 func (s SqlChannelStore) Update(channel *model.Channel) store.StoreChannel { 463 return store.Do(func(result *store.StoreResult) { 464 channel.PreUpdate() 465 466 if channel.DeleteAt != 0 { 467 result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.archived_channel.app_error", nil, "", http.StatusBadRequest) 468 return 469 } 470 471 if result.Err = channel.IsValid(); result.Err != nil { 472 return 473 } 474 475 count, err := s.GetMaster().Update(channel) 476 if err != nil { 477 if IsUniqueConstraintError(err, []string{"Name", "channels_name_teamid_key"}) { 478 dupChannel := model.Channel{} 479 s.GetReplica().SelectOne(&dupChannel, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Name= :Name AND DeleteAt > 0", map[string]interface{}{"TeamId": channel.TeamId, "Name": channel.Name}) 480 if dupChannel.DeleteAt > 0 { 481 result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.previously.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest) 482 return 483 } 484 result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.exists.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusBadRequest) 485 return 486 } 487 result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.updating.app_error", nil, "id="+channel.Id+", "+err.Error(), http.StatusInternalServerError) 488 return 489 } 490 491 if count != 1 { 492 result.Err = model.NewAppError("SqlChannelStore.Update", "store.sql_channel.update.app_error", nil, "id="+channel.Id, http.StatusInternalServerError) 493 return 494 } 495 496 result.Data = channel 497 }) 498 } 499 500 func (s SqlChannelStore) GetChannelUnread(channelId, userId string) store.StoreChannel { 501 return store.Do(func(result *store.StoreResult) { 502 var unreadChannel model.ChannelUnread 503 err := s.GetReplica().SelectOne(&unreadChannel, 504 `SELECT 505 Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps 506 FROM 507 Channels, ChannelMembers 508 WHERE 509 Id = ChannelId 510 AND Id = :ChannelId 511 AND UserId = :UserId 512 AND DeleteAt = 0`, 513 map[string]interface{}{"ChannelId": channelId, "UserId": userId}) 514 515 if err != nil { 516 result.Err = model.NewAppError("SqlChannelStore.GetChannelUnread", "store.sql_channel.get_unread.app_error", nil, "channelId="+channelId+" "+err.Error(), http.StatusInternalServerError) 517 if err == sql.ErrNoRows { 518 result.Err.StatusCode = http.StatusNotFound 519 } 520 } else { 521 result.Data = &unreadChannel 522 } 523 }) 524 } 525 526 func (s SqlChannelStore) InvalidateChannel(id string) { 527 channelCache.Remove(id) 528 if s.metrics != nil { 529 s.metrics.IncrementMemCacheInvalidationCounter("Channel - Remove by ChannelId") 530 } 531 } 532 533 func (s SqlChannelStore) InvalidateChannelByName(teamId, name string) { 534 channelByNameCache.Remove(teamId + name) 535 if s.metrics != nil { 536 s.metrics.IncrementMemCacheInvalidationCounter("Channel by Name - Remove by TeamId and Name") 537 } 538 } 539 540 func (s SqlChannelStore) Get(id string, allowFromCache bool) store.StoreChannel { 541 return s.get(id, false, allowFromCache) 542 } 543 544 func (s SqlChannelStore) GetPinnedPosts(channelId string) store.StoreChannel { 545 return store.Do(func(result *store.StoreResult) { 546 pl := model.NewPostList() 547 548 var posts []*model.Post 549 if _, err := s.GetReplica().Select(&posts, "SELECT * FROM Posts WHERE IsPinned = true AND ChannelId = :ChannelId AND DeleteAt = 0 ORDER BY CreateAt ASC", map[string]interface{}{"ChannelId": channelId}); err != nil { 550 result.Err = model.NewAppError("SqlPostStore.GetPinnedPosts", "store.sql_channel.pinned_posts.app_error", nil, err.Error(), http.StatusInternalServerError) 551 } else { 552 for _, post := range posts { 553 pl.AddPost(post) 554 pl.AddOrder(post.Id) 555 } 556 } 557 558 result.Data = pl 559 }) 560 } 561 562 func (s SqlChannelStore) GetFromMaster(id string) store.StoreChannel { 563 return s.get(id, true, false) 564 } 565 566 func (s SqlChannelStore) get(id string, master bool, allowFromCache bool) store.StoreChannel { 567 return store.Do(func(result *store.StoreResult) { 568 var db *gorp.DbMap 569 if master { 570 db = s.GetMaster() 571 } else { 572 db = s.GetReplica() 573 } 574 575 if allowFromCache { 576 if cacheItem, ok := channelCache.Get(id); ok { 577 if s.metrics != nil { 578 s.metrics.IncrementMemCacheHitCounter("Channel") 579 } 580 result.Data = (cacheItem.(*model.Channel)).DeepCopy() 581 return 582 } 583 } 584 585 if s.metrics != nil { 586 s.metrics.IncrementMemCacheMissCounter("Channel") 587 } 588 589 obj, err := db.Get(model.Channel{}, id) 590 if err != nil { 591 result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.find.app_error", nil, "id="+id+", "+err.Error(), http.StatusInternalServerError) 592 return 593 } 594 595 if obj == nil { 596 result.Err = model.NewAppError("SqlChannelStore.Get", "store.sql_channel.get.existing.app_error", nil, "id="+id, http.StatusNotFound) 597 return 598 } 599 600 result.Data = obj.(*model.Channel) 601 channelCache.AddWithExpiresInSecs(id, obj.(*model.Channel), CHANNEL_CACHE_SEC) 602 }) 603 } 604 605 func (s SqlChannelStore) Delete(channelId string, time int64) store.StoreChannel { 606 return s.SetDeleteAt(channelId, time, time) 607 } 608 609 func (s SqlChannelStore) Restore(channelId string, time int64) store.StoreChannel { 610 return s.SetDeleteAt(channelId, 0, time) 611 } 612 613 func (s SqlChannelStore) SetDeleteAt(channelId string, deleteAt int64, updateAt int64) store.StoreChannel { 614 return store.Do(func(result *store.StoreResult) { 615 _, err := s.GetMaster().Exec("Update Channels SET DeleteAt = :DeleteAt, UpdateAt = :UpdateAt WHERE Id = :ChannelId", map[string]interface{}{"DeleteAt": deleteAt, "UpdateAt": updateAt, "ChannelId": channelId}) 616 if err != nil { 617 result.Err = model.NewAppError("SqlChannelStore.Delete", "store.sql_channel.delete.channel.app_error", nil, "id="+channelId+", err="+err.Error(), http.StatusInternalServerError) 618 } 619 }) 620 } 621 622 func (s SqlChannelStore) PermanentDeleteByTeam(teamId string) store.StoreChannel { 623 return store.Do(func(result *store.StoreResult) { 624 if _, err := s.GetMaster().Exec("DELETE FROM Channels WHERE TeamId = :TeamId", map[string]interface{}{"TeamId": teamId}); err != nil { 625 result.Err = model.NewAppError("SqlChannelStore.PermanentDeleteByTeam", "store.sql_channel.permanent_delete_by_team.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError) 626 } 627 }) 628 } 629 630 func (s SqlChannelStore) PermanentDelete(channelId string) store.StoreChannel { 631 return store.Do(func(result *store.StoreResult) { 632 if _, err := s.GetMaster().Exec("DELETE FROM Channels WHERE Id = :ChannelId", map[string]interface{}{"ChannelId": channelId}); err != nil { 633 result.Err = model.NewAppError("SqlChannelStore.PermanentDelete", "store.sql_channel.permanent_delete.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError) 634 } 635 }) 636 } 637 638 func (s SqlChannelStore) PermanentDeleteMembersByChannel(channelId string) store.StoreChannel { 639 return store.Do(func(result *store.StoreResult) { 640 _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId", map[string]interface{}{"ChannelId": channelId}) 641 if err != nil { 642 result.Err = model.NewAppError("SqlChannelStore.RemoveAllMembersByChannel", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError) 643 } 644 }) 645 } 646 647 func (s SqlChannelStore) GetChannels(teamId string, userId string, includeDeleted bool) store.StoreChannel { 648 return store.Do(func(result *store.StoreResult) { 649 query := "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND DeleteAt = 0 AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName" 650 if includeDeleted { 651 query = "SELECT Channels.* FROM Channels, ChannelMembers WHERE Id = ChannelId AND UserId = :UserId AND (TeamId = :TeamId OR TeamId = '') ORDER BY DisplayName" 652 } 653 data := &model.ChannelList{} 654 _, err := s.GetReplica().Select(data, query, map[string]interface{}{"TeamId": teamId, "UserId": userId}) 655 656 if err != nil { 657 result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError) 658 return 659 } 660 661 if len(*data) == 0 { 662 result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.not_found.app_error", nil, "teamId="+teamId+", userId="+userId, http.StatusBadRequest) 663 return 664 } 665 666 result.Data = data 667 }) 668 } 669 670 func (s SqlChannelStore) GetMoreChannels(teamId string, userId string, offset int, limit int) store.StoreChannel { 671 return store.Do(func(result *store.StoreResult) { 672 data := &model.ChannelList{} 673 _, err := s.GetReplica().Select(data, 674 `SELECT 675 * 676 FROM 677 Channels 678 WHERE 679 TeamId = :TeamId1 680 AND Type IN ('O') 681 AND DeleteAt = 0 682 AND Id NOT IN (SELECT 683 Channels.Id 684 FROM 685 Channels, 686 ChannelMembers 687 WHERE 688 Id = ChannelId 689 AND TeamId = :TeamId2 690 AND UserId = :UserId 691 AND DeleteAt = 0) 692 ORDER BY DisplayName 693 LIMIT :Limit 694 OFFSET :Offset`, 695 map[string]interface{}{"TeamId1": teamId, "TeamId2": teamId, "UserId": userId, "Limit": limit, "Offset": offset}) 696 697 if err != nil { 698 result.Err = model.NewAppError("SqlChannelStore.GetMoreChannels", "store.sql_channel.get_more_channels.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError) 699 return 700 } 701 702 result.Data = data 703 }) 704 } 705 706 func (s SqlChannelStore) GetPublicChannelsForTeam(teamId string, offset int, limit int) store.StoreChannel { 707 return store.Do(func(result *store.StoreResult) { 708 data := &model.ChannelList{} 709 _, err := s.GetReplica().Select(data, 710 `SELECT 711 * 712 FROM 713 Channels 714 WHERE 715 TeamId = :TeamId 716 AND Type = 'O' 717 AND DeleteAt = 0 718 ORDER BY DisplayName 719 LIMIT :Limit 720 OFFSET :Offset`, 721 map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset}) 722 723 if err != nil { 724 result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsForTeam", "store.sql_channel.get_public_channels.get.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError) 725 return 726 } 727 728 result.Data = data 729 }) 730 } 731 732 func (s SqlChannelStore) GetPublicChannelsByIdsForTeam(teamId string, channelIds []string) store.StoreChannel { 733 return store.Do(func(result *store.StoreResult) { 734 props := make(map[string]interface{}) 735 props["teamId"] = teamId 736 737 idQuery := "" 738 739 for index, channelId := range channelIds { 740 if len(idQuery) > 0 { 741 idQuery += ", " 742 } 743 744 props["channelId"+strconv.Itoa(index)] = channelId 745 idQuery += ":channelId" + strconv.Itoa(index) 746 } 747 748 data := &model.ChannelList{} 749 _, err := s.GetReplica().Select(data, 750 `SELECT 751 * 752 FROM 753 Channels 754 WHERE 755 TeamId = :teamId 756 AND Type = 'O' 757 AND DeleteAt = 0 758 AND Id IN (`+idQuery+`) 759 ORDER BY DisplayName`, 760 props) 761 762 if err != nil { 763 result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.get.app_error", nil, err.Error(), http.StatusInternalServerError) 764 } 765 766 if len(*data) == 0 { 767 result.Err = model.NewAppError("SqlChannelStore.GetPublicChannelsByIdsForTeam", "store.sql_channel.get_channels_by_ids.not_found.app_error", nil, "", http.StatusNotFound) 768 } 769 770 result.Data = data 771 }) 772 } 773 774 type channelIdWithCountAndUpdateAt struct { 775 Id string 776 TotalMsgCount int64 777 UpdateAt int64 778 } 779 780 func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) store.StoreChannel { 781 return store.Do(func(result *store.StoreResult) { 782 var data []channelIdWithCountAndUpdateAt 783 _, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND (TeamId = :TeamId OR TeamId = '') AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId}) 784 785 if err != nil { 786 result.Err = model.NewAppError("SqlChannelStore.GetChannelCounts", "store.sql_channel.get_channel_counts.get.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError) 787 return 788 } 789 790 counts := &model.ChannelCounts{Counts: make(map[string]int64), UpdateTimes: make(map[string]int64)} 791 for i := range data { 792 v := data[i] 793 counts.Counts[v.Id] = v.TotalMsgCount 794 counts.UpdateTimes[v.Id] = v.UpdateAt 795 } 796 797 result.Data = counts 798 }) 799 } 800 801 func (s SqlChannelStore) GetTeamChannels(teamId string) store.StoreChannel { 802 return store.Do(func(result *store.StoreResult) { 803 data := &model.ChannelList{} 804 _, err := s.GetReplica().Select(data, "SELECT * FROM Channels WHERE TeamId = :TeamId And Type != 'D' ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId}) 805 806 if err != nil { 807 result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.get.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError) 808 return 809 } 810 811 if len(*data) == 0 { 812 result.Err = model.NewAppError("SqlChannelStore.GetChannels", "store.sql_channel.get_channels.not_found.app_error", nil, "teamId="+teamId, http.StatusNotFound) 813 return 814 } 815 816 result.Data = data 817 }) 818 } 819 820 func (s SqlChannelStore) GetByName(teamId string, name string, allowFromCache bool) store.StoreChannel { 821 return s.getByName(teamId, name, false, allowFromCache) 822 } 823 824 func (s SqlChannelStore) GetByNames(teamId string, names []string, allowFromCache bool) store.StoreChannel { 825 return store.Do(func(result *store.StoreResult) { 826 var channels []*model.Channel 827 828 if allowFromCache { 829 var misses []string 830 visited := make(map[string]struct{}) 831 for _, name := range names { 832 if _, ok := visited[name]; ok { 833 continue 834 } 835 visited[name] = struct{}{} 836 if cacheItem, ok := channelByNameCache.Get(teamId + name); ok { 837 if s.metrics != nil { 838 s.metrics.IncrementMemCacheHitCounter("Channel By Name") 839 } 840 channels = append(channels, cacheItem.(*model.Channel)) 841 } else { 842 if s.metrics != nil { 843 s.metrics.IncrementMemCacheMissCounter("Channel By Name") 844 } 845 misses = append(misses, name) 846 } 847 } 848 names = misses 849 } 850 851 if len(names) > 0 { 852 props := map[string]interface{}{} 853 var namePlaceholders []string 854 for _, name := range names { 855 key := fmt.Sprintf("Name%v", len(namePlaceholders)) 856 props[key] = name 857 namePlaceholders = append(namePlaceholders, ":"+key) 858 } 859 860 var query string 861 if teamId == "" { 862 query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND DeleteAt = 0` 863 } else { 864 props["TeamId"] = teamId 865 query = `SELECT * FROM Channels WHERE Name IN (` + strings.Join(namePlaceholders, ", ") + `) AND TeamId = :TeamId AND DeleteAt = 0` 866 } 867 868 var dbChannels []*model.Channel 869 if _, err := s.GetReplica().Select(&dbChannels, query, props); err != nil && err != sql.ErrNoRows { 870 result.Err = model.NewAppError("SqlChannelStore.GetByName", "store.sql_channel.get_by_name.existing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError) 871 return 872 } 873 for _, channel := range dbChannels { 874 channelByNameCache.AddWithExpiresInSecs(teamId+channel.Name, channel, CHANNEL_CACHE_SEC) 875 channels = append(channels, channel) 876 } 877 } 878 879 result.Data = channels 880 }) 881 } 882 883 func (s SqlChannelStore) GetByNameIncludeDeleted(teamId string, name string, allowFromCache bool) store.StoreChannel { 884 return s.getByName(teamId, name, true, allowFromCache) 885 } 886 887 func (s SqlChannelStore) getByName(teamId string, name string, includeDeleted bool, allowFromCache bool) store.StoreChannel { 888 var query string 889 if includeDeleted { 890 query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name" 891 } else { 892 query = "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt = 0" 893 } 894 return store.Do(func(result *store.StoreResult) { 895 channel := model.Channel{} 896 897 if allowFromCache { 898 if cacheItem, ok := channelByNameCache.Get(teamId + name); ok { 899 if s.metrics != nil { 900 s.metrics.IncrementMemCacheHitCounter("Channel By Name") 901 } 902 result.Data = cacheItem.(*model.Channel) 903 return 904 } 905 if s.metrics != nil { 906 s.metrics.IncrementMemCacheMissCounter("Channel By Name") 907 } 908 } 909 910 if err := s.GetReplica().SelectOne(&channel, query, map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil { 911 if err == sql.ErrNoRows { 912 result.Err = model.NewAppError("SqlChannelStore.GetByName", store.MISSING_CHANNEL_ERROR, nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusNotFound) 913 return 914 } 915 result.Err = model.NewAppError("SqlChannelStore.GetByName", "store.sql_channel.get_by_name.existing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusInternalServerError) 916 return 917 } 918 919 result.Data = &channel 920 channelByNameCache.AddWithExpiresInSecs(teamId+name, &channel, CHANNEL_CACHE_SEC) 921 }) 922 } 923 924 func (s SqlChannelStore) GetDeletedByName(teamId string, name string) store.StoreChannel { 925 return store.Do(func(result *store.StoreResult) { 926 channel := model.Channel{} 927 928 if err := s.GetReplica().SelectOne(&channel, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND Name = :Name AND DeleteAt != 0", map[string]interface{}{"TeamId": teamId, "Name": name}); err != nil { 929 if err == sql.ErrNoRows { 930 result.Err = model.NewAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.missing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusNotFound) 931 return 932 } 933 result.Err = model.NewAppError("SqlChannelStore.GetDeletedByName", "store.sql_channel.get_deleted_by_name.existing.app_error", nil, "teamId="+teamId+", "+"name="+name+", "+err.Error(), http.StatusInternalServerError) 934 return 935 } 936 937 result.Data = &channel 938 }) 939 } 940 941 func (s SqlChannelStore) GetDeleted(teamId string, offset int, limit int) store.StoreChannel { 942 return store.Do(func(result *store.StoreResult) { 943 channels := &model.ChannelList{} 944 945 if _, err := s.GetReplica().Select(channels, "SELECT * FROM Channels WHERE (TeamId = :TeamId OR TeamId = '') AND DeleteAt != 0 ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"TeamId": teamId, "Limit": limit, "Offset": offset}); err != nil { 946 if err == sql.ErrNoRows { 947 result.Err = model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.missing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusNotFound) 948 return 949 } 950 result.Err = model.NewAppError("SqlChannelStore.GetDeleted", "store.sql_channel.get_deleted.existing.app_error", nil, "teamId="+teamId+", "+err.Error(), http.StatusInternalServerError) 951 return 952 } 953 954 result.Data = channels 955 }) 956 } 957 958 var CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY = ` 959 SELECT 960 ChannelMembers.*, 961 TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole, 962 TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole, 963 ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole, 964 ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole 965 FROM 966 ChannelMembers 967 INNER JOIN 968 Channels ON ChannelMembers.ChannelId = Channels.Id 969 LEFT JOIN 970 Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id 971 LEFT JOIN 972 Teams ON Channels.TeamId = Teams.Id 973 LEFT JOIN 974 Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id 975 ` 976 977 func (s SqlChannelStore) SaveMember(member *model.ChannelMember) store.StoreChannel { 978 return store.Do(func(result *store.StoreResult) { 979 defer s.InvalidateAllChannelMembersForUser(member.UserId) 980 981 // Grab the channel we are saving this member to 982 cr := <-s.GetFromMaster(member.ChannelId) 983 if cr.Err != nil { 984 result.Err = cr.Err 985 return 986 } 987 988 channel := cr.Data.(*model.Channel) 989 990 transaction, err := s.GetMaster().Begin() 991 if err != nil { 992 result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 993 return 994 } 995 996 *result = s.saveMemberT(transaction, member, channel) 997 if result.Err != nil { 998 transaction.Rollback() 999 return 1000 } 1001 1002 if err := transaction.Commit(); err != nil { 1003 result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 1004 return 1005 } 1006 }) 1007 } 1008 1009 func (s SqlChannelStore) saveMemberT(transaction *gorp.Transaction, member *model.ChannelMember, channel *model.Channel) store.StoreResult { 1010 result := store.StoreResult{} 1011 1012 member.PreSave() 1013 if result.Err = member.IsValid(); result.Err != nil { 1014 return result 1015 } 1016 1017 dbMember := NewChannelMemberFromModel(member) 1018 1019 if err := transaction.Insert(dbMember); err != nil { 1020 if IsUniqueConstraintError(err, []string{"ChannelId", "channelmembers_pkey"}) { 1021 result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.exists.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusBadRequest) 1022 return result 1023 } 1024 result.Err = model.NewAppError("SqlChannelStore.SaveMember", "store.sql_channel.save_member.save.app_error", nil, "channel_id="+member.ChannelId+", user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError) 1025 return result 1026 } 1027 1028 var retrievedMember channelMemberWithSchemeRoles 1029 if err := transaction.SelectOne(&retrievedMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": dbMember.ChannelId, "UserId": dbMember.UserId}); err != nil { 1030 if err == sql.ErrNoRows { 1031 result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusNotFound) 1032 return result 1033 } 1034 result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+dbMember.ChannelId+"user_id="+dbMember.UserId+","+err.Error(), http.StatusInternalServerError) 1035 return result 1036 } 1037 1038 result.Data = retrievedMember.ToModel() 1039 return result 1040 } 1041 1042 func (s SqlChannelStore) UpdateMember(member *model.ChannelMember) store.StoreChannel { 1043 return store.Do(func(result *store.StoreResult) { 1044 member.PreUpdate() 1045 1046 if result.Err = member.IsValid(); result.Err != nil { 1047 return 1048 } 1049 1050 if _, err := s.GetMaster().Update(NewChannelMemberFromModel(member)); err != nil { 1051 result.Err = model.NewAppError("SqlChannelStore.UpdateMember", "store.sql_channel.update_member.app_error", nil, "channel_id="+member.ChannelId+", "+"user_id="+member.UserId+", "+err.Error(), http.StatusInternalServerError) 1052 return 1053 } 1054 1055 var dbMember channelMemberWithSchemeRoles 1056 1057 if err := s.GetReplica().SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil { 1058 if err == sql.ErrNoRows { 1059 result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusNotFound) 1060 return 1061 } 1062 result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+member.ChannelId+"user_id="+member.UserId+","+err.Error(), http.StatusInternalServerError) 1063 return 1064 } 1065 result.Data = dbMember.ToModel() 1066 }) 1067 } 1068 1069 func (s SqlChannelStore) GetMembers(channelId string, offset, limit int) store.StoreChannel { 1070 return store.Do(func(result *store.StoreResult) { 1071 var dbMembers channelMemberWithSchemeRolesList 1072 _, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelId = :ChannelId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"ChannelId": channelId, "Limit": limit, "Offset": offset}) 1073 if err != nil { 1074 result.Err = model.NewAppError("SqlChannelStore.GetMembers", "store.sql_channel.get_members.app_error", nil, "channel_id="+channelId+err.Error(), http.StatusInternalServerError) 1075 return 1076 } 1077 1078 result.Data = dbMembers.ToModel() 1079 }) 1080 } 1081 1082 func (s SqlChannelStore) GetMember(channelId string, userId string) store.StoreChannel { 1083 return store.Do(func(result *store.StoreResult) { 1084 var dbMember channelMemberWithSchemeRoles 1085 1086 if err := s.GetReplica().SelectOne(&dbMember, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}); err != nil { 1087 if err == sql.ErrNoRows { 1088 result.Err = model.NewAppError("SqlChannelStore.GetMember", store.MISSING_CHANNEL_MEMBER_ERROR, nil, "channel_id="+channelId+"user_id="+userId+","+err.Error(), http.StatusNotFound) 1089 return 1090 } 1091 result.Err = model.NewAppError("SqlChannelStore.GetMember", "store.sql_channel.get_member.app_error", nil, "channel_id="+channelId+"user_id="+userId+","+err.Error(), http.StatusInternalServerError) 1092 return 1093 } 1094 1095 result.Data = dbMember.ToModel() 1096 }) 1097 } 1098 1099 func (s SqlChannelStore) InvalidateAllChannelMembersForUser(userId string) { 1100 allChannelMembersForUserCache.Remove(userId) 1101 allChannelMembersForUserCache.Remove(userId + "_deleted") 1102 if s.metrics != nil { 1103 s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members for User - Remove by UserId") 1104 } 1105 } 1106 1107 func (s SqlChannelStore) IsUserInChannelUseCache(userId string, channelId string) bool { 1108 if cacheItem, ok := allChannelMembersForUserCache.Get(userId); ok { 1109 if s.metrics != nil { 1110 s.metrics.IncrementMemCacheHitCounter("All Channel Members for User") 1111 } 1112 ids := cacheItem.(map[string]string) 1113 if _, ok := ids[channelId]; ok { 1114 return true 1115 } 1116 return false 1117 } 1118 1119 if s.metrics != nil { 1120 s.metrics.IncrementMemCacheMissCounter("All Channel Members for User") 1121 } 1122 1123 result := <-s.GetAllChannelMembersForUser(userId, true, false) 1124 if result.Err != nil { 1125 mlog.Error("SqlChannelStore.IsUserInChannelUseCache: " + result.Err.Error()) 1126 return false 1127 } 1128 1129 ids := result.Data.(map[string]string) 1130 if _, ok := ids[channelId]; ok { 1131 return true 1132 } 1133 1134 return false 1135 } 1136 1137 func (s SqlChannelStore) GetMemberForPost(postId string, userId string) store.StoreChannel { 1138 return store.Do(func(result *store.StoreResult) { 1139 var dbMember channelMemberWithSchemeRoles 1140 if err := s.GetReplica().SelectOne(&dbMember, 1141 ` 1142 SELECT 1143 ChannelMembers.*, 1144 TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole, 1145 TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole, 1146 ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole, 1147 ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole 1148 FROM 1149 ChannelMembers 1150 INNER JOIN 1151 Posts ON ChannelMembers.ChannelId = Posts.ChannelId 1152 INNER JOIN 1153 Channels ON ChannelMembers.ChannelId = Channels.Id 1154 LEFT JOIN 1155 Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id 1156 LEFT JOIN 1157 Teams ON Channels.TeamId = Teams.Id 1158 LEFT JOIN 1159 Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id 1160 WHERE 1161 ChannelMembers.UserId = :UserId 1162 AND Posts.Id = :PostId`, map[string]interface{}{"UserId": userId, "PostId": postId}); err != nil { 1163 result.Err = model.NewAppError("SqlChannelStore.GetMemberForPost", "store.sql_channel.get_member_for_post.app_error", nil, "postId="+postId+", err="+err.Error(), http.StatusInternalServerError) 1164 return 1165 } 1166 result.Data = dbMember.ToModel() 1167 }) 1168 } 1169 1170 func (s SqlChannelStore) GetAllChannelMembersForUser(userId string, allowFromCache bool, includeDeleted bool) store.StoreChannel { 1171 return store.Do(func(result *store.StoreResult) { 1172 cache_key := userId 1173 if includeDeleted { 1174 cache_key += "_deleted" 1175 } 1176 if allowFromCache { 1177 if cacheItem, ok := allChannelMembersForUserCache.Get(cache_key); ok { 1178 if s.metrics != nil { 1179 s.metrics.IncrementMemCacheHitCounter("All Channel Members for User") 1180 } 1181 result.Data = cacheItem.(map[string]string) 1182 return 1183 } 1184 } 1185 1186 if s.metrics != nil { 1187 s.metrics.IncrementMemCacheMissCounter("All Channel Members for User") 1188 } 1189 1190 var deletedClause string 1191 if !includeDeleted { 1192 deletedClause = "Channels.DeleteAt = 0 AND" 1193 } 1194 1195 var data allChannelMembers 1196 _, err := s.GetReplica().Select(&data, ` 1197 SELECT 1198 ChannelMembers.ChannelId, ChannelMembers.Roles, ChannelMembers.SchemeUser, ChannelMembers.SchemeAdmin, 1199 TeamScheme.DefaultChannelUserRole TeamSchemeDefaultUserRole, 1200 TeamScheme.DefaultChannelAdminRole TeamSchemeDefaultAdminRole, 1201 ChannelScheme.DefaultChannelUserRole ChannelSchemeDefaultUserRole, 1202 ChannelScheme.DefaultChannelAdminRole ChannelSchemeDefaultAdminRole 1203 FROM 1204 ChannelMembers 1205 INNER JOIN 1206 Channels ON ChannelMembers.ChannelId = Channels.Id 1207 LEFT JOIN 1208 Schemes ChannelScheme ON Channels.SchemeId = ChannelScheme.Id 1209 LEFT JOIN 1210 Teams ON Channels.TeamId = Teams.Id 1211 LEFT JOIN 1212 Schemes TeamScheme ON Teams.SchemeId = TeamScheme.Id 1213 WHERE 1214 `+deletedClause+` 1215 ChannelMembers.UserId = :UserId`, map[string]interface{}{"UserId": userId}) 1216 1217 if err != nil { 1218 result.Err = model.NewAppError("SqlChannelStore.GetAllChannelMembersForUser", "store.sql_channel.get_channels.get.app_error", nil, "userId="+userId+", err="+err.Error(), http.StatusInternalServerError) 1219 return 1220 } 1221 1222 ids := data.ToMapStringString() 1223 result.Data = ids 1224 1225 if allowFromCache { 1226 allChannelMembersForUserCache.AddWithExpiresInSecs(cache_key, ids, ALL_CHANNEL_MEMBERS_FOR_USER_CACHE_SEC) 1227 } 1228 }) 1229 } 1230 1231 func (s SqlChannelStore) InvalidateCacheForChannelMembersNotifyProps(channelId string) { 1232 allChannelMembersNotifyPropsForChannelCache.Remove(channelId) 1233 if s.metrics != nil { 1234 s.metrics.IncrementMemCacheInvalidationCounter("All Channel Members Notify Props for Channel - Remove by ChannelId") 1235 } 1236 } 1237 1238 type allChannelMemberNotifyProps struct { 1239 UserId string 1240 NotifyProps model.StringMap 1241 } 1242 1243 func (s SqlChannelStore) GetAllChannelMembersNotifyPropsForChannel(channelId string, allowFromCache bool) store.StoreChannel { 1244 return store.Do(func(result *store.StoreResult) { 1245 if allowFromCache { 1246 if cacheItem, ok := allChannelMembersNotifyPropsForChannelCache.Get(channelId); ok { 1247 if s.metrics != nil { 1248 s.metrics.IncrementMemCacheHitCounter("All Channel Members Notify Props for Channel") 1249 } 1250 result.Data = cacheItem.(map[string]model.StringMap) 1251 return 1252 } 1253 } 1254 1255 if s.metrics != nil { 1256 s.metrics.IncrementMemCacheMissCounter("All Channel Members Notify Props for Channel") 1257 } 1258 1259 var data []allChannelMemberNotifyProps 1260 _, err := s.GetReplica().Select(&data, ` 1261 SELECT UserId, NotifyProps 1262 FROM ChannelMembers 1263 WHERE ChannelId = :ChannelId`, map[string]interface{}{"ChannelId": channelId}) 1264 1265 if err != nil { 1266 result.Err = model.NewAppError("SqlChannelStore.GetAllChannelMembersPropsForChannel", "store.sql_channel.get_members.app_error", nil, "channelId="+channelId+", err="+err.Error(), http.StatusInternalServerError) 1267 return 1268 } 1269 1270 props := make(map[string]model.StringMap) 1271 for i := range data { 1272 props[data[i].UserId] = data[i].NotifyProps 1273 } 1274 1275 result.Data = props 1276 1277 allChannelMembersNotifyPropsForChannelCache.AddWithExpiresInSecs(channelId, props, ALL_CHANNEL_MEMBERS_NOTIFY_PROPS_FOR_CHANNEL_CACHE_SEC) 1278 }) 1279 } 1280 1281 func (s SqlChannelStore) InvalidateMemberCount(channelId string) { 1282 channelMemberCountsCache.Remove(channelId) 1283 if s.metrics != nil { 1284 s.metrics.IncrementMemCacheInvalidationCounter("Channel Member Counts - Remove by ChannelId") 1285 } 1286 } 1287 1288 func (s SqlChannelStore) GetMemberCountFromCache(channelId string) int64 { 1289 if cacheItem, ok := channelMemberCountsCache.Get(channelId); ok { 1290 if s.metrics != nil { 1291 s.metrics.IncrementMemCacheHitCounter("Channel Member Counts") 1292 } 1293 return cacheItem.(int64) 1294 } 1295 1296 if s.metrics != nil { 1297 s.metrics.IncrementMemCacheMissCounter("Channel Member Counts") 1298 } 1299 1300 result := <-s.GetMemberCount(channelId, true) 1301 if result.Err != nil { 1302 return 0 1303 } 1304 1305 return result.Data.(int64) 1306 } 1307 1308 func (s SqlChannelStore) GetMemberCount(channelId string, allowFromCache bool) store.StoreChannel { 1309 return store.Do(func(result *store.StoreResult) { 1310 if allowFromCache { 1311 if cacheItem, ok := channelMemberCountsCache.Get(channelId); ok { 1312 if s.metrics != nil { 1313 s.metrics.IncrementMemCacheHitCounter("Channel Member Counts") 1314 } 1315 result.Data = cacheItem.(int64) 1316 return 1317 } 1318 } 1319 1320 if s.metrics != nil { 1321 s.metrics.IncrementMemCacheMissCounter("Channel Member Counts") 1322 } 1323 1324 count, err := s.GetReplica().SelectInt(` 1325 SELECT 1326 count(*) 1327 FROM 1328 ChannelMembers, 1329 Users 1330 WHERE 1331 ChannelMembers.UserId = Users.Id 1332 AND ChannelMembers.ChannelId = :ChannelId 1333 AND Users.DeleteAt = 0`, map[string]interface{}{"ChannelId": channelId}) 1334 if err != nil { 1335 result.Err = model.NewAppError("SqlChannelStore.GetMemberCount", "store.sql_channel.get_member_count.app_error", nil, "channel_id="+channelId+", "+err.Error(), http.StatusInternalServerError) 1336 return 1337 } 1338 result.Data = count 1339 1340 if allowFromCache { 1341 channelMemberCountsCache.AddWithExpiresInSecs(channelId, count, CHANNEL_MEMBERS_COUNTS_CACHE_SEC) 1342 } 1343 }) 1344 } 1345 1346 func (s SqlChannelStore) RemoveMember(channelId string, userId string) store.StoreChannel { 1347 return store.Do(func(result *store.StoreResult) { 1348 _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE ChannelId = :ChannelId AND UserId = :UserId", map[string]interface{}{"ChannelId": channelId, "UserId": userId}) 1349 if err != nil { 1350 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.remove_member.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 1351 } 1352 }) 1353 } 1354 1355 func (s SqlChannelStore) PermanentDeleteMembersByUser(userId string) store.StoreChannel { 1356 return store.Do(func(result *store.StoreResult) { 1357 if _, err := s.GetMaster().Exec("DELETE FROM ChannelMembers WHERE UserId = :UserId", map[string]interface{}{"UserId": userId}); err != nil { 1358 result.Err = model.NewAppError("SqlChannelStore.RemoveMember", "store.sql_channel.permanent_delete_members_by_user.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 1359 } 1360 }) 1361 } 1362 1363 func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string) store.StoreChannel { 1364 return store.Do(func(result *store.StoreResult) { 1365 props := make(map[string]interface{}) 1366 1367 updateIdQuery := "" 1368 for index, channelId := range channelIds { 1369 if len(updateIdQuery) > 0 { 1370 updateIdQuery += " OR " 1371 } 1372 1373 props["channelId"+strconv.Itoa(index)] = channelId 1374 updateIdQuery += "ChannelId = :channelId" + strconv.Itoa(index) 1375 } 1376 1377 selectIdQuery := strings.Replace(updateIdQuery, "ChannelId", "Id", -1) 1378 1379 var lastPostAtTimes []struct { 1380 Id string 1381 LastPostAt int64 1382 TotalMsgCount int64 1383 } 1384 1385 selectQuery := "SELECT Id, LastPostAt, TotalMsgCount FROM Channels WHERE (" + selectIdQuery + ")" 1386 1387 if _, err := s.GetMaster().Select(&lastPostAtTimes, selectQuery, props); err != nil { 1388 result.Err = model.NewAppError("SqlChannelStore.UpdateLastViewedAt", "store.sql_channel.update_last_viewed_at.app_error", nil, "channel_ids="+strings.Join(channelIds, ",")+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 1389 return 1390 } 1391 1392 times := map[string]int64{} 1393 msgCountQuery := "" 1394 lastViewedQuery := "" 1395 for index, t := range lastPostAtTimes { 1396 times[t.Id] = t.LastPostAt 1397 1398 props["msgCount"+strconv.Itoa(index)] = t.TotalMsgCount 1399 msgCountQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(MsgCount, :msgCount%d) ", index, index) 1400 1401 props["lastViewed"+strconv.Itoa(index)] = t.LastPostAt 1402 lastViewedQuery += fmt.Sprintf("WHEN :channelId%d THEN GREATEST(LastViewedAt, :lastViewed%d) ", index, index) 1403 1404 props["channelId"+strconv.Itoa(index)] = t.Id 1405 } 1406 1407 var updateQuery string 1408 1409 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 1410 updateQuery = `UPDATE 1411 ChannelMembers 1412 SET 1413 MentionCount = 0, 1414 MsgCount = CAST(CASE ChannelId ` + msgCountQuery + ` END AS BIGINT), 1415 LastViewedAt = CAST(CASE ChannelId ` + lastViewedQuery + ` END AS BIGINT), 1416 LastUpdateAt = CAST(CASE ChannelId ` + lastViewedQuery + ` END AS BIGINT) 1417 WHERE 1418 UserId = :UserId 1419 AND (` + updateIdQuery + `)` 1420 } else if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1421 updateQuery = `UPDATE 1422 ChannelMembers 1423 SET 1424 MentionCount = 0, 1425 MsgCount = CASE ChannelId ` + msgCountQuery + ` END, 1426 LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END, 1427 LastUpdateAt = CASE ChannelId ` + lastViewedQuery + ` END 1428 WHERE 1429 UserId = :UserId 1430 AND (` + updateIdQuery + `)` 1431 } 1432 1433 props["UserId"] = userId 1434 1435 if _, err := s.GetMaster().Exec(updateQuery, props); err != nil { 1436 result.Err = model.NewAppError("SqlChannelStore.UpdateLastViewedAt", "store.sql_channel.update_last_viewed_at.app_error", nil, "channel_ids="+strings.Join(channelIds, ",")+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 1437 return 1438 } 1439 1440 result.Data = times 1441 }) 1442 } 1443 1444 func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string) store.StoreChannel { 1445 return store.Do(func(result *store.StoreResult) { 1446 _, err := s.GetMaster().Exec( 1447 `UPDATE 1448 ChannelMembers 1449 SET 1450 MentionCount = MentionCount + 1, 1451 LastUpdateAt = :LastUpdateAt 1452 WHERE 1453 UserId = :UserId 1454 AND ChannelId = :ChannelId`, 1455 map[string]interface{}{"ChannelId": channelId, "UserId": userId, "LastUpdateAt": model.GetMillis()}) 1456 if err != nil { 1457 result.Err = model.NewAppError("SqlChannelStore.IncrementMentionCount", "store.sql_channel.increment_mention_count.app_error", nil, "channel_id="+channelId+", user_id="+userId+", "+err.Error(), http.StatusInternalServerError) 1458 } 1459 }) 1460 } 1461 1462 func (s SqlChannelStore) GetAll(teamId string) store.StoreChannel { 1463 return store.Do(func(result *store.StoreResult) { 1464 var data []*model.Channel 1465 _, err := s.GetReplica().Select(&data, "SELECT * FROM Channels WHERE TeamId = :TeamId AND Type != 'D' ORDER BY Name", map[string]interface{}{"TeamId": teamId}) 1466 1467 if err != nil { 1468 result.Err = model.NewAppError("SqlChannelStore.GetAll", "store.sql_channel.get_all.app_error", nil, "teamId="+teamId+", err="+err.Error(), http.StatusInternalServerError) 1469 return 1470 } 1471 1472 result.Data = data 1473 }) 1474 } 1475 1476 func (s SqlChannelStore) GetForPost(postId string) store.StoreChannel { 1477 return store.Do(func(result *store.StoreResult) { 1478 channel := &model.Channel{} 1479 if err := s.GetReplica().SelectOne( 1480 channel, 1481 `SELECT 1482 Channels.* 1483 FROM 1484 Channels, 1485 Posts 1486 WHERE 1487 Channels.Id = Posts.ChannelId 1488 AND Posts.Id = :PostId`, map[string]interface{}{"PostId": postId}); err != nil { 1489 result.Err = model.NewAppError("SqlChannelStore.GetForPost", "store.sql_channel.get_for_post.app_error", nil, "postId="+postId+", err="+err.Error(), http.StatusInternalServerError) 1490 return 1491 } 1492 1493 result.Data = channel 1494 }) 1495 } 1496 1497 func (s SqlChannelStore) AnalyticsTypeCount(teamId string, channelType string) store.StoreChannel { 1498 return store.Do(func(result *store.StoreResult) { 1499 query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType" 1500 1501 if len(teamId) > 0 { 1502 query += " AND TeamId = :TeamId" 1503 } 1504 1505 v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType}) 1506 if err != nil { 1507 result.Err = model.NewAppError("SqlChannelStore.AnalyticsTypeCount", "store.sql_channel.analytics_type_count.app_error", nil, err.Error(), http.StatusInternalServerError) 1508 return 1509 } 1510 1511 result.Data = v 1512 }) 1513 } 1514 1515 func (s SqlChannelStore) AnalyticsDeletedTypeCount(teamId string, channelType string) store.StoreChannel { 1516 return store.Do(func(result *store.StoreResult) { 1517 query := "SELECT COUNT(Id) AS Value FROM Channels WHERE Type = :ChannelType AND DeleteAt > 0" 1518 1519 if len(teamId) > 0 { 1520 query += " AND TeamId = :TeamId" 1521 } 1522 1523 v, err := s.GetReplica().SelectInt(query, map[string]interface{}{"TeamId": teamId, "ChannelType": channelType}) 1524 if err != nil { 1525 result.Err = model.NewAppError("SqlChannelStore.AnalyticsDeletedTypeCount", "store.sql_channel.analytics_deleted_type_count.app_error", nil, err.Error(), http.StatusInternalServerError) 1526 return 1527 } 1528 1529 result.Data = v 1530 }) 1531 } 1532 1533 func (s SqlChannelStore) GetMembersForUser(teamId string, userId string) store.StoreChannel { 1534 return store.Do(func(result *store.StoreResult) { 1535 var dbMembers channelMemberWithSchemeRolesList 1536 _, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.UserId = :UserId", map[string]interface{}{"TeamId": teamId, "UserId": userId}) 1537 1538 if err != nil { 1539 result.Err = model.NewAppError("SqlChannelStore.GetMembersForUser", "store.sql_channel.get_members.app_error", nil, "teamId="+teamId+", userId="+userId+", err="+err.Error(), http.StatusInternalServerError) 1540 return 1541 } 1542 1543 result.Data = dbMembers.ToModel() 1544 }) 1545 } 1546 1547 func (s SqlChannelStore) AutocompleteInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { 1548 return store.Do(func(result *store.StoreResult) { 1549 deleteFilter := "AND DeleteAt = 0" 1550 if includeDeleted { 1551 deleteFilter = "" 1552 } 1553 1554 queryFormat := ` 1555 SELECT 1556 * 1557 FROM 1558 Channels 1559 WHERE 1560 TeamId = :TeamId 1561 AND Type = 'O' 1562 ` + deleteFilter + ` 1563 %v 1564 LIMIT 50` 1565 1566 var channels model.ChannelList 1567 1568 if likeClause, likeTerm := s.buildLIKEClause(term); likeClause == "" { 1569 if _, err := s.GetReplica().Select(&channels, fmt.Sprintf(queryFormat, ""), map[string]interface{}{"TeamId": teamId}); err != nil { 1570 result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) 1571 } 1572 } else { 1573 // Using a UNION results in index_merge and fulltext queries and is much faster than the ref 1574 // query you would get using an OR of the LIKE and full-text clauses. 1575 fulltextClause, fulltextTerm := s.buildFulltextClause(term) 1576 likeQuery := fmt.Sprintf(queryFormat, "AND "+likeClause) 1577 fulltextQuery := fmt.Sprintf(queryFormat, "AND "+fulltextClause) 1578 query := fmt.Sprintf("(%v) UNION (%v) LIMIT 50", likeQuery, fulltextQuery) 1579 1580 if _, err := s.GetReplica().Select(&channels, query, map[string]interface{}{"TeamId": teamId, "LikeTerm": likeTerm, "FulltextTerm": fulltextTerm}); err != nil { 1581 result.Err = model.NewAppError("SqlChannelStore.AutocompleteInTeam", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) 1582 } 1583 } 1584 1585 sort.Slice(channels, func(a, b int) bool { 1586 return strings.ToLower(channels[a].DisplayName) < strings.ToLower(channels[b].DisplayName) 1587 }) 1588 result.Data = &channels 1589 }) 1590 } 1591 1592 func (s SqlChannelStore) SearchInTeam(teamId string, term string, includeDeleted bool) store.StoreChannel { 1593 return store.Do(func(result *store.StoreResult) { 1594 deleteFilter := "AND DeleteAt = 0" 1595 if includeDeleted { 1596 deleteFilter = "" 1597 } 1598 searchQuery := ` 1599 SELECT 1600 * 1601 FROM 1602 Channels 1603 WHERE 1604 TeamId = :TeamId 1605 AND Type = 'O' 1606 ` + deleteFilter + ` 1607 SEARCH_CLAUSE 1608 ORDER BY DisplayName 1609 LIMIT 100` 1610 1611 *result = s.performSearch(searchQuery, term, map[string]interface{}{"TeamId": teamId}) 1612 }) 1613 } 1614 1615 func (s SqlChannelStore) SearchMore(userId string, teamId string, term string) store.StoreChannel { 1616 return store.Do(func(result *store.StoreResult) { 1617 searchQuery := ` 1618 SELECT 1619 * 1620 FROM 1621 Channels 1622 WHERE 1623 TeamId = :TeamId 1624 AND Type = 'O' 1625 AND DeleteAt = 0 1626 AND Id NOT IN (SELECT 1627 Channels.Id 1628 FROM 1629 Channels, 1630 ChannelMembers 1631 WHERE 1632 Id = ChannelId 1633 AND TeamId = :TeamId 1634 AND UserId = :UserId 1635 AND DeleteAt = 0) 1636 SEARCH_CLAUSE 1637 ORDER BY DisplayName 1638 LIMIT 100` 1639 1640 *result = s.performSearch(searchQuery, term, map[string]interface{}{"TeamId": teamId, "UserId": userId}) 1641 }) 1642 } 1643 1644 func (s SqlChannelStore) buildLIKEClause(term string) (likeClause, likeTerm string) { 1645 likeTerm = term 1646 searchColumns := "Name, DisplayName, Purpose" 1647 1648 // These chars must be removed from the like query. 1649 for _, c := range ignoreLikeSearchChar { 1650 likeTerm = strings.Replace(likeTerm, c, "", -1) 1651 } 1652 1653 // These chars must be escaped in the like query. 1654 for _, c := range escapeLikeSearchChar { 1655 likeTerm = strings.Replace(likeTerm, c, "*"+c, -1) 1656 } 1657 1658 if likeTerm == "" { 1659 return 1660 } 1661 1662 // Prepare the LIKE portion of the query. 1663 var searchFields []string 1664 for _, field := range strings.Split(searchColumns, ", ") { 1665 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 1666 searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(%s) escape '*'", field, ":LikeTerm")) 1667 } else { 1668 searchFields = append(searchFields, fmt.Sprintf("%s LIKE %s escape '*'", field, ":LikeTerm")) 1669 } 1670 } 1671 1672 likeClause = fmt.Sprintf("(%s)", strings.Join(searchFields, " OR ")) 1673 likeTerm += "%" 1674 return 1675 } 1676 1677 func (s SqlChannelStore) buildFulltextClause(term string) (fulltextClause, fulltextTerm string) { 1678 // Copy the terms as we will need to prepare them differently for each search type. 1679 fulltextTerm = term 1680 1681 searchColumns := "Name, DisplayName, Purpose" 1682 1683 // These chars must be treated as spaces in the fulltext query. 1684 for _, c := range spaceFulltextSearchChar { 1685 fulltextTerm = strings.Replace(fulltextTerm, c, " ", -1) 1686 } 1687 1688 // Prepare the FULLTEXT portion of the query. 1689 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 1690 fulltextTerm = strings.Replace(fulltextTerm, "|", "", -1) 1691 1692 splitTerm := strings.Fields(fulltextTerm) 1693 for i, t := range strings.Fields(fulltextTerm) { 1694 if i == len(splitTerm)-1 { 1695 splitTerm[i] = t + ":*" 1696 } else { 1697 splitTerm[i] = t + ":* &" 1698 } 1699 } 1700 1701 fulltextTerm = strings.Join(splitTerm, " ") 1702 1703 fulltextClause = fmt.Sprintf("((%s) @@ to_tsquery(:FulltextTerm))", convertMySQLFullTextColumnsToPostgres(searchColumns)) 1704 } else if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 1705 splitTerm := strings.Fields(fulltextTerm) 1706 for i, t := range strings.Fields(fulltextTerm) { 1707 splitTerm[i] = "+" + t + "*" 1708 } 1709 1710 fulltextTerm = strings.Join(splitTerm, " ") 1711 1712 fulltextClause = fmt.Sprintf("MATCH(%s) AGAINST (:FulltextTerm IN BOOLEAN MODE)", searchColumns) 1713 } 1714 1715 return 1716 } 1717 1718 func (s SqlChannelStore) performSearch(searchQuery string, term string, parameters map[string]interface{}) store.StoreResult { 1719 result := store.StoreResult{} 1720 1721 likeClause, likeTerm := s.buildLIKEClause(term) 1722 if likeTerm == "" { 1723 // If the likeTerm is empty after preparing, then don't bother searching. 1724 searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "", 1) 1725 } else { 1726 parameters["LikeTerm"] = likeTerm 1727 fulltextClause, fulltextTerm := s.buildFulltextClause(term) 1728 parameters["FulltextTerm"] = fulltextTerm 1729 searchQuery = strings.Replace(searchQuery, "SEARCH_CLAUSE", "AND ("+likeClause+" OR "+fulltextClause+")", 1) 1730 } 1731 1732 var channels model.ChannelList 1733 1734 if _, err := s.GetReplica().Select(&channels, searchQuery, parameters); err != nil { 1735 result.Err = model.NewAppError("SqlChannelStore.Search", "store.sql_channel.search.app_error", nil, "term="+term+", "+", "+err.Error(), http.StatusInternalServerError) 1736 return result 1737 } 1738 1739 result.Data = &channels 1740 return result 1741 } 1742 1743 func (s SqlChannelStore) GetMembersByIds(channelId string, userIds []string) store.StoreChannel { 1744 return store.Do(func(result *store.StoreResult) { 1745 var dbMembers channelMemberWithSchemeRolesList 1746 props := make(map[string]interface{}) 1747 idQuery := "" 1748 1749 for index, userId := range userIds { 1750 if len(idQuery) > 0 { 1751 idQuery += ", " 1752 } 1753 1754 props["userId"+strconv.Itoa(index)] = userId 1755 idQuery += ":userId" + strconv.Itoa(index) 1756 } 1757 1758 props["ChannelId"] = channelId 1759 1760 if _, err := s.GetReplica().Select(&dbMembers, CHANNEL_MEMBERS_WITH_SCHEME_SELECT_QUERY+"WHERE ChannelMembers.ChannelId = :ChannelId AND ChannelMembers.UserId IN ("+idQuery+")", props); err != nil { 1761 result.Err = model.NewAppError("SqlChannelStore.GetMembersByIds", "store.sql_channel.get_members_by_ids.app_error", nil, "channelId="+channelId+" "+err.Error(), http.StatusInternalServerError) 1762 return 1763 } 1764 1765 result.Data = dbMembers.ToModel() 1766 }) 1767 } 1768 1769 func (s SqlChannelStore) GetChannelsByScheme(schemeId string, offset int, limit int) store.StoreChannel { 1770 return store.Do(func(result *store.StoreResult) { 1771 var channels model.ChannelList 1772 _, err := s.GetReplica().Select(&channels, "SELECT * FROM Channels WHERE SchemeId = :SchemeId ORDER BY DisplayName LIMIT :Limit OFFSET :Offset", map[string]interface{}{"SchemeId": schemeId, "Offset": offset, "Limit": limit}) 1773 if err != nil { 1774 result.Err = model.NewAppError("SqlChannelStore.GetChannelsByScheme", "store.sql_channel.get_by_scheme.app_error", nil, "schemeId="+schemeId+" "+err.Error(), http.StatusInternalServerError) 1775 return 1776 } 1777 result.Data = channels 1778 }) 1779 } 1780 1781 // This function does the Advanced Permissions Phase 2 migration for ChannelMember objects. It performs the migration 1782 // in batches as a single transaction per batch to ensure consistency but to also minimise execution time to avoid 1783 // causing unnecessary table locks. **THIS FUNCTION SHOULD NOT BE USED FOR ANY OTHER PURPOSE.** Executing this function 1784 // *after* the new Schemes functionality has been used on an installation will have unintended consequences. 1785 func (s SqlChannelStore) MigrateChannelMembers(fromChannelId string, fromUserId string) store.StoreChannel { 1786 return store.Do(func(result *store.StoreResult) { 1787 var transaction *gorp.Transaction 1788 var err error 1789 1790 if transaction, err = s.GetMaster().Begin(); err != nil { 1791 result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 1792 return 1793 } 1794 1795 var channelMembers []channelMember 1796 if _, err := transaction.Select(&channelMembers, "SELECT * from ChannelMembers WHERE (ChannelId, UserId) > (:FromChannelId, :FromUserId) ORDER BY ChannelId, UserId LIMIT 100", map[string]interface{}{"FromChannelId": fromChannelId, "FromUserId": fromUserId}); err != nil { 1797 result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.select.app_error", nil, err.Error(), http.StatusInternalServerError) 1798 return 1799 } 1800 1801 if len(channelMembers) == 0 { 1802 // No more channel members in query result means that the migration has finished. 1803 return 1804 } 1805 1806 for _, member := range channelMembers { 1807 roles := strings.Fields(member.Roles) 1808 var newRoles []string 1809 if !member.SchemeAdmin.Valid { 1810 member.SchemeAdmin = sql.NullBool{Bool: false, Valid: true} 1811 } 1812 if !member.SchemeUser.Valid { 1813 member.SchemeUser = sql.NullBool{Bool: false, Valid: true} 1814 } 1815 for _, role := range roles { 1816 if role == model.CHANNEL_ADMIN_ROLE_ID { 1817 member.SchemeAdmin = sql.NullBool{Bool: true, Valid: true} 1818 } else if role == model.CHANNEL_USER_ROLE_ID { 1819 member.SchemeUser = sql.NullBool{Bool: true, Valid: true} 1820 } else { 1821 newRoles = append(newRoles, role) 1822 } 1823 } 1824 member.Roles = strings.Join(newRoles, " ") 1825 1826 if _, err := transaction.Update(&member); err != nil { 1827 if err2 := transaction.Rollback(); err2 != nil { 1828 result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 1829 return 1830 } 1831 result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.update.app_error", nil, err.Error(), http.StatusInternalServerError) 1832 return 1833 } 1834 1835 } 1836 1837 if err := transaction.Commit(); err != nil { 1838 if err2 := transaction.Rollback(); err2 != nil { 1839 result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 1840 return 1841 } 1842 result.Err = model.NewAppError("SqlChannelStore.MigrateChannelMembers", "store.sql_channel.migrate_channel_members.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 1843 return 1844 } 1845 1846 data := make(map[string]string) 1847 data["ChannelId"] = channelMembers[len(channelMembers)-1].ChannelId 1848 data["UserId"] = channelMembers[len(channelMembers)-1].UserId 1849 result.Data = data 1850 }) 1851 } 1852 1853 func (s SqlChannelStore) ResetAllChannelSchemes() store.StoreChannel { 1854 return store.Do(func(result *store.StoreResult) { 1855 if _, err := s.GetMaster().Exec("UPDATE Channels SET SchemeId=''"); err != nil { 1856 result.Err = model.NewAppError("SqlChannelStore.ResetAllChannelSchemes", "store.sql_channel.reset_all_channel_schemes.app_error", nil, err.Error(), http.StatusInternalServerError) 1857 } 1858 }) 1859 } 1860 1861 func (s SqlChannelStore) ClearAllCustomRoleAssignments() store.StoreChannel { 1862 return store.Do(func(result *store.StoreResult) { 1863 builtInRoles := model.MakeDefaultRoles() 1864 lastUserId := strings.Repeat("0", 26) 1865 lastChannelId := strings.Repeat("0", 26) 1866 1867 for true { 1868 var transaction *gorp.Transaction 1869 var err error 1870 1871 if transaction, err = s.GetMaster().Begin(); err != nil { 1872 result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.open_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 1873 return 1874 } 1875 1876 var channelMembers []*channelMember 1877 if _, err := transaction.Select(&channelMembers, "SELECT * from ChannelMembers WHERE (ChannelId, UserId) > (:ChannelId, :UserId) ORDER BY ChannelId, UserId LIMIT 1000", map[string]interface{}{"ChannelId": lastChannelId, "UserId": lastUserId}); err != nil { 1878 if err2 := transaction.Rollback(); err2 != nil { 1879 result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 1880 return 1881 } 1882 result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.select.app_error", nil, err.Error(), http.StatusInternalServerError) 1883 return 1884 } 1885 1886 if len(channelMembers) == 0 { 1887 break 1888 } 1889 1890 for _, member := range channelMembers { 1891 lastUserId = member.UserId 1892 lastChannelId = member.ChannelId 1893 1894 var newRoles []string 1895 1896 for _, role := range strings.Fields(member.Roles) { 1897 for name := range builtInRoles { 1898 if name == role { 1899 newRoles = append(newRoles, role) 1900 break 1901 } 1902 } 1903 } 1904 1905 newRolesString := strings.Join(newRoles, " ") 1906 if newRolesString != member.Roles { 1907 if _, err := transaction.Exec("UPDATE ChannelMembers SET Roles = :Roles WHERE UserId = :UserId AND ChannelId = :ChannelId", map[string]interface{}{"Roles": newRolesString, "ChannelId": member.ChannelId, "UserId": member.UserId}); err != nil { 1908 if err2 := transaction.Rollback(); err2 != nil { 1909 result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 1910 return 1911 } 1912 result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.update.app_error", nil, err.Error(), http.StatusInternalServerError) 1913 return 1914 } 1915 } 1916 } 1917 1918 if err := transaction.Commit(); err != nil { 1919 if err2 := transaction.Rollback(); err2 != nil { 1920 result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.rollback_transaction.app_error", nil, err2.Error(), http.StatusInternalServerError) 1921 return 1922 } 1923 result.Err = model.NewAppError("SqlChannelStore.ClearAllCustomRoleAssignments", "store.sql_channel.clear_all_custom_role_assignments.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError) 1924 return 1925 } 1926 } 1927 }) 1928 } 1929 1930 func (s SqlChannelStore) ResetLastPostAt() store.StoreChannel { 1931 return store.Do(func(result *store.StoreResult) { 1932 var query string 1933 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 1934 query = "UPDATE Channels SET LastPostAt = COALESCE((SELECT UpdateAt FROM Posts WHERE ChannelId = Channels.Id ORDER BY UpdateAt DESC LIMIT 1), Channels.CreateAt);" 1935 } else { 1936 query = "UPDATE Channels SET LastPostAt = IFNULL((SELECT UpdateAt FROM Posts WHERE ChannelId = Channels.Id ORDER BY UpdateAt DESC LIMIT 1), Channels.CreateAt);" 1937 } 1938 1939 if _, err := s.GetMaster().Exec(query); err != nil { 1940 result.Err = model.NewAppError("SqlChannelStore.ResetLastPostAt", "store.sql_channel.reset_last_post_at.app_error", nil, err.Error(), http.StatusInternalServerError) 1941 } 1942 }) 1943 }