From c87d8c5f8e5c09e409e9d77405d485f8bb1c5388 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Wed, 21 Jun 2023 14:08:50 -0400 Subject: [PATCH] conversation_module: fix decline request on removeContact erase is ok if conversation is accepted, not removed, else it cannot be synced with other devices Change-Id: Ia5425cb8d0dbe635b2d7db3a45de6d6b9683100d --- src/jamidht/conversation_module.cpp | 14 ++-- .../conversation/conversationRequest.cpp | 72 +++++++++++++++++++ 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/src/jamidht/conversation_module.cpp b/src/jamidht/conversation_module.cpp index 6cefe3dbb9..8b352e26df 100644 --- a/src/jamidht/conversation_module.cpp +++ b/src/jamidht/conversation_module.cpp @@ -2300,19 +2300,19 @@ ConversationModule::removeContact(const std::string& uri, bool banned) { std::lock_guard<std::mutex> lk(pimpl_->conversationsRequestsMtx_); auto update = false; - auto it = pimpl_->conversationsRequests_.begin(); - while (it != pimpl_->conversationsRequests_.end()) { - if (it->second.from == uri) { + for (auto it = pimpl_->conversationsRequests_.begin(); it != pimpl_->conversationsRequests_.end(); ++it) { + if (it->second.from == uri && !it->second.declined) { + JAMI_DEBUG("Declining conversation request {:s} from {:s}", it->first, uri); emitSignal<libjami::ConversationSignal::ConversationRequestDeclined>( pimpl_->accountId_, it->first); update = true; - it = pimpl_->conversationsRequests_.erase(it); - } else { - ++it; + it->second.declined = std::time(nullptr); } } - if (update) + if (update) { pimpl_->saveConvRequests(); + pimpl_->needsSyncingCb_({}); + } } if (banned) return; // Keep the conversation in banned model diff --git a/test/unitTest/conversation/conversationRequest.cpp b/test/unitTest/conversation/conversationRequest.cpp index 408914e965..2c4f7511f3 100644 --- a/test/unitTest/conversation/conversationRequest.cpp +++ b/test/unitTest/conversation/conversationRequest.cpp @@ -64,6 +64,7 @@ public: void testAddContactDeleteAndReAdd(); void testInviteFromMessageAfterRemoved(); void testRemoveContact(); + void testRemoveContactMultiDevice(); void testRemoveSelfDoesntRemoveConversation(); void testRemoveConversationUpdateContactDetails(); void testBanContact(); @@ -93,6 +94,7 @@ private: CPPUNIT_TEST(testAddContactDeleteAndReAdd); CPPUNIT_TEST(testInviteFromMessageAfterRemoved); CPPUNIT_TEST(testRemoveContact); + CPPUNIT_TEST(testRemoveContactMultiDevice); CPPUNIT_TEST(testRemoveSelfDoesntRemoveConversation); CPPUNIT_TEST(testRemoveConversationUpdateContactDetails); CPPUNIT_TEST(testBanContact); @@ -715,6 +717,76 @@ ConversationRequestTest::testRemoveContact() CPPUNIT_ASSERT(!fileutils::isDirectory(repoPath)); } +void +ConversationRequestTest::testRemoveContactMultiDevice() +{ + auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); + auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId); + auto bobUri = bobAccount->getUsername(); + auto aliceUri = aliceAccount->getUsername(); + std::mutex mtx; + std::unique_lock<std::mutex> lk {mtx}; + std::condition_variable cv; + + // Add second device for Bob + std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers; + auto bobArchive = std::filesystem::current_path().string() + "/bob.gz"; + std::remove(bobArchive.c_str()); + bobAccount->exportArchive(bobArchive); + + std::map<std::string, std::string> details = libjami::getAccountTemplate("RING"); + details[ConfProperties::TYPE] = "RING"; + details[ConfProperties::DISPLAYNAME] = "BOB2"; + details[ConfProperties::ALIAS] = "BOB2"; + details[ConfProperties::UPNP_ENABLED] = "true"; + details[ConfProperties::ARCHIVE_PASSWORD] = ""; + details[ConfProperties::ARCHIVE_PIN] = ""; + details[ConfProperties::ARCHIVE_PATH] = bobArchive; + + bob2Id = Manager::instance().addAccount(details); + + wait_for_announcement_of(bob2Id); + auto bob2Account = Manager::instance().getAccount<JamiAccount>(bob2Id); + + bool requestB1Removed = false, requestB2Removed = false, requestB1Received = false, requestB2Received = false; + confHandlers.insert( + libjami::exportable_callback<libjami::ConfigurationSignal::IncomingTrustRequest>( + [&](const std::string& account_id, + const std::string& /*from*/, + const std::string& /*conversationId*/, + const std::vector<uint8_t>& /*payload*/, + time_t /*received*/) { + if (account_id == bobId) + requestB1Received = true; + else if (account_id == bob2Id) + requestB2Received = true; + cv.notify_one(); + })); + confHandlers.insert( + libjami::exportable_callback<libjami::ConversationSignal::ConversationRequestDeclined>( + [&](const std::string& accountId, const std::string&) { + if (accountId == bobId) { + requestB1Removed = true; + } else if (accountId == bob2Id) { + requestB2Removed = true; + } + cv.notify_one(); + })); + libjami::registerSignalHandlers(confHandlers); + + // First, Alice adds Bob + aliceAccount->addContact(bobUri); + aliceAccount->sendTrustRequest(bobUri, {}); + CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { + return requestB1Received && requestB2Received; + })); + + // Bob1 decline via removeContact, both device should remove the request + bobAccount->removeContact(aliceUri, false); + CPPUNIT_ASSERT( + cv.wait_for(lk, 30s, [&]() { return requestB1Removed && requestB2Removed; })); +} + void ConversationRequestTest::testRemoveSelfDoesntRemoveConversation() { -- GitLab