diff --git a/VERSION b/VERSION index fd382fe0e..62fe90d8e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.171.27 +0.171.28 diff --git a/protocol/messenger.go b/protocol/messenger.go index 8b25987e2..d866cc0bd 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -177,6 +177,9 @@ type Messenger struct { processBackedupMessages bool communityTokensService communitytokens.ServiceInterface + + // used to track dispatched messages + dispatchMessageTestCallback func(common.RawMessage) } type connStatus int @@ -2242,6 +2245,9 @@ func (m *Messenger) dispatchMessage(ctx context.Context, rawMessage common.RawMe return rawMessage, err } + if m.dispatchMessageTestCallback != nil { + m.dispatchMessageTestCallback(rawMessage) + } return rawMessage, nil } diff --git a/protocol/messenger_contacts.go b/protocol/messenger_contacts.go index f5e6d714c..bbbacb3b5 100644 --- a/protocol/messenger_contacts.go +++ b/protocol/messenger_contacts.go @@ -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)) @@ -286,23 +286,24 @@ func (m *Messenger) updateAcceptedContactRequest(response *MessengerResponse, co clock, _ := chat.NextClockAndTimestamp(m.transport) contact.AcceptContactRequest(clock) - acceptContactRequest := &protobuf.AcceptContactRequest{ - Id: contactRequest.ID, - Clock: clock, - } - encodedMessage, err := proto.Marshal(acceptContactRequest) - if err != nil { - return nil, err - } - - _, err = m.dispatchMessage(context.Background(), common.RawMessage{ - LocalChatID: contactRequest.From, - Payload: encodedMessage, - MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST, - ResendAutomatically: true, - }) - if err != nil { - return nil, err + if !fromSyncing { + acceptContactRequest := &protobuf.AcceptContactRequest{ + Id: contactRequest.ID, + Clock: clock, + } + encodedMessage, err := proto.Marshal(acceptContactRequest) + if err != nil { + return nil, err + } + _, err = m.dispatchMessage(context.Background(), common.RawMessage{ + LocalChatID: contactRequest.From, + Payload: encodedMessage, + MessageType: protobuf.ApplicationMetadataMessage_ACCEPT_CONTACT_REQUEST, + ResendAutomatically: true, + }) + if err != nil { + return nil, err + } } if response == nil { @@ -455,7 +456,7 @@ func (m *Messenger) addContact(ctx context.Context, pubKey, ensName, nickname, d } if len(contactRequestID) != 0 { - updatedResponse, err := m.updateAcceptedContactRequest(response, contactRequestID) + updatedResponse, err := m.updateAcceptedContactRequest(response, contactRequestID, false) if err != nil { return nil, err } diff --git a/protocol/messenger_handler.go b/protocol/messenger_handler.go index 7812bfe5b..d8bfefa53 100644 --- a/protocol/messenger_handler.go +++ b/protocol/messenger_handler.go @@ -3576,7 +3576,7 @@ func (m *Messenger) HandleSyncContactRequestDecision(state *ReceivedMessageState var response *MessengerResponse if message.DecisionStatus == protobuf.SyncContactRequestDecision_ACCEPTED { - response, err = m.updateAcceptedContactRequest(nil, message.RequestId) + response, err = m.updateAcceptedContactRequest(nil, message.RequestId, true) } else { response, err = m.declineContactRequest(message.RequestId, true) } diff --git a/protocol/messenger_sync_contact_request_decision_test.go b/protocol/messenger_sync_contact_request_decision_test.go new file mode 100644 index 000000000..0a5b9584f --- /dev/null +++ b/protocol/messenger_sync_contact_request_decision_test.go @@ -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") +}