feat: allow group admin to delete others message (#3259)

This commit is contained in:
yqrashawn 2023-03-07 22:38:09 +08:00 committed by GitHub
parent 3f3e8f8894
commit 475b5f855f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 7 deletions

View File

@ -1 +1 @@
0.137.1
0.137.2

View File

@ -14,6 +14,7 @@ import (
"github.com/status-im/status-go/eth-node/types"
userimage "github.com/status-im/status-go/images"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/tt"
"github.com/status-im/status-go/waku"
)
@ -356,3 +357,89 @@ func (s *MessengerGroupChatSuite) TestGroupChatEdit() {
defer s.NoError(admin.Shutdown())
defer s.NoError(member.Shutdown())
}
func (s *MessengerGroupChatSuite) TestGroupChatDeleteMemberMessage() {
admin := s.startNewMessenger()
member := s.startNewMessenger()
s.makeMutualContacts(admin, member)
groupChat := s.createGroupChat(admin, "test_group_chat", []string{common.PubkeyToHex(&member.identity.PublicKey)})
s.verifyGroupChatCreated(member, true)
ctx := context.Background()
inputMessage := buildTestMessage(*groupChat)
_, err := member.SendChatMessage(ctx, inputMessage)
s.Require().NoError(err)
response, err := WaitOnMessengerResponse(
admin,
func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
"messages not received",
)
s.Require().NoError(err)
s.Require().Len(response.Messages(), 1)
s.Require().Equal(inputMessage.Text, response.Messages()[0].Text)
message := response.Messages()[0]
deleteMessageResponse, err := admin.DeleteMessageAndSend(ctx, message.ID)
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(member, func(response *MessengerResponse) bool {
return len(response.RemovedMessages()) > 0
}, "removed messages not received")
s.Require().Equal(deleteMessageResponse.RemovedMessages()[0].DeletedBy, contactIDFromPublicKey(admin.IdentityPublicKey()))
s.Require().NoError(err)
message, err = member.MessageByID(message.ID)
s.Require().NoError(err)
s.Require().True(message.Deleted)
defer s.NoError(admin.Shutdown())
defer s.NoError(member.Shutdown())
}
func (s *MessengerGroupChatSuite) TestGroupChatHandleDeleteMemberMessage() {
admin := s.startNewMessenger()
member := s.startNewMessenger()
s.makeMutualContacts(admin, member)
groupChat := s.createGroupChat(admin, "test_group_chat", []string{common.PubkeyToHex(&member.identity.PublicKey)})
s.verifyGroupChatCreated(member, true)
ctx := context.Background()
inputMessage := buildTestMessage(*groupChat)
_, err := member.SendChatMessage(ctx, inputMessage)
s.Require().NoError(err)
response, err := WaitOnMessengerResponse(
admin,
func(r *MessengerResponse) bool { return len(r.Messages()) > 0 },
"messages not received",
)
s.Require().NoError(err)
s.Require().Len(response.Messages(), 1)
s.Require().Equal(inputMessage.Text, response.Messages()[0].Text)
deleteMessage := DeleteMessage{
DeleteMessage: protobuf.DeleteMessage{
Clock: 2,
MessageType: protobuf.MessageType_PRIVATE_GROUP,
MessageId: inputMessage.ID,
ChatId: groupChat.ID,
},
From: common.PubkeyToHex(&admin.identity.PublicKey),
}
state := &ReceivedMessageState{
Response: &MessengerResponse{},
}
err = member.HandleDeleteMessage(state, deleteMessage)
s.Require().NoError(err)
removedMessages := state.Response.RemovedMessages()
s.Require().Len(removedMessages, 1)
s.Require().Equal(removedMessages[0].MessageID, inputMessage.ID)
defer s.NoError(admin.Shutdown())
defer s.NoError(member.Shutdown())
}

View File

@ -1531,16 +1531,22 @@ func (m *Messenger) HandleDeleteMessage(state *ReceivedMessageState, deleteMessa
var canDeleteMessageForEveryone = false
if originalMessage.From != deleteMessage.From {
fromPublicKey, err := common.HexToPubkey(deleteMessage.From)
if err != nil {
return err
}
if chat.ChatType == ChatTypeCommunityChat {
fromPublicKey, err := common.HexToPubkey(deleteMessage.From)
if err != nil {
return err
canDeleteMessageForEveryone = m.CanDeleteMessageForEveryoneInCommunity(chat.CommunityID, fromPublicKey)
if !canDeleteMessageForEveryone {
return ErrInvalidDeletePermission
}
canDeleteMessageForEveryone = m.CanDeleteMessageForEveryone(chat.CommunityID, fromPublicKey)
} else if chat.ChatType == ChatTypePrivateGroupChat {
canDeleteMessageForEveryone = m.CanDeleteMessageForEveryoneInPrivateGroupChat(chat, fromPublicKey)
if !canDeleteMessageForEveryone {
return ErrInvalidDeletePermission
}
}
// Check edit is valid
if !canDeleteMessageForEveryone {
return errors.New("invalid delete, not the right author")

View File

@ -90,7 +90,7 @@ func (m *Messenger) EditMessage(ctx context.Context, request *requests.EditMessa
return response, nil
}
func (m *Messenger) CanDeleteMessageForEveryone(communityID string, publicKey *ecdsa.PublicKey) bool {
func (m *Messenger) CanDeleteMessageForEveryoneInCommunity(communityID string, publicKey *ecdsa.PublicKey) bool {
if communityID != "" {
community, err := m.communitiesManager.GetByIDString(communityID)
if err != nil {
@ -102,6 +102,16 @@ func (m *Messenger) CanDeleteMessageForEveryone(communityID string, publicKey *e
return false
}
func (m *Messenger) CanDeleteMessageForEveryoneInPrivateGroupChat(chat *Chat, publicKey *ecdsa.PublicKey) bool {
group, err := newProtocolGroupFromChat(chat)
if err != nil {
m.logger.Error("failed to find group", zap.String("chatID", chat.ID), zap.Error(err))
return false
}
admins := group.Admins()
return stringSliceContains(admins, common.PubkeyToHex(publicKey))
}
func (m *Messenger) DeleteMessageAndSend(ctx context.Context, messageID string) (*MessengerResponse, error) {
message, err := m.persistence.MessageByID(messageID)
if err != nil {
@ -119,7 +129,12 @@ func (m *Messenger) DeleteMessageAndSend(ctx context.Context, messageID string)
if message.From != common.PubkeyToHex(&m.identity.PublicKey) {
if message.MessageType == protobuf.MessageType_COMMUNITY_CHAT {
communityID := chat.CommunityID
canDeleteMessageForEveryone = m.CanDeleteMessageForEveryone(communityID, &m.identity.PublicKey)
canDeleteMessageForEveryone = m.CanDeleteMessageForEveryoneInCommunity(communityID, &m.identity.PublicKey)
if !canDeleteMessageForEveryone {
return nil, ErrInvalidDeletePermission
}
} else if message.MessageType == protobuf.MessageType_PRIVATE_GROUP {
canDeleteMessageForEveryone = m.CanDeleteMessageForEveryoneInPrivateGroupChat(chat, &m.identity.PublicKey)
if !canDeleteMessageForEveryone {
return nil, ErrInvalidDeletePermission
}