Skip to content

Commit

Permalink
fix_: persist left communities even for restored account (#5174)
Browse files Browse the repository at this point in the history
This PR fixes #7858 by making sure left persisted communities are
restored during the backup restore flow
  • Loading branch information
kounkou authored May 21, 2024
1 parent 0937850 commit 133ad09
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 3 deletions.
4 changes: 4 additions & 0 deletions protocol/communities/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,10 @@ func (m *Manager) JoinedAndPendingCommunitiesWithRequests() ([]*Community, error
return m.persistence.JoinedAndPendingCommunitiesWithRequests(&m.identity.PublicKey)
}

func (m *Manager) LeftCommunities() ([]*Community, error) {
return m.persistence.LeftCommunities(&m.identity.PublicKey)
}

func (m *Manager) DeletedCommunities() ([]*Community, error) {
return m.persistence.DeletedCommunities(&m.identity.PublicKey)
}
Expand Down
11 changes: 11 additions & 0 deletions protocol/communities/persistence.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,17 @@ func (p *Persistence) rowsToCommunities(rows *sql.Rows) (comms []*Community, err
return comms, nil
}

func (p *Persistence) LeftCommunities(memberIdentity *ecdsa.PublicKey) (comms []*Community, err error) {
query := communitiesBaseQuery + ` WHERE NOT c.Joined AND NOT c.spectated AND r.state != ?`

rows, err := p.db.Query(query, common.PubkeyToHex(memberIdentity), RequestToJoinStatePending)
if err != nil {
return nil, err
}

return p.rowsToCommunities(rows)
}

func (p *Persistence) JoinedAndPendingCommunitiesWithRequests(memberIdentity *ecdsa.PublicKey) (comms []*Community, err error) {
query := communitiesBaseQuery + ` WHERE c.Joined OR r.state = ?`

Expand Down
31 changes: 28 additions & 3 deletions protocol/messenger_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ var backupTickerInterval = 120 * time.Second
// backups
var backupIntervalSeconds uint64 = 28800

type CommunitySet struct {
Joined []*communities.Community
Left []*communities.Community
Deleted []*communities.Community
}

func (m *Messenger) backupEnabled() (bool, error) {
return m.settings.BackupEnabled()
}
Expand Down Expand Up @@ -286,20 +292,39 @@ func (m *Messenger) backupContacts(ctx context.Context) []*protobuf.Backup {
return backupMessages
}

func (m *Messenger) backupCommunities(ctx context.Context, clock uint64) ([]*protobuf.Backup, error) {
func (m *Messenger) retrieveAllCommunities() (*CommunitySet, error) {
joinedCs, err := m.communitiesManager.JoinedAndPendingCommunitiesWithRequests()
if err != nil {
return nil, err
}

leftCs, err := m.communitiesManager.LeftCommunities()
if err != nil {
return nil, err
}

deletedCs, err := m.communitiesManager.DeletedCommunities()
if err != nil {
return nil, err
}

return &CommunitySet{
Joined: joinedCs,
Left: leftCs,
Deleted: deletedCs,
}, nil
}

func (m *Messenger) backupCommunities(ctx context.Context, clock uint64) ([]*protobuf.Backup, error) {
communitySet, err := m.retrieveAllCommunities()
if err != nil {
return nil, err
}

var backupMessages []*protobuf.Backup
cs := append(joinedCs, deletedCs...)
for _, c := range cs {
combinedCs := append(append(communitySet.Joined, communitySet.Left...), communitySet.Deleted...)

for _, c := range combinedCs {
_, beingImported := m.importingCommunities[c.IDString()]
if !beingImported {
backupMessage, err := m.backupCommunity(c, clock)
Expand Down
55 changes: 55 additions & 0 deletions protocol/messenger_backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -917,3 +917,58 @@ func (s *MessengerBackupSuite) TestBackupChats() {
s.Require().True(ok)
s.Require().Equal("", chat.Name)
}

func (s *MessengerBackupSuite) TestLeftCommunitiesAreBackedUp() {
bob1 := s.m
// Create bob2
bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil)
s.Require().NoError(err)
defer TearDownMessenger(&s.Suite, bob2)

description := &requests.CreateCommunity{
Membership: protobuf.CommunityPermissions_MANUAL_ACCEPT,
Name: "other-status",
Color: "#fffff4",
Description: "other status community description",
}

// Create another community chat
response, err := bob1.CreateCommunity(description, true)
s.Require().NoError(err)
s.Require().NotNil(response)
s.Require().Len(response.Communities(), 1)

newCommunity := response.Communities()[0]

response, err = bob1.LeaveCommunity(newCommunity.ID())
s.Require().NoError(err)
s.Require().NotNil(response)

// trigger artificial Backup
_, err = bob1.BackupData(context.Background())
s.Require().NoError(err)

communities, err := bob1.Communities()
s.Require().NoError(err)
s.Require().Len(communities, 1)

// Safety check
communities, err = bob2.Communities()
s.Require().NoError(err)
s.Require().Len(communities, 0)

// Wait for the message to reach its destination
_, err = WaitOnMessengerResponse(
bob2,
func(r *MessengerResponse) bool {
return r.BackupHandled
},
"no messages",
)

s.Require().NoError(err)

communities, err = bob2.JoinedCommunities()
s.Require().NoError(err)
s.Require().Len(communities, 0)
}

0 comments on commit 133ad09

Please sign in to comment.