Skip to content

Commit

Permalink
fix_: mitigate permission stuck in pending state
Browse files Browse the repository at this point in the history
This PR mitigates permission stuck in pending state upon making device a
control node. It fixes
[#14023](status-im/status-desktop#14023)
  • Loading branch information
kounkou committed Apr 19, 2024
1 parent 9e5462e commit cd10710
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
40 changes: 40 additions & 0 deletions protocol/communities/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5147,6 +5147,17 @@ func (m *Manager) PromoteSelfToControlNode(community *Community, clock uint64) (
return community.emptyCommunityChanges(), m.saveAndPublish(community)
}

func (m *Manager) applyCommunityEvents(community *Community) map[string]uint64 {
appliedEvents := map[string]uint64{}
if community.config.EventsData != nil {
for _, event := range community.config.EventsData.Events {
appliedEvents[event.EventTypeID()] = event.CommunityEventClock
}
}

return appliedEvents
}

func (m *Manager) promoteSelfToControlNode(community *Community, clock uint64) (bool, error) {
ownerChanged := false
community.setPrivateKey(m.identity)
Expand Down Expand Up @@ -5188,6 +5199,35 @@ func (m *Manager) promoteSelfToControlNode(community *Community, clock uint64) (
return false, err
}

if community.config.EventsData != nil {
appliedEvents := m.applyCommunityEvents(community)

var message = &CommunityEventsMessage{
CommunityID: community.ID(),
EventsBaseCommunityDescription: community.toCommunityEventsMessage().EventsBaseCommunityDescription,
Events: community.config.EventsData.Events,
}

err = community.processEvents(message, appliedEvents)
if err != nil {
return false, err
}

community.config.EventsData = nil // clear events, they are already applied

err = m.persistence.SaveCommunity(community)
if err != nil {
return false, err
}

err = m.persistence.UpsertAppliedCommunityEvents(community.ID(), appliedEvents)
if err != nil {
return false, err
}

m.publish(&Subscription{Community: community})
}

community.increaseClock()

return ownerChanged, nil
Expand Down
30 changes: 30 additions & 0 deletions protocol/communities_events_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2523,3 +2523,33 @@ func testBanMemberWithDeletingAllMessages(base CommunityEventsTestsInterface, co

banMember(base, banRequest)
}

func testPendingCommunityEventsAppliedUponMakingDeviceControlNode(base CommunityEventsTestsInterface, community *communities.Community, pType protobuf.CommunityTokenPermission_Type) {
request := createTestPermissionRequest(community, pType)

sender := base.GetEventSender()
response, err := sender.CreateCommunityTokenPermission(request)
s := base.GetSuite()
s.Require().NoError(err)
s.Require().Len(response.CommunityChanges, 1)
s.Require().Len(response.CommunityChanges[0].TokenPermissionsAdded, 1)

addedPermission := func() *communities.CommunityTokenPermission {
for _, permission := range response.CommunityChanges[0].TokenPermissionsAdded {
return permission
}
return nil
}()
s.Require().NotNil(addedPermission)
// Permission added by event must be in pending state
s.Require().Equal(communities.TokenPermissionAdditionPending, addedPermission.State)

controlNode := base.GetControlNode()
s.Require().NotNil(controlNode)

response, err = sender.PromoteSelfToControlNode(community.ID())
s.Require().NoError(err)
s.Require().NotNil(addedPermission)
// Permission added by event must be in approved state
s.Require().Equal(communities.TokenPermissionApproved, addedPermission.State)
}
6 changes: 6 additions & 0 deletions protocol/communities_messenger_admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,9 @@ func (s *AdminCommunityEventsSuite) TestAdminBanMemberWithDeletingAllMessages()
community := setUpCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN)
testBanMemberWithDeletingAllMessages(s, community)
}

func (s *AdminCommunityEventsSuite) TestPermissionAppliedUponMakingDeviceControlNode() {
additionalAdmin := s.newMessenger("qwerty", []string{eventsSenderAccountAddress})
community := setUpOnRequestCommunityAndRoles(s, protobuf.CommunityMember_ROLE_ADMIN, []*Messenger{additionalAdmin})
testPendingCommunityEventsAppliedUponMakingDeviceControlNode(s, community, protobuf.CommunityTokenPermission_BECOME_MEMBER)
}

0 comments on commit cd10710

Please sign in to comment.