From 058120fad95056627badd8854b6655d70258db4c Mon Sep 17 00:00:00 2001 From: Mykhailo Prakhov Date: Mon, 4 Dec 2023 19:20:09 +0100 Subject: [PATCH] chore: parse all non confirmed requests to join of the community during getting all communities (#4409) --- protocol/communities/community.go | 3 ++ protocol/communities/manager.go | 20 ++++++-- protocol/communities/manager_test.go | 61 ++++++++++++++++++++++++ protocol/communities/persistence.go | 25 ++++++++++ protocol/communities/persistence_test.go | 48 +++++++++++++++++++ protocol/messenger_communities.go | 10 +++- 6 files changed, 162 insertions(+), 5 deletions(-) diff --git a/protocol/communities/community.go b/protocol/communities/community.go index fc2cac24a..f748af536 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -265,6 +265,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { PubsubTopic string `json:"pubsubTopic"` PubsubTopicKey string `json:"pubsubTopicKey"` Shard *shard.Shard `json:"shard"` + RequestsToJoinCommunity []*RequestToJoin `json:"requestsToJoinCommunity"` }{ ID: o.ID(), MemberRole: o.MemberRole(o.MemberIdentity()), @@ -287,6 +288,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { PubsubTopic: o.PubsubTopic(), PubsubTopicKey: o.PubsubTopicKey(), Shard: o.Shard(), + RequestsToJoinCommunity: []*RequestToJoin{}, } if o.config.CommunityDescription != nil { for id, c := range o.config.CommunityDescription.Categories { @@ -325,6 +327,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage communityItem.CommunityTokensMetadata = o.config.CommunityDescription.CommunityTokensMetadata communityItem.ActiveMembersCount = o.config.CommunityDescription.ActiveMembersCount + communityItem.RequestsToJoinCommunity = o.config.RequestsToJoin if o.config.CommunityDescription.Identity != nil { communityItem.Name = o.Name() diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 9e2dd288c..c12a507ca 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -622,7 +622,21 @@ func (m *Manager) publish(subscription *Subscription) { } func (m *Manager) All() ([]*Community, error) { - return m.persistence.AllCommunities(&m.identity.PublicKey) + communities, err := m.persistence.AllCommunities(&m.identity.PublicKey) + if err != nil { + return nil, err + } + + nonApprovedRequestsToJoin, err := m.persistence.AllNonApprovedCommunitiesRequestsToJoin() + if err != nil { + return nil, err + } + + for _, community := range communities { + community.config.RequestsToJoin = nonApprovedRequestsToJoin[community.IDString()] + } + + return communities, nil } type CommunityShard struct { @@ -1475,7 +1489,7 @@ func (m *Manager) DeleteCategory(request *requests.DeleteCommunityCategory) (*Co return changes.Community, changes, nil } -func (m *Manager) GenerateRequestsToJoinForAutoApprovalOnNewOwnership(communityID types.HexBytes, kickedMembers map[string]*protobuf.CommunityMember) error { +func (m *Manager) GenerateRequestsToJoinForAutoApprovalOnNewOwnership(communityID types.HexBytes, kickedMembers map[string]*protobuf.CommunityMember) ([]*RequestToJoin, error) { var requestsToJoin []*RequestToJoin clock := uint64(time.Now().Unix()) for pubKeyStr := range kickedMembers { @@ -1493,7 +1507,7 @@ func (m *Manager) GenerateRequestsToJoinForAutoApprovalOnNewOwnership(communityI requestsToJoin = append(requestsToJoin, requestToJoin) } - return m.persistence.SaveRequestsToJoin(requestsToJoin) + return requestsToJoin, m.persistence.SaveRequestsToJoin(requestsToJoin) } func (m *Manager) Queue(signer *ecdsa.PublicKey, community *Community, clock uint64, payload []byte) error { diff --git a/protocol/communities/manager_test.go b/protocol/communities/manager_test.go index d67d2a468..a07fbe0f1 100644 --- a/protocol/communities/manager_test.go +++ b/protocol/communities/manager_test.go @@ -1894,3 +1894,64 @@ func (s *ManagerSuite) TestCommunityQueueMultipleDifferentSignersIgnoreIfNotRetu s.Require().NoError(err) s.Require().Equal(clock1, fetchedCommunity.config.CommunityDescription.Clock) } + +func (s *ManagerSuite) TestGetAllCommunities() { + // default community + communities, err := s.manager.All() + s.Require().NoError(err) + s.Require().Len(communities, 1) + + request := &requests.CreateCommunity{ + Name: "status", + Description: "token membership description", + Membership: protobuf.CommunityPermissions_AUTO_ACCEPT, + } + + community, err := s.manager.CreateCommunity(request, true) + s.Require().NoError(err) + s.Require().NotNil(community) + + communities, err = s.manager.All() + s.Require().NoError(err) + s.Require().Len(communities, 2) + + // add requests to join to the community + allStates := []RequestToJoinState{ + RequestToJoinStatePending, + RequestToJoinStateDeclined, + RequestToJoinStateAccepted, + RequestToJoinStateCanceled, + RequestToJoinStateAcceptedPending, + RequestToJoinStateDeclinedPending, + RequestToJoinStateAwaitingAddresses, + } + + clock := uint64(time.Now().Unix()) + + for i := range allStates { + identity, err := crypto.GenerateKey() + s.Require().NoError(err) + + rtj := &RequestToJoin{ + ID: types.HexBytes{1, 2, 3, 4, 5, 6, 7, byte(i)}, + PublicKey: common.PubkeyToHex(&identity.PublicKey), + Clock: clock, + CommunityID: community.ID(), + State: allStates[i], + } + err = s.manager.SaveRequestToJoin(rtj) + s.Require().NoError(err) + } + + communities, err = s.manager.All() + s.Require().NoError(err) + s.Require().Len(communities, 2) + + for _, resultCommunity := range communities { + if resultCommunity.IDString() == community.IDString() { + s.Require().Len(resultCommunity.RequestsToJoin(), 6) + } else { + s.Require().Len(resultCommunity.RequestsToJoin(), 0) + } + } +} diff --git a/protocol/communities/persistence.go b/protocol/communities/persistence.go index aebd30ffa..42ea4ad64 100644 --- a/protocol/communities/persistence.go +++ b/protocol/communities/persistence.go @@ -1646,3 +1646,28 @@ func (p *Persistence) SetCuratedCommunities(communities *CuratedCommunities) err return nil } + +func (p *Persistence) AllNonApprovedCommunitiesRequestsToJoin() (map[string][]*RequestToJoin, error) { + nonApprovedRequestsToJoin := make(map[string][]*RequestToJoin) + rows, err := p.db.Query(`SELECT id,public_key,clock,ens_name,chat_id,community_id,state FROM communities_requests_to_join WHERE state != ?`, RequestToJoinStateAccepted) + + if err == sql.ErrNoRows { + return nonApprovedRequestsToJoin, nil + } else if err != nil { + return nil, err + } + + defer rows.Close() + + for rows.Next() { + request := &RequestToJoin{} + err := rows.Scan(&request.ID, &request.PublicKey, &request.Clock, &request.ENSName, &request.ChatID, &request.CommunityID, &request.State) + if err != nil { + return nil, err + } + + communityID := types.EncodeHex(request.CommunityID) + nonApprovedRequestsToJoin[communityID] = append(nonApprovedRequestsToJoin[communityID], request) + } + return nonApprovedRequestsToJoin, nil +} diff --git a/protocol/communities/persistence_test.go b/protocol/communities/persistence_test.go index 7377be2a6..bde4cf8c8 100644 --- a/protocol/communities/persistence_test.go +++ b/protocol/communities/persistence_test.go @@ -711,3 +711,51 @@ func (s *PersistenceSuite) TestGetCommunityRequestToJoinWithRevealedAddresses() s.Require().Equal(expectedRtj.CommunityID, rtjResult.CommunityID) s.Require().Len(rtjResult.RevealedAccounts, 1) } + +func (s *PersistenceSuite) TestAllNonApprovedCommunitiesRequestsToJoin() { + // check on empty db + result, err := s.db.AllNonApprovedCommunitiesRequestsToJoin() + s.Require().NoError(err) + s.Require().Len(result, 0) + + identity, err := crypto.GenerateKey() + s.Require().NoError(err, "crypto.GenerateKey shouldn't give any error") + + clock := uint64(time.Now().Unix()) + + // add a new community + community := s.makeNewCommunity(identity) + err = s.db.SaveCommunity(community) + s.Require().NoError(err) + + // add requests to join to the community + allStates := []RequestToJoinState{ + RequestToJoinStatePending, + RequestToJoinStateDeclined, + RequestToJoinStateAccepted, + RequestToJoinStateCanceled, + RequestToJoinStateAcceptedPending, + RequestToJoinStateDeclinedPending, + RequestToJoinStateAwaitingAddresses, + } + + for i := range allStates { + identity, err := crypto.GenerateKey() + s.Require().NoError(err) + + rtj := &RequestToJoin{ + ID: types.HexBytes{1, 2, 3, 4, 5, 6, 7, byte(i)}, + PublicKey: common.PubkeyToHex(&identity.PublicKey), + Clock: clock, + CommunityID: community.ID(), + State: allStates[i], + } + err = s.db.SaveRequestToJoin(rtj) + s.Require().NoError(err, "SaveRequestToJoin shouldn't give any error") + } + + result, err = s.db.AllNonApprovedCommunitiesRequestsToJoin() + s.Require().NoError(err) + s.Require().Len(result, 1) + s.Require().Len(result[community.IDString()], 6) // all except RequestToJoinStateAccepted +} diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index 0128946ba..3fa873001 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -4201,11 +4201,14 @@ func (m *Messenger) PromoteSelfToControlNode(communityID types.HexBytes) (*Messe return nil, err } + var response MessengerResponse + if len(changes.MembersRemoved) > 0 { - err = m.communitiesManager.GenerateRequestsToJoinForAutoApprovalOnNewOwnership(changes.Community.ID(), changes.MembersRemoved) + requestsToJoin, err := m.communitiesManager.GenerateRequestsToJoinForAutoApprovalOnNewOwnership(changes.Community.ID(), changes.MembersRemoved) if err != nil { return nil, err } + response.AddRequestsToJoinCommunity(requestsToJoin) } err = m.syncCommunity(context.Background(), changes.Community, m.dispatchMessage) @@ -4213,10 +4216,13 @@ func (m *Messenger) PromoteSelfToControlNode(communityID types.HexBytes) (*Messe return nil, err } - var response MessengerResponse response.AddCommunity(changes.Community) response.CommunityChanges = []*communities.CommunityChanges{changes} + if m.config.messengerSignalsHandler != nil { + m.config.messengerSignalsHandler.MessengerResponse(&response) + } + return &response, nil }