Nuke and pave the old login system

Also, account list now saves profile lists.
This commit is contained in:
Andrew 2013-11-20 18:31:15 -06:00
parent 03652b01d2
commit abf8408911
11 changed files with 150 additions and 120 deletions

View File

@ -544,11 +544,7 @@ void MainWindow::instanceActivated(QModelIndex index)
NagUtils::checkJVMArgs(inst->settings().get("JvmArgs").toString(), this); NagUtils::checkJVMArgs(inst->settings().get("JvmArgs").toString(), this);
bool autoLogin = inst->settings().get("AutoLogin").toBool(); doLogin();
if (autoLogin)
doAutoLogin();
else
doLogin();
} }
void MainWindow::on_actionLaunchInstance_triggered() void MainWindow::on_actionLaunchInstance_triggered()
@ -560,56 +556,34 @@ void MainWindow::on_actionLaunchInstance_triggered()
} }
} }
void MainWindow::doAutoLogin()
{
if (!m_selectedInstance)
return;
Keyring *k = Keyring::instance();
QStringList accounts = k->getStoredAccounts("minecraft");
if (!accounts.isEmpty())
{
QString username = accounts[0];
QString password = k->getPassword("minecraft", username);
if (!password.isEmpty())
{
QLOG_INFO() << "Automatically logging in with stored account: " << username;
m_activeInst = m_selectedInstance;
doLogin(username, password);
}
else
{
QLOG_ERROR() << "Auto login set for account, but no password was found: "
<< username;
doLogin(tr("Auto login attempted, but no password is stored."));
}
}
else
{
QLOG_ERROR() << "Auto login set but no accounts were stored.";
doLogin(tr("Auto login attempted, but no accounts are stored."));
}
}
void MainWindow::doLogin(QString username, QString password)
{
UserInfo uInfo{username, password};
ProgressDialog *tDialog = new ProgressDialog(this);
LoginTask *loginTask = new LoginTask(uInfo, tDialog);
connect(loginTask, SIGNAL(succeeded()), SLOT(onLoginComplete()), Qt::QueuedConnection);
connect(loginTask, SIGNAL(failed(QString)), SLOT(doLogin(QString)), Qt::QueuedConnection);
tDialog->exec(loginTask);
}
void MainWindow::doLogin(const QString &errorMsg) void MainWindow::doLogin(const QString &errorMsg)
{ {
if (!m_selectedInstance) if (!m_selectedInstance)
return; return;
// Find an account to use.
std::shared_ptr<MojangAccountList> accounts = MMC->accounts();
MojangAccountPtr account;
if (accounts->count() <= 0)
{
// Tell the user they need to log in at least one account in order to play.
CustomMessageBox::selectable(this, tr("No Accounts"),
tr("In order to play Minecraft, you must have at least one Mojang or Minecraft account logged in to MultiMC. Please add an account."),
QMessageBox::Warning)->show();
}
else
{
// TODO: Allow user to select different accounts.
// For now, we'll just use the first one in the list until I get arround to implementing that.
account = accounts->at(0);
}
// We'll need to validate the access token to make sure the account is still logged in.
// TODO: Do that ^
launchInstance(m_selectedInstance, account);
/*
LoginDialog *loginDlg = new LoginDialog(this, errorMsg); LoginDialog *loginDlg = new LoginDialog(this, errorMsg);
if (!m_selectedInstance->lastLaunch()) if (!m_selectedInstance->lastLaunch())
loginDlg->forceOnline(); loginDlg->forceOnline();
@ -632,6 +606,41 @@ void MainWindow::doLogin(const QString &errorMsg)
launchInstance(m_activeInst, m_activeLogin); launchInstance(m_activeInst, m_activeLogin);
} }
} }
*/
}
void MainWindow::launchInstance(BaseInstance *instance, MojangAccountPtr account)
{
Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL");
proc = instance->prepareForLaunch(account);
if (!proc)
return;
// Prepare GUI: If it shall stay open disable the required parts
if (MMC->settings()->get("NoHide").toBool())
{
ui->actionLaunchInstance->setEnabled(false);
}
else
{
this->hide();
}
console = new ConsoleWindow(proc);
connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console,
SLOT(write(QString, MessageLevel::Enum)));
connect(proc, SIGNAL(ended(BaseInstance *)), this, SLOT(instanceEnded(BaseInstance *)));
if (instance->settings().get("ShowConsole").toBool())
{
console->show();
}
// I think this will work...
proc->setLogin(account->username(), account->accessToken());
proc->launch();
} }
void MainWindow::onLoginComplete() void MainWindow::onLoginComplete()
@ -644,7 +653,7 @@ void MainWindow::onLoginComplete()
BaseUpdate *updateTask = m_activeInst->doUpdate(); BaseUpdate *updateTask = m_activeInst->doUpdate();
if (!updateTask) if (!updateTask)
{ {
launchInstance(m_activeInst, m_activeLogin); //launchInstance(m_activeInst, m_activeLogin);
} }
else else
{ {
@ -701,7 +710,7 @@ void MainWindow::onLoginComplete()
void MainWindow::onGameUpdateComplete() void MainWindow::onGameUpdateComplete()
{ {
launchInstance(m_activeInst, m_activeLogin); //launchInstance(m_activeInst, m_activeLogin);
} }
void MainWindow::onGameUpdateError(QString error) void MainWindow::onGameUpdateError(QString error)
@ -710,39 +719,6 @@ void MainWindow::onGameUpdateError(QString error)
QMessageBox::Warning)->show(); QMessageBox::Warning)->show();
} }
void MainWindow::launchInstance(BaseInstance *instance, LoginResponse response)
{
Q_ASSERT_X(instance != NULL, "launchInstance", "instance is NULL");
proc = instance->prepareForLaunch(response);
if (!proc)
return;
// Prepare GUI: If it shall stay open disable the required parts
if (MMC->settings()->get("NoHide").toBool())
{
ui->actionLaunchInstance->setEnabled(false);
}
else
{
this->hide();
}
console = new ConsoleWindow(proc);
connect(proc, SIGNAL(log(QString, MessageLevel::Enum)), console,
SLOT(write(QString, MessageLevel::Enum)));
connect(proc, SIGNAL(ended(BaseInstance *)), this, SLOT(instanceEnded(BaseInstance *)));
if (instance->settings().get("ShowConsole").toBool())
{
console->show();
}
proc->setLogin(response.username, response.session_id);
proc->launch();
}
void MainWindow::taskStart() void MainWindow::taskStart()
{ {
// Nothing to do here yet. // Nothing to do here yet.

View File

@ -21,6 +21,8 @@
#include "logic/net/LoginTask.h" #include "logic/net/LoginTask.h"
#include "logic/BaseInstance.h" #include "logic/BaseInstance.h"
#include "logic/auth/MojangAccount.h"
class QToolButton; class QToolButton;
class LabeledToolButton; class LabeledToolButton;
class QLabel; class QLabel;
@ -104,8 +106,12 @@ slots:
void on_actionEditInstNotes_triggered(); void on_actionEditInstNotes_triggered();
void doLogin(const QString &errorMsg = ""); void doLogin(const QString &errorMsg = "");
void doLogin(QString username, QString password);
void doAutoLogin(); /*!
* Launches the given instance with the given account.
* This function assumes that the given account has a valid, usable access token.
*/
void launchInstance(BaseInstance* instance, MojangAccountPtr account);
void onLoginComplete(); void onLoginComplete();
@ -137,8 +143,6 @@ slots:
void startTask(Task *task); void startTask(Task *task);
void launchInstance(BaseInstance *inst, LoginResponse response);
protected: protected:
bool eventFilter(QObject *obj, QEvent *ev); bool eventFilter(QObject *obj, QEvent *ev);
void setCatBackground(bool enabled); void setCatBackground(bool enabled);

View File

@ -22,7 +22,7 @@
#include "inifile.h" #include "inifile.h"
#include "lists/BaseVersionList.h" #include "lists/BaseVersionList.h"
#include "net/LoginTask.h" #include "logic/auth/MojangAccount.h"
class QDialog; class QDialog;
class BaseUpdate; class BaseUpdate;
@ -153,8 +153,8 @@ public:
/// returns a valid update task if update is needed, NULL otherwise /// returns a valid update task if update is needed, NULL otherwise
virtual BaseUpdate *doUpdate() = 0; virtual BaseUpdate *doUpdate() = 0;
/// returns a valid minecraft process, ready for launch /// returns a valid minecraft process, ready for launch with the given account.
virtual MinecraftProcess *prepareForLaunch(LoginResponse response) = 0; virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account) = 0;
/// do any necessary cleanups after the instance finishes. also runs before /// do any necessary cleanups after the instance finishes. also runs before
/// 'prepareForLaunch' /// 'prepareForLaunch'

View File

@ -38,6 +38,8 @@ void InstanceLauncher::onTerminated()
void InstanceLauncher::onLoginComplete() void InstanceLauncher::onLoginComplete()
{ {
// TODO: Fix this.
/*
LoginTask *task = (LoginTask *)QObject::sender(); LoginTask *task = (LoginTask *)QObject::sender();
auto result = task->getResult(); auto result = task->getResult();
auto instance = MMC->instances()->getInstanceById(instId); auto instance = MMC->instances()->getInstanceById(instId);
@ -55,6 +57,7 @@ void InstanceLauncher::onLoginComplete()
SLOT(write(QString, MessageLevel::Enum))); SLOT(write(QString, MessageLevel::Enum)));
proc->launch(); proc->launch();
*/
} }
void InstanceLauncher::doLogin(const QString &errorMsg) void InstanceLauncher::doLogin(const QString &errorMsg)

View File

@ -50,7 +50,7 @@ BaseUpdate *LegacyInstance::doUpdate()
return new LegacyUpdate(this, this); return new LegacyUpdate(this, this);
} }
MinecraftProcess *LegacyInstance::prepareForLaunch(LoginResponse response) MinecraftProcess *LegacyInstance::prepareForLaunch(MojangAccountPtr account)
{ {
MinecraftProcess *proc = new MinecraftProcess(this); MinecraftProcess *proc = new MinecraftProcess(this);
@ -103,8 +103,8 @@ MinecraftProcess *LegacyInstance::prepareForLaunch(LoginResponse response)
#endif #endif
args << "-jar" << LAUNCHER_FILE; args << "-jar" << LAUNCHER_FILE;
args << response.player_name; args << account->currentProfile()->name();
args << response.session_id; args << account->accessToken();
args << windowTitle; args << windowTitle;
args << windowSize; args << windowSize;
args << lwjgl; args << lwjgl;

View File

@ -80,7 +80,7 @@ public:
virtual void setShouldUpdate(bool val); virtual void setShouldUpdate(bool val);
virtual BaseUpdate *doUpdate(); virtual BaseUpdate *doUpdate();
virtual MinecraftProcess *prepareForLaunch(LoginResponse response); virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account);
virtual void cleanupAfterRun(); virtual void cleanupAfterRun();
virtual QDialog *createModEditDialog(QWidget *parent); virtual QDialog *createModEditDialog(QWidget *parent);
@ -93,4 +93,4 @@ public:
protected protected
slots: slots:
virtual void jarModsChanged(); virtual void jarModsChanged();
}; };

