diff options
Diffstat (limited to 'credentials.cpp')
| -rw-r--r-- | credentials.cpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/credentials.cpp b/credentials.cpp new file mode 100644 index 0000000..5cd6e6f --- /dev/null +++ b/credentials.cpp @@ -0,0 +1,218 @@ +#include "credentials.h" +#include <qt5keychain/keychain.h> +#include <QXmppPromise.h> +#include <QXmppConfiguration.h> +#include <iostream> + +static const QString service = "xxcc", sep = ";"; + +QXmppTask<Credentials::PairListResult> Credentials::load( + Credentials::PairList &pairs, + QStringList::const_iterator &it, + QStringList::const_iterator end) +{ + if (it == end) + return QXmpp::Private::makeReadyTask<PairListResult>( + PairListResult(pairs)); + + QXmppPromise<PairListResult> promise; + + load(*it).then(this, + [=] (LoadResult &&result) mutable + { + if (std::holds_alternative<QString>(result)) + { + pairs << Pair(*it, std::get<QString>(result)); + + load(pairs, ++it, end).then(this, + [=] (PairListResult &&result) mutable + { + promise.finish(result); + }); + } + else if (std::holds_alternative<Error>(result)) + promise.finish(Error{std::get<Error>(result)}); + }); + + return promise.task(); +} + +QXmppTask<Credentials::PairListResult> Credentials::load() +{ + QXmppPromise<PairListResult> promise; + + storedUsers().then(this, + [=] (Users &&result) mutable + { + if (std::holds_alternative<QStringList>(result)) + { + PairList pairs; + auto list = new QStringList(std::get<QStringList>(result)); + auto begin = list->cbegin(); + const auto end = list->cend(); + + load(pairs, begin, end).then(this, + [=] (PairListResult &&result) mutable + { + delete list; + promise.finish(result); + }); + } + else if (std::holds_alternative<Error>(result)) + promise.finish(Error{std::get<Error>(result)}); + }); + + return promise.task(); +} + +QXmppTask<Credentials::StoreResult> Credentials::store(Client *c) +{ + QXmppPromise<StoreResult> promise; + const QXmppConfiguration &cfg = c->configuration(); + const QString user = cfg.jidBare(); + + store(user, cfg.password()).then(this, + [=] (StoreResult &&result) mutable + { + store(user).then(this, + [=] (StoreResult &&result) mutable + { + promise.finish(result); + }); + }); + + return promise.task(); +} + +QXmppTask<Credentials::StoreResult> Credentials::store(const QString &user) +{ + QXmppPromise<StoreResult> promise; + + storedUsersList().then(this, + [=] (LoadResult &&result) mutable + { + if (std::holds_alternative<QString>(result)) + { + auto &list = std::get<QString>(result); + + if (!list.isEmpty()) + list += sep; + + list += user; + store("users", list).then(this, + [=] (StoreResult &&result) mutable + { + promise.finish(result); + }); + } + else if (std::holds_alternative<Error>(result)) + { + store("users", user).then(this, + [=] (StoreResult &&result) mutable + { + promise.finish(result); + }); + } + }); + + return promise.task(); +} + +QXmppTask<Credentials::LoadResult> Credentials::storedUsersList() +{ + QXmppPromise<LoadResult> promise; + + load("users").then(this, + [=] (LoadResult &&result) mutable + { + promise.finish(result); + }); + + return promise.task(); + +} + +QXmppTask<Credentials::LoadResult> Credentials::load(const QString &key) +{ + QXmppPromise<LoadResult> promise; + auto job = new QKeychain::ReadPasswordJob(service); + + job->setKey(key); + job->connect(job, &QKeychain::Job::finished, this, + [=] (QKeychain::Job *const job) mutable + { + auto readjob = dynamic_cast<QKeychain::ReadPasswordJob *>(job); + + if (readjob->error()) + { + const auto error = "Failed to load " + key + ": " + + readjob->errorString(); + + std::cerr << qPrintable(error) << std::endl; + promise.finish(Error{error}); + } + else + { + auto users = readjob->textData(); + + promise.finish(QString(users)); + } + }); + + job->start(); + return promise.task(); +} + +QXmppTask<Credentials::StoreResult> Credentials::store(const QString &key, + const QString &value) +{ + QXmppPromise<StoreResult> promise; + auto job = new QKeychain::WritePasswordJob(service); + + job->setKey(key); + job->setTextData(value); + job->connect(job, &QKeychain::Job::finished, this, + [=] (QKeychain::Job *const job) mutable + { + if (job->error()) + { + StoreResult sr; + + const auto error = "Failed to store " + key + ": " + + job->errorString(); + + std::cerr << qPrintable(error) << std::endl; + sr = Error{error}; + promise.finish(StoreResult(sr)); + } + else + promise.finish(Success{}); + }); + + job->start(); + return promise.task(); +} + +QXmppTask<Credentials::Users> Credentials::storedUsers() +{ + QXmppPromise<Users> promise; + + storedUsersList().then(this, + [=] (LoadResult &&result) mutable + { + if (std::holds_alternative<QString>(result)) + { + const auto &value = std::get<QString>(result); + + promise.finish(QStringList(value.split(sep))); + } + else if (std::holds_alternative<Error>(result)) + { + const auto &error = std::get<Error>(result); + + promise.finish(Error{error.description}); + } + }); + + return promise.task(); +} |
