Fix/duplicate accept cr messages (#4367)

* fix: Duplicate 'Contact Added' Notifications When Pair-Device User Accepts Request

* bump version
This commit is contained in:
frank 2023-12-05 12:22:20 +08:00 committed by GitHub
parent 058120fad9
commit d7e7792b51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 128 additions and 21 deletions

View File

@ -1 +1 @@
0.171.27 0.171.28

View File

@ -177,6 +177,9 @@ type Messenger struct {
processBackedupMessages bool processBackedupMessages bool
communityTokensService communitytokens.ServiceInterface communityTokensService communitytokens.ServiceInterface
// used to track dispatched messages
dispatchMessageTestCallback func(common.RawMessage)
} }
type connStatus int type connStatus int
@ -2242,6 +2245,9 @@ func (m *Messenger) dispatchMessage(ctx context.Context, rawMessage common.RawMe
return rawMessage, err return rawMessage, err
} }
if m.dispatchMessageTestCallback != nil {
m.dispatchMessageTestCallback(rawMessage)
}
return rawMessage, nil return rawMessage, nil
} }

View File

@ -250,7 +250,7 @@ func (m *Messenger) SendContactRequest(ctx context.Context, request *requests.Se
) )
} }
func (m *Messenger) updateAcceptedContactRequest(response *MessengerResponse, contactRequestID string) (*MessengerResponse, error) { func (m *Messenger) updateAcceptedContactRequest(response *MessengerResponse, contactRequestID string, fromSyncing bool) (*MessengerResponse, error) {
m.logger.Debug("updateAcceptedContactRequest", zap.String("contactRequestID", contactRequestID)) m.logger.Debug("updateAcceptedContactRequest", zap.String("contactRequestID", contactRequestID))
@ -286,23 +286,24 @@ func (m *Messenger) updateAcceptedContactRequest(response *MessengerResponse, co
clock, _ := chat.NextClockAndTimestamp(m.transport) clock, _ := chat.NextClockAndTimestamp(m.transport)
contact.AcceptContactRequest(clock) contact.AcceptContactRequest(clock)
acceptContactRequest := &protobuf.AcceptContactRequest{ if !fromSyncing {
Id: contactRequest.ID, acceptContactRequest := &protobuf.AcceptContactRequest{
Clock: clock, Id: contactRequest.ID,
} Clock: clock,
encodedMessage, err := proto.Marshal(acceptContactRequest) }
if err != nil { encodedMessage, err := proto.Marshal(acceptContactRequest)
return nil, err if err != nil {
} return nil, err
}
_, err = m.dispatchMessage(context.Background(), common.RawMessage{ _, err = m.dispatchMessage(context.Background(), common.RawMessage{
LocalChatID: contactRequest.From, LocalChatID: contactRequest.From,
Payload: encodedMessage, Payload: encodedMessage,
MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST, MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST,
ResendAutomatically: true, ResendAutomatically: true,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
}
} }
if response == nil { if response == nil {
@ -455,7 +456,7 @@ func (m *Messenger) addContact(ctx context.Context, pubKey, ensName, nickname, d
} }
if len(contactRequestID) != 0 { if len(contactRequestID) != 0 {
updatedResponse, err := m.updateAcceptedContactRequest(response, contactRequestID) updatedResponse, err := m.updateAcceptedContactRequest(response, contactRequestID, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -3576,7 +3576,7 @@ func (m *Messenger) HandleSyncContactRequestDecision(state *ReceivedMessageState
var response *MessengerResponse var response *MessengerResponse
if message.DecisionStatus == protobuf.SyncContactRequestDecision_ACCEPTED { if message.DecisionStatus == protobuf.SyncContactRequestDecision_ACCEPTED {
response, err = m.updateAcceptedContactRequest(nil, message.RequestId) response, err = m.updateAcceptedContactRequest(nil, message.RequestId, true)
} else { } else {
response, err = m.declineContactRequest(message.RequestId, true) response, err = m.declineContactRequest(message.RequestId, true)
} }

View File

@ -0,0 +1,100 @@
package protocol
import (
"context"
"testing"
"github.com/stretchr/testify/suite"
"github.com/ethereum/go-ethereum/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/protocol/common"
"github.com/status-im/status-go/protocol/protobuf"
"github.com/status-im/status-go/protocol/requests"
)
type MessengerSyncContactRequestDecisionSuite struct {
MessengerBaseTestSuite
m2 *Messenger
}
func TestMessengerSyncContactRequestDecision(t *testing.T) {
suite.Run(t, new(MessengerSyncContactRequestDecisionSuite))
}
func (s *MessengerSyncContactRequestDecisionSuite) SetupTest() {
s.MessengerBaseTestSuite.SetupTest()
m2, err := newMessengerWithKey(s.shh, s.privateKey, s.logger, nil)
s.Require().NoError(err)
s.m2 = m2
PairDevices(&s.Suite, m2, s.m)
PairDevices(&s.Suite, s.m, m2)
}
func (s *MessengerSyncContactRequestDecisionSuite) TearDownTest() {
s.Require().NoError(s.m2.Shutdown())
s.MessengerBaseTestSuite.TearDownTest()
}
func (s *MessengerSyncContactRequestDecisionSuite) createUserB() *Messenger {
key, err := crypto.GenerateKey()
s.Require().NoError(err)
userB, err := newMessengerWithKey(s.shh, key, s.logger, nil)
s.Require().NoError(err)
return userB
}
func (s *MessengerSyncContactRequestDecisionSuite) TestSyncAcceptContactRequest() {
userB := s.createUserB()
defer func() {
s.Require().NoError(userB.Shutdown())
}()
numM1DispatchedAcceptContactRequest := 0
numM2DispatchedAcceptContactRequest := 0
s.m.dispatchMessageTestCallback = func(message common.RawMessage) {
if message.MessageType == protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST {
numM1DispatchedAcceptContactRequest++
}
}
s.m2.dispatchMessageTestCallback = func(message common.RawMessage) {
if message.MessageType == protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST {
numM2DispatchedAcceptContactRequest++
}
}
// send contact request to m/m2, m and m2 are paired
request := &requests.AddContact{ID: common.PubkeyToHex(&s.m2.identity.PublicKey)}
_, err := userB.AddContact(context.Background(), request)
s.Require().NoError(err)
// check m and m2 received contact request
var contactRequestMessageID types.HexBytes
receivedContactRequestCondition := func(r *MessengerResponse) bool {
for _, n := range r.ActivityCenterNotifications() {
if n.Type == ActivityCenterNotificationTypeContactRequest {
contactRequestMessageID = n.ID
return true
}
}
return false
}
_, err = WaitOnMessengerResponse(s.m, receivedContactRequestCondition, "contact request not received on device 1")
s.Require().NoError(err)
_, err = WaitOnMessengerResponse(s.m2, receivedContactRequestCondition, "contact request not received on device 2")
s.Require().NoError(err)
// m accept contact request from userB
_, err = s.m.AcceptContactRequest(context.Background(), &requests.AcceptContactRequest{ID: contactRequestMessageID})
s.Require().NoError(err)
// check sync contact request decision processed for m2
_, err = WaitOnMessengerResponse(s.m2, func(r *MessengerResponse) bool {
return len(r.Contacts) > 0
}, "contact request not accepted on device 2")
s.Require().NoError(err)
s.Require().Equal(1, numM1DispatchedAcceptContactRequest, "we should dispatch only 1 accept contact request message")
s.Require().Equal(0, numM2DispatchedAcceptContactRequest, "we should not dispatch accept contact request message")
}