View File

@ -65,7 +65,7 @@ QString replaceTokensIn(QString text, QMap<QString, QString> with)
return result; return result;
} }
QStringList OneSixInstance::processMinecraftArgs(LoginResponse response) QStringList OneSixInstance::processMinecraftArgs(MojangAccountPtr account)
{ {
I_D(OneSixInstance); I_D(OneSixInstance);
auto version = d->version; auto version = d->version;
@ -73,11 +73,11 @@ QStringList OneSixInstance::processMinecraftArgs(LoginResponse response)
QMap<QString, QString> token_mapping; QMap<QString, QString> token_mapping;
// yggdrasil! // yggdrasil!
token_mapping["auth_username"] = response.username; token_mapping["auth_username"] = account->username();
token_mapping["auth_session"] = response.session_id; //token_mapping["auth_session"] = response.session_id;
token_mapping["auth_access_token"] = response.access_token; token_mapping["auth_access_token"] = account->accessToken();
token_mapping["auth_player_name"] = response.player_name; token_mapping["auth_player_name"] = account->currentProfile()->name();
token_mapping["auth_uuid"] = response.player_id; token_mapping["auth_uuid"] = account->currentProfile()->id();
// this is for offline?: // this is for offline?:
/* /*
@ -102,7 +102,7 @@ QStringList OneSixInstance::processMinecraftArgs(LoginResponse response)
return parts; return parts;
} }
MinecraftProcess *OneSixInstance::prepareForLaunch(LoginResponse response) MinecraftProcess *OneSixInstance::prepareForLaunch(MojangAccountPtr account)
{ {
I_D(OneSixInstance); I_D(OneSixInstance);
cleanupAfterRun(); cleanupAfterRun();
@ -169,7 +169,7 @@ MinecraftProcess *OneSixInstance::prepareForLaunch(LoginResponse response)
args << classPath; args << classPath;
} }
args << version->mainClass; args << version->mainClass;
args.append(processMinecraftArgs(response)); args.append(processMinecraftArgs(account));
// Set the width and height for 1.6 instances // Set the width and height for 1.6 instances
bool maximize = settings().get("LaunchMaximized").toBool(); bool maximize = settings().get("LaunchMaximized").toBool();

View File

@ -40,7 +40,7 @@ public:
virtual QString instanceConfigFolder() const; virtual QString instanceConfigFolder() const;
virtual BaseUpdate *doUpdate(); virtual BaseUpdate *doUpdate();
virtual MinecraftProcess *prepareForLaunch(LoginResponse response); virtual MinecraftProcess *prepareForLaunch(MojangAccountPtr account);
virtual void cleanupAfterRun(); virtual void cleanupAfterRun();
virtual QString intendedVersionId() const; virtual QString intendedVersionId() const;
@ -72,5 +72,5 @@ public:
virtual QString getStatusbarDescription(); virtual QString getStatusbarDescription();
private: private:
QStringList processMinecraftArgs(LoginResponse response); QStringList processMinecraftArgs(MojangAccountPtr account);
}; };

View File

@ -18,6 +18,8 @@
#include "MojangAccount.h" #include "MojangAccount.h"
#include <QUuid> #include <QUuid>
#include <QJsonObject>
#include <QJsonArray>
#include <logger/QsLog.h> #include <logger/QsLog.h>
@ -89,7 +91,12 @@ const QList<AccountProfile> MojangAccount::profiles() const
const AccountProfile* MojangAccount::currentProfile() const const AccountProfile* MojangAccount::currentProfile() const
{ {
if (m_currentProfile < 0) if (m_currentProfile < 0)
return nullptr; {
if (m_profiles.length() > 0)
return &m_profiles.at(0);
else
return nullptr;
}
else else
return &m_profiles.at(m_currentProfile); return &m_profiles.at(m_currentProfile);
} }
@ -128,9 +135,36 @@ MojangAccountPtr MojangAccount::loadFromJson(const QJsonObject& object)
QString clientToken = object.value("clientToken").toString(""); QString clientToken = object.value("clientToken").toString("");
QString accessToken = object.value("accessToken").toString(""); QString accessToken = object.value("accessToken").toString("");
// TODO: Load profiles? QJsonArray profileArray = object.value("profiles").toArray();
if (profileArray.size() < 1)
{
QLOG_ERROR() << "Can't load Mojang account with username \"" << username << "\". No profiles found.";
return nullptr;
}
return MojangAccountPtr(new MojangAccount(username, clientToken, accessToken)); ProfileList profiles;
for (QJsonValue profileVal : profileArray)
{
QJsonObject profileObject = profileVal.toObject();
QString id = profileObject.value("id").toString("");
QString name = profileObject.value("name").toString("");
if (id.isEmpty() || name.isEmpty())
{
QLOG_WARN() << "Unable to load a profile because it was missing an ID or a name.";
continue;
}
profiles.append(AccountProfile(id, name));
}
MojangAccountPtr account(new MojangAccount(username, clientToken, accessToken));
account->loadProfiles(profiles);
// Get the currently selected profile.
QString currentProfile = object.value("activeProfile").toString("");
if (!currentProfile.isEmpty())
account->setProfile(currentProfile);
return account;
} }
QJsonObject MojangAccount::saveToJson() QJsonObject MojangAccount::saveToJson()
@ -139,7 +173,20 @@ QJsonObject MojangAccount::saveToJson()
json.insert("username", username()); json.insert("username", username());
json.insert("clientToken", clientToken()); json.insert("clientToken", clientToken());
json.insert("accessToken", accessToken()); json.insert("accessToken", accessToken());
// TODO: Save profiles?
QJsonArray profileArray;
for (AccountProfile profile : m_profiles)
{
QJsonObject profileObj;
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());
return json; return json;
} }

View File

@ -123,7 +123,7 @@ public:
/** /**
* Returns a pointer to the currently selected profile. * Returns a pointer to the currently selected profile.
* If no profile is selected, returns nullptr. * If no profile is selected, returns the first profile in the profile list or nullptr if there are none.
*/ */
const AccountProfile* currentProfile() const; const AccountProfile* currentProfile() const;

View File

@ -185,7 +185,7 @@ bool MojangAccountList::loadList(const QString& filePath)
// TODO: We should probably report this error to the user. // TODO: We should probably report this error to the user.
if (!file.open(QIODevice::ReadOnly)) if (!file.open(QIODevice::ReadOnly))
{ {
QLOG_ERROR() << "Failed to read the account list file (" << path << ")."; QLOG_ERROR() << QString("Failed to read the account list file (%1).").arg(path).toUtf8();
return false; return false;
} }
@ -217,9 +217,9 @@ bool MojangAccountList::loadList(const QString& filePath)
// Make sure the format version matches. // Make sure the format version matches.
if (root.value("formatVersion").toVariant().toInt() != ACCOUNT_LIST_FORMAT_VERSION) if (root.value("formatVersion").toVariant().toInt() != ACCOUNT_LIST_FORMAT_VERSION)
{ {
QString newName = "accountlist-old.json"; QString newName = "accounts-old.json";
QLOG_WARN() << "Format version mismatch when loading account list. Existing one will be renamed to \"" QLOG_WARN() << "Format version mismatch when loading account list. Existing one will be renamed to"
<< newName << "\"."; << newName;
// Attempt to rename the old version. // Attempt to rename the old version.
file.rename(newName); file.rename(newName);
@ -257,7 +257,7 @@ bool MojangAccountList::saveList(const QString& filePath)
return false; return false;
} }
QLOG_INFO() << "Writing account list to \"" << path << "\"..."; QLOG_INFO() << "Writing account list to" << path;
QLOG_DEBUG() << "Building JSON data structure."; QLOG_DEBUG() << "Building JSON data structure.";
// Build the JSON document to write to the list file. // Build the JSON document to write to the list file.
@ -289,7 +289,7 @@ bool MojangAccountList::saveList(const QString& filePath)
// TODO: We should probably report this error to the user. // TODO: We should probably report this error to the user.
if (!file.open(QIODevice::WriteOnly)) if (!file.open(QIODevice::WriteOnly))
{ {
QLOG_ERROR() << "Failed to read the account list file (" << path << ")."; QLOG_ERROR() << QString("Failed to read the account list file (%1).").arg(path).toUtf8();
return false; return false;
} }
@ -297,7 +297,7 @@ bool MojangAccountList::saveList(const QString& filePath)
file.write(doc.toJson()); file.write(doc.toJson());
file.close(); file.close();
QLOG_INFO() << "Saved account list to \"" << path << "\"."; QLOG_INFO() << "Saved account list to" << path;
return true; return true;
} }