From bfc9e1e5d598f354dd39e5c2eb51d5e51585359b Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 28 Nov 2013 20:45:52 -0600 Subject: Verify access tokens before launching Minecraft Kind of an important thing to do... Heh... --- gui/MainWindow.cpp | 74 +++++++++++++++++++++++++++++++++++---- gui/MainWindow.h | 18 +++++++++- gui/dialogs/PasswordDialog.cpp | 38 ++++++++++++++++++++ gui/dialogs/PasswordDialog.h | 40 ++++++++++++++++++++++ gui/dialogs/PasswordDialog.ui | 78 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 7 deletions(-) create mode 100644 gui/dialogs/PasswordDialog.cpp create mode 100644 gui/dialogs/PasswordDialog.h create mode 100644 gui/dialogs/PasswordDialog.ui (limited to 'gui') diff --git a/gui/MainWindow.cpp b/gui/MainWindow.cpp index fb25ae36..72e754ee 100644 --- a/gui/MainWindow.cpp +++ b/gui/MainWindow.cpp @@ -60,6 +60,7 @@ #include "gui/dialogs/CopyInstanceDialog.h" #include "gui/dialogs/AccountListDialog.h" #include "gui/dialogs/AccountSelectDialog.h" +#include "gui/dialogs/PasswordDialog.h" #include "gui/ConsoleWindow.h" @@ -69,6 +70,9 @@ #include "logic/lists/IconList.h" #include "logic/lists/JavaVersionList.h" +#include "logic/auth/AuthenticateTask.h" +#include "logic/auth/ValidateTask.h" + #include "logic/net/LoginTask.h" #include "logic/BaseInstance.h" @@ -709,7 +713,7 @@ void MainWindow::instanceActivated(QModelIndex index) NagUtils::checkJVMArgs(inst->settings().get("JvmArgs").toString(), this); - doLogin(); + doLaunch(); } void MainWindow::on_actionLaunchInstance_triggered() @@ -717,11 +721,11 @@ void MainWindow::on_actionLaunchInstance_triggered() if (m_selectedInstance) { NagUtils::checkJVMArgs(m_selectedInstance->settings().get("JvmArgs").toString(), this); - doLogin(); + doLaunch(); } } -void MainWindow::doLogin(const QString &errorMsg) +void MainWindow::doLaunch() { if (!m_selectedInstance) return; @@ -761,11 +765,69 @@ void MainWindow::doLogin(const QString &errorMsg) if (account.get() != nullptr) { - // We'll need to validate the access token to make sure the account is still logged in. - // TODO: Do that ^ - + doLaunchInst(m_selectedInstance, account); + } +} + +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); + ValidateTask validateTask(account, &progDialog); + progDialog.exec(&validateTask); + + if (validateTask.successful()) + { prepareLaunch(m_selectedInstance, account); } + else + { + YggdrasilTask::Error* error = validateTask.getError(); + + if (error != nullptr) + { + if (error->getErrorMessage().contains("invalid token", Qt::CaseInsensitive)) + { + // TODO: Allow the user to enter their password and "refresh" their access token. + if (doRefreshToken(account, tr("Your account's access token is invalid. Please enter your password to log in again."))) + doLaunchInst(instance, account); + } + else + { + CustomMessageBox::selectable(this, tr("Access Token Validation Error"), + tr("There was an error when trying to validate your access token.\n" + "Details: %s").arg(error->getDisplayMessage()), + QMessageBox::Warning, QMessageBox::Ok)->exec(); + } + } + else + { + CustomMessageBox::selectable(this, tr("Access Token Validation Error"), + tr("There was an unknown error when trying to validate your access token." + "The authentication server might be down, or you might not be connected to the Internet."), + QMessageBox::Warning, QMessageBox::Ok)->exec(); + } + } +} + +bool MainWindow::doRefreshToken(MojangAccountPtr account, const QString& errorMsg) +{ + PasswordDialog passDialog(errorMsg, this); + if (passDialog.exec() == QDialog::Accepted) + { + // To refresh the token, we just create an authenticate task with the given account and the user's password. + ProgressDialog progDialog(this); + AuthenticateTask authTask(account, passDialog.password(), &progDialog); + progDialog.exec(&authTask); + if (authTask.successful()) + return true; + else + { + // If the authentication task failed, recurse with the task's error message. + return doRefreshToken(account, authTask.failReason()); + } + } + else return false; } void MainWindow::prepareLaunch(BaseInstance* instance, MojangAccountPtr account) diff --git a/gui/MainWindow.h b/gui/MainWindow.h index 4191e590..650fdee2 100644 --- a/gui/MainWindow.h +++ b/gui/MainWindow.h @@ -106,7 +106,23 @@ slots: void on_actionEditInstNotes_triggered(); - void doLogin(const QString &errorMsg = ""); + /*! + * Launches the currently selected instance with the default account. + * If no default account is selected, prompts the user to pick an account. + */ + void doLaunch(); + + /*! + * Launches the given instance with the given account. + */ + void doLaunchInst(BaseInstance* instance, MojangAccountPtr account); + + /*! + * Opens an input dialog, allowing the user to input their password and refresh its access token. + * This function will execute the proper Yggdrasil task to refresh the access token. + * Returns true if successful. False if the user cancelled. + */ + bool doRefreshToken(MojangAccountPtr account, const QString& errorMsg=""); /*! * Launches the given instance with the given account. diff --git a/gui/dialogs/PasswordDialog.cpp b/gui/dialogs/PasswordDialog.cpp new file mode 100644 index 00000000..c67fc6a2 --- /dev/null +++ b/gui/dialogs/PasswordDialog.cpp @@ -0,0 +1,38 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PasswordDialog.h" +#include "ui_PasswordDialog.h" + +PasswordDialog::PasswordDialog(const QString& errorMsg, QWidget *parent) : + QDialog(parent), + ui(new Ui::PasswordDialog) +{ + ui->setupUi(this); + + ui->errorLabel->setText(errorMsg); + ui->errorLabel->setVisible(!errorMsg.isEmpty()); +} + +PasswordDialog::~PasswordDialog() +{ + delete ui; +} + +QString PasswordDialog::password() const +{ + return ui->passTextBox->text(); +} + diff --git a/gui/dialogs/PasswordDialog.h b/gui/dialogs/PasswordDialog.h new file mode 100644 index 00000000..0919e6e4 --- /dev/null +++ b/gui/dialogs/PasswordDialog.h @@ -0,0 +1,40 @@ +/* Copyright 2013 MultiMC Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace Ui { +class PasswordDialog; +} + +class PasswordDialog : public QDialog +{ + Q_OBJECT + +public: + explicit PasswordDialog(const QString& errorMsg="", QWidget *parent = 0); + ~PasswordDialog(); + + /*! + * Gets the text entered in the dialog's password field. + */ + QString password() const; + +private: + Ui::PasswordDialog *ui; +}; + diff --git a/gui/dialogs/PasswordDialog.ui b/gui/dialogs/PasswordDialog.ui new file mode 100644 index 00000000..6c70b033 --- /dev/null +++ b/gui/dialogs/PasswordDialog.ui @@ -0,0 +1,78 @@ + + + PasswordDialog + + + + 0 + 0 + 400 + 94 + + + + Dialog + + + + + + Error message here... + + + + + + + QLineEdit::Password + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + PasswordDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + PasswordDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + -- cgit v1.2.3