From 72d2a97449fa5f795dce383b5dd440c92899df54 Mon Sep 17 00:00:00 2001 From: Michal Iskierko Date: Thu, 23 Jun 2022 09:12:15 +0200 Subject: [PATCH] feat: unban user in community Issue #2724 --- protocol/communities/community.go | 26 ++++++++++++++++ protocol/communities/manager.go | 30 +++++++++++++++++++ protocol/communities_messenger_test.go | 12 ++++++++ protocol/messenger_communities.go | 11 +++++++ .../requests/unban_user_from_community.go | 27 +++++++++++++++++ services/chat/api.go | 2 ++ services/ext/api.go | 5 ++++ 7 files changed, 113 insertions(+) create mode 100644 protocol/requests/unban_user_from_community.go diff --git a/protocol/communities/community.go b/protocol/communities/community.go index e33c304e0..116dd8f58 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -110,6 +110,7 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) { Link string `json:"link"` CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"` Encrypted bool `json:"encrypted"` + BanList []string `json:"banList"` }{ ID: o.ID(), Verified: o.config.Verified, @@ -150,6 +151,7 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) { communityItem.Link = fmt.Sprintf("https://join.status.im/c/0x%x", o.ID()) communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage + communityItem.BanList = o.config.CommunityDescription.BanList if o.config.CommunityDescription.Identity != nil { communityItem.Name = o.Name() @@ -204,6 +206,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { Muted bool `json:"muted"` CommunityAdminSettings CommunityAdminSettings `json:"adminSettings"` Encrypted bool `json:"encrypted"` + BanList []string `json:"banList"` }{ ID: o.ID(), Admin: o.IsAdmin(), @@ -252,6 +255,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { communityItem.Permissions = o.config.CommunityDescription.Permissions communityItem.IntroMessage = o.config.CommunityDescription.IntroMessage communityItem.OutroMessage = o.config.CommunityDescription.OutroMessage + communityItem.BanList = o.config.CommunityDescription.BanList if o.config.CommunityDescription.Identity != nil { communityItem.Name = o.Name() @@ -728,6 +732,28 @@ func (o *Community) RemoveUserFromOrg(pk *ecdsa.PublicKey) (*protobuf.CommunityD return o.config.CommunityDescription, nil } +func (o *Community) UnbanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.CommunityDescription, error) { + o.mutex.Lock() + defer o.mutex.Unlock() + + if o.config.PrivateKey == nil { + return nil, ErrNotAdmin + } + key := common.PubkeyToHex(pk) + + for i, v := range o.config.CommunityDescription.BanList { + if v == key { + o.config.CommunityDescription.BanList = + append(o.config.CommunityDescription.BanList[:i], o.config.CommunityDescription.BanList[i+1:]...) + break + } + } + + o.increaseClock() + + return o.config.CommunityDescription, nil +} + func (o *Community) BanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.CommunityDescription, error) { o.mutex.Lock() defer o.mutex.Unlock() diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 2e27cccc4..adde2789f 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -996,6 +996,36 @@ func (m *Manager) RemoveUserFromCommunity(id types.HexBytes, pk *ecdsa.PublicKey return community, nil } +func (m *Manager) UnbanUserFromCommunity(request *requests.UnbanUserFromCommunity) (*Community, error) { + id := request.CommunityID + publicKey, err := common.HexToPubkey(request.User.String()) + if err != nil { + return nil, err + } + + community, err := m.GetByID(id) + if err != nil { + return nil, err + } + if community == nil { + return nil, ErrOrgNotFound + } + + _, err = community.UnbanUserFromCommunity(publicKey) + if err != nil { + return nil, err + } + + err = m.persistence.SaveCommunity(community) + if err != nil { + return nil, err + } + + m.publish(&Subscription{Community: community}) + + return community, nil +} + func (m *Manager) BanUserFromCommunity(request *requests.BanUserFromCommunity) (*Community, error) { id := request.CommunityID diff --git a/protocol/communities_messenger_test.go b/protocol/communities_messenger_test.go index 4fc771ed9..f262fbe16 100644 --- a/protocol/communities_messenger_test.go +++ b/protocol/communities_messenger_test.go @@ -1143,6 +1143,18 @@ func (s *MessengerCommunitiesSuite) TestBanUser() { s.Require().False(community.HasMember(&s.alice.identity.PublicKey)) s.Require().True(community.IsBanned(&s.alice.identity.PublicKey)) + response, err = s.bob.UnbanUserFromCommunity( + &requests.UnbanUserFromCommunity{ + CommunityID: community.ID(), + User: common.PubkeyToHexBytes(&s.alice.identity.PublicKey), + }, + ) + s.Require().NoError(err) + s.Require().NotNil(response) + s.Require().Len(response.Communities(), 1) + + community = response.Communities()[0] + s.Require().False(community.IsBanned(&s.alice.identity.PublicKey)) } func (s *MessengerCommunitiesSuite) TestSyncCommunitySettings() { diff --git a/protocol/messenger_communities.go b/protocol/messenger_communities.go index 28b854c7e..8ab50c56a 100644 --- a/protocol/messenger_communities.go +++ b/protocol/messenger_communities.go @@ -979,6 +979,17 @@ func (m *Messenger) SendKeyExchangeMessage(communityID []byte, pubkeys []*ecdsa. return nil } +func (m *Messenger) UnbanUserFromCommunity(request *requests.UnbanUserFromCommunity) (*MessengerResponse, error) { + community, err := m.communitiesManager.UnbanUserFromCommunity(request) + if err != nil { + return nil, err + } + + response := &MessengerResponse{} + response.AddCommunity(community) + return response, nil +} + func (m *Messenger) BanUserFromCommunity(request *requests.BanUserFromCommunity) (*MessengerResponse, error) { community, err := m.communitiesManager.BanUserFromCommunity(request) if err != nil { diff --git a/protocol/requests/unban_user_from_community.go b/protocol/requests/unban_user_from_community.go new file mode 100644 index 000000000..e9a7b3e2b --- /dev/null +++ b/protocol/requests/unban_user_from_community.go @@ -0,0 +1,27 @@ +package requests + +import ( + "errors" + + "github.com/status-im/status-go/eth-node/types" +) + +var ErrUnbanUserFromCommunityInvalidCommunityID = errors.New("unban-user-from-community: invalid community id") +var ErrUnbanUserFromCommunityInvalidUser = errors.New("unban-user-from-community: invalid user id") + +type UnbanUserFromCommunity struct { + CommunityID types.HexBytes `json:"communityId"` + User types.HexBytes `json:"user"` +} + +func (b *UnbanUserFromCommunity) Validate() error { + if len(b.CommunityID) == 0 { + return ErrUnbanUserFromCommunityInvalidCommunityID + } + + if len(b.User) == 0 { + return ErrUnbanUserFromCommunityInvalidUser + } + + return nil +} diff --git a/services/chat/api.go b/services/chat/api.go index a1b2cf6f6..97fed3c25 100644 --- a/services/chat/api.go +++ b/services/chat/api.go @@ -94,6 +94,7 @@ type ChannelGroup struct { Members map[string]*protobuf.CommunityMember `json:"members"` CanManageUsers bool `json:"canManageUsers"` Muted bool `json:"muted"` + BanList []string `json:"banList"` } func NewAPI(service *Service) *API { @@ -166,6 +167,7 @@ func (api *API) GetChats(ctx context.Context) (map[string]ChannelGroup, error) { Members: community.Description().Members, CanManageUsers: community.CanManageUsers(community.MemberIdentity()), Muted: community.Muted(), + BanList: community.Description().BanList, } for t, i := range community.Images() { diff --git a/services/ext/api.go b/services/ext/api.go index 1bc263138..f79598b12 100644 --- a/services/ext/api.go +++ b/services/ext/api.go @@ -449,6 +449,11 @@ func (api *PublicAPI) BanUserFromCommunity(request *requests.BanUserFromCommunit return api.service.messenger.BanUserFromCommunity(request) } +// UnbanUserFromCommunity removes the user's pk from the community ban list +func (api *PublicAPI) UnbanUserFromCommunity(request *requests.UnbanUserFromCommunity) (*protocol.MessengerResponse, error) { + return api.service.messenger.UnbanUserFromCommunity(request) +} + // MyPendingRequestsToJoin returns the pending requests for the logged in user func (api *PublicAPI) MyPendingRequestsToJoin() ([]*communities.RequestToJoin, error) { return api.service.messenger.MyPendingRequestsToJoin()