diff --git a/src/jamidht/conversationrepository.cpp b/src/jamidht/conversationrepository.cpp index 1442f507a4b49504d2e5de7a4978796a937295ff..d08538f72c5a645cc231eb8954ad9383f1ea1676 100644 --- a/src/jamidht/conversationrepository.cpp +++ b/src/jamidht/conversationrepository.cpp @@ -84,7 +84,9 @@ public: const std::string& commitId, const std::string& parentId) const; bool isValidUserAtCommit(const std::string& userDevice, const std::string& commitId) const; - bool checkInitialCommit(const std::string& userDevice, const std::string& commitId) const; + bool checkInitialCommit(const std::string& userDevice, + const std::string& commitId, + const std::string& commitMsg) const; bool checkValidAdd(const std::string& userDevice, const std::string& uriMember, const std::string& commitid, @@ -1168,7 +1170,8 @@ ConversationRepository::Impl::isValidUserAtCommit(const std::string& userDevice, bool ConversationRepository::Impl::checkInitialCommit(const std::string& userDevice, - const std::string& commitId) const + const std::string& commitId, + const std::string& commitMsg) const { auto account = account_.lock(); if (!account) @@ -1189,11 +1192,24 @@ ConversationRepository::Impl::checkInitialCommit(const std::string& userDevice, return false; } + std::string invited = {}; + if (mode_ == ConversationMode::ONE_TO_ONE) { + std::string err; + Json::Value cm; + Json::CharReaderBuilder rbuilder; + auto reader = std::unique_ptr<Json::CharReader>(rbuilder.newCharReader()); + if (reader->parse(commitMsg.data(), commitMsg.data() + commitMsg.size(), &cm, &err)) { + invited = cm["invited"].asString(); + } else { + JAMI_WARN("%s", err.c_str()); + } + } + auto hasDevice = false, hasAdmin = false; std::string adminsFile = std::string("admins") + "/" + userUri + ".crt"; std::string deviceFile = std::string("devices") + "/" + userDevice + ".crt"; - std::string invitedFile = std::string("invited") + "/" + account->getUsername(); std::string crlFile = std::string("CRLs") + "/" + userUri; + std::string invitedFile = std::string("invited") + "/" + invited; // Check that admin cert is added // Check that device cert is added // Check CRLs added @@ -1204,13 +1220,11 @@ ConversationRepository::Impl::checkInitialCommit(const std::string& userDevice, hasAdmin = true; } else if (changedFile == deviceFile) { hasDevice = true; - } else if (changedFile == crlFile) { - // Nothing to do - } else if (changedFile == invitedFile && mode_ == ConversationMode::ONE_TO_ONE) { + } else if (changedFile == crlFile || changedFile == invitedFile) { // Nothing to do } else { // Invalid file detected - JAMI_ERR("Invalid add file detected: %s", changedFile.c_str()); + JAMI_ERR("Invalid add file detected: %s %u", changedFile.c_str(), (int) *mode_); return false; } } @@ -1979,7 +1993,7 @@ ConversationRepository::Impl::validCommits( auto userDevice = commit.author.email; auto validUserAtCommit = commit.id; if (commit.parents.size() == 0) { - if (!checkInitialCommit(userDevice, commit.id)) { + if (!checkInitialCommit(userDevice, commit.id, commit.commit_msg)) { JAMI_WARN("Malformed initial commit %s. Please check you use the latest " "version of Jami, or that your contact is not doing unwanted stuff.", commit.id.c_str()); diff --git a/test/unitTest/syncHistory/syncHistory.cpp b/test/unitTest/syncHistory/syncHistory.cpp index 0bae77f930bf18bac4c743ff0880962cb67f32cc..bc4dae93eeec018774d74a4c49fb93cfb4fb14d0 100644 --- a/test/unitTest/syncHistory/syncHistory.cpp +++ b/test/unitTest/syncHistory/syncHistory.cpp @@ -67,6 +67,7 @@ private: void testSyncCreateAccountExportDeleteReimportOldBackup(); void testSyncCreateAccountExportDeleteReimportWithConvId(); void testSyncCreateAccountExportDeleteReimportWithConvReq(); + void testSyncOneToOne(); CPPUNIT_TEST_SUITE(SyncHistoryTest); CPPUNIT_TEST(testCreateConversationThenSync); @@ -78,6 +79,7 @@ private: CPPUNIT_TEST(testSyncCreateAccountExportDeleteReimportOldBackup); CPPUNIT_TEST(testSyncCreateAccountExportDeleteReimportWithConvId); CPPUNIT_TEST(testSyncCreateAccountExportDeleteReimportWithConvReq); + CPPUNIT_TEST(testSyncOneToOne); CPPUNIT_TEST_SUITE_END(); }; @@ -804,6 +806,62 @@ SyncHistoryTest::testSyncCreateAccountExportDeleteReimportWithConvReq() std::remove(aliceArchive.c_str()); } +void +SyncHistoryTest::testSyncOneToOne() +{ + auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId); + auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId); + // Start conversation + std::string convId; + + std::mutex mtx; + std::unique_lock<std::mutex> lk {mtx}; + std::condition_variable cv; + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers; + auto conversationReady = false, alice2Ready = false; + confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>( + [&](const std::string& accountId, const std::string& conversationId) { + if (accountId == aliceId) + convId = conversationId; + else if (accountId == alice2Id && conversationId == convId) + conversationReady = true; + cv.notify_one(); + })); + confHandlers.insert( + DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>( + [&](const std::string& accountId, const std::map<std::string, std::string>& details) { + if (alice2Id != accountId) { + return; + } + alice2Ready = details.at(DRing::Account::VolatileProperties::DEVICE_ANNOUNCED) + == "true"; + cv.notify_one(); + })); + DRing::registerSignalHandlers(confHandlers); + + aliceAccount->addContact(bobAccount->getUsername()); + CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { return !convId.empty(); })); + + // Now create alice2 + auto aliceArchive = std::filesystem::current_path().string() + "/alice.gz"; + std::remove(aliceArchive.c_str()); + aliceAccount->exportArchive(aliceArchive); + std::map<std::string, std::string> details = DRing::getAccountTemplate("RING"); + details[ConfProperties::TYPE] = "RING"; + details[ConfProperties::DISPLAYNAME] = "ALICE2"; + details[ConfProperties::ALIAS] = "ALICE2"; + details[ConfProperties::UPNP_ENABLED] = "true"; + details[ConfProperties::ARCHIVE_PASSWORD] = ""; + details[ConfProperties::ARCHIVE_PIN] = ""; + details[ConfProperties::ARCHIVE_PATH] = aliceArchive; + + alice2Id = Manager::instance().addAccount(details); + CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&] { + return alice2Ready && conversationReady; + })); + std::remove(aliceArchive.c_str()); +} + } // namespace test } // namespace jami