From f028aa76bc5d28b7fc4d1ea4e194895690e9944e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Thu, 5 Dec 2013 02:39:52 +0100 Subject: Offline mode support, part 1 Refactor MojangAccount so it exposes a less generic interface and supports login. Hide the ugly details. Yggdrasil tasks are now only used from MojangAccount. --- gui/MainWindow.cpp | 22 ++-- gui/dialogs/AccountListDialog.cpp | 10 +- gui/dialogs/AccountSelectDialog.cpp | 2 - logic/LegacyInstance.cpp | 2 +- logic/MinecraftProcess.cpp | 22 ++-- logic/OneSixInstance.cpp | 4 +- logic/auth/MojangAccount.cpp | 196 +++++++++++++--------------------- logic/auth/MojangAccount.h | 182 ++++++++++++++++--------------- logic/auth/YggdrasilTask.cpp | 40 +++---- logic/auth/YggdrasilTask.h | 11 +- logic/auth/flows/AuthenticateTask.cpp | 23 ++-- logic/auth/flows/AuthenticateTask.h | 2 +- logic/auth/flows/RefreshTask.cpp | 18 ++-- logic/auth/flows/RefreshTask.h | 2 +- logic/auth/flows/ValidateTask.cpp | 4 +- logic/auth/flows/ValidateTask.h | 2 +- logic/lists/MojangAccountList.cpp | 24 ++--- logic/lists/MojangAccountList.h | 5 +- 18 files changed, 257 insertions(+), 314 deletions(-) diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index 854091c6..69591f8b 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -69,10 +69,6 @@ #include "logic/lists/IconList.h" #include "logic/lists/JavaVersionList.h" -#include "logic/auth/flows/AuthenticateTask.h" -#include "logic/auth/flows/RefreshTask.h" -#include "logic/auth/flows/ValidateTask.h" - #include "logic/BaseInstance.h" #include "logic/InstanceFactory.h" #include "logic/MinecraftProcess.h" @@ -210,9 +206,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi for(AccountProfile profile : account->profiles()) { - auto meta = MMC->metacache()->resolveEntry("skins", profile.name() + ".png"); + auto meta = MMC->metacache()->resolveEntry("skins", profile.name + ".png"); auto action = CacheDownload::make( - QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name() + ".png"), + QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name + ".png"), meta); job->addNetAction(action); meta->stale = true; @@ -310,9 +306,9 @@ void MainWindow::repopulateAccountsMenu() section->setEnabled(false); accountMenu->addAction(section); - for (AccountProfile profile : account->profiles()) + for (auto profile : account->profiles()) { - QAction *action = new QAction(profile.name(), this); + QAction *action = new QAction(profile.name, this); action->setData(account->username()); action->setCheckable(true); if(active_username == account->username()) @@ -320,7 +316,7 @@ void MainWindow::repopulateAccountsMenu() action->setChecked(true); } - action->setIcon(SkinUtils::getFaceFromCache(profile.name())); + action->setIcon(SkinUtils::getFaceFromCache(profile.name)); accountMenu->addAction(action); connect(action, SIGNAL(triggered(bool)), SLOT(changeActiveAccount())); } @@ -378,7 +374,7 @@ void MainWindow::activeAccountChanged() const AccountProfile *profile = account->currentProfile(); if (profile != nullptr) { - accountMenuButton->setIcon(SkinUtils::getFaceFromCache(profile->name())); + accountMenuButton->setIcon(SkinUtils::getFaceFromCache(profile->name)); return; } } @@ -790,6 +786,7 @@ void MainWindow::doLaunch() void MainWindow::doLaunchInst(BaseInstance* instance, MojangAccountPtr account) { // We'll need to validate the access token to make sure the account is still logged in. + /* ProgressDialog progDialog(this); RefreshTask refreshtask(account, &progDialog); progDialog.exec(&refreshtask); @@ -829,10 +826,12 @@ void MainWindow::doLaunchInst(BaseInstance* instance, MojangAccountPtr account) QMessageBox::Warning, QMessageBox::Ok)->exec(); } } + */ } bool MainWindow::doRefreshToken(MojangAccountPtr account, const QString& errorMsg) { + /* EditAccountDialog passDialog(errorMsg, this, EditAccountDialog::PasswordField); if (passDialog.exec() == QDialog::Accepted) { @@ -848,7 +847,8 @@ bool MainWindow::doRefreshToken(MojangAccountPtr account, const QString& errorMs return doRefreshToken(account, authTask.failReason()); } } - else return false; + else return false;*/ + return false; } void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account) diff --git a/gui/dialogs/AccountListDialog.cpp b/gui/dialogs/AccountListDialog.cpp index f5268b61..e1f65c16 100644 --- a/gui/dialogs/AccountListDialog.cpp +++ b/gui/dialogs/AccountListDialog.cpp @@ -20,7 +20,6 @@ #include -#include #include #include @@ -117,8 +116,8 @@ void AccountListDialog::addAccount(const QString& errMsg) QString username(loginDialog.username()); QString password(loginDialog.password()); - MojangAccountPtr account = MojangAccountPtr(new MojangAccount(username)); - + MojangAccountPtr account = MojangAccount::createFromUsername(username); +/* ProgressDialog progDialog(this); AuthenticateTask authTask(account, password, &progDialog); if (progDialog.exec(&authTask)) @@ -132,9 +131,9 @@ void AccountListDialog::addAccount(const QString& errMsg) for(AccountProfile profile : account->profiles()) { - auto meta = MMC->metacache()->resolveEntry("skins", profile.name() + ".png"); + auto meta = MMC->metacache()->resolveEntry("skins", profile.name + ".png"); auto action = CacheDownload::make( - QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name() + ".png"), + QUrl("http://skins.minecraft.net/MinecraftSkins/" + profile.name + ".png"), meta); job->addNetAction(action); meta->stale = true; @@ -142,5 +141,6 @@ void AccountListDialog::addAccount(const QString& errMsg) job->start(); } + */ } } diff --git a/gui/dialogs/AccountSelectDialog.cpp b/gui/dialogs/AccountSelectDialog.cpp index b8fa9e42..ec2f09be 100644 --- a/gui/dialogs/AccountSelectDialog.cpp +++ b/gui/dialogs/AccountSelectDialog.cpp @@ -20,8 +20,6 @@ #include -#include - #include #include diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 72b6c51a..decfd39d 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -105,7 +105,7 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account) #endif args << "-jar" << LAUNCHER_FILE; - args << account->currentProfile()->name(); + args << account->currentProfile()->name; args << account->sessionId(); args << windowTitle; args << windowSize; diff --git a/logic/MinecraftProcess.cpp b/logic/MinecraftProcess.cpp index 5d99bfae..209929b7 100644 --- a/logic/MinecraftProcess.cpp +++ b/logic/MinecraftProcess.cpp @@ -75,20 +75,22 @@ QString MinecraftProcess::censorPrivateInfo(QString in) { if(!m_account) return in; - else + + QString sessionId = m_account->sessionId(); + QString accessToken = m_account->accessToken(); + QString clientToken = m_account->clientToken(); + in.replace(sessionId, ""); + in.replace(accessToken, ""); + in.replace(clientToken, ""); + auto profile = m_account->currentProfile(); + if(profile) { - QString sessionId = m_account->sessionId(); - QString accessToken = m_account->accessToken(); - QString clientToken = m_account->clientToken(); - QString profileId = m_account->currentProfile()->id(); - QString profileName = m_account->currentProfile()->name(); - in.replace(sessionId, ""); - in.replace(accessToken, ""); - in.replace(clientToken, ""); + QString profileId = profile->id; + QString profileName = profile->name; in.replace(profileId, ""); in.replace(profileName, ""); - return in; } + return in; } // console window diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 08b63bf9..5362e894 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -77,8 +77,8 @@ QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account) token_mapping["auth_username"] = account->username(); token_mapping["auth_session"] = account->sessionId(); token_mapping["auth_access_token"] = account->accessToken(); - token_mapping["auth_player_name"] = account->currentProfile()->name(); - token_mapping["auth_uuid"] = account->currentProfile()->id(); + token_mapping["auth_player_name"] = account->currentProfile()->name; + token_mapping["auth_uuid"] = account->currentProfile()->id; // this is for offline?: /* diff --git a/logic/auth/MojangAccount.cpp b/logic/auth/MojangAccount.cpp index 4a61cf19..9ab71077 100644 --- a/logic/auth/MojangAccount.cpp +++ b/logic/auth/MojangAccount.cpp @@ -16,113 +16,16 @@ */ #include "MojangAccount.h" +#include "flows/RefreshTask.h" +#include "flows/AuthenticateTask.h" #include #include #include +#include #include -MojangAccount::MojangAccount(const QString &username, QObject *parent) : QObject(parent) -{ - // Generate a client token. - m_clientToken = QUuid::createUuid().toString(); - - m_username = username; - - m_currentProfile = -1; -} - -MojangAccount::MojangAccount(const QString &username, const QString &clientToken, - const QString &accessToken, QObject *parent) - : QObject(parent) -{ - m_username = username; - m_clientToken = clientToken; - m_accessToken = accessToken; - - m_currentProfile = -1; -} - -MojangAccount::MojangAccount(const MojangAccount &other, QObject *parent) -{ - m_username = other.username(); - m_clientToken = other.clientToken(); - m_accessToken = other.accessToken(); - - m_profiles = other.m_profiles; - m_currentProfile = other.m_currentProfile; -} - -QString MojangAccount::username() const -{ - return m_username; -} - -QString MojangAccount::clientToken() const -{ - return m_clientToken; -} - -void MojangAccount::setClientToken(const QString &clientToken) -{ - m_clientToken = clientToken; -} - -QString MojangAccount::accessToken() const -{ - return m_accessToken; -} - -void MojangAccount::setAccessToken(const QString &accessToken) -{ - m_accessToken = accessToken; -} - -QString MojangAccount::sessionId() const -{ - return "token:" + m_accessToken + ":" + currentProfile()->id(); -} - -const QList MojangAccount::profiles() const -{ - return m_profiles; -} - -const AccountProfile *MojangAccount::currentProfile() const -{ - if (m_currentProfile < 0) - { - if (m_profiles.length() > 0) - return &m_profiles.at(0); - else - return nullptr; - } - else - return &m_profiles.at(m_currentProfile); -} - -bool MojangAccount::setProfile(const QString &profileId) -{ - const QList &profiles = this->profiles(); - for (int i = 0; i < profiles.length(); i++) - { - if (profiles.at(i).id() == profileId) - { - m_currentProfile = i; - return true; - } - } - return false; -} - -void MojangAccount::loadProfiles(const ProfileList &profiles) -{ - m_profiles.clear(); - for (auto profile : profiles) - m_profiles.append(profile); -} - MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) { // The JSON object must at least have a username for it to be valid. @@ -143,7 +46,7 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) return nullptr; } - ProfileList profiles; + QList profiles; for (QJsonValue profileVal : profileArray) { QJsonObject profileObject = profileVal.toObject(); @@ -154,67 +57,112 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject &object) QLOG_WARN() << "Unable to load a profile because it was missing an ID or a name."; continue; } - profiles.append(AccountProfile(id, name)); + profiles.append({id, name}); } - MojangAccountPtr account(new MojangAccount(username, clientToken, accessToken)); - account->loadProfiles(profiles); + MojangAccountPtr account(new MojangAccount()); + account->m_username = username; + account->m_clientToken = clientToken; + account->m_accessToken = accessToken; + account->m_profiles = profiles; // Get the currently selected profile. QString currentProfile = object.value("activeProfile").toString(""); if (!currentProfile.isEmpty()) - account->setProfile(currentProfile); + account->setCurrentProfile(currentProfile); + + return account; +} +MojangAccountPtr MojangAccount::createFromUsername(const QString& username) +{ + MojangAccountPtr account(new MojangAccount()); + account->m_clientToken = QUuid::createUuid().toString().remove(QRegExp("[{}-]")); + account->m_username = username; return account; } -QJsonObject MojangAccount::saveToJson() +QJsonObject MojangAccount::saveToJson() const { QJsonObject json; - json.insert("username", username()); - json.insert("clientToken", clientToken()); - json.insert("accessToken", accessToken()); + json.insert("username", m_username); + json.insert("clientToken", m_clientToken); + json.insert("accessToken", m_accessToken); QJsonArray profileArray; for (AccountProfile profile : m_profiles) { QJsonObject profileObj; - profileObj.insert("id", profile.id()); - profileObj.insert("name", profile.name()); + profileObj.insert("id", profile.id); + profileObj.insert("name", profile.name); profileArray.append(profileObj); } json.insert("profiles", profileArray); - if (currentProfile() != nullptr) - json.insert("activeProfile", currentProfile()->id()); + if (m_currentProfile != -1) + json.insert("activeProfile", currentProfile()->id); return json; } +bool MojangAccount::setCurrentProfile(const QString &profileId) +{ + for (int i = 0; i < m_profiles.length(); i++) + { + if (m_profiles[i].id == profileId) + { + m_currentProfile = i; + return true; + } + } + return false; +} -AccountProfile::AccountProfile(const QString& id, const QString& name) +const AccountProfile* MojangAccount::currentProfile() const { - m_id = id; - m_name = name; + if(m_currentProfile == -1) + return nullptr; + return &m_profiles[m_currentProfile]; } -AccountProfile::AccountProfile(const AccountProfile &other) +AccountStatus MojangAccount::accountStatus() const { - m_id = other.m_id; - m_name = other.m_name; + if(m_accessToken.isEmpty()) + return NotVerified; + if(!m_online) + return Verified; + return Online; } -QString AccountProfile::id() const +bool MojangAccount::login(QString password) { - return m_id; + if(m_currentTask) + return false; + if(password.isEmpty()) + { + m_currentTask.reset(new RefreshTask(this, this)); + } + else + { + m_currentTask.reset(new AuthenticateTask(this, password, this)); + } + connect(m_currentTask.get(), SIGNAL(succeeded()), SLOT(authSucceeded())); + connect(m_currentTask.get(), SIGNAL(failed(QString)), SLOT(authFailed(QString))); + m_currentTask->start(); + return true; } -QString AccountProfile::name() const +void MojangAccount::authSucceeded() { - return m_name; + m_online = true; + m_currentTask.reset(); + emit changed(); } -void MojangAccount::propagateChange() +void MojangAccount::authFailed(QString reason) { + m_online = false; + m_accessToken = QString(); + m_currentTask.reset(); emit changed(); } diff --git a/logic/auth/MojangAccount.h b/logic/auth/MojangAccount.h index 25a85790..751aafe5 100644 --- a/logic/auth/MojangAccount.h +++ b/logic/auth/MojangAccount.h @@ -23,34 +23,25 @@ #include +class YggdrasilTask; class MojangAccount; typedef std::shared_ptr MojangAccountPtr; Q_DECLARE_METATYPE(MojangAccountPtr) /** - * Class that represents a profile within someone's Mojang account. + * A profile within someone's Mojang account. * * Currently, the profile system has not been implemented by Mojang yet, * but we might as well add some things for it in MultiMC right now so * we don't have to rip the code to pieces to add it later. */ -class AccountProfile +struct AccountProfile { -public: - AccountProfile(const QString &id, const QString &name); - AccountProfile(const AccountProfile &other); - - QString id() const; - QString name() const; - -protected: - QString m_id; - QString m_name; + QString id; + QString name; }; -typedef QList ProfileList; - struct User { QString id; @@ -59,6 +50,13 @@ struct User QList> properties; }; +enum AccountStatus +{ + NotVerified, + Verified, + Online +}; + /** * Object that stores information about a certain Mojang account. * @@ -68,106 +66,112 @@ struct User class MojangAccount : public QObject { Q_OBJECT -public: - /** - * Constructs a new MojangAccount with the given username. - * The client token will be generated automatically and the access token will be blank. - */ - explicit MojangAccount(const QString &username, QObject *parent = 0); +public: /* construction */ + //! Do not copy accounts. ever. + explicit MojangAccount(const MojangAccount &other, QObject *parent) = delete; - /** - * Constructs a new MojangAccount with the given username, client token, and access token. - */ - explicit MojangAccount(const QString &username, const QString &clientToken, - const QString &accessToken, QObject *parent = 0); + //! Default constructor + explicit MojangAccount(QObject *parent = 0) : QObject(parent) {}; - /** - * Constructs a new MojangAccount matching the given account. - */ - MojangAccount(const MojangAccount &other, QObject *parent); + //! Creates an empty account for the specified user name. + static MojangAccountPtr createFromUsername(const QString &username); - /** - * Loads a MojangAccount from the given JSON object. - */ + //! Loads a MojangAccount from the given JSON object. static MojangAccountPtr loadFromJson(const QJsonObject &json); - /** - * Saves a MojangAccount to a JSON object and returns it. - */ - QJsonObject saveToJson(); + //! Saves a MojangAccount to a JSON object and returns it. + QJsonObject saveToJson() const; +public: /* manipulation */ /** - * Update the account on disk and lists (it changed, for whatever reason) - * This is called by various Yggdrasil tasks. - */ - void propagateChange(); - - /** - * This MojangAccount's username. May be an email address if the account is migrated. + * Sets the currently selected profile to the profile with the given ID string. + * If profileId is not in the list of available profiles, the function will simply return + * false. */ - QString username() const; + bool setCurrentProfile(const QString &profileId); /** - * This MojangAccount's client token. This is a UUID used by Mojang's auth servers to identify this client. - * This is unique for each MojangAccount. + * Attempt to login. Empty password means we use the token. + * If the attempt fails because we already are performing some task, it returns false. */ - QString clientToken() const; + bool login(QString password = QString()); - /** - * Sets the MojangAccount's client token to the given value. - */ - void setClientToken(const QString &token); +public: /* queries */ + const QString &username() const + { + return m_username; + } - /** - * This MojangAccount's access token. - * If the user has not chosen to stay logged in, this will be an empty string. - */ - QString accessToken() const; + const QString &clientToken() const + { + return m_clientToken; + } - /** - * Changes this MojangAccount's access token to the given value. - */ - void setAccessToken(const QString &token); + const QString &accessToken() const + { + return m_accessToken; + } - /** - * Get full session ID - */ - QString sessionId() const; + const QList &profiles() const + { + return m_profiles; + } - /** - * Returns a list of the available account profiles. - */ - const ProfileList profiles() const; + //! Get the session ID required for legacy Minecraft versions + QString sessionId() const + { + if (m_currentProfile != -1 && !m_accessToken.isEmpty()) + return "token:" + m_accessToken + ":" + m_profiles[m_currentProfile].id; + return "-"; + } - /** - * Returns a pointer to the currently selected profile. - * If no profile is selected, returns the first profile in the profile list or nullptr if there are none. - */ + //! Returns the currently selected profile (if none, returns nullptr) const AccountProfile *currentProfile() const; - /** - * Sets the currently selected profile to the profile with the given ID string. - * If profileId is not in the list of available profiles, the function will simply return false. - */ - bool setProfile(const QString &profileId); - - /** - * Clears the current account profile list and replaces it with the given profile list. - */ - void loadProfiles(const ProfileList &profiles); + //! Returns whether the account is NotVerified, Verified or Online + AccountStatus accountStatus() const; signals: /** - * This isgnal is emitted whrn the account changes + * This signal is emitted when the account changes */ void changed(); -protected: + // TODO: better signalling for the various possible state changes - especially errors + +protected: /* variables */ QString m_username; + + // Used to identify the client - the user can have multiple clients for the same account + // Think: different launchers, all connecting to the same account/profile QString m_clientToken; - QString m_accessToken; // Blank if not logged in. - int m_currentProfile; // Index of the selected profile within the list of available - // profiles. -1 if nothing is selected. - ProfileList m_profiles; // List of available profiles. - User m_user; // the user structure, whatever it is. + + // Blank if not logged in. + QString m_accessToken; + + // Index of the selected profile within the list of available + // profiles. -1 if nothing is selected. + int m_currentProfile = -1; + + // List of available profiles. + QList m_profiles; + + // the user structure, whatever it is. + User m_user; + + // true when the account is verified + bool m_online = false; + + // current task we are executing here + std::shared_ptr m_currentTask; + +private slots: + void authSucceeded(); + void authFailed(QString reason); + +public: + friend class YggdrasilTask; + friend class AuthenticateTask; + friend class ValidateTask; + friend class RefreshTask; }; diff --git a/logic/auth/YggdrasilTask.cpp b/logic/auth/YggdrasilTask.cpp index 797e84cd..e06ae182 100644 --- a/logic/auth/YggdrasilTask.cpp +++ b/logic/auth/YggdrasilTask.cpp @@ -25,10 +25,9 @@ #include #include -YggdrasilTask::YggdrasilTask(MojangAccountPtr account, QObject *parent) : Task(parent) +YggdrasilTask::YggdrasilTask(MojangAccount *account, QObject *parent) + : Task(parent), m_account(account) { - m_error = nullptr; - m_account = account; } YggdrasilTask::~YggdrasilTask() @@ -81,8 +80,9 @@ void YggdrasilTask::processReply(QNetworkReply *reply) if (responseCode == 200) { - // If the response code was 200, then there shouldn't be an error. Make sure anyways. - // Also, sometimes an empty reply indicates success. If there was no data received, + // If the response code was 200, then there shouldn't be an error. Make sure + // anyways. + // Also, sometimes an empty reply indicates success. If there was no data received, // pass an empty json object to the processResponse function. if (jsonError.error == QJsonParseError::NoError || replyData.size() == 0) { @@ -102,25 +102,34 @@ void YggdrasilTask::processReply(QNetworkReply *reply) } else { - emitFailed(tr("Failed to parse Yggdrasil JSON response: %1 at offset %2.").arg(jsonError.errorString()).arg(jsonError.offset)); + emitFailed(tr("Failed to parse Yggdrasil JSON response: %1 at offset %2.") + .arg(jsonError.errorString()) + .arg(jsonError.offset)); } } else { - // If the response code was not 200, then Yggdrasil may have given us information about the error. - // If we can parse the response, then get information from it. Otherwise just say there was an unknown error. + // If the response code was not 200, then Yggdrasil may have given us information + // about the error. + // If we can parse the response, then get information from it. Otherwise just say + // there was an unknown error. if (jsonError.error == QJsonParseError::NoError) { // We were able to parse the server's response. Woo! - // Call processError. If a subclass has overridden it then they'll handle their stuff there. - QLOG_DEBUG() << "The request failed, but the server gave us an error message. Processing error."; + // Call processError. If a subclass has overridden it then they'll handle their + // stuff there. + QLOG_DEBUG() << "The request failed, but the server gave us an error message. " + "Processing error."; emitFailed(processError(doc.object())); } else { - // The server didn't say anything regarding the error. Give the user an unknown error. - QLOG_DEBUG() << "The request failed and the server gave no error message. Unknown error."; - emitFailed(tr("An unknown error occurred when trying to communicate with the authentication server: %1").arg(reply->errorString())); + // The server didn't say anything regarding the error. Give the user an unknown + // error. + QLOG_DEBUG() << "The request failed and the server gave no error message. " + "Unknown error."; + emitFailed(tr("An unknown error occurred when trying to communicate with the " + "authentication server: %1").arg(reply->errorString())); } } } @@ -161,8 +170,3 @@ YggdrasilTask::Error *YggdrasilTask::getError() const { return this->m_error; } - -MojangAccountPtr YggdrasilTask::getMojangAccount() const -{ - return this->m_account; -} diff --git a/logic/auth/YggdrasilTask.h b/logic/auth/YggdrasilTask.h index 62638c9d..18d3dc61 100644 --- a/logic/auth/YggdrasilTask.h +++ b/logic/auth/YggdrasilTask.h @@ -31,7 +31,7 @@ class YggdrasilTask : public Task { Q_OBJECT public: - explicit YggdrasilTask(MojangAccountPtr account, QObject *parent = 0); + explicit YggdrasilTask(MojangAccount * account, QObject *parent = 0); ~YggdrasilTask(); /** @@ -59,11 +59,6 @@ public: QString m_cause; }; - /** - * Gets the Mojang account that this task is operating on. - */ - virtual MojangAccountPtr getMojangAccount() const; - /** * Returns a pointer to a YggdrasilTask::Error object if an error has occurred. * If no error has occurred, returns a null pointer. @@ -120,11 +115,11 @@ protected: */ virtual QString getStateMessage(const State state) const; - MojangAccountPtr m_account; + MojangAccount *m_account = nullptr; QNetworkReply *m_netReply; - Error *m_error; + Error *m_error = nullptr; protected slots: diff --git a/logic/auth/flows/AuthenticateTask.cpp b/logic/auth/flows/AuthenticateTask.cpp index ec2004d6..966548ec 100644 --- a/logic/auth/flows/AuthenticateTask.cpp +++ b/logic/auth/flows/AuthenticateTask.cpp @@ -26,7 +26,7 @@ #include "logger/QsLog.h" -AuthenticateTask::AuthenticateTask(MojangAccountPtr account, const QString &password, +AuthenticateTask::AuthenticateTask(MojangAccount * account, const QString &password, QObject *parent) : YggdrasilTask(account, parent), m_password(password) { @@ -59,14 +59,14 @@ QJsonObject AuthenticateTask::getRequestContent() const req.insert("agent", agent); } - req.insert("username", getMojangAccount()->username()); + req.insert("username", m_account->username()); req.insert("password", m_password); req.insert("requestUser", true); // If we already have a client token, give it to the server. // Otherwise, let the server give us one. - if (!getMojangAccount()->clientToken().isEmpty()) - req.insert("clientToken", getMojangAccount()->clientToken()); + if (!m_account->m_clientToken.isEmpty()) + req.insert("clientToken", m_account->m_clientToken); return req; } @@ -88,8 +88,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) QLOG_ERROR() << "Server didn't send a client token."; return false; } - if (!getMojangAccount()->clientToken().isEmpty() && - clientToken != getMojangAccount()->clientToken()) + if (!m_account->m_clientToken.isEmpty() && clientToken != m_account->m_clientToken) { // The server changed our client token! Obey its wishes, but complain. That's what I do // for my parents, so... @@ -97,7 +96,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) << "'. This shouldn't happen, but it isn't really a big deal."; } // Set the client token. - getMojangAccount()->setClientToken(clientToken); + m_account->m_clientToken = clientToken; // Now, we set the access token. QLOG_DEBUG() << "Getting access token."; @@ -109,7 +108,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) QLOG_ERROR() << "Server didn't send an access token."; } // Set the access token. - getMojangAccount()->setAccessToken(accessToken); + m_account->m_accessToken = accessToken; // Now we load the list of available profiles. // Mojang hasn't yet implemented the profile system, @@ -117,7 +116,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) // don't have trouble implementing it later. QLOG_DEBUG() << "Loading profile list."; QJsonArray availableProfiles = responseData.value("availableProfiles").toArray(); - ProfileList loadedProfiles; + QList loadedProfiles; for (auto iter : availableProfiles) { QJsonObject profile = iter.toObject(); @@ -135,10 +134,10 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) } // Now, add a new AccountProfile entry to the list. - loadedProfiles.append(AccountProfile(id, name)); + loadedProfiles.append({id, name}); } // Put the list of profiles we loaded into the MojangAccount object. - getMojangAccount()->loadProfiles(loadedProfiles); + m_account->m_profiles = loadedProfiles; // Finally, we set the current profile to the correct value. This is pretty simple. // We do need to make sure that the current profile that the server gave us @@ -153,7 +152,7 @@ bool AuthenticateTask::processResponse(QJsonObject responseData) QLOG_ERROR() << "Server didn't specify a currently selected profile."; return false; } - if (!getMojangAccount()->setProfile(currentProfileId)) + if (!m_account->setCurrentProfile(currentProfileId)) { // TODO: Set an error to display to the user. QLOG_ERROR() << "Server specified a selected profile that wasn't in the available " diff --git a/logic/auth/flows/AuthenticateTask.h b/logic/auth/flows/AuthenticateTask.h index 3b99caad..b6564657 100644 --- a/logic/auth/flows/AuthenticateTask.h +++ b/logic/auth/flows/AuthenticateTask.h @@ -30,7 +30,7 @@ class AuthenticateTask : public YggdrasilTask { Q_OBJECT public: - AuthenticateTask(MojangAccountPtr account, const QString &password, QObject *parent = 0); + AuthenticateTask(MojangAccount *account, const QString &password, QObject *parent = 0); protected: virtual QJsonObject getRequestContent() const; diff --git a/logic/auth/flows/RefreshTask.cpp b/logic/auth/flows/RefreshTask.cpp index b56ed9bc..39fb493f 100644 --- a/logic/auth/flows/RefreshTask.cpp +++ b/logic/auth/flows/RefreshTask.cpp @@ -25,7 +25,7 @@ #include "logger/QsLog.h" -RefreshTask::RefreshTask(MojangAccountPtr account, QObject *parent) +RefreshTask::RefreshTask(MojangAccount *account, QObject *parent) : YggdrasilTask(account, parent) { } @@ -44,13 +44,12 @@ QJsonObject RefreshTask::getRequestContent() const * "requestUser": true/false // request the user structure * } */ - auto account = getMojangAccount(); QJsonObject req; - req.insert("clientToken", account->clientToken()); - req.insert("accessToken", account->accessToken()); + req.insert("clientToken", m_account->m_clientToken); + req.insert("accessToken", m_account->m_accessToken); /* { - auto currentProfile = account->currentProfile(); + auto currentProfile = m_account->currentProfile(); QJsonObject profile; profile.insert("id", currentProfile->id()); profile.insert("name", currentProfile->name()); @@ -64,8 +63,6 @@ QJsonObject RefreshTask::getRequestContent() const bool RefreshTask::processResponse(QJsonObject responseData) { - auto account = getMojangAccount(); - // Read the response data. We need to get the client token, access token, and the selected // profile. QLOG_DEBUG() << "Processing authentication response."; @@ -80,7 +77,7 @@ bool RefreshTask::processResponse(QJsonObject responseData) QLOG_ERROR() << "Server didn't send a client token."; return false; } - if (!account->clientToken().isEmpty() && clientToken != account->clientToken()) + if (!m_account->m_clientToken.isEmpty() && clientToken != m_account->m_clientToken) { // The server changed our client token! Obey its wishes, but complain. That's what I do // for my parents, so... @@ -104,7 +101,7 @@ bool RefreshTask::processResponse(QJsonObject responseData) // profile) QJsonObject currentProfile = responseData.value("selectedProfile").toObject(); QString currentProfileId = currentProfile.value("id").toString(""); - if (account->currentProfile()->id() != currentProfileId) + if (m_account->currentProfile()->id != currentProfileId) { // TODO: Set an error to display to the user. QLOG_ERROR() << "Server didn't specify the same selected profile as ours."; @@ -132,8 +129,7 @@ bool RefreshTask::processResponse(QJsonObject responseData) // we've succeeded. QLOG_DEBUG() << "Finished reading refresh response."; // Reset the access token. - account->setAccessToken(accessToken); - account->propagateChange(); + m_account->m_accessToken = accessToken; return true; } diff --git a/logic/auth/flows/RefreshTask.h b/logic/auth/flows/RefreshTask.h index 2596f6c7..2fd50c60 100644 --- a/logic/auth/flows/RefreshTask.h +++ b/logic/auth/flows/RefreshTask.h @@ -30,7 +30,7 @@ class RefreshTask : public YggdrasilTask { Q_OBJECT public: - RefreshTask(MojangAccountPtr account, QObject *parent = 0); + RefreshTask(MojangAccount * account, QObject *parent = 0); protected: virtual QJsonObject getRequestContent() const; diff --git a/logic/auth/flows/ValidateTask.cpp b/logic/auth/flows/ValidateTask.cpp index d9e0e46b..84d5e703 100644 --- a/logic/auth/flows/ValidateTask.cpp +++ b/logic/auth/flows/ValidateTask.cpp @@ -26,7 +26,7 @@ #include "logger/QsLog.h" -ValidateTask::ValidateTask(MojangAccountPtr account, QObject *parent) +ValidateTask::ValidateTask(MojangAccount * account, QObject *parent) : YggdrasilTask(account, parent) { } @@ -34,7 +34,7 @@ ValidateTask::ValidateTask(MojangAccountPtr account, QObject *parent) QJsonObject ValidateTask::getRequestContent() const { QJsonObject req; - req.insert("accessToken", getMojangAccount()->accessToken()); + req.insert("accessToken", m_account->m_accessToken); return req; } diff --git a/logic/auth/flows/ValidateTask.h b/logic/auth/flows/ValidateTask.h index 3ff78c6a..9788f20b 100644 --- a/logic/auth/flows/ValidateTask.h +++ b/logic/auth/flows/ValidateTask.h @@ -28,7 +28,7 @@ class ValidateTask : public YggdrasilTask { Q_OBJECT public: - ValidateTask(MojangAccountPtr account, QObject *parent = 0); + ValidateTask(MojangAccount *account, QObject *parent = 0); protected: virtual QJsonObject getRequestContent() const; diff --git a/logic/lists/MojangAccountList.cpp b/logic/lists/MojangAccountList.cpp index 466cc934..defa5d8c 100644 --- a/logic/lists/MojangAccountList.cpp +++ b/logic/lists/MojangAccountList.cpp @@ -83,10 +83,7 @@ void MojangAccountList::removeAccount(QModelIndex index) MojangAccountPtr MojangAccountList::activeAccount() const { - if (m_activeAccount.isEmpty()) - return nullptr; - else - return findAccount(m_activeAccount); + return m_activeAccount; } void MojangAccountList::setActiveAccount(const QString &username) @@ -94,14 +91,14 @@ void MojangAccountList::setActiveAccount(const QString &username) beginResetModel(); if (username.isEmpty()) { - m_activeAccount = ""; + m_activeAccount = nullptr; } else { for (MojangAccountPtr account : m_accounts) { if (account->username() == username) - m_activeAccount = username; + m_activeAccount = account; } } endResetModel(); @@ -152,7 +149,7 @@ QVariant MojangAccountList::data(const QModelIndex &index, int role) const switch (index.column()) { case ActiveColumn: - return account->username() == m_activeAccount; + return account == m_activeAccount; case NameColumn: return account->username(); @@ -297,11 +294,9 @@ bool MojangAccountList::loadList(const QString &filePath) QLOG_WARN() << "Failed to load an account."; } } - endResetModel(); - // Load the active account. - m_activeAccount = root.value("activeAccount").toString(""); - + m_activeAccount = findAccount(root.value("activeAccount").toString("")); + endResetModel(); return true; } @@ -336,8 +331,11 @@ bool MojangAccountList::saveList(const QString &filePath) // Insert the account list into the root object. root.insert("accounts", accounts); - // Save the active account. - root.insert("activeAccount", m_activeAccount); + if(m_activeAccount) + { + // Save the active account. + root.insert("activeAccount", m_activeAccount->username()); + } // Create a JSON document object to convert our JSON to bytes. QJsonDocument doc(root); diff --git a/logic/lists/MojangAccountList.h b/logic/lists/MojangAccountList.h index 744f3c51..b3301bf6 100644 --- a/logic/lists/MojangAccountList.h +++ b/logic/lists/MojangAccountList.h @@ -161,10 +161,9 @@ protected: QList m_accounts; /*! - * Username of the account that is currently active. - * Empty string if no account is active. + * Account that is currently active. */ - QString m_activeAccount; + MojangAccountPtr m_activeAccount; //! Path to the account list file. Empty string if there isn't one. QString m_listFilePath; -- cgit v1.2.3