219 lines
5.4 KiB
C++
219 lines
5.4 KiB
C++
#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();
|
|
}
|