fix_: persist left communities even for restored account (#5174)

This PR fixes #7858 by making sure left persisted communities are
restored during the backup restore flow
This commit is contained in:
Godfrain Jacques 2024-05-21 14:01:14 -07:00 committed by GitHub
parent 0937850268
commit 133ad0946b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 98 additions and 3 deletions

View File

@ -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)
}

View File

@ -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 = ?`

View File

@ -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()
}
@ -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)

View File

@ -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)
}