feat: get and delete community member messages API (#4932)

This commit is contained in:
Mykhailo Prakhov 2024-03-19 20:44:49 +01:00 committed by GitHub
parent b911297a3d
commit ad342c8887
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 937 additions and 117 deletions

View File

@ -771,7 +771,7 @@ func banMember(base CommunityEventsTestsInterface, banRequest *requests.BanUserF
waitOnMessengerResponse(s, verifyPendingState, base.GetMember())
checkMsgDeletion := func(messenger *Messenger, expectedMsgsCount int) {
msgs, err := messenger.persistence.GetCommunityMemberAllMessagesID(bannedPK, communityStr)
msgs, err := messenger.persistence.GetCommunityMemberMessagesToDelete(bannedPK, communityStr)
s.Require().NoError(err)
s.Require().Len(msgs, expectedMsgsCount)
}

View File

@ -2922,7 +2922,7 @@ func (db sqlitePersistence) saveBridgeMessage(tx *sql.Tx, message *protobuf.Brid
return
}
func (db sqlitePersistence) GetCommunityMemberAllMessagesID(member string, communityID string) ([]*DeletedMessage, error) {
func (db sqlitePersistence) GetCommunityMemberMessagesToDelete(member string, communityID string) ([]*protobuf.DeleteCommunityMemberMessage, error) {
rows, err := db.db.Query(`SELECT m.id, m.chat_id FROM user_messages as m
INNER JOIN chats AS ch ON ch.id = m.chat_id AND ch.community_id = ?
WHERE m.source = ?`, communityID, member)
@ -2933,11 +2933,11 @@ func (db sqlitePersistence) GetCommunityMemberAllMessagesID(member string, commu
defer rows.Close()
result := []*DeletedMessage{}
result := []*protobuf.DeleteCommunityMemberMessage{}
for rows.Next() {
removeMsgsInfo := &DeletedMessage{}
err = rows.Scan(&removeMsgsInfo.ID, &removeMsgsInfo.ChatID)
removeMsgsInfo := &protobuf.DeleteCommunityMemberMessage{}
err = rows.Scan(&removeMsgsInfo.Id, &removeMsgsInfo.ChatId)
if err != nil {
return nil, err
}
@ -3025,3 +3025,20 @@ func (db sqlitePersistence) findAndUpdateRepliedTo(tx *sql.Tx, discordParentMess
}
return db.updateStatusMessagesWithResponse(tx, []string{statusMessageID}, repliedMessageID)
}
func (db sqlitePersistence) GetCommunityMemberAllMessages(member string, communityID string) ([]*common.Message, error) {
additionalRequestData := "INNER JOIN chats AS ch ON ch.id = m1.chat_id AND ch.community_id = ? WHERE m1.source = ?"
query := db.buildMessagesQueryWithAdditionalFields("", additionalRequestData)
rows, err := db.db.Query(query, communityID, member)
if err != nil {
if err == sql.ErrNoRows {
return []*common.Message{}, nil
}
return nil, err
}
return getMessagesFromScanRows(db, rows, false)
}

View File

@ -2740,7 +2740,7 @@ func (m *Messenger) BanUserFromCommunity(ctx context.Context, request *requests.
response.AddCommunity(community)
if request.DeleteAllMessages && community.IsControlNode() {
deleteMessagesResponse, err := m.DeleteAllCommunityMemberMessages(request.User.String(), request.CommunityID.String())
deleteMessagesResponse, err := m.deleteCommunityMemberMessages(request.User.String(), request.CommunityID.String(), []*protobuf.DeleteCommunityMemberMessage{})
if err != nil {
return nil, err
}
@ -2894,7 +2894,7 @@ func (m *Messenger) handleCommunityResponse(state *ReceivedMessageState, communi
if len(communityResponse.Changes.MembersBanned) > 0 {
for memberID, deleteAllMessages := range communityResponse.Changes.MembersBanned {
if deleteAllMessages {
response, err := m.DeleteAllCommunityMemberMessages(memberID, community.IDString())
response, err := m.deleteCommunityMemberMessages(memberID, community.IDString(), []*protobuf.DeleteCommunityMemberMessage{})
if err != nil {
return err
}
@ -4435,3 +4435,105 @@ func (m *Messenger) leaveCommunityDueToKickOrBan(changes *communities.CommunityC
m.logger.Error("cannot merge leave and notification response", zap.Error(err))
}
}
func (m *Messenger) GetCommunityMemberAllMessages(request *requests.CommunityMemberMessages) ([]*common.Message, error) {
if err := request.Validate(); err != nil {
return nil, err
}
messages, err := m.persistence.GetCommunityMemberAllMessages(request.MemberPublicKey, request.CommunityID)
if err != nil {
return nil, err
}
for _, message := range messages {
updatedMessages, err := m.persistence.MessagesByResponseTo(message.ID)
if err != nil {
return nil, err
}
messages = append(messages, updatedMessages...)
}
return messages, nil
}
func (m *Messenger) DeleteCommunityMemberMessages(request *requests.DeleteCommunityMemberMessages) (*MessengerResponse, error) {
if err := request.Validate(); err != nil {
return nil, err
}
community, err := m.GetCommunityByID(request.CommunityID)
if err != nil {
return nil, err
}
if community == nil {
return nil, communities.ErrOrgNotFound
}
if !community.IsControlNode() && !community.IsPrivilegedMember(m.IdentityPublicKey()) {
return nil, communities.ErrNotEnoughPermissions
}
memberPubKey, err := common.HexToPubkey(request.MemberPubKey)
if err != nil {
return nil, err
}
if community.IsMemberOwner(memberPubKey) && !m.IdentityPublicKey().Equal(memberPubKey) {
return nil, communities.ErrNotOwner
}
deleteMessagesResponse, err := m.deleteCommunityMemberMessages(request.MemberPubKey, request.CommunityID.String(), request.Messages)
if err != nil {
return nil, err
}
deletedMessages := &protobuf.DeleteCommunityMemberMessages{
Clock: uint64(time.Now().Unix()),
CommunityId: community.ID(),
MemberId: request.MemberPubKey,
Messages: request.Messages,
}
payload, err := proto.Marshal(deletedMessages)
if err != nil {
return nil, err
}
rawMessage := common.RawMessage{
Payload: payload,
Sender: community.PrivateKey(),
SkipEncryptionLayer: true,
MessageType: protobuf.ApplicationMetadataMessage_DELETE_COMMUNITY_MEMBER_MESSAGES,
PubsubTopic: community.PubsubTopic(),
}
_, err = m.sender.SendPublic(context.Background(), community.IDString(), rawMessage)
return deleteMessagesResponse, err
}
func (m *Messenger) HandleDeleteCommunityMemberMessages(state *ReceivedMessageState, request *protobuf.DeleteCommunityMemberMessages, statusMessage *v1protocol.StatusMessage) error {
community, err := m.communitiesManager.GetByID(request.CommunityId)
if err != nil {
return err
}
if community == nil {
return communities.ErrOrgNotFound
}
if !community.ControlNode().Equal(state.CurrentMessageState.PublicKey) && !community.IsPrivilegedMember(state.CurrentMessageState.PublicKey) {
return communities.ErrNotAuthorized
}
deleteMessagesResponse, err := m.deleteCommunityMemberMessages(request.MemberId, community.IDString(), request.Messages)
if err != nil {
return err
}
return state.Response.Merge(deleteMessagesResponse)
}

View File

@ -0,0 +1,360 @@
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)
}

View File

@ -253,6 +253,9 @@ func (m *Messenger) dispatchToHandler(messageState *ReceivedMessageState, protoB
case protobuf.ApplicationMetadataMessage_COMMUNITY_REEVALUATE_PERMISSIONS_REQUEST:
return m.handleCommunityReevaluatePermissionsRequestProtobuf(messageState, protoBytes, msg, filter)
case protobuf.ApplicationMetadataMessage_DELETE_COMMUNITY_MEMBER_MESSAGES:
return m.handleDeleteCommunityMemberMessagesProtobuf(messageState, protoBytes, msg, filter)
default:
m.logger.Info("protobuf type not found", zap.String("type", string(msg.ApplicationLayer.Type)))
return errors.New("protobuf type not found")
@ -1817,3 +1820,21 @@ func (m *Messenger) handleCommunityReevaluatePermissionsRequestProtobuf(messageS
}
func (m *Messenger) handleDeleteCommunityMemberMessagesProtobuf(messageState *ReceivedMessageState, protoBytes []byte, msg *v1protocol.StatusMessage, filter transport.Filter) error {
m.logger.Info("handling DeleteCommunityMemberMessages")
p := &protobuf.DeleteCommunityMemberMessages{}
err := proto.Unmarshal(protoBytes, p)
if err != nil {
return err
}
m.outputToCSV(msg.TransportLayer.Message.Timestamp, msg.ApplicationLayer.ID, messageState.CurrentMessageState.Contact.ID, filter.ContentTopic, filter.ChatID, msg.ApplicationLayer.Type, p)
return m.HandleDeleteCommunityMemberMessages(messageState, p, msg)
}

View File

@ -519,10 +519,14 @@ func (m *Messenger) SendGroupChatMessage(request *requests.SendGroupChatMessage)
return m.sendChatMessage(context.Background(), message)
}
func (m *Messenger) DeleteAllCommunityMemberMessages(member string, communityID string) (*MessengerResponse, error) {
messagesToDelete, err := m.persistence.GetCommunityMemberAllMessagesID(member, communityID)
if err != nil {
return nil, err
func (m *Messenger) deleteCommunityMemberMessages(member string, communityID string, deleteMessages []*protobuf.DeleteCommunityMemberMessage) (*MessengerResponse, error) {
messagesToDelete := deleteMessages
var err error
if len(deleteMessages) == 0 {
messagesToDelete, err = m.persistence.GetCommunityMemberMessagesToDelete(member, communityID)
if err != nil {
return nil, err
}
}
response := &MessengerResponse{}
@ -532,7 +536,7 @@ func (m *Messenger) DeleteAllCommunityMemberMessages(member string, communityID
}
for _, messageToDelete := range messagesToDelete {
updatedMessages, err := m.persistence.MessagesByResponseTo(messageToDelete.ID)
updatedMessages, err := m.persistence.MessagesByResponseTo(messageToDelete.Id)
if err != nil {
return nil, err
}
@ -544,7 +548,7 @@ func (m *Messenger) DeleteAllCommunityMemberMessages(member string, communityID
messageIDs := make([]string, 0, len(messagesToDelete))
for _, rm := range messagesToDelete {
messageIDs = append(messageIDs, rm.ID)
messageIDs = append(messageIDs, rm.Id)
}
if err = m.persistence.DeleteMessages(messageIDs); err != nil {

View File

@ -11,15 +11,15 @@ import (
"github.com/status-im/status-go/server"
)
func TestMessengerDeleteMessageSuite(t *testing.T) {
suite.Run(t, new(MessengerDeleteMessageSuite))
func TestMessengerRemoveMessageSuite(t *testing.T) {
suite.Run(t, new(MessengerRemoveMessageSuite))
}
type MessengerDeleteMessageSuite struct {
type MessengerRemoveMessageSuite struct {
MessengerBaseTestSuite
}
func (s *MessengerDeleteMessageSuite) TestDeleteMessage() {
func (s *MessengerRemoveMessageSuite) TestDeleteMessage() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -68,7 +68,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessage() {
s.Require().ErrorContains(err, "can't find chat")
}
func (s *MessengerDeleteMessageSuite) TestDeleteMessagePreviousLastMessage() {
func (s *MessengerRemoveMessageSuite) TestDeleteMessagePreviousLastMessage() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -117,7 +117,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessagePreviousLastMessage() {
}
func (s *MessengerDeleteMessageSuite) TestDeleteWrongMessageType() {
func (s *MessengerRemoveMessageSuite) TestDeleteWrongMessageType() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -144,7 +144,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteWrongMessageType() {
// TODO fix activity center notifications not being deleted when a message is deleted
func (s *MessengerDeleteMessageSuite) TestDeleteMessageFirstThenMessage() {
func (s *MessengerRemoveMessageSuite) TestDeleteMessageFirstThenMessage() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -197,7 +197,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessageFirstThenMessage() {
s.Require().Nil(state.Response.Chats()[0].LastMessage)
}
func (s *MessengerDeleteMessageSuite) TestDeleteImageMessage() {
func (s *MessengerRemoveMessageSuite) TestDeleteImageMessage() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -271,7 +271,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteImageMessage() {
s.Require().ErrorContains(err, "can't find chat")
}
func (s *MessengerDeleteMessageSuite) TestDeleteImageMessageFirstThenMessage() {
func (s *MessengerRemoveMessageSuite) TestDeleteImageMessageFirstThenMessage() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -349,7 +349,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteImageMessageFirstThenMessage() {
s.Require().Nil(state.Response.Chats()[0].LastMessage)
}
func (s *MessengerDeleteMessageSuite) TestDeleteMessageWithAMention() {
func (s *MessengerRemoveMessageSuite) TestDeleteMessageWithAMention() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -409,7 +409,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessageWithAMention() {
// This test makes sure the UnviewMessageCount doesn't go below 0 in a very rare case where the Chat could be marked
// as read but the message still unseen (Seen == false)
func (s *MessengerDeleteMessageSuite) TestDeleteMessageAndChatIsAlreadyRead() {
func (s *MessengerRemoveMessageSuite) TestDeleteMessageAndChatIsAlreadyRead() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -468,7 +468,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessageAndChatIsAlreadyRead() {
s.Require().Equal(0, int(state.Response.Chats()[0].UnviewedMessagesCount))
}
func (s *MessengerDeleteMessageSuite) TestDeleteMessageReplyToImage() {
func (s *MessengerRemoveMessageSuite) TestDeleteMessageReplyToImage() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)
@ -521,7 +521,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessageReplyToImage() {
s.Require().NotEmpty(sendResponse.Messages()[0].ImageLocalURL)
}
func (s *MessengerDeleteMessageSuite) TestDeleteMessageForMeReplyToImage() {
func (s *MessengerRemoveMessageSuite) TestDeleteMessageForMeReplyToImage() {
theirMessenger := s.newMessenger()
defer TearDownMessenger(&s.Suite, theirMessenger)

View File

@ -33,11 +33,6 @@ type RemovedMessage struct {
DeletedBy string `json:"deletedBy,omitempty"`
}
type DeletedMessage struct {
ID string `json:"id"`
ChatID string `json:"chatID"`
}
type ClearedHistory struct {
ChatID string `json:"chatId"`
ClearedAt uint64 `json:"clearedAt"`
@ -605,13 +600,13 @@ func (r *MessengerResponse) AddRemovedMessage(rm *RemovedMessage) {
}
}
func (r *MessengerResponse) AddDeletedMessages(messagesToAdd []*DeletedMessage) {
func (r *MessengerResponse) AddDeletedMessages(messagesToAdd []*protobuf.DeleteCommunityMemberMessage) {
if r.deletedMessages == nil {
r.deletedMessages = make(map[string]string)
}
for _, message := range messagesToAdd {
r.deletedMessages[message.ID] = message.ChatID
r.deletedMessages[message.Id] = message.ChatId
}
}

View File

@ -2029,25 +2029,25 @@ func TestBridgeMessageReplies(t *testing.T) {
require.Equal(t, "333", responseTo)
}
func TestGetCommunityMemberAllNonDeletedMessages(t *testing.T) {
func createAndSaveMessage(p *sqlitePersistence, id string, from string, deleted bool, communityID string) error {
return p.SaveMessages([]*common.Message{{
ID: id,
From: from,
CommunityID: communityID,
ChatMessage: &protobuf.ChatMessage{
Timestamp: uint64(time.Now().Unix()),
Text: "some-text",
ChatId: testPublicChatID,
},
Deleted: deleted,
}})
}
func TestGetCommunityMemberMessagesID(t *testing.T) {
db, err := openTestDB()
require.NoError(t, err)
p := newSQLitePersistence(db)
testCommunity := "test-community"
clock := uint64(time.Now().Unix())
saveMessage := func(id string, from string, deleted bool) {
err = p.SaveMessages([]*common.Message{{
ID: id,
From: from,
CommunityID: testCommunity,
ChatMessage: &protobuf.ChatMessage{
Timestamp: clock,
Text: "some-text",
ChatId: testPublicChatID,
},
Deleted: deleted,
}})
}
chat := &Chat{
ID: testPublicChatID,
@ -2057,35 +2057,81 @@ func TestGetCommunityMemberAllNonDeletedMessages(t *testing.T) {
err = p.SaveChats([]*Chat{chat})
require.NoError(t, err)
messages, err := p.GetCommunityMemberAllMessagesID(testPK, testCommunity)
messages, err := p.GetCommunityMemberMessagesToDelete(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 0)
saveMessage("1", testPK, false)
require.NoError(t, createAndSaveMessage(p, "1", testPK, false, testCommunity))
messages, err = p.GetCommunityMemberAllMessagesID(testPK, "wrong community")
messages, err = p.GetCommunityMemberMessagesToDelete(testPK, "wrong community")
require.NoError(t, err)
require.Len(t, messages, 0)
messages, err = p.GetCommunityMemberAllMessagesID("wrong user name", testCommunity)
messages, err = p.GetCommunityMemberMessagesToDelete("wrong user name", testCommunity)
require.NoError(t, err)
require.Len(t, messages, 0)
messages, err = p.GetCommunityMemberAllMessagesID(testPK, testCommunity)
messages, err = p.GetCommunityMemberMessagesToDelete(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 1)
require.Exactly(t, "1", messages[0].ID)
require.Exactly(t, testPublicChatID, messages[0].ChatID)
require.Exactly(t, "1", messages[0].Id)
require.Exactly(t, testPublicChatID, messages[0].ChatId)
saveMessage("2", "another user", false)
require.NoError(t, createAndSaveMessage(p, "2", "another user", false, testCommunity))
messages, err = p.GetCommunityMemberAllMessagesID(testPK, testCommunity)
messages, err = p.GetCommunityMemberMessagesToDelete(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 1)
saveMessage("3", testPK, true)
require.NoError(t, createAndSaveMessage(p, "3", testPK, true, testCommunity))
messages, err = p.GetCommunityMemberAllMessagesID(testPK, testCommunity)
messages, err = p.GetCommunityMemberMessagesToDelete(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 2)
}
func TestGetCommunityMemberMessages(t *testing.T) {
db, err := openTestDB()
require.NoError(t, err)
p := newSQLitePersistence(db)
testCommunity := "test-community"
chat := &Chat{
ID: testPublicChatID,
CommunityID: testCommunity,
}
err = p.SaveChats([]*Chat{chat})
require.NoError(t, err)
messages, err := p.GetCommunityMemberAllMessages(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 0)
require.NoError(t, createAndSaveMessage(p, "1", testPK, false, testCommunity))
messages, err = p.GetCommunityMemberAllMessages(testPK, "wrong community")
require.NoError(t, err)
require.Len(t, messages, 0)
messages, err = p.GetCommunityMemberAllMessages("wrong user name", testCommunity)
require.NoError(t, err)
require.Len(t, messages, 0)
messages, err = p.GetCommunityMemberAllMessages(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 1)
require.Exactly(t, "1", messages[0].ID)
require.NoError(t, createAndSaveMessage(p, "2", "another user", false, testCommunity))
messages, err = p.GetCommunityMemberAllMessages(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 1)
require.NoError(t, createAndSaveMessage(p, "3", testPK, true, testCommunity))
messages, err = p.GetCommunityMemberAllMessages(testPK, testCommunity)
require.NoError(t, err)
require.Len(t, messages, 2)
}

View File

@ -106,6 +106,7 @@ const (
ApplicationMetadataMessage_SYNC_PROFILE_SHOWCASE_PREFERENCES ApplicationMetadataMessage_Type = 82
ApplicationMetadataMessage_COMMUNITY_PUBLIC_STORENODES_INFO ApplicationMetadataMessage_Type = 83
ApplicationMetadataMessage_COMMUNITY_REEVALUATE_PERMISSIONS_REQUEST ApplicationMetadataMessage_Type = 84
ApplicationMetadataMessage_DELETE_COMMUNITY_MEMBER_MESSAGES ApplicationMetadataMessage_Type = 85
)
// Enum value maps for ApplicationMetadataMessage_Type.
@ -192,6 +193,7 @@ var (
82: "SYNC_PROFILE_SHOWCASE_PREFERENCES",
83: "COMMUNITY_PUBLIC_STORENODES_INFO",
84: "COMMUNITY_REEVALUATE_PERMISSIONS_REQUEST",
85: "DELETE_COMMUNITY_MEMBER_MESSAGES",
}
ApplicationMetadataMessage_Type_value = map[string]int32{
"UNKNOWN": 0,
@ -275,6 +277,7 @@ var (
"SYNC_PROFILE_SHOWCASE_PREFERENCES": 82,
"COMMUNITY_PUBLIC_STORENODES_INFO": 83,
"COMMUNITY_REEVALUATE_PERMISSIONS_REQUEST": 84,
"DELETE_COMMUNITY_MEMBER_MESSAGES": 85,
}
)
@ -376,7 +379,7 @@ var File_application_metadata_message_proto protoreflect.FileDescriptor
var file_application_metadata_message_proto_rawDesc = []byte{
0x0a, 0x22, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x9b,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0xc1,
0x15, 0x0a, 0x1a, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65,
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a,
0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
@ -386,7 +389,7 @@ var file_application_metadata_message_proto_rawDesc = []byte{
0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41,
0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
0x74, 0x79, 0x70, 0x65, 0x22, 0x85, 0x14, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a,
0x74, 0x79, 0x70, 0x65, 0x22, 0xab, 0x14, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a,
0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x48,
0x41, 0x54, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e,
0x43, 0x4f, 0x4e, 0x54, 0x41, 0x43, 0x54, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x02,
@ -538,17 +541,19 @@ var file_application_metadata_message_proto_rawDesc = []byte{
0x54, 0x4f, 0x52, 0x45, 0x4e, 0x4f, 0x44, 0x45, 0x53, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x53,
0x12, 0x2c, 0x0a, 0x28, 0x43, 0x4f, 0x4d, 0x4d, 0x55, 0x4e, 0x49, 0x54, 0x59, 0x5f, 0x52, 0x45,
0x45, 0x56, 0x41, 0x4c, 0x55, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x52, 0x4d, 0x49, 0x53, 0x53,
0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x54, 0x22, 0x04,
0x08, 0x0e, 0x10, 0x0e, 0x22, 0x04, 0x08, 0x41, 0x10, 0x41, 0x22, 0x04, 0x08, 0x42, 0x10, 0x42,
0x2a, 0x1d, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x49, 0x4e, 0x53, 0x54, 0x41, 0x4c, 0x4c, 0x41, 0x54,
0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x5f, 0x43, 0x48, 0x41, 0x54, 0x2a,
0x22, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x49, 0x54, 0x59, 0x5f, 0x43,
0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49,
0x4f, 0x4e, 0x53, 0x2a, 0x27, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x49,
0x54, 0x59, 0x5f, 0x43, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x49,
0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x42, 0x0d, 0x5a, 0x0b,
0x2e, 0x2f, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x54, 0x12, 0x24,
0x0a, 0x20, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x4d, 0x55, 0x4e, 0x49,
0x54, 0x59, 0x5f, 0x4d, 0x45, 0x4d, 0x42, 0x45, 0x52, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47,
0x45, 0x53, 0x10, 0x55, 0x22, 0x04, 0x08, 0x0e, 0x10, 0x0e, 0x22, 0x04, 0x08, 0x41, 0x10, 0x41,
0x22, 0x04, 0x08, 0x42, 0x10, 0x42, 0x2a, 0x1d, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x49, 0x4e, 0x53,
0x54, 0x41, 0x4c, 0x4c, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43,
0x5f, 0x43, 0x48, 0x41, 0x54, 0x2a, 0x22, 0x53, 0x59, 0x4e, 0x43, 0x5f, 0x41, 0x43, 0x54, 0x49,
0x56, 0x49, 0x54, 0x59, 0x5f, 0x43, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x49,
0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x2a, 0x27, 0x53, 0x59, 0x4e, 0x43, 0x5f,
0x41, 0x43, 0x54, 0x49, 0x56, 0x49, 0x54, 0x59, 0x5f, 0x43, 0x45, 0x4e, 0x54, 0x45, 0x52, 0x5f,
0x4e, 0x4f, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41,
0x54, 0x45, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -102,5 +102,6 @@ message ApplicationMetadataMessage {
SYNC_PROFILE_SHOWCASE_PREFERENCES = 82;
COMMUNITY_PUBLIC_STORENODES_INFO = 83;
COMMUNITY_REEVALUATE_PERMISSIONS_REQUEST = 84;
DELETE_COMMUNITY_MEMBER_MESSAGES = 85;
}
}

View File

@ -2378,6 +2378,132 @@ func (x *CommunityReevaluatePermissionsRequest) GetCommunityId() []byte {
return nil
}
type DeleteCommunityMemberMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
ChatId string `protobuf:"bytes,2,opt,name=chat_id,json=chatId,proto3" json:"chat_id,omitempty"`
}
func (x *DeleteCommunityMemberMessage) Reset() {
*x = DeleteCommunityMemberMessage{}
if protoimpl.UnsafeEnabled {
mi := &file_communities_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteCommunityMemberMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteCommunityMemberMessage) ProtoMessage() {}
func (x *DeleteCommunityMemberMessage) ProtoReflect() protoreflect.Message {
mi := &file_communities_proto_msgTypes[28]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteCommunityMemberMessage.ProtoReflect.Descriptor instead.
func (*DeleteCommunityMemberMessage) Descriptor() ([]byte, []int) {
return file_communities_proto_rawDescGZIP(), []int{28}
}
func (x *DeleteCommunityMemberMessage) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *DeleteCommunityMemberMessage) GetChatId() string {
if x != nil {
return x.ChatId
}
return ""
}
type DeleteCommunityMemberMessages struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Clock uint64 `protobuf:"varint,1,opt,name=clock,proto3" json:"clock,omitempty"`
CommunityId []byte `protobuf:"bytes,2,opt,name=community_id,json=communityId,proto3" json:"community_id,omitempty"`
MemberId string `protobuf:"bytes,3,opt,name=member_id,json=memberId,proto3" json:"member_id,omitempty"`
Messages []*DeleteCommunityMemberMessage `protobuf:"bytes,4,rep,name=messages,proto3" json:"messages,omitempty"`
}
func (x *DeleteCommunityMemberMessages) Reset() {
*x = DeleteCommunityMemberMessages{}
if protoimpl.UnsafeEnabled {
mi := &file_communities_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteCommunityMemberMessages) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteCommunityMemberMessages) ProtoMessage() {}
func (x *DeleteCommunityMemberMessages) ProtoReflect() protoreflect.Message {
mi := &file_communities_proto_msgTypes[29]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteCommunityMemberMessages.ProtoReflect.Descriptor instead.
func (*DeleteCommunityMemberMessages) Descriptor() ([]byte, []int) {
return file_communities_proto_rawDescGZIP(), []int{29}
}
func (x *DeleteCommunityMemberMessages) GetClock() uint64 {
if x != nil {
return x.Clock
}
return 0
}
func (x *DeleteCommunityMemberMessages) GetCommunityId() []byte {
if x != nil {
return x.CommunityId
}
return nil
}
func (x *DeleteCommunityMemberMessages) GetMemberId() string {
if x != nil {
return x.MemberId
}
return ""
}
func (x *DeleteCommunityMemberMessages) GetMessages() []*DeleteCommunityMemberMessage {
if x != nil {
return x.Messages
}
return nil
}
var File_communities_proto protoreflect.FileDescriptor
var file_communities_proto_rawDesc = []byte{
@ -2834,9 +2960,25 @@ var file_communities_proto_rawDesc = []byte{
0x52, 0x65, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73,
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c,
0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x49, 0x64, 0x42,
0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x49, 0x64, 0x22,
0x47, 0x0a, 0x1c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69,
0x74, 0x79, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12,
0x17, 0x0a, 0x07, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x06, 0x63, 0x68, 0x61, 0x74, 0x49, 0x64, 0x22, 0xb9, 0x01, 0x0a, 0x1d, 0x44, 0x65, 0x6c,
0x65, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6d, 0x62,
0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c,
0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x63, 0x6c, 0x6f, 0x63, 0x6b,
0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74,
0x79, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x69, 0x64,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64,
0x12, 0x42, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x4d, 0x65, 0x6d,
0x62, 0x65, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x73, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -2852,7 +2994,7 @@ func file_communities_proto_rawDescGZIP() []byte {
}
var file_communities_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
var file_communities_proto_msgTypes = make([]protoimpl.MessageInfo, 38)
var file_communities_proto_msgTypes = make([]protoimpl.MessageInfo, 40)
var file_communities_proto_goTypes = []interface{}{
(CommunityMember_Roles)(0), // 0: protobuf.CommunityMember.Roles
(CommunityMember_ChannelRole)(0), // 1: protobuf.CommunityMember.ChannelRole
@ -2886,65 +3028,68 @@ var file_communities_proto_goTypes = []interface{}{
(*CommunityStorenodes)(nil), // 29: protobuf.CommunityStorenodes
(*Storenode)(nil), // 30: protobuf.Storenode
(*CommunityReevaluatePermissionsRequest)(nil), // 31: protobuf.CommunityReevaluatePermissionsRequest
nil, // 32: protobuf.CommunityTokenMetadata.ContractAddressesEntry
nil, // 33: protobuf.TokenCriteria.ContractAddressesEntry
nil, // 34: protobuf.CommunityDescription.MembersEntry
nil, // 35: protobuf.CommunityDescription.ChatsEntry
nil, // 36: protobuf.CommunityDescription.CategoriesEntry
nil, // 37: protobuf.CommunityDescription.TokenPermissionsEntry
nil, // 38: protobuf.CommunityDescription.BannedMembersEntry
nil, // 39: protobuf.CommunityDescription.PrivateDataEntry
nil, // 40: protobuf.CommunityChat.MembersEntry
nil, // 41: protobuf.WakuMessageArchiveIndex.ArchivesEntry
(CommunityTokenType)(0), // 42: protobuf.CommunityTokenType
(*ChatIdentity)(nil), // 43: protobuf.ChatIdentity
(*Shard)(nil), // 44: protobuf.Shard
(*DeleteCommunityMemberMessage)(nil), // 32: protobuf.DeleteCommunityMemberMessage
(*DeleteCommunityMemberMessages)(nil), // 33: protobuf.DeleteCommunityMemberMessages
nil, // 34: protobuf.CommunityTokenMetadata.ContractAddressesEntry
nil, // 35: protobuf.TokenCriteria.ContractAddressesEntry
nil, // 36: protobuf.CommunityDescription.MembersEntry
nil, // 37: protobuf.CommunityDescription.ChatsEntry
nil, // 38: protobuf.CommunityDescription.CategoriesEntry
nil, // 39: protobuf.CommunityDescription.TokenPermissionsEntry
nil, // 40: protobuf.CommunityDescription.BannedMembersEntry
nil, // 41: protobuf.CommunityDescription.PrivateDataEntry
nil, // 42: protobuf.CommunityChat.MembersEntry
nil, // 43: protobuf.WakuMessageArchiveIndex.ArchivesEntry
(CommunityTokenType)(0), // 44: protobuf.CommunityTokenType
(*ChatIdentity)(nil), // 45: protobuf.ChatIdentity
(*Shard)(nil), // 46: protobuf.Shard
}
var file_communities_proto_depIdxs = []int32{
0, // 0: protobuf.CommunityMember.roles:type_name -> protobuf.CommunityMember.Roles
15, // 1: protobuf.CommunityMember.revealed_accounts:type_name -> protobuf.RevealedAccount
1, // 2: protobuf.CommunityMember.channel_role:type_name -> protobuf.CommunityMember.ChannelRole
32, // 3: protobuf.CommunityTokenMetadata.contract_addresses:type_name -> protobuf.CommunityTokenMetadata.ContractAddressesEntry
42, // 4: protobuf.CommunityTokenMetadata.tokenType:type_name -> protobuf.CommunityTokenType
34, // 3: protobuf.CommunityTokenMetadata.contract_addresses:type_name -> protobuf.CommunityTokenMetadata.ContractAddressesEntry
44, // 4: protobuf.CommunityTokenMetadata.tokenType:type_name -> protobuf.CommunityTokenType
2, // 5: protobuf.CommunityPermissions.access:type_name -> protobuf.CommunityPermissions.Access
33, // 6: protobuf.TokenCriteria.contract_addresses:type_name -> protobuf.TokenCriteria.ContractAddressesEntry
42, // 7: protobuf.TokenCriteria.type:type_name -> protobuf.CommunityTokenType
35, // 6: protobuf.TokenCriteria.contract_addresses:type_name -> protobuf.TokenCriteria.ContractAddressesEntry
44, // 7: protobuf.TokenCriteria.type:type_name -> protobuf.CommunityTokenType
3, // 8: protobuf.CommunityTokenPermission.type:type_name -> protobuf.CommunityTokenPermission.Type
8, // 9: protobuf.CommunityTokenPermission.token_criteria:type_name -> protobuf.TokenCriteria
34, // 10: protobuf.CommunityDescription.members:type_name -> protobuf.CommunityDescription.MembersEntry
36, // 10: protobuf.CommunityDescription.members:type_name -> protobuf.CommunityDescription.MembersEntry
7, // 11: protobuf.CommunityDescription.permissions:type_name -> protobuf.CommunityPermissions
43, // 12: protobuf.CommunityDescription.identity:type_name -> protobuf.ChatIdentity
35, // 13: protobuf.CommunityDescription.chats:type_name -> protobuf.CommunityDescription.ChatsEntry
36, // 14: protobuf.CommunityDescription.categories:type_name -> protobuf.CommunityDescription.CategoriesEntry
45, // 12: protobuf.CommunityDescription.identity:type_name -> protobuf.ChatIdentity
37, // 13: protobuf.CommunityDescription.chats:type_name -> protobuf.CommunityDescription.ChatsEntry
38, // 14: protobuf.CommunityDescription.categories:type_name -> protobuf.CommunityDescription.CategoriesEntry
12, // 15: protobuf.CommunityDescription.admin_settings:type_name -> protobuf.CommunityAdminSettings
37, // 16: protobuf.CommunityDescription.token_permissions:type_name -> protobuf.CommunityDescription.TokenPermissionsEntry
39, // 16: protobuf.CommunityDescription.token_permissions:type_name -> protobuf.CommunityDescription.TokenPermissionsEntry
6, // 17: protobuf.CommunityDescription.community_tokens_metadata:type_name -> protobuf.CommunityTokenMetadata
38, // 18: protobuf.CommunityDescription.banned_members:type_name -> protobuf.CommunityDescription.BannedMembersEntry
39, // 19: protobuf.CommunityDescription.privateData:type_name -> protobuf.CommunityDescription.PrivateDataEntry
40, // 20: protobuf.CommunityChat.members:type_name -> protobuf.CommunityChat.MembersEntry
40, // 18: protobuf.CommunityDescription.banned_members:type_name -> protobuf.CommunityDescription.BannedMembersEntry
41, // 19: protobuf.CommunityDescription.privateData:type_name -> protobuf.CommunityDescription.PrivateDataEntry
42, // 20: protobuf.CommunityChat.members:type_name -> protobuf.CommunityChat.MembersEntry
7, // 21: protobuf.CommunityChat.permissions:type_name -> protobuf.CommunityPermissions
43, // 22: protobuf.CommunityChat.identity:type_name -> protobuf.ChatIdentity
45, // 22: protobuf.CommunityChat.identity:type_name -> protobuf.ChatIdentity
15, // 23: protobuf.CommunityRequestToJoin.revealed_accounts:type_name -> protobuf.RevealedAccount
15, // 24: protobuf.CommunityEditSharedAddresses.revealed_accounts:type_name -> protobuf.RevealedAccount
10, // 25: protobuf.CommunityRequestToJoinResponse.community:type_name -> protobuf.CommunityDescription
44, // 26: protobuf.CommunityRequestToJoinResponse.shard:type_name -> protobuf.Shard
46, // 26: protobuf.CommunityRequestToJoinResponse.shard:type_name -> protobuf.Shard
24, // 27: protobuf.WakuMessageArchive.metadata:type_name -> protobuf.WakuMessageArchiveMetadata
23, // 28: protobuf.WakuMessageArchive.messages:type_name -> protobuf.WakuMessage
24, // 29: protobuf.WakuMessageArchiveIndexMetadata.metadata:type_name -> protobuf.WakuMessageArchiveMetadata
41, // 30: protobuf.WakuMessageArchiveIndex.archives:type_name -> protobuf.WakuMessageArchiveIndex.ArchivesEntry
43, // 30: protobuf.WakuMessageArchiveIndex.archives:type_name -> protobuf.WakuMessageArchiveIndex.ArchivesEntry
30, // 31: protobuf.CommunityStorenodes.storenodes:type_name -> protobuf.Storenode
5, // 32: protobuf.CommunityDescription.MembersEntry.value:type_name -> protobuf.CommunityMember
13, // 33: protobuf.CommunityDescription.ChatsEntry.value:type_name -> protobuf.CommunityChat
14, // 34: protobuf.CommunityDescription.CategoriesEntry.value:type_name -> protobuf.CommunityCategory
9, // 35: protobuf.CommunityDescription.TokenPermissionsEntry.value:type_name -> protobuf.CommunityTokenPermission
11, // 36: protobuf.CommunityDescription.BannedMembersEntry.value:type_name -> protobuf.CommunityBanInfo
5, // 37: protobuf.CommunityChat.MembersEntry.value:type_name -> protobuf.CommunityMember
26, // 38: protobuf.WakuMessageArchiveIndex.ArchivesEntry.value:type_name -> protobuf.WakuMessageArchiveIndexMetadata
39, // [39:39] is the sub-list for method output_type
39, // [39:39] is the sub-list for method input_type
39, // [39:39] is the sub-list for extension type_name
39, // [39:39] is the sub-list for extension extendee
0, // [0:39] is the sub-list for field type_name
32, // 32: protobuf.DeleteCommunityMemberMessages.messages:type_name -> protobuf.DeleteCommunityMemberMessage
5, // 33: protobuf.CommunityDescription.MembersEntry.value:type_name -> protobuf.CommunityMember
13, // 34: protobuf.CommunityDescription.ChatsEntry.value:type_name -> protobuf.CommunityChat
14, // 35: protobuf.CommunityDescription.CategoriesEntry.value:type_name -> protobuf.CommunityCategory
9, // 36: protobuf.CommunityDescription.TokenPermissionsEntry.value:type_name -> protobuf.CommunityTokenPermission
11, // 37: protobuf.CommunityDescription.BannedMembersEntry.value:type_name -> protobuf.CommunityBanInfo
5, // 38: protobuf.CommunityChat.MembersEntry.value:type_name -> protobuf.CommunityMember
26, // 39: protobuf.WakuMessageArchiveIndex.ArchivesEntry.value:type_name -> protobuf.WakuMessageArchiveIndexMetadata
40, // [40:40] is the sub-list for method output_type
40, // [40:40] is the sub-list for method input_type
40, // [40:40] is the sub-list for extension type_name
40, // [40:40] is the sub-list for extension extendee
0, // [0:40] is the sub-list for field type_name
}
func init() { file_communities_proto_init() }
@ -3292,6 +3437,30 @@ func file_communities_proto_init() {
return nil
}
}
file_communities_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteCommunityMemberMessage); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_communities_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteCommunityMemberMessages); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -3299,7 +3468,7 @@ func file_communities_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_communities_proto_rawDesc,
NumEnums: 4,
NumMessages: 38,
NumMessages: 40,
NumExtensions: 0,
NumServices: 0,
},

View File

@ -257,3 +257,15 @@ message Storenode {
message CommunityReevaluatePermissionsRequest {
bytes community_id = 1;
}
message DeleteCommunityMemberMessage {
string id = 1;
string chat_id = 2;
}
message DeleteCommunityMemberMessages {
uint64 clock = 1;
bytes community_id = 2;
string member_id = 3;
repeated DeleteCommunityMemberMessage messages = 4;
}

View File

@ -0,0 +1,25 @@
package requests
import (
"errors"
)
var ErrCommunityMemberMessagesCommunityID = errors.New("community member messages: invalid id")
var ErrCommunityMemberMessagesMemberPK = errors.New("community member messages: invalid member PK")
type CommunityMemberMessages struct {
CommunityID string `json:"communityId"`
MemberPublicKey string `json:"memberPublicKey"`
}
func (c *CommunityMemberMessages) Validate() error {
if len(c.CommunityID) == 0 {
return ErrCommunityMemberMessagesCommunityID
}
if len(c.MemberPublicKey) == 0 {
return ErrCommunityMemberMessagesMemberPK
}
return nil
}

View File

@ -0,0 +1,54 @@
package requests
import (
"errors"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/protobuf"
)
var ErrDeleteCommunityMemberMessagesInvalidCommunityID = errors.New("delete-community-member-messages: invalid community id")
var ErrDeleteCommunityMemberMessagesInvalidMemberID = errors.New("delete-community-member-messages: invalid member id")
var ErrDeleteCommunityMemberMessagesInvalidData = errors.New("delete-community-member-messages: invalid data")
var ErrDeleteCommunityMemberMessagesInvalidDeleteAll = errors.New("delete-community-member-messages: invalid delete all setup")
var ErrDeleteCommunityMemberMessagesInvalidDeleteMessagesByID = errors.New("delete-community-member-messages: invalid delete messages by ID setups")
var ErrDeleteCommunityMemberMessagesInvalidMsgID = errors.New("delete-community-member-messages: invalid messages Id")
var ErrDeleteCommunityMemberMessagesInvalidMsgChatID = errors.New("delete-community-member-messages: invalid messages chatId")
type DeleteCommunityMemberMessages struct {
CommunityID types.HexBytes `json:"communityId"`
MemberPubKey string `json:"memberPubKey"`
Messages []*protobuf.DeleteCommunityMemberMessage `json:"messages"`
DeleteAll bool `json:"deleteAll"`
}
func (d *DeleteCommunityMemberMessages) Validate() error {
if len(d.CommunityID) == 0 {
return ErrDeleteCommunityMemberMessagesInvalidCommunityID
}
if len(d.MemberPubKey) == 0 {
return ErrDeleteCommunityMemberMessagesInvalidMemberID
}
if d.Messages != nil && len(d.Messages) > 0 && d.DeleteAll {
return ErrDeleteCommunityMemberMessagesInvalidDeleteAll
}
if (d.Messages == nil || (d.Messages != nil && len(d.Messages) == 0)) && !d.DeleteAll {
return ErrDeleteCommunityMemberMessagesInvalidDeleteMessagesByID
}
if d.Messages != nil {
for _, message := range d.Messages {
if len(message.Id) == 0 {
return ErrDeleteCommunityMemberMessagesInvalidMsgID
}
if len(message.ChatId) == 0 {
return ErrDeleteCommunityMemberMessagesInvalidMsgChatID
}
}
}
return nil
}

View File

@ -1775,6 +1775,15 @@ func (api *PublicAPI) SetCustomizationColor(ctx context.Context, request *reques
return api.service.messenger.SetCustomizationColor(ctx, request)
}
func (api *PublicAPI) GetCommunityMemberAllMessages(request *requests.CommunityMemberMessages) ([]*common.Message, error) {
return api.service.messenger.GetCommunityMemberAllMessages(request)
}
// Delete a specific community member messages or all community member messages (based on provided parameters)
func (api *PublicAPI) DeleteCommunityMemberMessages(request *requests.DeleteCommunityMemberMessages) (*protocol.MessengerResponse, error) {
return api.service.messenger.DeleteCommunityMemberMessages(request)
}
// -----
// HELPER
// -----