75 lines
1.9 KiB
C++
75 lines
1.9 KiB
C++
#include "Credential.hpp"
|
|
|
|
#include <QDateTime>
|
|
#include <QEventLoop>
|
|
|
|
#include <keychain.h>
|
|
|
|
namespace geopro::app {
|
|
|
|
namespace {
|
|
|
|
const QString kService = QStringLiteral("Geopro3");
|
|
const QString kKey = QStringLiteral("session");
|
|
|
|
// QtKeychain 的 job 是异步的;用局部事件循环跑成同步(启动/登录时一次性调用,可接受)。
|
|
QString readRaw()
|
|
{
|
|
QKeychain::ReadPasswordJob job(kService);
|
|
job.setAutoDelete(false);
|
|
job.setKey(kKey);
|
|
QEventLoop loop;
|
|
QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
|
|
job.start();
|
|
loop.exec();
|
|
if (job.error() != QKeychain::NoError) return {};
|
|
return job.textData();
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void rememberSession(const QString& token)
|
|
{
|
|
if (token.isEmpty()) return;
|
|
const QString payload =
|
|
QString::number(QDateTime::currentSecsSinceEpoch()) + QStringLiteral("|") + token;
|
|
|
|
QKeychain::WritePasswordJob job(kService);
|
|
job.setAutoDelete(false);
|
|
job.setKey(kKey);
|
|
job.setTextData(payload);
|
|
QEventLoop loop;
|
|
QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
|
|
job.start();
|
|
loop.exec();
|
|
}
|
|
|
|
QString recallValidToken(int maxAgeDays)
|
|
{
|
|
const QString raw = readRaw();
|
|
if (raw.isEmpty()) return {};
|
|
const int sep = raw.indexOf(QLatin1Char('|'));
|
|
if (sep <= 0) return {};
|
|
|
|
bool ok = false;
|
|
const qint64 ts = raw.left(sep).toLongLong(&ok);
|
|
if (!ok) return {};
|
|
|
|
const qint64 ageSec = QDateTime::currentSecsSinceEpoch() - ts;
|
|
if (ageSec < 0 || ageSec > static_cast<qint64>(maxAgeDays) * 24 * 3600) return {};
|
|
return raw.mid(sep + 1);
|
|
}
|
|
|
|
void forgetSession()
|
|
{
|
|
QKeychain::DeletePasswordJob job(kService);
|
|
job.setAutoDelete(false);
|
|
job.setKey(kKey);
|
|
QEventLoop loop;
|
|
QObject::connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
|
|
job.start();
|
|
loop.exec();
|
|
}
|
|
|
|
} // namespace geopro::app
|