From 621b31a2798dc1fbf0d48a431ea3e377445c4e28 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Mon, 15 Jul 2024 13:53:20 -0400 Subject: [PATCH] fix(community)_: fix pure readonly channels not respecting the right roles (#5513) Fixes https://github.com/status-im/status-desktop/issues/15547 --- protocol/communities/community.go | 14 +++- ...nities_messenger_token_permissions_test.go | 71 +++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/protocol/communities/community.go b/protocol/communities/community.go index 9e7dabc62..d30e73c6b 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -1666,7 +1666,7 @@ func dehydrateChannelsMembers(description *protobuf.CommunityDescription) { // To save space, we don't attach members for channels without permissions, // otherwise the message will hit waku msg size limit. for channelID, channel := range description.Chats { - if !channelEncrypted(ChatID(description.ID, channelID), description.TokenPermissions) { + if !channelHasPermissions(ChatID(description.ID, channelID), description.TokenPermissions) { channel.Members = map[string]*protobuf.CommunityMember{} // clean members } } @@ -1674,7 +1674,7 @@ func dehydrateChannelsMembers(description *protobuf.CommunityDescription) { func hydrateChannelsMembers(description *protobuf.CommunityDescription) { for channelID, channel := range description.Chats { - if !channelEncrypted(ChatID(description.ID, channelID), description.TokenPermissions) { + if !channelHasPermissions(ChatID(description.ID, channelID), description.TokenPermissions) { channel.Members = make(map[string]*protobuf.CommunityMember) for pubKey, member := range description.Members { channel.Members[pubKey] = member @@ -1874,6 +1874,16 @@ func (o *Community) HasTokenPermissions() bool { return len(o.tokenPermissions()) > 0 } +func channelHasPermissions(chatID string, permissions map[string]*protobuf.CommunityTokenPermission) bool { + for _, p := range permissions { + if includes(p.ChatIds, chatID) { + return true + } + } + + return false +} + func channelEncrypted(chatID string, permissions map[string]*protobuf.CommunityTokenPermission) bool { hasPermission := false viewableByEveryone := false diff --git a/protocol/communities_messenger_token_permissions_test.go b/protocol/communities_messenger_token_permissions_test.go index 0e7be16b2..c3dbf85c9 100644 --- a/protocol/communities_messenger_token_permissions_test.go +++ b/protocol/communities_messenger_token_permissions_test.go @@ -1037,6 +1037,77 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestViewChannelPermissions() } } +func (s *MessengerCommunitiesTokenPermissionsSuite) TestAnnouncementsChannelPermissions() { + community, chat := s.createCommunity() + + // bob joins the community + s.advertiseCommunityTo(community, s.bob) + s.joinCommunity(community, s.bob, bobPassword, []string{}) + + // setup view channel permission + channelPermissionRequest := requests.CreateCommunityTokenPermission{ + CommunityID: community.ID(), + Type: protobuf.CommunityTokenPermission_CAN_VIEW_CHANNEL, + ChatIds: []string{chat.ID}, + } + + response, err := s.owner.CreateCommunityTokenPermission(&channelPermissionRequest) + s.Require().NoError(err) + s.Require().Len(response.Communities(), 1) + s.Require().False(s.owner.communitiesManager.IsChannelEncrypted(community.IDString(), chat.ID)) + + // bob should be in the bloom filter list since everyone has access to readonly channels + community, err = s.bob.communitiesManager.GetByID(community.ID()) + s.Require().NoError(err) + s.Require().True(community.IsMemberLikelyInChat(chat.CommunityChatID())) + + // force owner to reevaluate channel members + // in production it will happen automatically, by periodic check + err = s.owner.communitiesManager.ForceMembersReevaluation(community.ID()) + s.Require().NoError(err) + + // bob receives community changes + _, err = WaitOnMessengerResponse( + s.bob, + func(r *MessengerResponse) bool { + c, err := s.bob.GetCommunityByID(community.ID()) + if err != nil { + return false + } + if c == nil { + return false + } + channel := c.Chats()[chat.CommunityChatID()] + + if channel == nil || len(channel.Members) != 2 { + return false + } + member := channel.Members[s.bob.IdentityPublicKeyString()] + return member != nil && member.ChannelRole == protobuf.CommunityMember_CHANNEL_ROLE_VIEWER + }, + "no community that satisfies criteria", + ) + s.Require().NoError(err) + + // bob should be in the bloom filter list + community, err = s.bob.communitiesManager.GetByID(community.ID()) + s.Require().NoError(err) + s.Require().True(community.IsMemberLikelyInChat(chat.CommunityChatID())) + + // bob can't post + msg := &common.Message{ + ChatMessage: &protobuf.ChatMessage{ + ChatId: chat.ID, + ContentType: protobuf.ChatMessage_TEXT_PLAIN, + Text: "I can't post on read-only channel", + }, + } + + _, err = s.bob.SendChatMessage(context.Background(), msg) + s.Require().Error(err) + s.Require().Contains(err.Error(), "can't post") +} + func (s *MessengerCommunitiesTokenPermissionsSuite) TestSearchMessageinPermissionedChannel() { community, chat := s.createCommunity()