feat_: delete or update permission when deleting a channel (#5297)
* feat_: delete or update channel permissions when deleting a channel * chore_: review fixes * chore_: review fixes (second iteration, squash it!)
This commit is contained in:
parent
24da58d7fa
commit
b0213e6a41
|
@ -74,6 +74,54 @@ func EmptyCommunityChanges() *CommunityChanges {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *CommunityChanges) Merge(other *CommunityChanges) {
|
||||
for memberID, member := range other.MembersAdded {
|
||||
c.MembersAdded[memberID] = member
|
||||
}
|
||||
for memberID := range other.MembersRemoved {
|
||||
c.MembersRemoved[memberID] = other.MembersRemoved[memberID]
|
||||
}
|
||||
for memberID, banned := range other.MembersBanned {
|
||||
c.MembersBanned[memberID] = banned
|
||||
}
|
||||
for memberID, unbanned := range other.MembersUnbanned {
|
||||
c.MembersUnbanned[memberID] = unbanned
|
||||
}
|
||||
for permissionID, permission := range other.TokenPermissionsAdded {
|
||||
c.TokenPermissionsAdded[permissionID] = permission
|
||||
}
|
||||
for permissionID, permission := range other.TokenPermissionsModified {
|
||||
c.TokenPermissionsModified[permissionID] = permission
|
||||
}
|
||||
for permissionID, permission := range other.TokenPermissionsRemoved {
|
||||
c.TokenPermissionsRemoved[permissionID] = permission
|
||||
}
|
||||
for chatID, chat := range other.ChatsRemoved {
|
||||
c.ChatsRemoved[chatID] = chat
|
||||
}
|
||||
for chatID, chat := range other.ChatsAdded {
|
||||
c.ChatsAdded[chatID] = chat
|
||||
}
|
||||
for chatID, changes := range other.ChatsModified {
|
||||
c.ChatsModified[chatID] = changes
|
||||
}
|
||||
|
||||
c.CategoriesRemoved = append(c.CategoriesRemoved, other.CategoriesRemoved...)
|
||||
|
||||
for categoryID, category := range other.CategoriesAdded {
|
||||
c.CategoriesAdded[categoryID] = category
|
||||
}
|
||||
for categoryID, category := range other.CategoriesModified {
|
||||
c.CategoriesModified[categoryID] = category
|
||||
}
|
||||
|
||||
c.MemberWalletsRemoved = append(c.MemberWalletsRemoved, other.MemberWalletsRemoved...)
|
||||
|
||||
for walletID, wallets := range other.MemberWalletsAdded {
|
||||
c.MemberWalletsAdded[walletID] = wallets
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CommunityChanges) HasNewMember(identity string) bool {
|
||||
if len(c.MembersAdded) == 0 {
|
||||
return false
|
||||
|
|
|
@ -2,6 +2,7 @@ package communities
|
|||
|
||||
import (
|
||||
"reflect"
|
||||
"slices"
|
||||
|
||||
"github.com/status-im/status-go/protocol/protobuf"
|
||||
)
|
||||
|
@ -46,6 +47,18 @@ func (p *CommunityTokenPermission) Equals(other *CommunityTokenPermission) bool
|
|||
return reflect.DeepEqual(p.ChatIds, other.ChatIds)
|
||||
}
|
||||
|
||||
func (p *CommunityTokenPermission) HasChat(chatId string) bool {
|
||||
return slices.Contains(p.ChatIds, chatId)
|
||||
}
|
||||
|
||||
func (p *CommunityTokenPermission) ChatIdsAsMap() map[string]struct{} {
|
||||
chats := map[string]struct{}{}
|
||||
for _, id := range p.GetChatIds() {
|
||||
chats[id] = struct{}{}
|
||||
}
|
||||
return chats
|
||||
}
|
||||
|
||||
func compareTokenCriteria(a, b *protobuf.TokenCriteria) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
|
|
|
@ -1768,14 +1768,50 @@ func (m *Manager) DeleteChat(communityID types.HexBytes, chatID string) (*Commun
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Check for channel permissions
|
||||
changes := community.emptyCommunityChanges()
|
||||
for tokenPermissionID, tokenPermission := range community.tokenPermissions() {
|
||||
chats := tokenPermission.ChatIdsAsMap()
|
||||
_, hasChat := chats[chatID]
|
||||
if !hasChat {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(chats) == 1 {
|
||||
// Delete channel permission, if there is only one channel
|
||||
deletePermissionChanges, err := community.DeleteTokenPermission(tokenPermissionID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
changes.Merge(deletePermissionChanges)
|
||||
} else {
|
||||
// Remove the channel from the permission, if there are other channels
|
||||
delete(chats, chatID)
|
||||
|
||||
var chatIDs []string
|
||||
for chatID := range chats {
|
||||
chatIDs = append(chatIDs, chatID)
|
||||
}
|
||||
tokenPermission.ChatIds = chatIDs
|
||||
|
||||
updatePermissionChanges, err := community.UpsertTokenPermission(tokenPermission.CommunityTokenPermission)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
changes.Merge(updatePermissionChanges)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove communityID prefix from chatID if exists
|
||||
if strings.HasPrefix(chatID, communityID.String()) {
|
||||
chatID = strings.TrimPrefix(chatID, communityID.String())
|
||||
}
|
||||
changes, err := community.DeleteChat(chatID)
|
||||
|
||||
deleteChanges, err := community.DeleteChat(chatID)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
changes.Merge(deleteChanges)
|
||||
|
||||
err = m.saveAndPublish(community)
|
||||
if err != nil {
|
||||
|
|
|
@ -2368,3 +2368,73 @@ func (s *MessengerCommunitiesTokenPermissionsSuite) TestImportDecryptedArchiveMe
|
|||
s.Require().True(ok)
|
||||
s.Require().Equal(messageText1, receivedMessage1.Text)
|
||||
}
|
||||
|
||||
func (s *MessengerCommunitiesTokenPermissionsSuite) TestDeleteChannelWithTokenPermission() {
|
||||
// Setup community with two permitted channels
|
||||
community, firstChat := s.createCommunity()
|
||||
|
||||
response, err := s.owner.CreateCommunityChat(community.ID(), &protobuf.CommunityChat{
|
||||
Permissions: &protobuf.CommunityPermissions{
|
||||
Access: protobuf.CommunityPermissions_AUTO_ACCEPT,
|
||||
},
|
||||
Identity: &protobuf.ChatIdentity{
|
||||
DisplayName: "new channel",
|
||||
Emoji: "",
|
||||
Description: "chat created after joining the community",
|
||||
},
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.Chats(), 1)
|
||||
secondChat := response.Chats()[0]
|
||||
|
||||
channelPermission := &requests.CreateCommunityTokenPermission{
|
||||
CommunityID: community.ID(),
|
||||
Type: protobuf.CommunityTokenPermission_CAN_VIEW_AND_POST_CHANNEL,
|
||||
ChatIds: []string{firstChat.ID, secondChat.ID},
|
||||
TokenCriteria: []*protobuf.TokenCriteria{
|
||||
{
|
||||
Type: protobuf.CommunityTokenType_ERC20,
|
||||
ContractAddresses: map[uint64]string{testChainID1: "0x124"},
|
||||
Symbol: "TEST2",
|
||||
AmountInWei: "200000000000000000000",
|
||||
Decimals: uint64(18),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
response, err = s.owner.CreateCommunityTokenPermission(channelPermission)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(response)
|
||||
s.Require().Len(response.Communities(), 1)
|
||||
|
||||
// Make sure both channels are covered with permission
|
||||
community, err = s.owner.GetCommunityByID(community.ID())
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(community.Chats(), 2)
|
||||
s.Require().Len(community.TokenPermissions(), 1)
|
||||
for _, permission := range community.TokenPermissions() {
|
||||
s.Require().Len(permission.ChatIds, 2)
|
||||
s.Require().True(permission.HasChat(firstChat.ID))
|
||||
s.Require().True(permission.HasChat(secondChat.ID))
|
||||
}
|
||||
|
||||
// Delete first community channel
|
||||
response, err = s.owner.DeleteCommunityChat(community.ID(), firstChat.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.Communities(), 1)
|
||||
community = response.Communities()[0]
|
||||
s.Require().Len(community.Chats(), 1)
|
||||
for _, permission := range community.TokenPermissions() {
|
||||
s.Require().Len(permission.ChatIds, 1)
|
||||
s.Require().False(permission.HasChat(firstChat.ID))
|
||||
s.Require().True(permission.HasChat(secondChat.ID))
|
||||
}
|
||||
|
||||
// Delete second community channel
|
||||
response, err = s.owner.DeleteCommunityChat(community.ID(), secondChat.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.Communities(), 1)
|
||||
community = response.Communities()[0]
|
||||
s.Require().Len(community.Chats(), 0)
|
||||
s.Require().Len(community.TokenPermissions(), 0)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue