github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/store/sqlstore/shared_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 10 "github.com/masterhung0112/hk_server/v5/model" 11 "github.com/masterhung0112/hk_server/v5/store" 12 13 sq "github.com/Masterminds/squirrel" 14 "github.com/pkg/errors" 15 ) 16 17 const ( 18 DefaultGetUsersForSyncLimit = 100 19 ) 20 21 type SqlSharedChannelStore struct { 22 *SqlStore 23 } 24 25 func newSqlSharedChannelStore(sqlStore *SqlStore) store.SharedChannelStore { 26 s := &SqlSharedChannelStore{ 27 SqlStore: sqlStore, 28 } 29 30 for _, db := range sqlStore.GetAllConns() { 31 tableSharedChannels := db.AddTableWithName(model.SharedChannel{}, "SharedChannels").SetKeys(false, "ChannelId") 32 tableSharedChannels.ColMap("ChannelId").SetMaxSize(26) 33 tableSharedChannels.ColMap("TeamId").SetMaxSize(26) 34 tableSharedChannels.ColMap("CreatorId").SetMaxSize(26) 35 tableSharedChannels.ColMap("ShareName").SetMaxSize(64) 36 tableSharedChannels.SetUniqueTogether("ShareName", "TeamId") 37 tableSharedChannels.ColMap("ShareDisplayName").SetMaxSize(64) 38 tableSharedChannels.ColMap("SharePurpose").SetMaxSize(250) 39 tableSharedChannels.ColMap("ShareHeader").SetMaxSize(1024) 40 tableSharedChannels.ColMap("RemoteId").SetMaxSize(26) 41 42 tableSharedChannelRemotes := db.AddTableWithName(model.SharedChannelRemote{}, "SharedChannelRemotes").SetKeys(false, "Id", "ChannelId") 43 tableSharedChannelRemotes.ColMap("Id").SetMaxSize(26) 44 tableSharedChannelRemotes.ColMap("ChannelId").SetMaxSize(26) 45 tableSharedChannelRemotes.ColMap("CreatorId").SetMaxSize(26) 46 tableSharedChannelRemotes.ColMap("RemoteId").SetMaxSize(26) 47 tableSharedChannelRemotes.ColMap("LastPostId").SetMaxSize(26) 48 tableSharedChannelRemotes.SetUniqueTogether("ChannelId", "RemoteId") 49 50 tableSharedChannelUsers := db.AddTableWithName(model.SharedChannelUser{}, "SharedChannelUsers").SetKeys(false, "Id") 51 tableSharedChannelUsers.ColMap("Id").SetMaxSize(26) 52 tableSharedChannelUsers.ColMap("UserId").SetMaxSize(26) 53 tableSharedChannelUsers.ColMap("RemoteId").SetMaxSize(26) 54 tableSharedChannelUsers.ColMap("ChannelId").SetMaxSize(26) 55 tableSharedChannelUsers.SetUniqueTogether("UserId", "ChannelId", "RemoteId") 56 57 tableSharedChannelFiles := db.AddTableWithName(model.SharedChannelAttachment{}, "SharedChannelAttachments").SetKeys(false, "Id") 58 tableSharedChannelFiles.ColMap("Id").SetMaxSize(26) 59 tableSharedChannelFiles.ColMap("FileId").SetMaxSize(26) 60 tableSharedChannelFiles.ColMap("RemoteId").SetMaxSize(26) 61 tableSharedChannelFiles.SetUniqueTogether("FileId", "RemoteId") 62 } 63 64 return s 65 } 66 67 func (s SqlSharedChannelStore) createIndexesIfNotExists() { 68 s.CreateIndexIfNotExists("idx_sharedchannelusers_remote_id", "SharedChannelUsers", "RemoteId") 69 } 70 71 // Save inserts a new shared channel record. 72 func (s SqlSharedChannelStore) Save(sc *model.SharedChannel) (*model.SharedChannel, error) { 73 sc.PreSave() 74 if err := sc.IsValid(); err != nil { 75 return nil, err 76 } 77 78 // make sure the shared channel is associated with a real channel. 79 channel, err := s.stores.channel.Get(sc.ChannelId, true) 80 if err != nil { 81 return nil, fmt.Errorf("invalid channel: %w", err) 82 } 83 84 transaction, err := s.GetMaster().Begin() 85 if err != nil { 86 return nil, errors.Wrap(err, "begin_transaction") 87 } 88 defer finalizeTransaction(transaction) 89 90 if err := transaction.Insert(sc); err != nil { 91 return nil, errors.Wrapf(err, "save_shared_channel: ChannelId=%s", sc.ChannelId) 92 } 93 94 // set `Shared` flag in Channels table if needed 95 if channel.Shared == nil || !*channel.Shared { 96 if err := s.stores.channel.SetShared(channel.Id, true); err != nil { 97 return nil, err 98 } 99 } 100 101 if err := transaction.Commit(); err != nil { 102 return nil, errors.Wrap(err, "commit_transaction") 103 } 104 return sc, nil 105 } 106 107 // Get fetches a shared channel by channel_id. 108 func (s SqlSharedChannelStore) Get(channelId string) (*model.SharedChannel, error) { 109 var sc model.SharedChannel 110 111 query := s.getQueryBuilder(). 112 Select("*"). 113 From("SharedChannels"). 114 Where(sq.Eq{"SharedChannels.ChannelId": channelId}) 115 116 squery, args, err := query.ToSql() 117 if err != nil { 118 return nil, errors.Wrapf(err, "getsharedchannel_tosql") 119 } 120 121 if err := s.GetReplica().SelectOne(&sc, squery, args...); err != nil { 122 if err == sql.ErrNoRows { 123 return nil, store.NewErrNotFound("SharedChannel", channelId) 124 } 125 return nil, errors.Wrapf(err, "failed to find shared channel with ChannelId=%s", channelId) 126 } 127 return &sc, nil 128 } 129 130 // HasChannel returns whether a given channelID is a shared channel or not. 131 func (s SqlSharedChannelStore) HasChannel(channelID string) (bool, error) { 132 builder := s.getQueryBuilder(). 133 Select("1"). 134 Prefix("SELECT EXISTS ("). 135 From("SharedChannels"). 136 Where(sq.Eq{"SharedChannels.ChannelId": channelID}). 137 Suffix(")") 138 139 query, args, err := builder.ToSql() 140 if err != nil { 141 return false, errors.Wrapf(err, "get_shared_channel_exists_tosql") 142 } 143 144 var exists bool 145 if err := s.GetReplica().SelectOne(&exists, query, args...); err != nil { 146 return exists, errors.Wrapf(err, "failed to get shared channel for channel_id=%s", channelID) 147 } 148 return exists, nil 149 } 150 151 // GetAll fetches a paginated list of shared channels filtered by SharedChannelSearchOpts. 152 func (s SqlSharedChannelStore) GetAll(offset, limit int, opts model.SharedChannelFilterOpts) ([]*model.SharedChannel, error) { 153 if opts.ExcludeHome && opts.ExcludeRemote { 154 return nil, errors.New("cannot exclude home and remote shared channels") 155 } 156 157 safeConv := func(offset, limit int) (uint64, uint64, error) { 158 if offset < 0 { 159 return 0, 0, errors.New("offset must be positive integer") 160 } 161 if limit < 0 { 162 return 0, 0, errors.New("limit must be positive integer") 163 } 164 return uint64(offset), uint64(limit), nil 165 } 166 167 safeOffset, safeLimit, err := safeConv(offset, limit) 168 if err != nil { 169 return nil, err 170 } 171 172 query := s.getSharedChannelsQuery(opts, false) 173 query = query.OrderBy("sc.ShareDisplayName, sc.ShareName").Limit(safeLimit).Offset(safeOffset) 174 175 squery, args, err := query.ToSql() 176 if err != nil { 177 return nil, errors.Wrap(err, "failed to create query") 178 } 179 180 var channels []*model.SharedChannel 181 _, err = s.GetReplica().Select(&channels, squery, args...) 182 if err != nil { 183 return nil, errors.Wrap(err, "failed to get shared channels") 184 } 185 return channels, nil 186 } 187 188 // GetAllCount returns the number of shared channels that would be fetched using SharedChannelSearchOpts. 189 func (s SqlSharedChannelStore) GetAllCount(opts model.SharedChannelFilterOpts) (int64, error) { 190 if opts.ExcludeHome && opts.ExcludeRemote { 191 return 0, errors.New("cannot exclude home and remote shared channels") 192 } 193 194 query := s.getSharedChannelsQuery(opts, true) 195 squery, args, err := query.ToSql() 196 if err != nil { 197 return 0, errors.Wrap(err, "failed to create query") 198 } 199 200 count, err := s.GetReplica().SelectInt(squery, args...) 201 if err != nil { 202 return 0, errors.Wrap(err, "failed to count channels") 203 } 204 return count, nil 205 } 206 207 func (s SqlSharedChannelStore) getSharedChannelsQuery(opts model.SharedChannelFilterOpts, forCount bool) sq.SelectBuilder { 208 var selectStr string 209 if forCount { 210 selectStr = "count(sc.ChannelId)" 211 } else { 212 selectStr = "sc.*" 213 } 214 215 query := s.getQueryBuilder(). 216 Select(selectStr). 217 From("SharedChannels AS sc") 218 219 if opts.TeamId != "" { 220 query = query.Where(sq.Eq{"sc.TeamId": opts.TeamId}) 221 } 222 223 if opts.CreatorId != "" { 224 query = query.Where(sq.Eq{"sc.CreatorId": opts.CreatorId}) 225 } 226 227 if opts.ExcludeHome { 228 query = query.Where(sq.NotEq{"sc.Home": true}) 229 } 230 231 if opts.ExcludeRemote { 232 query = query.Where(sq.Eq{"sc.Home": true}) 233 } 234 235 return query 236 } 237 238 // Update updates the shared channel. 239 func (s SqlSharedChannelStore) Update(sc *model.SharedChannel) (*model.SharedChannel, error) { 240 if err := sc.IsValid(); err != nil { 241 return nil, err 242 } 243 244 count, err := s.GetMaster().Update(sc) 245 if err != nil { 246 return nil, errors.Wrapf(err, "failed to update shared channel with channelId=%s", sc.ChannelId) 247 } 248 249 if count != 1 { 250 return nil, fmt.Errorf("expected number of shared channels to be updated is 1 but was %d", count) 251 } 252 return sc, nil 253 } 254 255 // Delete deletes a single shared channel plus associated SharedChannelRemotes. 256 // Returns true if shared channel found and deleted, false if not found. 257 func (s SqlSharedChannelStore) Delete(channelId string) (bool, error) { 258 transaction, err := s.GetMaster().Begin() 259 if err != nil { 260 return false, errors.Wrap(err, "DeleteSharedChannel: begin_transaction") 261 } 262 defer finalizeTransaction(transaction) 263 264 squery, args, err := s.getQueryBuilder(). 265 Delete("SharedChannels"). 266 Where(sq.Eq{"SharedChannels.ChannelId": channelId}). 267 ToSql() 268 if err != nil { 269 return false, errors.Wrap(err, "delete_shared_channel_tosql") 270 } 271 272 result, err := transaction.Exec(squery, args...) 273 if err != nil { 274 return false, errors.Wrap(err, "failed to delete SharedChannel") 275 } 276 277 // Also remove remotes from SharedChannelRemotes (if any). 278 squery, args, err = s.getQueryBuilder(). 279 Delete("SharedChannelRemotes"). 280 Where(sq.Eq{"ChannelId": channelId}). 281 ToSql() 282 if err != nil { 283 return false, errors.Wrap(err, "delete_shared_channel_remotes_tosql") 284 } 285 286 _, err = transaction.Exec(squery, args...) 287 if err != nil { 288 return false, errors.Wrap(err, "failed to delete SharedChannelRemotes") 289 } 290 291 count, err := result.RowsAffected() 292 if err != nil { 293 return false, errors.Wrap(err, "failed to determine rows affected") 294 } 295 296 if count > 0 { 297 // unset the channel's Shared flag 298 if err = s.Channel().SetShared(channelId, false); err != nil { 299 return false, errors.Wrap(err, "error unsetting channel share flag") 300 } 301 } 302 303 if err = transaction.Commit(); err != nil { 304 return false, errors.Wrap(err, "commit_transaction") 305 } 306 307 return count > 0, nil 308 } 309 310 // SaveRemote inserts a new shared channel remote record. 311 func (s SqlSharedChannelStore) SaveRemote(remote *model.SharedChannelRemote) (*model.SharedChannelRemote, error) { 312 remote.PreSave() 313 if err := remote.IsValid(); err != nil { 314 return nil, err 315 } 316 317 // make sure the shared channel remote is associated with a real channel. 318 if _, err := s.stores.channel.Get(remote.ChannelId, true); err != nil { 319 return nil, fmt.Errorf("invalid channel: %w", err) 320 } 321 322 if err := s.GetMaster().Insert(remote); err != nil { 323 return nil, errors.Wrapf(err, "save_shared_channel_remote: channel_id=%s, id=%s", remote.ChannelId, remote.Id) 324 } 325 return remote, nil 326 } 327 328 // Update updates the shared channel remote. 329 func (s SqlSharedChannelStore) UpdateRemote(remote *model.SharedChannelRemote) (*model.SharedChannelRemote, error) { 330 if err := remote.IsValid(); err != nil { 331 return nil, err 332 } 333 334 count, err := s.GetMaster().Update(remote) 335 if err != nil { 336 return nil, errors.Wrapf(err, "failed to update shared channel remote with remoteId=%s", remote.Id) 337 } 338 339 if count != 1 { 340 return nil, fmt.Errorf("expected number of shared channel remotes to be updated is 1 but was %d", count) 341 } 342 return remote, nil 343 } 344 345 // GetRemote fetches a shared channel remote by id. 346 func (s SqlSharedChannelStore) GetRemote(id string) (*model.SharedChannelRemote, error) { 347 var remote model.SharedChannelRemote 348 349 query := s.getQueryBuilder(). 350 Select("*"). 351 From("SharedChannelRemotes"). 352 Where(sq.Eq{"SharedChannelRemotes.Id": id}) 353 354 squery, args, err := query.ToSql() 355 if err != nil { 356 return nil, errors.Wrapf(err, "get_shared_channel_remote_tosql") 357 } 358 359 if err := s.GetReplica().SelectOne(&remote, squery, args...); err != nil { 360 if err == sql.ErrNoRows { 361 return nil, store.NewErrNotFound("SharedChannelRemote", id) 362 } 363 return nil, errors.Wrapf(err, "failed to find shared channel remote with id=%s", id) 364 } 365 return &remote, nil 366 } 367 368 // GetRemoteByIds fetches a shared channel remote by channel id and remote cluster id. 369 func (s SqlSharedChannelStore) GetRemoteByIds(channelId string, remoteId string) (*model.SharedChannelRemote, error) { 370 var remote model.SharedChannelRemote 371 372 query := s.getQueryBuilder(). 373 Select("*"). 374 From("SharedChannelRemotes"). 375 Where(sq.Eq{"SharedChannelRemotes.ChannelId": channelId}). 376 Where(sq.Eq{"SharedChannelRemotes.RemoteId": remoteId}) 377 378 squery, args, err := query.ToSql() 379 if err != nil { 380 return nil, errors.Wrapf(err, "get_shared_channel_remote_by_ids_tosql") 381 } 382 383 if err := s.GetReplica().SelectOne(&remote, squery, args...); err != nil { 384 if err == sql.ErrNoRows { 385 return nil, store.NewErrNotFound("SharedChannelRemote", fmt.Sprintf("channelId=%s, remoteId=%s", channelId, remoteId)) 386 } 387 return nil, errors.Wrapf(err, "failed to find shared channel remote with channelId=%s, remoteId=%s", channelId, remoteId) 388 } 389 return &remote, nil 390 } 391 392 // GetRemotes fetches all shared channel remotes associated with channel_id. 393 func (s SqlSharedChannelStore) GetRemotes(opts model.SharedChannelRemoteFilterOpts) ([]*model.SharedChannelRemote, error) { 394 var remotes []*model.SharedChannelRemote 395 396 query := s.getQueryBuilder(). 397 Select("*"). 398 From("SharedChannelRemotes") 399 400 if opts.ChannelId != "" { 401 query = query.Where(sq.Eq{"ChannelId": opts.ChannelId}) 402 } 403 404 if opts.RemoteId != "" { 405 query = query.Where(sq.Eq{"RemoteId": opts.RemoteId}) 406 } 407 408 if !opts.InclUnconfirmed { 409 query = query.Where(sq.Eq{"IsInviteConfirmed": true}) 410 } 411 412 squery, args, err := query.ToSql() 413 if err != nil { 414 return nil, errors.Wrapf(err, "get_shared_channel_remotes_tosql") 415 } 416 417 if _, err := s.GetReplica().Select(&remotes, squery, args...); err != nil { 418 if err != sql.ErrNoRows { 419 return nil, errors.Wrapf(err, "failed to get shared channel remotes for channel_id=%s; remote_id=%s", 420 opts.ChannelId, opts.RemoteId) 421 } 422 } 423 return remotes, nil 424 } 425 426 // HasRemote returns whether a given remoteId and channelId are present in the shared channel remotes or not. 427 func (s SqlSharedChannelStore) HasRemote(channelID string, remoteId string) (bool, error) { 428 builder := s.getQueryBuilder(). 429 Select("1"). 430 Prefix("SELECT EXISTS ("). 431 From("SharedChannelRemotes"). 432 Where(sq.Eq{"RemoteId": remoteId}). 433 Where(sq.Eq{"ChannelId": channelID}). 434 Suffix(")") 435 436 query, args, err := builder.ToSql() 437 if err != nil { 438 return false, errors.Wrapf(err, "get_shared_channel_hasremote_tosql") 439 } 440 441 var hasRemote bool 442 if err := s.GetReplica().SelectOne(&hasRemote, query, args...); err != nil { 443 return hasRemote, errors.Wrapf(err, "failed to get channel remotes for channel_id=%s", channelID) 444 } 445 return hasRemote, nil 446 } 447 448 // GetRemoteForUser returns a remote cluster for the given userId only if the user belongs to at least one channel 449 // shared with the remote. 450 func (s SqlSharedChannelStore) GetRemoteForUser(remoteId string, userId string) (*model.RemoteCluster, error) { 451 builder := s.getQueryBuilder(). 452 Select("rc.*"). 453 From("RemoteClusters AS rc"). 454 Join("SharedChannelRemotes AS scr ON rc.RemoteId = scr.RemoteId"). 455 Join("ChannelMembers AS cm ON scr.ChannelId = cm.ChannelId"). 456 Where(sq.Eq{"rc.RemoteId": remoteId}). 457 Where(sq.Eq{"cm.UserId": userId}) 458 459 query, args, err := builder.ToSql() 460 if err != nil { 461 return nil, errors.Wrapf(err, "get_remote_for_user_tosql") 462 } 463 464 var rc model.RemoteCluster 465 if err := s.GetReplica().SelectOne(&rc, query, args...); err != nil { 466 if err == sql.ErrNoRows { 467 return nil, store.NewErrNotFound("RemoteCluster", remoteId) 468 } 469 return nil, errors.Wrapf(err, "failed to get remote for user_id=%s", userId) 470 } 471 return &rc, nil 472 } 473 474 // UpdateRemoteCursor updates the LastPostUpdateAt timestamp and LastPostId for the specified SharedChannelRemote. 475 func (s SqlSharedChannelStore) UpdateRemoteCursor(id string, cursor model.GetPostsSinceForSyncCursor) error { 476 squery, args, err := s.getQueryBuilder(). 477 Update("SharedChannelRemotes"). 478 Set("LastPostUpdateAt", cursor.LastPostUpdateAt). 479 Set("LastPostId", cursor.LastPostId). 480 Where(sq.Eq{"Id": id}). 481 ToSql() 482 if err != nil { 483 return errors.Wrap(err, "update_shared_channel_remote_cursor_tosql") 484 } 485 486 result, err := s.GetMaster().Exec(squery, args...) 487 if err != nil { 488 return errors.Wrap(err, "failed to update cursor for SharedChannelRemote") 489 } 490 491 count, err := result.RowsAffected() 492 if err != nil { 493 return errors.Wrap(err, "failed to determine rows affected") 494 } 495 if count == 0 { 496 return fmt.Errorf("id not found: %s", id) 497 } 498 return nil 499 } 500 501 // DeleteRemote deletes a single shared channel remote. 502 // Returns true if remote found and deleted, false if not found. 503 func (s SqlSharedChannelStore) DeleteRemote(id string) (bool, error) { 504 squery, args, err := s.getQueryBuilder(). 505 Delete("SharedChannelRemotes"). 506 Where(sq.Eq{"Id": id}). 507 ToSql() 508 if err != nil { 509 return false, errors.Wrap(err, "delete_shared_channel_remote_tosql") 510 } 511 512 result, err := s.GetMaster().Exec(squery, args...) 513 if err != nil { 514 return false, errors.Wrap(err, "failed to delete SharedChannelRemote") 515 } 516 517 count, err := result.RowsAffected() 518 if err != nil { 519 return false, errors.Wrap(err, "failed to determine rows affected") 520 } 521 522 return count > 0, nil 523 } 524 525 // GetRemotesStatus returns the status for each remote invited to the 526 // specified shared channel. 527 func (s SqlSharedChannelStore) GetRemotesStatus(channelId string) ([]*model.SharedChannelRemoteStatus, error) { 528 var status []*model.SharedChannelRemoteStatus 529 530 query := s.getQueryBuilder(). 531 Select("scr.ChannelId, rc.DisplayName, rc.SiteURL, rc.LastPingAt, scr.NextSyncAt, sc.ReadOnly, scr.IsInviteAccepted"). 532 From("SharedChannelRemotes scr, RemoteClusters rc, SharedChannels sc"). 533 Where("scr.RemoteId = rc.RemoteId"). 534 Where("scr.ChannelId = sc.ChannelId"). 535 Where(sq.Eq{"scr.ChannelId": channelId}) 536 537 squery, args, err := query.ToSql() 538 if err != nil { 539 return nil, errors.Wrapf(err, "get_shared_channel_remotes_status_tosql") 540 } 541 542 if _, err := s.GetReplica().Select(&status, squery, args...); err != nil { 543 if err == sql.ErrNoRows { 544 return nil, store.NewErrNotFound("SharedChannelRemoteStatus", channelId) 545 } 546 return nil, errors.Wrapf(err, "failed to get shared channel remote status for channel_id=%s", channelId) 547 } 548 return status, nil 549 } 550 551 // SaveUser inserts a new shared channel user record to the SharedChannelUsers table. 552 func (s SqlSharedChannelStore) SaveUser(scUser *model.SharedChannelUser) (*model.SharedChannelUser, error) { 553 scUser.PreSave() 554 if err := scUser.IsValid(); err != nil { 555 return nil, err 556 } 557 558 if err := s.GetMaster().Insert(scUser); err != nil { 559 return nil, errors.Wrapf(err, "save_shared_channel_user: user_id=%s, remote_id=%s", scUser.UserId, scUser.RemoteId) 560 } 561 return scUser, nil 562 } 563 564 // GetSingleUser fetches a shared channel user based on userID, channelID and remoteID. 565 func (s SqlSharedChannelStore) GetSingleUser(userID string, channelID string, remoteID string) (*model.SharedChannelUser, error) { 566 var scu model.SharedChannelUser 567 568 squery, args, err := s.getQueryBuilder(). 569 Select("*"). 570 From("SharedChannelUsers"). 571 Where(sq.Eq{"SharedChannelUsers.UserId": userID}). 572 Where(sq.Eq{"SharedChannelUsers.RemoteId": remoteID}). 573 Where(sq.Eq{"SharedChannelUsers.ChannelId": channelID}). 574 ToSql() 575 576 if err != nil { 577 return nil, errors.Wrapf(err, "getsharedchannelsingleuser_tosql") 578 } 579 580 if err := s.GetReplica().SelectOne(&scu, squery, args...); err != nil { 581 if err == sql.ErrNoRows { 582 return nil, store.NewErrNotFound("SharedChannelUser", userID) 583 } 584 return nil, errors.Wrapf(err, "failed to find shared channel user with UserId=%s, ChannelId=%s, RemoteId=%s", userID, channelID, remoteID) 585 } 586 return &scu, nil 587 } 588 589 // GetUsersForUser fetches all shared channel user records based on userID. 590 func (s SqlSharedChannelStore) GetUsersForUser(userID string) ([]*model.SharedChannelUser, error) { 591 squery, args, err := s.getQueryBuilder(). 592 Select("*"). 593 From("SharedChannelUsers"). 594 Where(sq.Eq{"SharedChannelUsers.UserId": userID}). 595 ToSql() 596 597 if err != nil { 598 return nil, errors.Wrapf(err, "getsharedchanneluser_tosql") 599 } 600 601 var users []*model.SharedChannelUser 602 if _, err := s.GetReplica().Select(&users, squery, args...); err != nil { 603 if err == sql.ErrNoRows { 604 return make([]*model.SharedChannelUser, 0), nil 605 } 606 return nil, errors.Wrapf(err, "failed to find shared channel user with UserId=%s", userID) 607 } 608 return users, nil 609 } 610 611 // GetUsersForSync fetches all shared channel users that need to be synchronized, meaning their 612 // `SharedChannelUsers.LastSyncAt` is less than or equal to `User.UpdateAt`. 613 func (s SqlSharedChannelStore) GetUsersForSync(filter model.GetUsersForSyncFilter) ([]*model.User, error) { 614 if filter.Limit <= 0 { 615 filter.Limit = DefaultGetUsersForSyncLimit 616 } 617 618 query := s.getQueryBuilder(). 619 Select("u.*"). 620 Distinct(). 621 From("Users AS u"). 622 Join("SharedChannelUsers AS scu ON u.Id = scu.UserId"). 623 OrderBy("u.Id"). 624 Limit(filter.Limit) 625 626 if filter.CheckProfileImage { 627 query = query.Where("scu.LastSyncAt < u.LastPictureUpdate") 628 } else { 629 query = query.Where("scu.LastSyncAt < u.UpdateAt") 630 } 631 632 if filter.ChannelID != "" { 633 query = query.Where(sq.Eq{"scu.ChannelId": filter.ChannelID}) 634 } 635 636 sqlQuery, args, err := query.ToSql() 637 if err != nil { 638 return nil, errors.Wrapf(err, "getsharedchannelusersforsync_tosql") 639 } 640 641 var users []*model.User 642 if _, err := s.GetReplica().Select(&users, sqlQuery, args...); err != nil { 643 if err == sql.ErrNoRows { 644 return make([]*model.User, 0), nil 645 } 646 return nil, errors.Wrapf(err, "failed to fetch shared channel users with ChannelId=%s", 647 filter.ChannelID) 648 } 649 return users, nil 650 } 651 652 // UpdateUserLastSyncAt updates the LastSyncAt timestamp for the specified SharedChannelUser. 653 func (s SqlSharedChannelStore) UpdateUserLastSyncAt(userID string, channelID string, remoteID string) error { 654 args := map[string]interface{}{"UserId": userID, "ChannelId": channelID, "RemoteId": remoteID} 655 656 var query string 657 if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 658 query = ` 659 UPDATE 660 SharedChannelUsers AS scu 661 SET 662 LastSyncAt = GREATEST(Users.UpdateAt, Users.LastPictureUpdate) 663 FROM 664 Users 665 WHERE 666 Users.Id = scu.UserId AND scu.UserId = :UserId AND scu.ChannelId = :ChannelId AND scu.RemoteId = :RemoteId 667 ` 668 } else if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 669 query = ` 670 UPDATE 671 SharedChannelUsers AS scu 672 INNER JOIN 673 Users ON scu.UserId = Users.Id 674 SET 675 LastSyncAt = GREATEST(Users.UpdateAt, Users.LastPictureUpdate) 676 WHERE 677 scu.UserId = :UserId AND scu.ChannelId = :ChannelId AND scu.RemoteId = :RemoteId 678 ` 679 } else { 680 return errors.New("unsupported DB driver " + s.DriverName()) 681 } 682 683 result, err := s.GetMaster().Exec(query, args) 684 if err != nil { 685 return fmt.Errorf("failed to update LastSyncAt for SharedChannelUser with userId=%s, channelId=%s, remoteId=%s: %w", 686 userID, channelID, remoteID, err) 687 } 688 689 count, err := result.RowsAffected() 690 if err != nil { 691 return errors.Wrap(err, "failed to determine rows affected") 692 } 693 if count == 0 { 694 return fmt.Errorf("SharedChannelUser not found: userId=%s, channelId=%s, remoteId=%s", userID, channelID, remoteID) 695 } 696 return nil 697 } 698 699 // SaveAttachment inserts a new shared channel file attachment record to the SharedChannelFiles table. 700 func (s SqlSharedChannelStore) SaveAttachment(attachment *model.SharedChannelAttachment) (*model.SharedChannelAttachment, error) { 701 attachment.PreSave() 702 if err := attachment.IsValid(); err != nil { 703 return nil, err 704 } 705 706 if err := s.GetMaster().Insert(attachment); err != nil { 707 return nil, errors.Wrapf(err, "save_shared_channel_attachment: file_id=%s, remote_id=%s", attachment.FileId, attachment.RemoteId) 708 } 709 return attachment, nil 710 } 711 712 // UpsertAttachment inserts a new shared channel file attachment record to the SharedChannelFiles table or updates its 713 // LastSyncAt. 714 func (s SqlSharedChannelStore) UpsertAttachment(attachment *model.SharedChannelAttachment) (string, error) { 715 attachment.PreSave() 716 if err := attachment.IsValid(); err != nil { 717 return "", err 718 } 719 720 params := map[string]interface{}{ 721 "Id": attachment.Id, 722 "FileId": attachment.FileId, 723 "RemoteId": attachment.RemoteId, 724 "CreateAt": attachment.CreateAt, 725 "LastSyncAt": attachment.LastSyncAt, 726 } 727 728 if s.DriverName() == model.DATABASE_DRIVER_MYSQL { 729 if _, err := s.GetMaster().Exec( 730 `INSERT INTO 731 SharedChannelAttachments 732 (Id, FileId, RemoteId, CreateAt, LastSyncAt) 733 VALUES 734 (:Id, :FileId, :RemoteId, :CreateAt, :LastSyncAt) 735 ON DUPLICATE KEY UPDATE 736 LastSyncAt = :LastSyncAt`, params); err != nil { 737 return "", err 738 } 739 } else if s.DriverName() == model.DATABASE_DRIVER_POSTGRES { 740 if _, err := s.GetMaster().Exec( 741 `INSERT INTO 742 SharedChannelAttachments 743 (Id, FileId, RemoteId, CreateAt, LastSyncAt) 744 VALUES 745 (:Id, :FileId, :RemoteId, :CreateAt, :LastSyncAt) 746 ON CONFLICT (Id) 747 DO UPDATE SET LastSyncAt = :LastSyncAt`, params); err != nil { 748 return "", err 749 } 750 } 751 return attachment.Id, nil 752 } 753 754 // GetAttachment fetches a shared channel file attachment record based on file_id and remoteId. 755 func (s SqlSharedChannelStore) GetAttachment(fileId string, remoteId string) (*model.SharedChannelAttachment, error) { 756 var attachment model.SharedChannelAttachment 757 758 squery, args, err := s.getQueryBuilder(). 759 Select("*"). 760 From("SharedChannelAttachments"). 761 Where(sq.Eq{"SharedChannelAttachments.FileId": fileId}). 762 Where(sq.Eq{"SharedChannelAttachments.RemoteId": remoteId}). 763 ToSql() 764 765 if err != nil { 766 return nil, errors.Wrapf(err, "getsharedchannelattachment_tosql") 767 } 768 769 if err := s.GetReplica().SelectOne(&attachment, squery, args...); err != nil { 770 if err == sql.ErrNoRows { 771 return nil, store.NewErrNotFound("SharedChannelAttachment", fileId) 772 } 773 return nil, errors.Wrapf(err, "failed to find shared channel attachment with FileId=%s, RemoteId=%s", fileId, remoteId) 774 } 775 return &attachment, nil 776 } 777 778 // UpdateAttachmentLastSyncAt updates the LastSyncAt timestamp for the specified SharedChannelAttachment. 779 func (s SqlSharedChannelStore) UpdateAttachmentLastSyncAt(id string, syncTime int64) error { 780 squery, args, err := s.getQueryBuilder(). 781 Update("SharedChannelAttachments"). 782 Set("LastSyncAt", syncTime). 783 Where(sq.Eq{"Id": id}). 784 ToSql() 785 if err != nil { 786 return errors.Wrap(err, "update_shared_channel_attachment_last_sync_at_tosql") 787 } 788 789 result, err := s.GetMaster().Exec(squery, args...) 790 if err != nil { 791 return errors.Wrap(err, "failed to update LastSycnAt for SharedChannelAttachment") 792 } 793 794 count, err := result.RowsAffected() 795 if err != nil { 796 return errors.Wrap(err, "failed to determine rows affected") 797 } 798 if count == 0 { 799 return fmt.Errorf("id not found: %s", id) 800 } 801 return nil 802 }