#include "authmanager.h" #include "networkmanager.h" #include #include #include #include #include namespace { constexpr char key[] = "network/session_token"; } AuthManager::AuthManager(QObject *parent) : QObject{parent}, m_sessionData(nullptr), m_settings(new QSettings(this)), m_isSignedIn(false), m_lastEmail(""), m_sessionToken("") { connect(&NetworkManager::instance(), &NetworkManager::unauthorizedDetected, this, [this]() { if (!m_isSignedIn) { return; } setIsSignedIn(false); if (m_sessionData) { delete m_sessionData; m_sessionData = nullptr; } setSessionToken(""); }); } void AuthManager::tryRestoreSession() { QString storageSessionToken = m_settings->value(key).toString(); if (storageSessionToken.isEmpty()) { return; } qDebug() << "Storage session token is: " << storageSessionToken; // set it here, and unset if it fails...network manager needs to inject into the request setSessionToken(storageSessionToken); QNetworkReply *reply = NetworkManager::instance().get("/auth/me"); connect(reply, &QNetworkReply::finished, this, [=]() { reply->deleteLater(); if (reply->error() != QNetworkReply::NoError) { qDebug() << "Saved session token is invalid"; setSessionToken(""); return; } qDebug() << "Saved session token is valid"; QByteArray responseData = reply->readAll(); QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData); if (jsonDoc.isNull()) { qWarning() << "Failed to create a JSON doc."; setSessionToken(""); return; } QJsonObject jsonObj = jsonDoc.object(); if (!m_sessionData) { m_sessionData = new SessionData{}; } m_sessionData->id = jsonObj["id"].toString(); m_sessionData->email = jsonObj["email"].toString(); m_sessionData->emailPrefix = jsonObj["email_prefix"].toString(); setSessionToken(storageSessionToken); setIsSignedIn(true); }); } void AuthManager::setIsSignedIn(bool newValue) { if (m_isSignedIn == newValue) { return; } m_isSignedIn = newValue; emit isSignedInChanged(); if (m_isSignedIn) { emit signedIn(); } else { emit signedOut(); } } bool AuthManager::isSignedIn() const { return m_isSignedIn; } SessionData *AuthManager::sessionData() const { return m_sessionData; } void AuthManager::requestSignInCode(const QString &email) { if (isSignedIn()) { qWarning() << "Must sign out first"; return; } QJsonDocument body; QJsonObject object; object["email"] = email; body.setObject(object); QNetworkReply *reply = NetworkManager::instance().post("/auth/request-code", body); connect(reply, &QNetworkReply::finished, this, [=]() { reply->deleteLater(); if (reply->error() != QNetworkReply::NoError) { emit errorOccurred("Unable to send code. Please try again."); qDebug() << "Error in emailing auth code: " << reply->errorString(); return; } qDebug() << "Code successfully sent"; m_lastEmail = email; emit codeSentToEmail(email); }); } void AuthManager::signIn(const QString &code) { if (isSignedIn()) { qWarning() << "Must sign out first"; return; } assert(!m_lastEmail.isEmpty()); QJsonDocument body; QJsonObject object; object["email"] = m_lastEmail; object["code"] = code; body.setObject(object); QNetworkReply *reply = NetworkManager::instance().post("/auth/sign-in", body); connect(reply, &QNetworkReply::finished, this, [=]() { reply->deleteLater(); if (reply->error() != QNetworkReply::NoError) { emit errorOccurred("Unable to verify code. Please try again."); qDebug() << "Error in verify code: " << reply->errorString(); return; } qDebug() << "Session successfully created"; QByteArray responseData = reply->readAll(); QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData); if (jsonDoc.isNull()) { qWarning() << "Failed to create a JSON doc."; emit errorOccurred("Unable to verify code"); return; } QJsonObject jsonObj = jsonDoc.object(); if (!m_sessionData) { m_sessionData = new SessionData{}; } QJsonObject human = jsonObj["human"].toObject(); m_sessionData->id = human["id"].toString(); m_sessionData->email = human["email"].toString(); m_sessionData->emailPrefix = human["email_prefix"].toString(); setSessionToken(jsonObj["token"].toString()); setIsSignedIn(true); }); } void AuthManager::signOut() { if (!isSignedIn()) { qWarning() << "Not signed in, skipping sign out"; return; } setIsSignedIn(false); if (m_sessionData) { delete m_sessionData; m_sessionData = nullptr; } setSessionToken(""); QNetworkReply *reply = NetworkManager::instance().post("/auth/sign-out", QJsonDocument()); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); } void AuthManager::setSessionToken(const QString &newValue) { if (newValue.isEmpty()) { m_settings->remove(key); } else { m_settings->setValue(key, newValue); } m_sessionToken = newValue; NetworkManager::instance().setSessionToken(newValue); }