From 894eb5758e8ff8f449312f92149f8698058d0fbb Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Tue, 19 Mar 2024 17:14:24 +0000 Subject: [PATCH] Add canView to chat & fix admin role --- protocol/communities/community.go | 54 ++++++++++++------- protocol/communities/community_test.go | 38 +++++++++++++ protocol/communities/manager.go | 2 +- ...nities_messenger_token_permissions_test.go | 19 +++++++ 4 files changed, 92 insertions(+), 21 deletions(-) diff --git a/protocol/communities/community.go b/protocol/communities/community.go index a62cd6413..5da5e0f54 100644 --- a/protocol/communities/community.go +++ b/protocol/communities/community.go @@ -104,6 +104,7 @@ type CommunityChat struct { Members map[string]*protobuf.CommunityMember `json:"members"` Permissions *protobuf.CommunityPermissions `json:"permissions"` CanPost bool `json:"canPost"` + CanView bool `json:"canView"` ViewersCanPostReactions bool `json:"viewersCanPostReactions"` Position int `json:"position"` CategoryID string `json:"categoryID"` @@ -187,6 +188,8 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) { if err != nil { return nil, err } + canView := o.CanView(o.config.MemberIdentity, id) + chat := CommunityChat{ ID: id, Name: c.Identity.DisplayName, @@ -196,6 +199,7 @@ func (o *Community) MarshalPublicAPIJSON() ([]byte, error) { Permissions: c.Permissions, Members: c.Members, CanPost: canPost, + CanView: canView, ViewersCanPostReactions: c.ViewersCanPostReactions, TokenGated: o.channelEncrypted(id), CategoryID: c.CategoryId, @@ -328,6 +332,8 @@ func (o *Community) MarshalJSON() ([]byte, error) { if err != nil { return nil, err } + canView := o.CanView(o.config.MemberIdentity, id) + chat := CommunityChat{ ID: id, Name: c.Identity.DisplayName, @@ -337,6 +343,7 @@ func (o *Community) MarshalJSON() ([]byte, error) { Permissions: c.Permissions, Members: c.Members, CanPost: canPost, + CanView: canView, ViewersCanPostReactions: c.ViewersCanPostReactions, TokenGated: o.channelEncrypted(id), CategoryID: c.CategoryId, @@ -1877,63 +1884,70 @@ func (o *Community) VerifyGrantSignature(data []byte) (*protobuf.Grant, error) { return grant, nil } -func (o *Community) CanPost(pk *ecdsa.PublicKey, chatID string, messageType protobuf.ApplicationMetadataMessage_Type) (bool, error) { +func (o *Community) CanView(pk *ecdsa.PublicKey, chatID string) bool { if o.config.CommunityDescription.Chats == nil { - o.config.Logger.Debug("Community.CanPost: no-chats") - return false, nil + o.config.Logger.Debug("Community.CanView: no-chats") + return false } chat, ok := o.config.CommunityDescription.Chats[chatID] if !ok { - o.config.Logger.Debug("Community.CanPost: no chat with id", zap.String("chat-id", chatID)) - return false, nil + o.config.Logger.Debug("Community.CanView: no chat with id", zap.String("chat-id", chatID)) + return false } // community creator can always post, return immediately if common.IsPubKeyEqual(pk, o.ControlNode()) { - return true, nil + return true } if o.isBanned(pk) { - o.config.Logger.Debug("Community.CanPost: user is banned", zap.String("chat-id", chatID)) - return false, nil + o.config.Logger.Debug("Community.CanView: user is banned", zap.String("chat-id", chatID)) + return false } if o.config.CommunityDescription.Members == nil { - o.config.Logger.Debug("Community.CanPost: no members in org", zap.String("chat-id", chatID)) - return false, nil + o.config.Logger.Debug("Community.CanView: no members in org", zap.String("chat-id", chatID)) + return false } // If community member, also check chat membership next _, ok = o.config.CommunityDescription.Members[common.PubkeyToHex(pk)] if !ok { - o.config.Logger.Debug("Community.CanPost: not a community member", zap.String("chat-id", chatID)) - return false, nil + o.config.Logger.Debug("Community.CanView: not a community member", zap.String("chat-id", chatID)) + return false } if chat.Members == nil { - o.config.Logger.Debug("Community.CanPost: no members in chat", zap.String("chat-id", chatID)) + o.config.Logger.Debug("Community.CanView: no members in chat", zap.String("chat-id", chatID)) + return false + } + + _, isChatMember := chat.Members[common.PubkeyToHex(pk)] + return isChatMember +} + +func (o *Community) CanPost(pk *ecdsa.PublicKey, chatID string, messageType protobuf.ApplicationMetadataMessage_Type) (bool, error) { + hasAccessToChat := o.CanView(pk, chatID) + if !hasAccessToChat { return false, nil } - member, isChatMember := chat.Members[common.PubkeyToHex(pk)] + chat := o.config.CommunityDescription.Chats[chatID] + member := chat.Members[common.PubkeyToHex(pk)] switch messageType { case protobuf.ApplicationMetadataMessage_PIN_MESSAGE: pinAllowed := o.IsPrivilegedMember(pk) || o.AllowsAllMembersToPinMessage() - return isChatMember && pinAllowed, nil + return pinAllowed, nil case protobuf.ApplicationMetadataMessage_EMOJI_REACTION: - if !isChatMember { - return false, nil - } - isPoster := member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_POSTER isViewer := member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_VIEWER return isPoster || (isViewer && chat.ViewersCanPostReactions), nil default: - return isChatMember, nil + return member.GetChannelRole() == protobuf.CommunityMember_CHANNEL_ROLE_POSTER, nil } } diff --git a/protocol/communities/community_test.go b/protocol/communities/community_test.go index 43616a235..dfde3fefa 100644 --- a/protocol/communities/community_test.go +++ b/protocol/communities/community_test.go @@ -451,6 +451,44 @@ func (s *CommunitySuite) TestValidateRequestToJoin() { } } +func (s *CommunitySuite) TestCanPostCanView() { + chatID := "chat-id" + memberKey := common.PubkeyToHex(&s.member1.PublicKey) + // Member has no channel role + description := &protobuf.CommunityDescription{ + Members: map[string]*protobuf.CommunityMember{ + memberKey: &protobuf.CommunityMember{}, + }, + Chats: map[string]*protobuf.CommunityChat{ + chatID: &protobuf.CommunityChat{ + Members: map[string]*protobuf.CommunityMember{ + memberKey: &protobuf.CommunityMember{}, + }, + }, + }, + } + + community := &Community{config: &Config{ID: &s.member2.PublicKey}} + community.config.CommunityDescription = description + + result, err := community.CanPost(&s.member1.PublicKey, chatID, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) + s.Require().NoError(err) + s.Require().True(result) + + result = community.CanView(&s.member1.PublicKey, chatID) + s.Require().True(result) + + // member has view channel permissions + description.Chats[chatID].Members[memberKey].ChannelRole = protobuf.CommunityMember_CHANNEL_ROLE_VIEWER + + result, err = community.CanPost(&s.member1.PublicKey, chatID, protobuf.ApplicationMetadataMessage_CHAT_MESSAGE) + s.Require().NoError(err) + s.Require().False(result) + + result = community.CanView(&s.member1.PublicKey, chatID) + s.Require().True(result) +} + func (s *CommunitySuite) TestCanPost() { notMember := &s.member3.PublicKey member := &s.member1.PublicKey diff --git a/protocol/communities/manager.go b/protocol/communities/manager.go index 2c08951cf..72f2c4a33 100644 --- a/protocol/communities/manager.go +++ b/protocol/communities/manager.go @@ -1006,7 +1006,7 @@ func (m *Manager) ReevaluateMembers(community *Community) (map[protobuf.Communit if isNewRoleAdmin { if !isCurrentRoleAdmin { newPrivilegedRoles[protobuf.CommunityMember_ROLE_ADMIN] = - append(newPrivilegedRoles[protobuf.CommunityMember_ROLE_TOKEN_MASTER], memberPubKey) + append(newPrivilegedRoles[protobuf.CommunityMember_ROLE_ADMIN], memberPubKey) } // Skip further validation if user has Admin permissions continue diff --git a/protocol/communities_messenger_token_permissions_test.go b/protocol/communities_messenger_token_permissions_test.go index b9618565b..206863b7d 100644 --- a/protocol/communities_messenger_token_permissions_test.go +++ b/protocol/communities_messenger_token_permissions_test.go @@ -1361,6 +1361,25 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestMemberRoleGetUpdatedWhen err = <-waitOnChannelKeyToBeDistributedToBob s.Require().NoError(err) + // wait until bob permissions are upgraded + _, err = WaitOnMessengerResponse( + s.bob, + func(r *MessengerResponse) bool { + community, err = s.bob.communitiesManager.GetByID(community.ID()) + s.Require().NoError(err) + chats := community.Chats() + if len(chats) == 0 { + return false + } + if chats[chat.ID] == nil { + return false + } + members = chats[chat.ID].Members + return len(members) == 2 && members[s.bob.myHexIdentity()] != nil && members[s.bob.myHexIdentity()].ChannelRole == protobuf.CommunityMember_CHANNEL_ROLE_POSTER + }, + "bob never got post permissions", + ) + msg = s.sendChatMessage(s.bob, chat.ID, "hello on closed channel from Bob") // owner can read the message