status-go/protocol/messenger_delete_messages_t...

361 lines
14 KiB
Go

package protocol
import (
"context"
"testing"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
"github.com/ethereum/go-ethereum/crypto"
gethbridge "github.com/status-im/status-go/eth-node/bridge/geth"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/communities"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/protocol/tt"
"github.com/status-im/status-go/waku"
)
func TestMessengerDeleteMessagesSuite(t *testing.T) {
suite.Run(t, new(MessengerDeleteMessagesSuite))
}
type MessengerDeleteMessagesSuite struct {
suite.Suite
owner *Messenger
admin *Messenger
bob *Messenger
shh types.Waku
logger *zap.Logger
}
func (s *MessengerDeleteMessagesSuite) SetupTest() {
s.logger = tt.MustCreateTestLogger()
config := waku.DefaultConfig
config.MinimumAcceptedPoW = 0
shh := waku.New(&config, s.logger)
s.shh = gethbridge.NewGethWakuWrapper(shh)
s.Require().NoError(shh.Start())
s.owner = s.newMessenger()
s.bob = s.newMessenger()
s.admin = s.newMessenger()
}
func (s *MessengerDeleteMessagesSuite) TearDownTest() {
TearDownMessenger(&s.Suite, s.owner)
TearDownMessenger(&s.Suite, s.bob)
TearDownMessenger(&s.Suite, s.admin)
_ = s.logger.Sync()
}
func (s *MessengerDeleteMessagesSuite) newMessenger() *Messenger {
privateKey, err := crypto.GenerateKey()
s.Require().NoError(err)
messenger, err := newMessengerWithKey(s.shh, privateKey, s.logger, nil)
s.Require().NoError(err)
return messenger
}
func (s *MessengerDeleteMessagesSuite) sendMessageAndCheckDelivery(sender *Messenger, text string, chatID string) *common.Message {
ctx := context.Background()
messageToSend := common.NewMessage()
messageToSend.ChatId = chatID
messageToSend.ContentType = protobuf.ChatMessage_TEXT_PLAIN
messageToSend.Text = text
response, err := sender.SendChatMessage(ctx, messageToSend)
s.Require().NoError(err)
s.Require().Len(response.Messages(), 1)
var message *common.Message
if sender.identity != s.admin.identity {
response, err := WaitOnMessengerResponse(s.admin, func(response *MessengerResponse) bool {
return len(response.Messages()) == 1
}, "admin did not receive message")
s.Require().NoError(err)
message = response.Messages()[0]
s.Require().Equal(messageToSend.Text, message.Text)
}
if sender.identity != s.owner.identity {
response, err = WaitOnMessengerResponse(s.owner, func(response *MessengerResponse) bool {
return len(response.Messages()) == 1
}, "owner did not receive message")
s.Require().NoError(err)
message = response.Messages()[0]
s.Require().Equal(messageToSend.Text, message.Text)
}
if sender.identity != s.bob.identity {
response, err = WaitOnMessengerResponse(s.bob, func(response *MessengerResponse) bool {
return len(response.Messages()) == 1
}, "bob did not receive message")
s.Require().NoError(err)
message = response.Messages()[0]
s.Require().Equal(messageToSend.Text, message.Text)
}
return message
}
func (s *MessengerDeleteMessagesSuite) checkStoredMemberMessagesAmount(messenger *Messenger, memberPubKey string, expectedAmount int, communityID string) {
storedMessages, err := messenger.GetCommunityMemberAllMessages(
&requests.CommunityMemberMessages{
CommunityID: communityID,
MemberPublicKey: memberPubKey})
s.Require().NoError(err)
s.Require().Len(storedMessages, expectedAmount)
}
func (s *MessengerDeleteMessagesSuite) checkAllMembersHasMemberMessages(memberPubKey string, expectedAmount int, communityID string) {
s.checkStoredMemberMessagesAmount(s.bob, memberPubKey, expectedAmount, communityID)
s.checkStoredMemberMessagesAmount(s.owner, memberPubKey, expectedAmount, communityID)
s.checkStoredMemberMessagesAmount(s.admin, memberPubKey, expectedAmount, communityID)
}
func (s *MessengerDeleteMessagesSuite) TestDeleteMessageErrors() {
community, communityChat := createCommunity(&s.Suite, s.owner)
request := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
advertiseCommunityTo(&s.Suite, community, s.owner, s.admin)
joinCommunity(&s.Suite, community, s.owner, s.admin, request, "")
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
joinCommunity(&s.Suite, community, s.owner, s.bob, request, "")
grantPermission(&s.Suite, community, s.owner, s.admin, protobuf.CommunityMember_ROLE_ADMIN)
bobMessage := s.sendMessageAndCheckDelivery(s.bob, "bob message", communityChat.ID)
expectedMsgsToRemove := 1
communityID := community.IDString()
s.checkAllMembersHasMemberMessages(s.bob.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
// empty request
deleteMessagesRequest := &requests.DeleteCommunityMemberMessages{}
_, err := s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, requests.ErrDeleteCommunityMemberMessagesInvalidCommunityID)
// only community ID provided
deleteMessagesRequest.CommunityID = community.ID()
_, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, requests.ErrDeleteCommunityMemberMessagesInvalidMemberID)
// only community ID and member ID provided, but delete flag false and no messages IDs
deleteMessagesRequest.MemberPubKey = s.bob.IdentityPublicKeyString()
_, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, requests.ErrDeleteCommunityMemberMessagesInvalidDeleteMessagesByID)
// message provided without id
deleteMessagesRequest.Messages = []*protobuf.DeleteCommunityMemberMessage{&protobuf.DeleteCommunityMemberMessage{
ChatId: bobMessage.ChatId,
}}
_, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, requests.ErrDeleteCommunityMemberMessagesInvalidMsgID)
// message provided without chatId
deleteMessagesRequest.Messages = []*protobuf.DeleteCommunityMemberMessage{&protobuf.DeleteCommunityMemberMessage{
Id: bobMessage.ID,
}}
_, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, requests.ErrDeleteCommunityMemberMessagesInvalidMsgChatID)
// messages id provided but with flag deleteAll
deleteMessagesRequest.CommunityID = community.ID()
deleteMessagesRequest.Messages = []*protobuf.DeleteCommunityMemberMessage{&protobuf.DeleteCommunityMemberMessage{
Id: bobMessage.ID,
ChatId: bobMessage.ChatId,
}}
deleteMessagesRequest.DeleteAll = true
_, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, requests.ErrDeleteCommunityMemberMessagesInvalidDeleteAll)
// bob tries to delete his own message
deleteMessagesRequest.DeleteAll = false
_, err = s.bob.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, communities.ErrNotEnoughPermissions)
// admin tries to delete owner message
deleteMessagesRequest.MemberPubKey = s.owner.IdentityPublicKeyString()
_, err = s.admin.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().ErrorIs(err, communities.ErrNotOwner)
}
func (s *MessengerDeleteMessagesSuite) TestDeleteMessage() {
community, communityChat := createCommunity(&s.Suite, s.owner)
request := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
advertiseCommunityTo(&s.Suite, community, s.owner, s.admin)
joinCommunity(&s.Suite, community, s.owner, s.admin, request, "")
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
joinCommunity(&s.Suite, community, s.owner, s.bob, request, "")
grantPermission(&s.Suite, community, s.owner, s.admin, protobuf.CommunityMember_ROLE_ADMIN)
bobMessage := s.sendMessageAndCheckDelivery(s.bob, "bob message", communityChat.ID)
bobMessage2 := s.sendMessageAndCheckDelivery(s.bob, "bob message2", communityChat.ID)
ownerMessage := s.sendMessageAndCheckDelivery(s.owner, "owner message", communityChat.ID)
adminMessage := s.sendMessageAndCheckDelivery(s.admin, "admin message", communityChat.ID)
identityString := s.bob.IdentityPublicKeyString()
expectedMsgsToRemove := 2
communityID := community.IDString()
s.checkAllMembersHasMemberMessages(identityString, expectedMsgsToRemove, communityID)
s.checkAllMembersHasMemberMessages(s.admin.IdentityPublicKeyString(), 1, communityID)
s.checkAllMembersHasMemberMessages(s.owner.IdentityPublicKeyString(), 1, communityID)
// delete bob message
deleteMessagesRequest := &requests.DeleteCommunityMemberMessages{
CommunityID: community.ID(),
MemberPubKey: identityString,
Messages: []*protobuf.DeleteCommunityMemberMessage{&protobuf.DeleteCommunityMemberMessage{
Id: bobMessage.ID,
ChatId: bobMessage.ChatId,
}},
}
response, err := s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().NoError(err)
checkMessageDeleted := func(response *MessengerResponse) bool {
if len(response.DeletedMessages()) == 0 {
return false
}
if _, exists := response.DeletedMessages()[deleteMessagesRequest.Messages[0].Id]; !exists {
return false
}
return true
}
s.Require().True(checkMessageDeleted(response))
_, err = WaitOnMessengerResponse(s.bob, checkMessageDeleted, "message was not deleted for bob")
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.admin, checkMessageDeleted, "message was not deleted for admin")
s.Require().NoError(err)
expectedMsgsToRemove = 1
s.checkAllMembersHasMemberMessages(s.bob.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
// check that other users messages were not removed
s.checkAllMembersHasMemberMessages(s.admin.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
s.checkAllMembersHasMemberMessages(s.owner.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
// check that admin can delete member message
deleteMessagesRequest.Messages = []*protobuf.DeleteCommunityMemberMessage{&protobuf.DeleteCommunityMemberMessage{
Id: bobMessage2.ID,
ChatId: bobMessage2.ChatId,
}}
response, err = s.admin.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().NoError(err)
s.Require().True(checkMessageDeleted(response))
_, err = WaitOnMessengerResponse(s.bob, checkMessageDeleted, "message2 was not deleted for bob")
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.owner, checkMessageDeleted, "message2 was not deleted for owner")
s.Require().NoError(err)
expectedMsgsToRemove = 0
s.checkAllMembersHasMemberMessages(s.bob.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
// check that other users messages were not removed
expectedMsgsToRemove = 1
s.checkAllMembersHasMemberMessages(s.admin.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
s.checkAllMembersHasMemberMessages(s.owner.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
// check that owner can delete member message
deleteMessagesRequest.Messages = []*protobuf.DeleteCommunityMemberMessage{&protobuf.DeleteCommunityMemberMessage{
Id: adminMessage.ID,
ChatId: adminMessage.ChatId,
}}
response, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().NoError(err)
s.Require().True(checkMessageDeleted(response))
_, err = WaitOnMessengerResponse(s.bob, checkMessageDeleted, "adminMessage was not deleted for bob")
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.admin, checkMessageDeleted, "adminMessage was not deleted for admin")
s.Require().NoError(err)
s.checkAllMembersHasMemberMessages(s.admin.IdentityPublicKeyString(), 0, communityID)
s.checkAllMembersHasMemberMessages(s.owner.IdentityPublicKeyString(), 1, communityID)
// check that owner can delete his own message
deleteMessagesRequest.Messages = []*protobuf.DeleteCommunityMemberMessage{&protobuf.DeleteCommunityMemberMessage{
Id: ownerMessage.ID,
ChatId: ownerMessage.ChatId,
}}
response, err = s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().NoError(err)
s.Require().True(checkMessageDeleted(response))
_, err = WaitOnMessengerResponse(s.bob, checkMessageDeleted, "ownerMessage was not deleted for bob")
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.admin, checkMessageDeleted, "ownerMessage was not deleted for admin")
s.Require().NoError(err)
s.checkAllMembersHasMemberMessages(s.owner.IdentityPublicKeyString(), 0, communityID)
}
func (s *MessengerDeleteMessagesSuite) TestDeleteAllMemberMessage() {
community, communityChat := createCommunity(&s.Suite, s.owner)
request := &requests.RequestToJoinCommunity{CommunityID: community.ID()}
advertiseCommunityTo(&s.Suite, community, s.owner, s.admin)
joinCommunity(&s.Suite, community, s.owner, s.admin, request, "")
advertiseCommunityTo(&s.Suite, community, s.owner, s.bob)
joinCommunity(&s.Suite, community, s.owner, s.bob, request, "")
grantPermission(&s.Suite, community, s.owner, s.admin, protobuf.CommunityMember_ROLE_ADMIN)
_ = s.sendMessageAndCheckDelivery(s.bob, "bob message", communityChat.ID)
_ = s.sendMessageAndCheckDelivery(s.bob, "bob message2", communityChat.ID)
_ = s.sendMessageAndCheckDelivery(s.owner, "owner message", communityChat.ID)
_ = s.sendMessageAndCheckDelivery(s.admin, "admin message", communityChat.ID)
identityString := s.bob.IdentityPublicKeyString()
expectedMsgsToRemove := 2
communityID := community.IDString()
s.checkAllMembersHasMemberMessages(identityString, expectedMsgsToRemove, communityID)
s.checkAllMembersHasMemberMessages(s.admin.IdentityPublicKeyString(), 1, communityID)
s.checkAllMembersHasMemberMessages(s.owner.IdentityPublicKeyString(), 1, communityID)
// delete all bob message
deleteMessagesRequest := &requests.DeleteCommunityMemberMessages{
CommunityID: community.ID(),
MemberPubKey: identityString,
DeleteAll: true,
}
response, err := s.owner.DeleteCommunityMemberMessages(deleteMessagesRequest)
s.Require().NoError(err)
checkMessageDeleted := func(response *MessengerResponse) bool {
return len(response.DeletedMessages()) == 2
}
s.Require().True(checkMessageDeleted(response))
_, err = WaitOnMessengerResponse(s.bob, checkMessageDeleted, "messages were not deleted for bob")
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.admin, checkMessageDeleted, "messages were not deleted for admin")
s.Require().NoError(err)
expectedMsgsToRemove = 0
s.checkAllMembersHasMemberMessages(s.bob.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
// check that other users messages were not removed
expectedMsgsToRemove = 1
s.checkAllMembersHasMemberMessages(s.admin.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
s.checkAllMembersHasMemberMessages(s.owner.IdentityPublicKeyString(), expectedMsgsToRemove, communityID)
}