diff --git a/src/jamidht/account_manager.h b/src/jamidht/account_manager.h index bd3f8490998a8c926ec2ff7c3b9de0f742eac70b..dfe97618e45993f5eb187af665a0aee7428250da 100644 --- a/src/jamidht/account_manager.h +++ b/src/jamidht/account_manager.h @@ -67,20 +67,17 @@ dynamic_unique_cast(std::unique_ptr<From>&& p) return {}; } -class AccountManager +class AccountManager: public std::enable_shared_from_this<AccountManager> { public: - using AsyncUser = std::function<void(AccountManager&)>; - using OnAsync = std::function<void(AsyncUser&&)>; using OnChangeCallback = ContactList::OnChangeCallback; using clock = std::chrono::system_clock; using time_point = clock::time_point; using OnNewDeviceCb = std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>; using OnDeviceAnnouncedCb = std::function<void()>; - AccountManager(const std::string& path, OnAsync&& onAsync, const std::string& nameServer) + AccountManager(const std::string& path, const std::string& nameServer) : path_(path) - , onAsync_(std::move(onAsync)) , nameDir_(NameDirectory::instance(nameServer)) {}; virtual ~AccountManager(); @@ -269,7 +266,6 @@ public: protected: std::string path_; - OnAsync onAsync_; OnChangeCallback onChange_; std::unique_ptr<AccountInfo> info_; std::shared_ptr<dht::DhtRunner> dht_; diff --git a/src/jamidht/archive_account_manager.cpp b/src/jamidht/archive_account_manager.cpp index 9b887bb4bec4b43d235975ee3a90e72ec9ec6696..63fa1e11b1bbb864823fc6455c12a6a3c2595314 100644 --- a/src/jamidht/archive_account_manager.cpp +++ b/src/jamidht/archive_account_manager.cpp @@ -66,53 +66,52 @@ ArchiveAccountManager::initAuthentication(const std::string& accountId, return; } - dht::ThreadPool::computation().run([ctx = std::move(ctx), onAsync = onAsync_]() mutable { - onAsync([ctx = std::move(ctx)](AccountManager& accountManager) mutable { - auto& this_ = *static_cast<ArchiveAccountManager*>(&accountManager); - try { - if (ctx->credentials->scheme == "file") { - // Import from external archive - this_.loadFromFile(*ctx); - } else { - // Create/migrate local account - bool hasArchive = not ctx->credentials->uri.empty() - and fileutils::isFile(ctx->credentials->uri); - if (hasArchive) { - // Create/migrate from local archive - if (ctx->credentials->updateIdentity.first - and ctx->credentials->updateIdentity.second - and needsMigration(ctx->credentials->updateIdentity)) { - this_.migrateAccount(*ctx); - } else { - this_.loadFromFile(*ctx); - } - } else if (ctx->credentials->updateIdentity.first - and ctx->credentials->updateIdentity.second) { - auto future_keypair = dht::ThreadPool::computation().get<dev::KeyPair>( - &dev::KeyPair::create); - AccountArchive a; - JAMI_WARN("[Auth] converting certificate from old account %s", - ctx->credentials->updateIdentity.first->getPublicKey() - .getId() - .toString() - .c_str()); - a.id = std::move(ctx->credentials->updateIdentity); - try { - a.ca_key = std::make_shared<dht::crypto::PrivateKey>( - fileutils::loadFile("ca.key", this_.path_)); - } catch (...) { - } - this_.updateCertificates(a, ctx->credentials->updateIdentity); - a.eth_key = future_keypair.get().secret().makeInsecure().asBytes(); - this_.onArchiveLoaded(*ctx, std::move(a)); + dht::ThreadPool::computation().run([ctx = std::move(ctx), w = weak_from_this()] mutable { + auto this_ = std::static_pointer_cast<ArchiveAccountManager>(w.lock()); + if (not this_) return; + try { + if (ctx->credentials->scheme == "file") { + // Import from external archive + this_->loadFromFile(*ctx); + } else { + // Create/migrate local account + bool hasArchive = not ctx->credentials->uri.empty() + and fileutils::isFile(ctx->credentials->uri); + if (hasArchive) { + // Create/migrate from local archive + if (ctx->credentials->updateIdentity.first + and ctx->credentials->updateIdentity.second + and needsMigration(ctx->credentials->updateIdentity)) { + this_->migrateAccount(*ctx); } else { - this_.createAccount(*ctx); + this_->loadFromFile(*ctx); + } + } else if (ctx->credentials->updateIdentity.first + and ctx->credentials->updateIdentity.second) { + auto future_keypair = dht::ThreadPool::computation().get<dev::KeyPair>( + &dev::KeyPair::create); + AccountArchive a; + JAMI_WARN("[Auth] converting certificate from old account %s", + ctx->credentials->updateIdentity.first->getPublicKey() + .getId() + .toString() + .c_str()); + a.id = std::move(ctx->credentials->updateIdentity); + try { + a.ca_key = std::make_shared<dht::crypto::PrivateKey>( + fileutils::loadFile("ca.key", this_->path_)); + } catch (...) { } + this_->updateCertificates(a, ctx->credentials->updateIdentity); + a.eth_key = future_keypair.get().secret().makeInsecure().asBytes(); + this_->onArchiveLoaded(*ctx, std::move(a)); + } else { + this_->createAccount(*ctx); } - } catch (const std::exception& e) { - ctx->onFailure(AuthError::UNKNOWN, e.what()); } - }); + } catch (const std::exception& e) { + ctx->onFailure(AuthError::UNKNOWN, e.what()); + } }); } @@ -283,7 +282,7 @@ ArchiveAccountManager::loadFromDHT(const std::shared_ptr<AuthContext>& ctx) } }; - auto search = [ctx, searchEnded, onAsync = onAsync_](bool previous) { + auto search = [ctx, searchEnded, w=weak_from_this()](bool previous) { std::vector<uint8_t> key; dht::InfoHash loc; auto& s = previous ? ctx->dhtContext->stateOld : ctx->dhtContext->stateNew; @@ -301,7 +300,7 @@ ArchiveAccountManager::loadFromDHT(const std::shared_ptr<AuthContext>& ctx) } ctx->dhtContext->dht.get( loc, - [ctx, key = std::move(key), onAsync](const std::shared_ptr<dht::Value>& val) { + [ctx, key = std::move(key), w](const std::shared_ptr<dht::Value>& val) { std::vector<uint8_t> decrypted; try { decrypted = archiver::decompress(dht::crypto::aesDecrypt(val->data, key)); @@ -311,19 +310,17 @@ ArchiveAccountManager::loadFromDHT(const std::shared_ptr<AuthContext>& ctx) JAMI_DBG("[Auth] found archive on the DHT"); ctx->dhtContext->found = true; dht::ThreadPool::computation().run([ctx, - decrypted = std::move(decrypted), - onAsync] { + decrypted = std::move(decrypted), w] { try { auto archive = AccountArchive(decrypted); - onAsync([&](AccountManager& accountManager) { - auto& this_ = *static_cast<ArchiveAccountManager*>(&accountManager); + if (auto sthis = std::static_pointer_cast<ArchiveAccountManager>(w.lock())) { if (ctx->dhtContext) { ctx->dhtContext->dht.join(); ctx->dhtContext.reset(); } - this_.onArchiveLoaded(*ctx, + sthis->onArchiveLoaded(*ctx, std::move(archive) /*, std::move(contacts)*/); - }); + } } catch (const std::exception& e) { ctx->onFailure(AuthError::UNKNOWN, ""); } @@ -671,53 +668,51 @@ generatePIN(size_t length = 16, size_t split = 8) void ArchiveAccountManager::addDevice(const std::string& password, AddDeviceCallback cb) { - dht::ThreadPool::computation().run([onAsync = onAsync_, password, cb = std::move(cb)]() mutable { - onAsync([password = std::move(password), - cb = std::move(cb)](AccountManager& accountManager) mutable { - auto& this_ = *static_cast<ArchiveAccountManager*>(&accountManager); - - std::vector<uint8_t> key; - dht::InfoHash loc; - std::string pin_str; - AccountArchive a; - try { - JAMI_DBG("[Auth] exporting account"); + dht::ThreadPool::computation().run([password, cb = std::move(cb), w=weak_from_this()] mutable { + auto this_ = std::static_pointer_cast<ArchiveAccountManager>(w.lock()); + if (not this_) return; - a = this_.readArchive(password); + std::vector<uint8_t> key; + dht::InfoHash loc; + std::string pin_str; + AccountArchive a; + try { + JAMI_DBG("[Auth] exporting account"); - // Generate random PIN - pin_str = generatePIN(); + a = this_->readArchive(password); - std::tie(key, loc) = computeKeys(password, pin_str); - } catch (const std::exception& e) { - JAMI_ERR("[Auth] can't export account: %s", e.what()); - cb(AddDeviceResult::ERROR_CREDENTIALS, {}); - return; - } - // now that key and loc are computed, display to user in lowercase - std::transform(pin_str.begin(), pin_str.end(), pin_str.begin(), ::tolower); - try { - this_.updateArchive(a); - auto encrypted = dht::crypto::aesEncrypt(archiver::compress(a.serialize()), key); - if (not this_.dht_ or not this_.dht_->isRunning()) - throw std::runtime_error("DHT is not running.."); - JAMI_WARN("[Auth] exporting account with PIN: %s at %s (size %zu)", - pin_str.c_str(), - loc.toString().c_str(), - encrypted.size()); - this_.dht_->put(loc, encrypted, [cb, pin = std::move(pin_str)](bool ok) { - JAMI_DBG("[Auth] account archive published: %s", ok ? "success" : "failure"); - if (ok) - cb(AddDeviceResult::SUCCESS_SHOW_PIN, pin); - else - cb(AddDeviceResult::ERROR_NETWORK, {}); - }); - } catch (const std::exception& e) { - JAMI_ERR("[Auth] can't export account: %s", e.what()); - cb(AddDeviceResult::ERROR_NETWORK, {}); - return; - } - }); + // Generate random PIN + pin_str = generatePIN(); + + std::tie(key, loc) = computeKeys(password, pin_str); + } catch (const std::exception& e) { + JAMI_ERR("[Auth] can't export account: %s", e.what()); + cb(AddDeviceResult::ERROR_CREDENTIALS, {}); + return; + } + // now that key and loc are computed, display to user in lowercase + std::transform(pin_str.begin(), pin_str.end(), pin_str.begin(), ::tolower); + try { + this_->updateArchive(a); + auto encrypted = dht::crypto::aesEncrypt(archiver::compress(a.serialize()), key); + if (not this_->dht_ or not this_->dht_->isRunning()) + throw std::runtime_error("DHT is not running.."); + JAMI_WARN("[Auth] exporting account with PIN: %s at %s (size %zu)", + pin_str.c_str(), + loc.toString().c_str(), + encrypted.size()); + this_->dht_->put(loc, encrypted, [cb, pin = std::move(pin_str)](bool ok) { + JAMI_DBG("[Auth] account archive published: %s", ok ? "success" : "failure"); + if (ok) + cb(AddDeviceResult::SUCCESS_SHOW_PIN, pin); + else + cb(AddDeviceResult::ERROR_NETWORK, {}); + }); + } catch (const std::exception& e) { + JAMI_ERR("[Auth] can't export account: %s", e.what()); + cb(AddDeviceResult::ERROR_NETWORK, {}); + return; + } }); } @@ -730,45 +725,40 @@ ArchiveAccountManager::revokeDevice( auto fa = dht::ThreadPool::computation().getShared<AccountArchive>( [this, password] { return readArchive(password); }); findCertificate(DeviceId(device), - [fa = std::move(fa), password, device, cb, onAsync = onAsync_]( - const std::shared_ptr<dht::crypto::Certificate>& crt) mutable { - if (not crt) { - cb(RevokeDeviceResult::ERROR_NETWORK); - return; - } - onAsync([cb, - crt = std::move(crt), - fa = std::move(fa), - password = std::move(password)]( - AccountManager& accountManager) mutable { - auto& this_ = *static_cast<ArchiveAccountManager*>(&accountManager); - this_.info_->contacts->foundAccountDevice(crt); - AccountArchive a; - try { - a = fa.get(); - } catch (...) { - cb(RevokeDeviceResult::ERROR_CREDENTIALS); - return; - } - // Add revoked device to the revocation list and resign it - if (not a.revoked) - a.revoked = std::make_shared<decltype(a.revoked)::element_type>(); - a.revoked->revoke(*crt); - a.revoked->sign(a.id); - // add to CRL cache - this_.certStore().pinRevocationList(a.id.second->getId().toString(), a.revoked); - this_.certStore().loadRevocations(*a.id.second); - - // Announce CRL immediately - auto h = a.id.second->getId(); - this_.dht_->put(h, a.revoked, dht::DoneCallback {}, {}, true); - - this_.saveArchive(a, password); - this_.info_->contacts->removeAccountDevice(crt->getLongId()); - cb(RevokeDeviceResult::SUCCESS); - this_.syncDevices(); - }); - }); + [fa = std::move(fa), password, device, cb, w=weak_from_this()]( + const std::shared_ptr<dht::crypto::Certificate>& crt) mutable { + if (not crt) { + cb(RevokeDeviceResult::ERROR_NETWORK); + return; + } + auto this_ = std::static_pointer_cast<ArchiveAccountManager>(w.lock()); + if (not this_) return; + this_->info_->contacts->foundAccountDevice(crt); + AccountArchive a; + try { + a = fa.get(); + } catch (...) { + cb(RevokeDeviceResult::ERROR_CREDENTIALS); + return; + } + // Add revoked device to the revocation list and resign it + if (not a.revoked) + a.revoked = std::make_shared<decltype(a.revoked)::element_type>(); + a.revoked->revoke(*crt); + a.revoked->sign(a.id); + // add to CRL cache + this_->certStore().pinRevocationList(a.id.second->getId().toString(), a.revoked); + this_->certStore().loadRevocations(*a.id.second); + + // Announce CRL immediately + auto h = a.id.second->getId(); + this_->dht_->put(h, a.revoked, dht::DoneCallback {}, {}, true); + + this_->saveArchive(a, password); + this_->info_->contacts->removeAccountDevice(crt->getLongId()); + cb(RevokeDeviceResult::SUCCESS); + this_->syncDevices(); + }); return false; } diff --git a/src/jamidht/archive_account_manager.h b/src/jamidht/archive_account_manager.h index 5d1181f3f465b6cbd657f51c3575e699955a39c9..dfd5ae4a38e683736f9ac2442dc284a014938a7e 100644 --- a/src/jamidht/archive_account_manager.h +++ b/src/jamidht/archive_account_manager.h @@ -27,11 +27,10 @@ public: using OnExportConfig = std::function<std::map<std::string, std::string>()>; ArchiveAccountManager(const std::string& path, - OnAsync&& onAsync, OnExportConfig&& onExportConfig, std::string archivePath, const std::string& nameServer) - : AccountManager(path, std::move(onAsync), nameServer) + : AccountManager(path, nameServer) , onExportConfig_(std::move(onExportConfig)) , archivePath_(std::move(archivePath)) {} diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp index 0fe2858d4bba820cf850c4efcfcf0cbe95e5bc7a..d1f7527d5143df7f201fd809a38982cedefcb565 100644 --- a/src/jamidht/jamiaccount.cpp +++ b/src/jamidht/jamiaccount.cpp @@ -269,11 +269,11 @@ dhtStatusStr(dht::NodeStatus status) JamiAccount::JamiAccount(const std::string& accountId) : SIPAccountBase(accountId) - , certStore_ {std::make_unique<dhtnet::tls::CertificateStore>(idPath_, Logger::dhtLogger())} - , dht_(new dht::DhtRunner) , idPath_(fileutils::get_data_dir() + DIR_SEPARATOR_STR + accountId) , cachePath_(fileutils::get_cache_dir() + DIR_SEPARATOR_STR + accountId) , dataPath_(cachePath_ + DIR_SEPARATOR_STR "values") + , certStore_ {std::make_unique<dhtnet::tls::CertificateStore>(idPath_, Logger::dhtLogger())} + , dht_(new dht::DhtRunner) , connectionManager_ {} , nonSwarmTransferManager_(std::make_shared<TransferManager>(accountId, "")) {} @@ -1177,20 +1177,14 @@ JamiAccount::loadAccount(const std::string& archive_password, const auto& conf = config(); try { - auto onAsync = [w = weak()](AccountManager::AsyncUser&& cb) { - if (auto this_ = w.lock()) - cb(*this_->accountManager_); - }; if (conf.managerUri.empty()) { - accountManager_.reset(new ArchiveAccountManager( + accountManager_ = std::make_shared<ArchiveAccountManager>( getPath(), - onAsync, [this]() { return getAccountDetails(); }, conf.archivePath.empty() ? "archive.gz" : conf.archivePath, - conf.nameServer)); + conf.nameServer); } else { - accountManager_.reset( - new ServerAccountManager(getPath(), onAsync, conf.managerUri, conf.nameServer)); + accountManager_ = std::make_shared<ServerAccountManager>(getPath(), conf.managerUri, conf.nameServer); } auto id = accountManager_->loadIdentity(getAccountID(), @@ -1265,10 +1259,12 @@ JamiAccount::loadAccount(const std::string& archive_password, fDeviceKey, ip_utils::getDeviceName(), std::move(creds), - [this, migrating, hasPassword](const AccountInfo& info, + [w=weak(), this, migrating, hasPassword](const AccountInfo& info, const std::map<std::string, std::string>& config, std::string&& receipt, std::vector<uint8_t>&& receipt_signature) { + auto sthis = w.lock(); + if (not sthis) return; JAMI_LOG("[Account {}] Auth success!", getAccountID()); fileutils::check_dir(idPath_.c_str(), 0700); diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h index dc85f4527977ae120dd52927798b4080439fc12a..919af7d415f4780e3faf5ec46b232872ce5da265 100644 --- a/src/jamidht/jamiaccount.h +++ b/src/jamidht/jamiaccount.h @@ -698,6 +698,10 @@ private: void newSwarmOutgoingCallHelper(const std::shared_ptr<SIPCall>& call, const Uri& uri); std::shared_ptr<SIPCall> createSubCall(const std::shared_ptr<SIPCall>& mainCall); + std::string idPath_ {}; + std::string cachePath_ {}; + std::string dataPath_ {}; + #if HAVE_RINGNS std::string registeredName_; #endif @@ -705,16 +709,13 @@ private: std::unique_ptr<dhtnet::tls::CertificateStore> certStore_; std::shared_ptr<dht::DhtRunner> dht_ {}; - std::unique_ptr<AccountManager> accountManager_; + std::shared_ptr<AccountManager> accountManager_; dht::crypto::Identity id_ {}; mutable std::mutex messageMutex_ {}; std::map<dht::Value::Id, PendingMessage> sentMessages_; std::set<std::string, std::less<>> treatedMessages_ {}; - std::string idPath_ {}; - std::string cachePath_ {}; - std::string dataPath_ {}; /* tracked buddies presence */ mutable std::mutex buddyInfoMtx; diff --git a/src/jamidht/server_account_manager.cpp b/src/jamidht/server_account_manager.cpp index 03ed1e029337f906c19454d8a076bf8822051fb7..e1b57f5ec3727f6b68a71810e659999146eb8f69 100644 --- a/src/jamidht/server_account_manager.cpp +++ b/src/jamidht/server_account_manager.cpp @@ -43,10 +43,9 @@ constexpr std::string_view PATH_SEARCH = JAMI_PATH_AUTH "/directory/search"; constexpr std::string_view PATH_CONTACTS = JAMI_PATH_AUTH "/contacts"; ServerAccountManager::ServerAccountManager(const std::string& path, - OnAsync&& onAsync, const std::string& managerHostname, const std::string& nameServer) - : AccountManager(path, std::move(onAsync), nameServer) + : AccountManager(path, nameServer) , managerHostname_(managerHostname) , logger_(Logger::dhtLogger()) {} @@ -84,131 +83,125 @@ ServerAccountManager::initAuthentication(const std::string& accountId, ctx->credentials->username.c_str(), url.c_str()); - dht::ThreadPool::computation().run([onAsync = onAsync_, ctx, url] { - onAsync([=](AccountManager& accountManager) { - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - Json::Value body; - { - auto csr = ctx->request.get()->toString(); - body["csr"] = csr; - body["deviceName"] = ctx->deviceName; - } - auto request = std::make_shared<Request>( - *Manager::instance().ioContext(), - url, - body, - [ctx, onAsync](Json::Value json, const dht::http::Response& response) { - JAMI_DBG("[Auth] Got request callback with status code=%u", - response.status_code); - if (response.status_code == 0) - ctx->onFailure(AuthError::SERVER_ERROR, "Can't connect to server"); - else if (response.status_code >= 400 && response.status_code < 500) - ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); - else if (response.status_code < 200 || response.status_code > 299) - ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); - else { - do { - try { - JAMI_WARNING("[Auth] Got server response: {}", response.body); - auto cert = std::make_shared<dht::crypto::Certificate>( - json["certificateChain"].asString()); - auto accountCert = cert->issuer; - if (not accountCert) { - JAMI_ERR("[Auth] Can't parse certificate: no issuer"); - ctx->onFailure(AuthError::SERVER_ERROR, - "Invalid certificate from server"); - break; - } - auto receipt = json["deviceReceipt"].asString(); - Json::Value receiptJson; - std::string err; - auto receiptReader = std::unique_ptr<Json::CharReader>( - Json::CharReaderBuilder {}.newCharReader()); - if (!receiptReader->parse(receipt.data(), - receipt.data() + receipt.size(), - &receiptJson, - &err)) { - JAMI_ERR("[Auth] Can't parse receipt from server: %s", - err.c_str()); - ctx->onFailure(AuthError::SERVER_ERROR, - "Can't parse receipt from server"); - break; + dht::ThreadPool::computation().run([ctx, url, w=weak_from_this()] { + auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock()); + if (not this_) return; + Json::Value body; + { + auto csr = ctx->request.get()->toString(); + body["csr"] = csr; + body["deviceName"] = ctx->deviceName; + } + auto request = std::make_shared<Request>( + *Manager::instance().ioContext(), + url, + body, + [ctx, w](Json::Value json, const dht::http::Response& response) { + JAMI_DBG("[Auth] Got request callback with status code=%u", + response.status_code); + auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock()); + if (response.status_code == 0 || this_ == nullptr) + ctx->onFailure(AuthError::SERVER_ERROR, "Can't connect to server"); + else if (response.status_code >= 400 && response.status_code < 500) + ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); + else if (response.status_code < 200 || response.status_code > 299) + ctx->onFailure(AuthError::INVALID_ARGUMENTS, ""); + else { + do { + try { + JAMI_WARNING("[Auth] Got server response: {}", response.body); + auto cert = std::make_shared<dht::crypto::Certificate>( + json["certificateChain"].asString()); + auto accountCert = cert->issuer; + if (not accountCert) { + JAMI_ERR("[Auth] Can't parse certificate: no issuer"); + ctx->onFailure(AuthError::SERVER_ERROR, + "Invalid certificate from server"); + break; + } + auto receipt = json["deviceReceipt"].asString(); + Json::Value receiptJson; + std::string err; + auto receiptReader = std::unique_ptr<Json::CharReader>( + Json::CharReaderBuilder {}.newCharReader()); + if (!receiptReader->parse(receipt.data(), + receipt.data() + receipt.size(), + &receiptJson, + &err)) { + JAMI_ERR("[Auth] Can't parse receipt from server: %s", + err.c_str()); + ctx->onFailure(AuthError::SERVER_ERROR, + "Can't parse receipt from server"); + break; + } + auto receiptSignature = base64::decode( + json["receiptSignature"].asString()); + + auto info = std::make_unique<AccountInfo>(); + info->identity.first = ctx->key.get(); + info->identity.second = cert; + info->devicePk = cert->getSharedPublicKey(); + info->deviceId = info->devicePk->getLongId().toString(); + info->accountId = accountCert->getId().toString(); + info->contacts = std::make_unique<ContactList>(ctx->accountId, + accountCert, + this_->path_, + this_->onChange_); + // info->contacts->setContacts(a.contacts); + if (ctx->deviceName.empty()) + ctx->deviceName = info->deviceId.substr(8); + info->contacts->foundAccountDevice(cert, + ctx->deviceName, + clock::now()); + info->ethAccount = receiptJson["eth"].asString(); + info->announce + = parseAnnounce(receiptJson["announce"].asString(), + info->accountId, + info->devicePk->getId().toString()); + if (not info->announce) { + ctx->onFailure(AuthError::SERVER_ERROR, + "Can't parse announce from server"); + return; + } + info->username = ctx->credentials->username; + + this_->creds_ = std::move(ctx->credentials); + this_->info_ = std::move(info); + std::map<std::string, std::string> config; + for (auto itr = json.begin(); itr != json.end(); ++itr) { + const auto& name = itr.name(); + if (name == "nameServer"sv) { + auto nameServer = json["nameServer"].asString(); + if (!nameServer.empty() && nameServer[0] == '/') + nameServer = this_->managerHostname_ + nameServer; + this_->nameDir_ = NameDirectory::instance(nameServer); + config + .emplace(libjami::Account::ConfProperties::RingNS::URI, + std::move(nameServer)); + } else if (name == "userPhoto"sv) { + this_->info_->photo = json["userPhoto"].asString(); + } else { + config.emplace(name, itr->asString()); } - onAsync([=](AccountManager& accountManager) mutable { - auto& this_ = *static_cast<ServerAccountManager*>( - &accountManager); - auto receiptSignature = base64::decode( - json["receiptSignature"].asString()); - - auto info = std::make_unique<AccountInfo>(); - info->identity.first = ctx->key.get(); - info->identity.second = cert; - info->devicePk = cert->getSharedPublicKey(); - info->deviceId = info->devicePk->getLongId().toString(); - info->accountId = accountCert->getId().toString(); - info->contacts = std::make_unique<ContactList>(ctx->accountId, - accountCert, - this_.path_, - this_.onChange_); - // info->contacts->setContacts(a.contacts); - if (ctx->deviceName.empty()) - ctx->deviceName = info->deviceId.substr(8); - info->contacts->foundAccountDevice(cert, - ctx->deviceName, - clock::now()); - info->ethAccount = receiptJson["eth"].asString(); - info->announce - = parseAnnounce(receiptJson["announce"].asString(), - info->accountId, - info->devicePk->getId().toString()); - if (not info->announce) { - ctx->onFailure(AuthError::SERVER_ERROR, - "Can't parse announce from server"); - return; - } - info->username = ctx->credentials->username; - - this_.creds_ = std::move(ctx->credentials); - this_.info_ = std::move(info); - std::map<std::string, std::string> config; - for (auto itr = json.begin(); itr != json.end(); ++itr) { - const auto& name = itr.name(); - if (name == "nameServer"sv) { - auto nameServer = json["nameServer"].asString(); - if (!nameServer.empty() && nameServer[0] == '/') - nameServer = this_.managerHostname_ + nameServer; - this_.nameDir_ = NameDirectory::instance(nameServer); - config - .emplace(libjami::Account::ConfProperties::RingNS::URI, - std::move(nameServer)); - } else if (name == "userPhoto"sv) { - this_.info_->photo = json["userPhoto"].asString(); - } else { - config.emplace(name, itr->asString()); - } - } - - ctx->onSuccess(*this_.info_, - std::move(config), - std::move(receipt), - std::move(receiptSignature)); - }); - } catch (const std::exception& e) { - JAMI_ERR("Error when loading account: %s", e.what()); - ctx->onFailure(AuthError::NETWORK, ""); } - } while (false); - } - onAsync([response](AccountManager& accountManager) { - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - this_.clearRequest(response.request); - }); - }, - this_.logger_); - request->set_auth(ctx->credentials->username, ctx->credentials->password); - this_.sendRequest(request); - }); + ctx->onSuccess(*this_->info_, + std::move(config), + std::move(receipt), + std::move(receiptSignature)); + } catch (const std::exception& e) { + JAMI_ERR("Error when loading account: %s", e.what()); + ctx->onFailure(AuthError::NETWORK, ""); + } + } while (false); + } + + if (auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock())) + this_->clearRequest(response.request); + }, + this_->logger_); + request->set_auth(ctx->credentials->username, ctx->credentials->password); + this_->sendRequest(request); }); } @@ -244,11 +237,9 @@ ServerAccountManager::authenticateDevice() *Manager::instance().ioContext(), url, Json::Value {Json::objectValue}, - [onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { - static_cast<ServerAccountManager*>(&accountManager) - ->onAuthEnded(json, response, TokenScope::Device); - }); + [w=weak_from_this()](Json::Value json, const dht::http::Response& response) { + if (auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock())) + this_->onAuthEnded(json, response, TokenScope::Device); }, logger_); request->set_identity(info_->identity); @@ -265,11 +256,9 @@ ServerAccountManager::authenticateAccount(const std::string& username, const std *Manager::instance().ioContext(), url, Json::Value {Json::objectValue}, - [onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { - static_cast<ServerAccountManager*>(&accountManager) - ->onAuthEnded(json, response, TokenScope::User); - }); + [w=weak_from_this()](Json::Value json, const dht::http::Response& response) { + if (auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock())) + this_->onAuthEnded(json, response, TokenScope::User); }, logger_); request->set_auth(username, password); @@ -401,33 +390,32 @@ ServerAccountManager::syncDevices() *Manager::instance().ioContext(), urlContacts, jsonContacts, - [onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { + [w=weak_from_this()](Json::Value json, const dht::http::Response& response) { JAMI_DBG("[Auth] Got contact sync request callback with status code=%u", response.status_code); - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - if (response.status_code >= 200 && response.status_code < 300) { - try { - JAMI_WARN("[Auth] Got server response: %s", response.body.c_str()); - if (not json.isArray()) { - JAMI_ERR("[Auth] Can't parse server response: not an array"); - } else { - for (unsigned i = 0, n = json.size(); i < n; i++) { - const auto& e = json[i]; - Contact contact(e); - this_.info_->contacts - ->updateContact(dht::InfoHash {e["uri"].asString()}, contact); - } - this_.info_->contacts->saveContacts(); + auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock()); + if (!this_) return; + if (response.status_code >= 200 && response.status_code < 300) { + try { + JAMI_WARN("[Auth] Got server response: %s", response.body.c_str()); + if (not json.isArray()) { + JAMI_ERR("[Auth] Can't parse server response: not an array"); + } else { + for (unsigned i = 0, n = json.size(); i < n; i++) { + const auto& e = json[i]; + Contact contact(e); + this_->info_->contacts + ->updateContact(dht::InfoHash {e["uri"].asString()}, contact); } - } catch (const std::exception& e) { - JAMI_ERR("Error when iterating contact list: %s", e.what()); + this_->info_->contacts->saveContacts(); } - } else if (response.status_code == 401) - this_.authError(TokenScope::Device); + } catch (const std::exception& e) { + JAMI_ERR("Error when iterating contact list: %s", e.what()); + } + } else if (response.status_code == 401) + this_->authError(TokenScope::Device); - this_.clearRequest(response.request); - }); + this_->clearRequest(response.request); }, logger_)); @@ -435,34 +423,33 @@ ServerAccountManager::syncDevices() sendDeviceRequest(std::make_shared<Request>( *Manager::instance().ioContext(), urlDevices, - [onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { - JAMI_DBG("[Auth] Got request callback with status code=%u", response.status_code); - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - if (response.status_code >= 200 && response.status_code < 300) { - try { - JAMI_WARN("[Auth] Got server response: %s", response.body.c_str()); - if (not json.isArray()) { - JAMI_ERR("[Auth] Can't parse server response: not an array"); - } else { - for (unsigned i = 0, n = json.size(); i < n; i++) { - const auto& e = json[i]; - dht::PkId deviceId(e["deviceId"].asString()); - if (deviceId) { - this_.info_->contacts->foundAccountDevice(deviceId, - e["alias"].asString(), - clock::now()); - } + [w=weak_from_this()](Json::Value json, const dht::http::Response& response) { + JAMI_DBG("[Auth] Got request callback with status code=%u", response.status_code); + auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock()); + if (!this_) return; + if (response.status_code >= 200 && response.status_code < 300) { + try { + JAMI_WARN("[Auth] Got server response: %s", response.body.c_str()); + if (not json.isArray()) { + JAMI_ERR("[Auth] Can't parse server response: not an array"); + } else { + for (unsigned i = 0, n = json.size(); i < n; i++) { + const auto& e = json[i]; + dht::PkId deviceId(e["deviceId"].asString()); + if (deviceId) { + this_->info_->contacts->foundAccountDevice(deviceId, + e["alias"].asString(), + clock::now()); } } - } catch (const std::exception& e) { - JAMI_ERR("Error when iterating device list: %s", e.what()); } - } else if (response.status_code == 401) - this_.authError(TokenScope::Device); + } catch (const std::exception& e) { + JAMI_ERR("Error when iterating device list: %s", e.what()); + } + } else if (response.status_code == 401) + this_->authError(TokenScope::Device); - this_.clearRequest(response.request); - }); + this_->clearRequest(response.request); }, logger_)); } @@ -482,25 +469,24 @@ ServerAccountManager::revokeDevice(const std::string& password, auto request = std::make_shared<Request>( *Manager::instance().ioContext(), url, - [cb, onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { - JAMI_DBG("[Revoke] Got request callback with status code=%u", response.status_code); - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - if (response.status_code >= 200 && response.status_code < 300) { - try { - JAMI_WARN("[Revoke] Got server response"); - if (json["errorDetails"].empty()) { - if (cb) - cb(RevokeDeviceResult::SUCCESS); - this_.syncDevices(); - } - } catch (const std::exception& e) { - JAMI_ERR("Error when loading device list: %s", e.what()); + [cb, w=weak_from_this()](Json::Value json, const dht::http::Response& response) { + JAMI_DBG("[Revoke] Got request callback with status code=%u", response.status_code); + auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock()); + if (!this_) return; + if (response.status_code >= 200 && response.status_code < 300) { + try { + JAMI_WARN("[Revoke] Got server response"); + if (json["errorDetails"].empty()) { + if (cb) + cb(RevokeDeviceResult::SUCCESS); + this_->syncDevices(); } - } else if (cb) - cb(RevokeDeviceResult::ERROR_NETWORK); - this_.clearRequest(response.request); - }); + } catch (const std::exception& e) { + JAMI_ERR("Error when loading device list: %s", e.what()); + } + } else if (cb) + cb(RevokeDeviceResult::ERROR_NETWORK); + this_->clearRequest(response.request); }, logger_); request->set_method(restinio::http_method_delete()); @@ -523,40 +509,39 @@ ServerAccountManager::searchUser(const std::string& query, SearchCallback cb) sendDeviceRequest(std::make_shared<Request>( *Manager::instance().ioContext(), url, - [cb, onAsync = onAsync_](Json::Value json, const dht::http::Response& response) { - onAsync([=](AccountManager& accountManager) { - JAMI_DBG("[Search] Got request callback with status code=%u", response.status_code); - auto& this_ = *static_cast<ServerAccountManager*>(&accountManager); - if (response.status_code >= 200 && response.status_code < 300) { - try { - const auto& profiles = json["profiles"]; - Json::Value::ArrayIndex rcount = profiles.size(); - std::vector<std::map<std::string, std::string>> results; - results.reserve(rcount); - JAMI_WARN("[Search] Got server response: %s", response.body.c_str()); - for (Json::Value::ArrayIndex i = 0; i < rcount; i++) { - const auto& ruser = profiles[i]; - std::map<std::string, std::string> user; - for (const auto& member : ruser.getMemberNames()) { - const auto& rmember = ruser[member]; - if (rmember.isString()) - user[member] = rmember.asString(); - } - results.emplace_back(std::move(user)); + [cb, w=weak_from_this()](Json::Value json, const dht::http::Response& response) { + JAMI_DBG("[Search] Got request callback with status code=%u", response.status_code); + auto this_ = std::static_pointer_cast<ServerAccountManager>(w.lock()); + if (!this_) return; + if (response.status_code >= 200 && response.status_code < 300) { + try { + const auto& profiles = json["profiles"]; + Json::Value::ArrayIndex rcount = profiles.size(); + std::vector<std::map<std::string, std::string>> results; + results.reserve(rcount); + JAMI_WARN("[Search] Got server response: %s", response.body.c_str()); + for (Json::Value::ArrayIndex i = 0; i < rcount; i++) { + const auto& ruser = profiles[i]; + std::map<std::string, std::string> user; + for (const auto& member : ruser.getMemberNames()) { + const auto& rmember = ruser[member]; + if (rmember.isString()) + user[member] = rmember.asString(); } - if (cb) - cb(results, SearchResponse::found); - } catch (const std::exception& e) { - JAMI_ERR("[Search] Error during search: %s", e.what()); + results.emplace_back(std::move(user)); } - } else { - if (response.status_code == 401) - this_.authError(TokenScope::Device); if (cb) - cb({}, SearchResponse::error); + cb(results, SearchResponse::found); + } catch (const std::exception& e) { + JAMI_ERR("[Search] Error during search: %s", e.what()); } - this_.clearRequest(response.request); - }); + } else { + if (response.status_code == 401) + this_->authError(TokenScope::Device); + if (cb) + cb({}, SearchResponse::error); + } + this_->clearRequest(response.request); }, logger_)); return true; diff --git a/src/jamidht/server_account_manager.h b/src/jamidht/server_account_manager.h index dd94248715df9820695df3543f27565b97f57438..82e24d64c986197700acb0255bc586a10b85ee6e 100644 --- a/src/jamidht/server_account_manager.h +++ b/src/jamidht/server_account_manager.h @@ -30,7 +30,6 @@ class ServerAccountManager : public AccountManager { public: ServerAccountManager(const std::string& path, - OnAsync&& onAsync, const std::string& managerHostname, const std::string& nameServer);