From 6724cf4c753da412926e931996367a48c798f650 Mon Sep 17 00:00:00 2001 From: Andrea Maria Piana Date: Fri, 5 Nov 2021 15:11:10 +0000 Subject: [PATCH] Block contact endpoint --- protocol/contact.go | 1 + protocol/messenger.go | 3 + protocol/messenger_backup.go | 9 +- protocol/messenger_backup_test.go | 116 +++++++++++++++++++- protocol/messenger_chats.go | 28 ++++- protocol/messenger_contacts.go | 24 +++- protocol/messenger_handler.go | 8 +- protocol/messenger_mailserver.go | 2 +- protocol/messenger_test.go | 7 +- protocol/requests/create_one_to_one_chat.go | 3 +- services/ext/api.go | 6 +- waku/api.go | 1 - 12 files changed, 185 insertions(+), 23 deletions(-) diff --git a/protocol/contact.go b/protocol/contact.go index 4ff957738..c1ea43896 100644 --- a/protocol/contact.go +++ b/protocol/contact.go @@ -98,6 +98,7 @@ func (c Contact) PublicKey() (*ecdsa.PublicKey, error) { func (c *Contact) Block() { c.Blocked = true + c.Added = false } func (c *Contact) Unblock() { diff --git a/protocol/messenger.go b/protocol/messenger.go index 9efcb65de..15ce09cb4 100644 --- a/protocol/messenger.go +++ b/protocol/messenger.go @@ -3270,6 +3270,9 @@ func (m *Messenger) handleRetrievedMessages(chatWithMessages map[transport.Filte // Hydrate chat alias and identicon for id := range messageState.Response.chats { chat, _ := messageState.AllChats.Load(id) + if chat == nil { + continue + } if chat.OneToOne() { contact, ok := m.allContacts.Load(chat.ID) if ok { diff --git a/protocol/messenger_backup.go b/protocol/messenger_backup.go index 1553c5b52..b09bc0982 100644 --- a/protocol/messenger_backup.go +++ b/protocol/messenger_backup.go @@ -108,10 +108,11 @@ func (m *Messenger) BackupData(ctx context.Context) (uint64, error) { } _, err = m.dispatchMessage(ctx, common.RawMessage{ - LocalChatID: chat.ID, - Payload: encodedMessage, - SkipEncryption: true, - MessageType: protobuf.ApplicationMetadataMessage_BACKUP, + LocalChatID: chat.ID, + Payload: encodedMessage, + SkipEncryption: true, + SendOnPersonalTopic: true, + MessageType: protobuf.ApplicationMetadataMessage_BACKUP, }) if err != nil { return 0, err diff --git a/protocol/messenger_backup_test.go b/protocol/messenger_backup_test.go index 78bdc5b8a..9e87ce086 100644 --- a/protocol/messenger_backup_test.go +++ b/protocol/messenger_backup_test.go @@ -145,7 +145,7 @@ func (s *MessengerBackupSuite) TestBackupContactsGreaterThanBatch() { _, err = bob2.Start() s.Require().NoError(err) - // Create 2 contacts + // Create contacts for i := 0; i < BackupContactsPerBatch*2; i++ { @@ -270,3 +270,117 @@ func (s *MessengerBackupSuite) TestBackupRemovedContact() { s.Require().NotEmpty(lastBackup) s.Require().Equal(clock, lastBackup) } + +func (s *MessengerBackupSuite) TestBackupLocalNickname() { + bob1 := s.m + // Create bob2 + bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil) + nickname := "don van vliet" + s.Require().NoError(err) + _, err = bob2.Start() + s.Require().NoError(err) + + // Set contact nickname + + contact1Key, err := crypto.GenerateKey() + s.Require().NoError(err) + contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey)) + + _, err = bob1.SetContactLocalNickname(&requests.SetContactLocalNickname{ID: types.Hex2Bytes(contactID1), Nickname: nickname}) + s.Require().NoError(err) + + // Backup + + clock, err := bob1.BackupData(context.Background()) + s.Require().NoError(err) + + // Safety check + s.Require().Len(bob2.Contacts(), 0) + + var actualContact *Contact + // Wait for the message to reach its destination + _, err = WaitOnMessengerResponse( + bob2, + func(r *MessengerResponse) bool { + _, err := s.m.RetrieveAll() + if err != nil { + s.logger.Info("Failed") + return false + } + + for _, c := range bob2.Contacts() { + if c.ID == contactID1 { + actualContact = c + return true + } + } + return false + + }, + "contacts not backed up", + ) + s.Require().NoError(err) + + s.Require().Equal(actualContact.LocalNickname, nickname) + lastBackup, err := bob1.lastBackup() + s.Require().NoError(err) + s.Require().NotEmpty(lastBackup) + s.Require().Equal(clock, lastBackup) +} + +func (s *MessengerBackupSuite) TestBackupBlockedContacts() { + bob1 := s.m + // Create bob2 + bob2, err := newMessengerWithKey(s.shh, bob1.identity, s.logger, nil) + s.Require().NoError(err) + _, err = bob2.Start() + s.Require().NoError(err) + + // Create contact + contact1Key, err := crypto.GenerateKey() + s.Require().NoError(err) + contactID1 := types.EncodeHex(crypto.FromECDSAPub(&contact1Key.PublicKey)) + + _, err = bob1.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contactID1)}) + s.Require().NoError(err) + + // Backup + _, err = bob1.BackupData(context.Background()) + s.Require().NoError(err) + + // Safety check + s.Require().Len(bob2.Contacts(), 0) + + // Wait for the message to reach its destination + _, err = WaitOnMessengerResponse( + bob2, + func(r *MessengerResponse) bool { + return len(bob2.Contacts()) >= 1 + }, + "contacts not backed up", + ) + s.Require().NoError(err) + s.Require().Len(bob2.AddedContacts(), 1) + + actualContacts := bob2.AddedContacts() + s.Require().Equal(actualContacts[0].ID, contactID1) + + _, err = bob1.BlockContact(contactID1) + s.Require().NoError(err) + + // Backup + _, err = bob1.BackupData(context.Background()) + s.Require().NoError(err) + + // Wait for the message to reach its destination + _, err = WaitOnMessengerResponse( + bob2, + func(r *MessengerResponse) bool { + return len(bob2.BlockedContacts()) == 1 + + }, + "blocked contact not received", + ) + s.Require().NoError(err) + s.Require().Len(bob2.BlockedContacts(), 1) +} diff --git a/protocol/messenger_chats.go b/protocol/messenger_chats.go index d2e03ab32..ee5db1d98 100644 --- a/protocol/messenger_chats.go +++ b/protocol/messenger_chats.go @@ -257,6 +257,32 @@ func (m *Messenger) CreateOneToOneChat(request *requests.CreateOneToOneChat) (*M return nil, err } + response := &MessengerResponse{} + + ensName := request.ENSName + if ensName != "" { + clock := m.getTimesource().GetCurrentTime() + err := m.ensVerifier.ENSVerified(chatID, ensName, clock) + if err != nil { + return nil, err + } + contact, ok := m.allContacts.Load(chatID) + if !ok { + var err error + contact, err = buildContactFromPkString(chatID) + if err != nil { + return nil, err + } + } + contact.Name = ensName + contact.ENSVerified = true + err = m.persistence.SaveContact(contact, nil) + if err != nil { + return nil, err + } + response.Contacts = []*Contact{contact} + } + chat, ok := m.allChats.Load(chatID) if !ok { chat = CreateOneToOneChat(chatID, pk, m.getTimesource()) @@ -271,7 +297,6 @@ func (m *Messenger) CreateOneToOneChat(request *requests.CreateOneToOneChat) (*M // TODO(Samyoul) remove storing of an updated reference pointer? m.allChats.Store(chatID, chat) - response := &MessengerResponse{} response.AddChat(chat) willSync, err := m.scheduleSyncFilters(filters) @@ -291,7 +316,6 @@ func (m *Messenger) CreateOneToOneChat(request *requests.CreateOneToOneChat) (*M return nil, err } return response, nil - } func (m *Messenger) DeleteChat(chatID string) error { diff --git a/protocol/messenger_contacts.go b/protocol/messenger_contacts.go index 0ca8fdf90..ccabfb295 100644 --- a/protocol/messenger_contacts.go +++ b/protocol/messenger_contacts.go @@ -226,6 +226,17 @@ func (m *Messenger) AddedContacts() []*Contact { return contacts } +func (m *Messenger) BlockedContacts() []*Contact { + var contacts []*Contact + m.allContacts.Range(func(contactID string, contact *Contact) (shouldContinue bool) { + if contact.Blocked { + contacts = append(contacts, contact) + } + return true + }) + return contacts +} + // GetContactByID assumes pubKey includes 0x prefix func (m *Messenger) GetContactByID(pubKey string) *Contact { contact, _ := m.allContacts.Load(pubKey) @@ -263,6 +274,8 @@ func (m *Messenger) SetContactLocalNickname(request *requests.SetContactLocalNic return nil, err } + m.allContacts.Store(contact.ID, contact) + response := &MessengerResponse{} response.Contacts = []*Contact{contact} @@ -274,7 +287,16 @@ func (m *Messenger) SetContactLocalNickname(request *requests.SetContactLocalNic return response, nil } -func (m *Messenger) BlockContact(contact *Contact) ([]*Chat, error) { +func (m *Messenger) BlockContact(contactID string) ([]*Chat, error) { + contact, ok := m.allContacts.Load(contactID) + if !ok { + var err error + contact, err = buildContactFromPkString(contactID) + if err != nil { + return nil, err + } + + } contact.Block() contact.LastUpdatedLocally = m.getTimesource().GetCurrentTime() diff --git a/protocol/messenger_handler.go b/protocol/messenger_handler.go index 855cbf0d6..7c07cd967 100644 --- a/protocol/messenger_handler.go +++ b/protocol/messenger_handler.go @@ -290,7 +290,7 @@ func (m *Messenger) HandleSyncInstallationContact(state *ReceivedMessageState, m if !ok && (message.Added || message.Muted) && !removedOrBlcoked { pubKey, err := common.HexToPubkey(message.Id) if err != nil { - return nil + return err } chat = OneToOneFromPublicKey(pubKey, state.Timesource) @@ -329,7 +329,7 @@ func (m *Messenger) HandleSyncInstallationContact(state *ReceivedMessageState, m contact.Name = message.EnsName publicKey, err := contact.PublicKey() if err != nil { - return nil + return err } err = m.ENSVerified(common.PubkeyToHex(publicKey), message.EnsName) @@ -343,7 +343,8 @@ func (m *Messenger) HandleSyncInstallationContact(state *ReceivedMessageState, m if message.Blocked != contact.Blocked { if message.Blocked { - chats, err := m.BlockContact(contact) + state.AllContacts.Store(contact.ID, contact) + chats, err := m.BlockContact(contact.ID) if err != nil { return err } @@ -380,7 +381,6 @@ func (m *Messenger) HandleSyncInstallationContact(state *ReceivedMessageState, m } if chat != nil { - // TODO(samyoul) remove storing of an updated reference pointer? state.AllChats.Store(chat.ID, chat) } diff --git a/protocol/messenger_mailserver.go b/protocol/messenger_mailserver.go index e65e24271..1737f66f0 100644 --- a/protocol/messenger_mailserver.go +++ b/protocol/messenger_mailserver.go @@ -21,7 +21,7 @@ import ( // tolerance is how many seconds of potentially out-of-order messages we want to fetch var tolerance uint32 = 60 var mailserverRequestTimeout = 45 * time.Second -var oneMonthInSeconds uint32 = 31 * 24 * 60 * 6 +var oneMonthInSeconds uint32 = 31 * 24 * 60 * 60 func (m *Messenger) shouldSync() (bool, error) { if m.mailserver == nil || !m.online() { diff --git a/protocol/messenger_test.go b/protocol/messenger_test.go index cffb991a6..c381d37b1 100644 --- a/protocol/messenger_test.go +++ b/protocol/messenger_test.go @@ -712,7 +712,7 @@ func (s *MessengerSuite) TestRetrieveBlockedContact() { Blocked: true, } - _, err = s.m.BlockContact(&blockedContact) + _, err = s.m.BlockContact(blockedContact.ID) s.Require().NoError(err) inputMessage := buildTestMessage(*chat) @@ -1347,8 +1347,6 @@ func (s *MessengerSuite) TestBlockContact() { _, err := s.m.AddContact(context.Background(), &requests.AddContact{ID: types.Hex2Bytes(contact.ID)}) s.Require().NoError(err) - contact.Name = "blocked" - messages := []*common.Message{ { ID: "test-1", @@ -1430,7 +1428,7 @@ func (s *MessengerSuite) TestBlockContact() { err = s.m.SaveMessages(messages) s.Require().NoError(err) - response, err := s.m.BlockContact(&contact) + response, err := s.m.BlockContact(contact.ID) s.Require().NoError(err) var actualChat2, actualChat3 *Chat @@ -1456,7 +1454,6 @@ func (s *MessengerSuite) TestBlockContact() { // The contact is updated savedContacts := s.m.Contacts() s.Require().Equal(1, len(savedContacts)) - s.Require().Equal("blocked", savedContacts[0].Name) // The chat is deleted actualChats := s.m.Chats() diff --git a/protocol/requests/create_one_to_one_chat.go b/protocol/requests/create_one_to_one_chat.go index 7ae43bbb8..2f84ab424 100644 --- a/protocol/requests/create_one_to_one_chat.go +++ b/protocol/requests/create_one_to_one_chat.go @@ -9,7 +9,8 @@ import ( var ErrCreateOneToOneChatInvalidID = errors.New("create-one-to-one-chat: invalid id") type CreateOneToOneChat struct { - ID types.HexBytes `json:"id"` + ID types.HexBytes `json:"id"` + ENSName string `json:"ensName"` } func (c *CreateOneToOneChat) Validate() error { diff --git a/services/ext/api.go b/services/ext/api.go index 8dd769e53..17985f042 100644 --- a/services/ext/api.go +++ b/services/ext/api.go @@ -293,9 +293,9 @@ func (api *PublicAPI) UnmuteChat(parent context.Context, chatID string) error { return api.service.messenger.UnmuteChat(chatID) } -func (api *PublicAPI) BlockContact(parent context.Context, contact *protocol.Contact) ([]*protocol.Chat, error) { - api.log.Info("blocking contact", "contact", contact.ID) - return api.service.messenger.BlockContact(contact) +func (api *PublicAPI) BlockContact(parent context.Context, contactID string) ([]*protocol.Chat, error) { + api.log.Info("blocking contact", "contact", contactID) + return api.service.messenger.BlockContact(contactID) } func (api *PublicAPI) UnblockContact(parent context.Context, contactID string) error { diff --git a/waku/api.go b/waku/api.go index c6be44c70..9c6c2206d 100644 --- a/waku/api.go +++ b/waku/api.go @@ -484,7 +484,6 @@ func toMessage(messages []*common.ReceivedMessage) []*Message { // are received between the last poll and now. func (api *PublicWakuAPI) GetFilterMessages(id string) ([]*Message, error) { logger := api.w.logger.With(zap.String("site", "getFilterMessages"), zap.String("filterId", id)) - logger.Debug("retrieving filter messages") api.mu.Lock() f := api.w.GetFilter(id) if f == nil {