Improve login UI
Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
parent
849c3faeb4
commit
abedc6a23c
@ -217,15 +217,9 @@ set(MINECRAFT_SOURCES
|
|||||||
minecraft/auth/Parsers.cpp
|
minecraft/auth/Parsers.cpp
|
||||||
minecraft/auth/Parsers.h
|
minecraft/auth/Parsers.h
|
||||||
|
|
||||||
minecraft/auth/flows/AuthFlow.cpp
|
minecraft/auth/AuthFlow.cpp
|
||||||
minecraft/auth/flows/AuthFlow.h
|
minecraft/auth/AuthFlow.h
|
||||||
minecraft/auth/flows/MSA.cpp
|
|
||||||
minecraft/auth/flows/MSA.h
|
|
||||||
minecraft/auth/flows/Offline.cpp
|
|
||||||
minecraft/auth/flows/Offline.h
|
|
||||||
|
|
||||||
minecraft/auth/steps/OfflineStep.cpp
|
|
||||||
minecraft/auth/steps/OfflineStep.h
|
|
||||||
minecraft/auth/steps/EntitlementsStep.cpp
|
minecraft/auth/steps/EntitlementsStep.cpp
|
||||||
minecraft/auth/steps/EntitlementsStep.h
|
minecraft/auth/steps/EntitlementsStep.h
|
||||||
minecraft/auth/steps/GetSkinStep.cpp
|
minecraft/auth/steps/GetSkinStep.cpp
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void tokenToJSONV3(QJsonObject& parent, Katabasis::Token t, const char* tokenName)
|
void tokenToJSONV3(QJsonObject& parent, Token t, const char* tokenName)
|
||||||
{
|
{
|
||||||
if (!t.persistent) {
|
if (!t.persistent) {
|
||||||
return;
|
return;
|
||||||
@ -74,9 +74,9 @@ void tokenToJSONV3(QJsonObject& parent, Katabasis::Token t, const char* tokenNam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Katabasis::Token tokenFromJSONV3(const QJsonObject& parent, const char* tokenName)
|
Token tokenFromJSONV3(const QJsonObject& parent, const char* tokenName)
|
||||||
{
|
{
|
||||||
Katabasis::Token out;
|
Token out;
|
||||||
auto tokenObject = parent.value(tokenName).toObject();
|
auto tokenObject = parent.value(tokenName).toObject();
|
||||||
if (tokenObject.isEmpty()) {
|
if (tokenObject.isEmpty()) {
|
||||||
return out;
|
return out;
|
||||||
@ -94,7 +94,7 @@ Katabasis::Token tokenFromJSONV3(const QJsonObject& parent, const char* tokenNam
|
|||||||
auto token = tokenObject.value("token");
|
auto token = tokenObject.value("token");
|
||||||
if (token.isString()) {
|
if (token.isString()) {
|
||||||
out.token = token.toString();
|
out.token = token.toString();
|
||||||
out.validity = Katabasis::Validity::Assumed;
|
out.validity = Validity::Assumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto refresh_token = tokenObject.value("refresh_token");
|
auto refresh_token = tokenObject.value("refresh_token");
|
||||||
@ -241,13 +241,13 @@ MinecraftProfile profileFromJSONV3(const QJsonObject& parent, const char* tokenN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.validity = Katabasis::Validity::Assumed;
|
out.validity = Validity::Assumed;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void entitlementToJSONV3(QJsonObject& parent, MinecraftEntitlement p)
|
void entitlementToJSONV3(QJsonObject& parent, MinecraftEntitlement p)
|
||||||
{
|
{
|
||||||
if (p.validity == Katabasis::Validity::None) {
|
if (p.validity == Validity::None) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QJsonObject out;
|
QJsonObject out;
|
||||||
@ -271,7 +271,7 @@ bool entitlementFromJSONV3(const QJsonObject& parent, MinecraftEntitlement& out)
|
|||||||
}
|
}
|
||||||
out.canPlayMinecraft = canPlayMinecraftV.toBool(false);
|
out.canPlayMinecraft = canPlayMinecraftV.toBool(false);
|
||||||
out.ownsMinecraft = ownsMinecraftV.toBool(false);
|
out.ownsMinecraft = ownsMinecraftV.toBool(false);
|
||||||
out.validity = Katabasis::Validity::Assumed;
|
out.validity = Validity::Assumed;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -313,10 +313,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data)
|
|||||||
|
|
||||||
minecraftProfile = profileFromJSONV3(data, "profile");
|
minecraftProfile = profileFromJSONV3(data, "profile");
|
||||||
if (!entitlementFromJSONV3(data, minecraftEntitlement)) {
|
if (!entitlementFromJSONV3(data, minecraftEntitlement)) {
|
||||||
if (minecraftProfile.validity != Katabasis::Validity::None) {
|
if (minecraftProfile.validity != Validity::None) {
|
||||||
minecraftEntitlement.canPlayMinecraft = true;
|
minecraftEntitlement.canPlayMinecraft = true;
|
||||||
minecraftEntitlement.ownsMinecraft = true;
|
minecraftEntitlement.ownsMinecraft = true;
|
||||||
minecraftEntitlement.validity = Katabasis::Validity::Assumed;
|
minecraftEntitlement.validity = Validity::Assumed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,18 +44,6 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
namespace Katabasis {
|
|
||||||
enum class Activity {
|
|
||||||
Idle,
|
|
||||||
LoggingIn,
|
|
||||||
LoggingOut,
|
|
||||||
Refreshing,
|
|
||||||
FailedSoft, //!< soft failure. this generally means the user auth details haven't been invalidated
|
|
||||||
FailedHard, //!< hard failure. auth is invalid
|
|
||||||
FailedGone, //!< hard failure. auth is invalid, and the account no longer exists
|
|
||||||
Succeeded
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class Validity { None, Assumed, Certain };
|
enum class Validity { None, Assumed, Certain };
|
||||||
|
|
||||||
struct Token {
|
struct Token {
|
||||||
@ -69,8 +57,6 @@ struct Token {
|
|||||||
bool persistent = true;
|
bool persistent = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Katabasis
|
|
||||||
|
|
||||||
struct Skin {
|
struct Skin {
|
||||||
QString id;
|
QString id;
|
||||||
QString url;
|
QString url;
|
||||||
@ -90,7 +76,7 @@ struct Cape {
|
|||||||
struct MinecraftEntitlement {
|
struct MinecraftEntitlement {
|
||||||
bool ownsMinecraft = false;
|
bool ownsMinecraft = false;
|
||||||
bool canPlayMinecraft = false;
|
bool canPlayMinecraft = false;
|
||||||
Katabasis::Validity validity = Katabasis::Validity::None;
|
Validity validity = Validity::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MinecraftProfile {
|
struct MinecraftProfile {
|
||||||
@ -99,7 +85,7 @@ struct MinecraftProfile {
|
|||||||
Skin skin;
|
Skin skin;
|
||||||
QString currentCape;
|
QString currentCape;
|
||||||
QMap<QString, Cape> capes;
|
QMap<QString, Cape> capes;
|
||||||
Katabasis::Validity validity = Katabasis::Validity::None;
|
Validity validity = Validity::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AccountType { MSA, Offline };
|
enum class AccountType { MSA, Offline };
|
||||||
@ -124,15 +110,15 @@ struct AccountData {
|
|||||||
AccountType type = AccountType::MSA;
|
AccountType type = AccountType::MSA;
|
||||||
|
|
||||||
QString msaClientID;
|
QString msaClientID;
|
||||||
Katabasis::Token msaToken;
|
Token msaToken;
|
||||||
Katabasis::Token userToken;
|
Token userToken;
|
||||||
Katabasis::Token xboxApiToken;
|
Token xboxApiToken;
|
||||||
Katabasis::Token mojangservicesToken;
|
Token mojangservicesToken;
|
||||||
|
|
||||||
Katabasis::Token yggdrasilToken;
|
Token yggdrasilToken;
|
||||||
MinecraftProfile minecraftProfile;
|
MinecraftProfile minecraftProfile;
|
||||||
MinecraftEntitlement minecraftEntitlement;
|
MinecraftEntitlement minecraftEntitlement;
|
||||||
Katabasis::Validity validity_ = Katabasis::Validity::None;
|
Validity validity_ = Validity::None;
|
||||||
|
|
||||||
// runtime only information (not saved with the account)
|
// runtime only information (not saved with the account)
|
||||||
QString internalId;
|
QString internalId;
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "MinecraftAccount.h"
|
#include "MinecraftAccount.h"
|
||||||
#include "minecraft/auth/flows/AuthFlow.h"
|
#include "minecraft/auth/AuthFlow.h"
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
@ -3,27 +3,47 @@
|
|||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
|
#include "minecraft/auth/AccountData.h"
|
||||||
|
#include "minecraft/auth/steps/EntitlementsStep.h"
|
||||||
|
#include "minecraft/auth/steps/GetSkinStep.h"
|
||||||
|
#include "minecraft/auth/steps/LauncherLoginStep.h"
|
||||||
|
#include "minecraft/auth/steps/MSAStep.h"
|
||||||
|
#include "minecraft/auth/steps/MinecraftProfileStep.h"
|
||||||
|
#include "minecraft/auth/steps/XboxAuthorizationStep.h"
|
||||||
|
#include "minecraft/auth/steps/XboxProfileStep.h"
|
||||||
|
#include "minecraft/auth/steps/XboxUserStep.h"
|
||||||
|
|
||||||
#include "AuthFlow.h"
|
#include "AuthFlow.h"
|
||||||
|
|
||||||
#include <Application.h>
|
#include <Application.h>
|
||||||
|
|
||||||
AuthFlow::AuthFlow(AccountData* data, QObject* parent) : Task(parent), m_data(data)
|
AuthFlow::AuthFlow(AccountData* data, bool silent, QObject* parent) : Task(parent), m_data(data)
|
||||||
{
|
{
|
||||||
|
if (data->type == AccountType::MSA) {
|
||||||
|
auto oauthStep = makeShared<MSAStep>(m_data, silent);
|
||||||
|
connect(oauthStep.get(), &MSAStep::authorizeWithBrowser, this, &AuthFlow::authorizeWithBrowser);
|
||||||
|
m_steps.append(oauthStep);
|
||||||
|
m_steps.append(makeShared<XboxUserStep>(m_data));
|
||||||
|
m_steps.append(makeShared<XboxAuthorizationStep>(m_data, &m_data->xboxApiToken, "http://xboxlive.com", "Xbox"));
|
||||||
|
m_steps.append(
|
||||||
|
makeShared<XboxAuthorizationStep>(m_data, &m_data->mojangservicesToken, "rp://api.minecraftservices.com/", "Mojang"));
|
||||||
|
m_steps.append(makeShared<LauncherLoginStep>(m_data));
|
||||||
|
m_steps.append(makeShared<XboxProfileStep>(m_data));
|
||||||
|
m_steps.append(makeShared<EntitlementsStep>(m_data));
|
||||||
|
m_steps.append(makeShared<MinecraftProfileStep>(m_data));
|
||||||
|
m_steps.append(makeShared<GetSkinStep>(m_data));
|
||||||
|
}
|
||||||
changeState(AccountTaskState::STATE_CREATED);
|
changeState(AccountTaskState::STATE_CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthFlow::succeed()
|
void AuthFlow::succeed()
|
||||||
{
|
{
|
||||||
m_data->validity_ = Katabasis::Validity::Certain;
|
m_data->validity_ = Validity::Certain;
|
||||||
changeState(AccountTaskState::STATE_SUCCEEDED, tr("Finished all authentication steps"));
|
changeState(AccountTaskState::STATE_SUCCEEDED, tr("Finished all authentication steps"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthFlow::executeTask()
|
void AuthFlow::executeTask()
|
||||||
{
|
{
|
||||||
if (m_currentStep) {
|
|
||||||
emitFailed("No task");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
changeState(AccountTaskState::STATE_WORKING, tr("Initializing"));
|
changeState(AccountTaskState::STATE_WORKING, tr("Initializing"));
|
||||||
nextStep();
|
nextStep();
|
||||||
}
|
}
|
||||||
@ -46,9 +66,8 @@ void AuthFlow::nextStep()
|
|||||||
|
|
||||||
void AuthFlow::stepFinished(AccountTaskState resultingState, QString message)
|
void AuthFlow::stepFinished(AccountTaskState resultingState, QString message)
|
||||||
{
|
{
|
||||||
if (changeState(resultingState, message)) {
|
if (changeState(resultingState, message))
|
||||||
nextStep();
|
nextStep();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AuthFlow::changeState(AccountTaskState newState, QString reason)
|
bool AuthFlow::changeState(AccountTaskState newState, QString reason)
|
@ -15,30 +15,26 @@ class AuthFlow : public Task {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AuthFlow(AccountData* data, QObject* parent = 0);
|
explicit AuthFlow(AccountData* data, bool silent = false, QObject* parent = 0);
|
||||||
virtual ~AuthFlow() = default;
|
virtual ~AuthFlow() = default;
|
||||||
|
|
||||||
Katabasis::Validity validity() { return m_data->validity_; };
|
|
||||||
|
|
||||||
void executeTask() override;
|
void executeTask() override;
|
||||||
|
|
||||||
AccountTaskState taskState() { return m_taskState; }
|
AccountTaskState taskState() { return m_taskState; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void activityChanged(Katabasis::Activity activity);
|
void authorizeWithBrowser(const QUrl& url);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void succeed();
|
void succeed();
|
||||||
void nextStep();
|
void nextStep();
|
||||||
|
|
||||||
protected slots:
|
private slots:
|
||||||
// NOTE: true -> non-terminal state, false -> terminal state
|
// NOTE: true -> non-terminal state, false -> terminal state
|
||||||
bool changeState(AccountTaskState newState, QString reason = QString());
|
bool changeState(AccountTaskState newState, QString reason = QString());
|
||||||
|
|
||||||
private slots:
|
|
||||||
void stepFinished(AccountTaskState resultingState, QString message);
|
void stepFinished(AccountTaskState resultingState, QString message);
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
AccountTaskState m_taskState = AccountTaskState::STATE_CREATED;
|
AccountTaskState m_taskState = AccountTaskState::STATE_CREATED;
|
||||||
QList<AuthStep::Ptr> m_steps;
|
QList<AuthStep::Ptr> m_steps;
|
||||||
AuthStep::Ptr m_currentStep;
|
AuthStep::Ptr m_currentStep;
|
@ -50,11 +50,8 @@
|
|||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
#include "flows/MSA.h"
|
|
||||||
#include "flows/Offline.h"
|
|
||||||
#include "minecraft/auth/AccountData.h"
|
#include "minecraft/auth/AccountData.h"
|
||||||
#include "minecraft/auth/flows/AuthFlow.h"
|
#include "minecraft/auth/AuthFlow.h"
|
||||||
#include "tasks/Task.h"
|
|
||||||
|
|
||||||
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent)
|
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
@ -82,7 +79,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString& username)
|
|||||||
auto account = makeShared<MinecraftAccount>();
|
auto account = makeShared<MinecraftAccount>();
|
||||||
account->data.type = AccountType::Offline;
|
account->data.type = AccountType::Offline;
|
||||||
account->data.yggdrasilToken.token = "0";
|
account->data.yggdrasilToken.token = "0";
|
||||||
account->data.yggdrasilToken.validity = Katabasis::Validity::Certain;
|
account->data.yggdrasilToken.validity = Validity::Certain;
|
||||||
account->data.yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
|
account->data.yggdrasilToken.issueInstant = QDateTime::currentDateTimeUtc();
|
||||||
account->data.yggdrasilToken.extra["userName"] = username;
|
account->data.yggdrasilToken.extra["userName"] = username;
|
||||||
account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
|
account->data.yggdrasilToken.extra["clientToken"] = QUuid::createUuid().toString().remove(QRegularExpression("[{}-]"));
|
||||||
@ -90,7 +87,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString& username)
|
|||||||
account->data.minecraftEntitlement.canPlayMinecraft = true;
|
account->data.minecraftEntitlement.canPlayMinecraft = true;
|
||||||
account->data.minecraftProfile.id = uuidFromUsername(username).toString().remove(QRegularExpression("[{}-]"));
|
account->data.minecraftProfile.id = uuidFromUsername(username).toString().remove(QRegularExpression("[{}-]"));
|
||||||
account->data.minecraftProfile.name = username;
|
account->data.minecraftProfile.name = username;
|
||||||
account->data.minecraftProfile.validity = Katabasis::Validity::Certain;
|
account->data.minecraftProfile.validity = Validity::Certain;
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,23 +119,11 @@ QPixmap MinecraftAccount::getFace() const
|
|||||||
return skin.scaled(64, 64, Qt::KeepAspectRatio);
|
return skin.scaled(64, 64, Qt::KeepAspectRatio);
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_qobject_ptr<AuthFlow> MinecraftAccount::loginMSA()
|
shared_qobject_ptr<AuthFlow> MinecraftAccount::login()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_currentTask.get() == nullptr);
|
Q_ASSERT(m_currentTask.get() == nullptr);
|
||||||
|
|
||||||
m_currentTask.reset(new MSAInteractive(&data));
|
m_currentTask.reset(new AuthFlow(&data, false, this));
|
||||||
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
|
|
||||||
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
|
|
||||||
connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
|
|
||||||
emit activityChanged(true);
|
|
||||||
return m_currentTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
shared_qobject_ptr<AuthFlow> MinecraftAccount::loginOffline()
|
|
||||||
{
|
|
||||||
Q_ASSERT(m_currentTask.get() == nullptr);
|
|
||||||
|
|
||||||
m_currentTask.reset(new OfflineLogin(&data));
|
|
||||||
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
|
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
|
||||||
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
|
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
|
||||||
connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
|
connect(m_currentTask.get(), &Task::aborted, this, [this] { authFailed(tr("Aborted")); });
|
||||||
@ -152,11 +137,7 @@ shared_qobject_ptr<AuthFlow> MinecraftAccount::refresh()
|
|||||||
return m_currentTask;
|
return m_currentTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.type == AccountType::MSA) {
|
m_currentTask.reset(new AuthFlow(&data, true, this));
|
||||||
m_currentTask.reset(new MSASilent(&data));
|
|
||||||
} else {
|
|
||||||
m_currentTask.reset(new OfflineLogin(&data));
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
|
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
|
||||||
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
|
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
|
||||||
@ -191,17 +172,17 @@ void MinecraftAccount::authFailed(QString reason)
|
|||||||
if (accountType() == AccountType::MSA) {
|
if (accountType() == AccountType::MSA) {
|
||||||
data.msaToken.token = QString();
|
data.msaToken.token = QString();
|
||||||
data.msaToken.refresh_token = QString();
|
data.msaToken.refresh_token = QString();
|
||||||
data.msaToken.validity = Katabasis::Validity::None;
|
data.msaToken.validity = Validity::None;
|
||||||
data.validity_ = Katabasis::Validity::None;
|
data.validity_ = Validity::None;
|
||||||
} else {
|
} else {
|
||||||
data.yggdrasilToken.token = QString();
|
data.yggdrasilToken.token = QString();
|
||||||
data.yggdrasilToken.validity = Katabasis::Validity::None;
|
data.yggdrasilToken.validity = Validity::None;
|
||||||
data.validity_ = Katabasis::Validity::None;
|
data.validity_ = Validity::None;
|
||||||
}
|
}
|
||||||
emit changed();
|
emit changed();
|
||||||
} break;
|
} break;
|
||||||
case AccountTaskState::STATE_FAILED_GONE: {
|
case AccountTaskState::STATE_FAILED_GONE: {
|
||||||
data.validity_ = Katabasis::Validity::None;
|
data.validity_ = Validity::None;
|
||||||
emit changed();
|
emit changed();
|
||||||
} break;
|
} break;
|
||||||
case AccountTaskState::STATE_CREATED:
|
case AccountTaskState::STATE_CREATED:
|
||||||
@ -231,13 +212,13 @@ bool MinecraftAccount::shouldRefresh() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (data.validity_) {
|
switch (data.validity_) {
|
||||||
case Katabasis::Validity::Certain: {
|
case Validity::Certain: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Katabasis::Validity::None: {
|
case Validity::None: {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case Katabasis::Validity::Assumed: {
|
case Validity::Assumed: {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
#include "AuthSession.h"
|
#include "AuthSession.h"
|
||||||
#include "QObjectPtr.h"
|
#include "QObjectPtr.h"
|
||||||
#include "Usable.h"
|
#include "Usable.h"
|
||||||
#include "minecraft/auth/flows/AuthFlow.h"
|
#include "minecraft/auth/AuthFlow.h"
|
||||||
|
|
||||||
class Task;
|
class Task;
|
||||||
class MinecraftAccount;
|
class MinecraftAccount;
|
||||||
@ -95,9 +95,7 @@ class MinecraftAccount : public QObject, public Usable {
|
|||||||
QJsonObject saveToJson() const;
|
QJsonObject saveToJson() const;
|
||||||
|
|
||||||
public: /* manipulation */
|
public: /* manipulation */
|
||||||
shared_qobject_ptr<AuthFlow> loginMSA();
|
shared_qobject_ptr<AuthFlow> login();
|
||||||
|
|
||||||
shared_qobject_ptr<AuthFlow> loginOffline();
|
|
||||||
|
|
||||||
shared_qobject_ptr<AuthFlow> refresh();
|
shared_qobject_ptr<AuthFlow> refresh();
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ bool getBool(QJsonValue value, bool& out)
|
|||||||
// 2148916238 = child account not linked to a family
|
// 2148916238 = child account not linked to a family
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString name)
|
bool parseXTokenResponse(QByteArray& data, Token& output, QString name)
|
||||||
{
|
{
|
||||||
qDebug() << "Parsing" << name << ":";
|
qDebug() << "Parsing" << name << ":";
|
||||||
qCDebug(authCredentials()) << data;
|
qCDebug(authCredentials()) << data;
|
||||||
@ -135,7 +135,7 @@ bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString nam
|
|||||||
qWarning() << "Missing uhs";
|
qWarning() << "Missing uhs";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
output.validity = Katabasis::Validity::Certain;
|
output.validity = Validity::Certain;
|
||||||
qDebug() << name << "is valid.";
|
qDebug() << name << "is valid.";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output)
|
|||||||
output.capes[capeOut.id] = capeOut;
|
output.capes[capeOut.id] = capeOut;
|
||||||
}
|
}
|
||||||
output.currentCape = currentCape;
|
output.currentCape = currentCape;
|
||||||
output.validity = Katabasis::Validity::Certain;
|
output.validity = Validity::Certain;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +388,7 @@ bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output)
|
|||||||
output.currentCape = capeOut.alias;
|
output.currentCape = capeOut.alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
output.validity = Katabasis::Validity::Certain;
|
output.validity = Validity::Certain;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +422,7 @@ bool parseMinecraftEntitlements(QByteArray& data, MinecraftEntitlement& output)
|
|||||||
output.ownsMinecraft = true;
|
output.ownsMinecraft = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
output.validity = Katabasis::Validity::Certain;
|
output.validity = Validity::Certain;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ bool parseRolloutResponse(QByteArray& data, bool& result)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parseMojangResponse(QByteArray& data, Katabasis::Token& output)
|
bool parseMojangResponse(QByteArray& data, Token& output)
|
||||||
{
|
{
|
||||||
QJsonParseError jsonError;
|
QJsonParseError jsonError;
|
||||||
qDebug() << "Parsing Mojang response...";
|
qDebug() << "Parsing Mojang response...";
|
||||||
@ -488,7 +488,7 @@ bool parseMojangResponse(QByteArray& data, Katabasis::Token& output)
|
|||||||
qWarning() << "access_token is not valid";
|
qWarning() << "access_token is not valid";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
output.validity = Katabasis::Validity::Certain;
|
output.validity = Validity::Certain;
|
||||||
qDebug() << "Mojang response is valid.";
|
qDebug() << "Mojang response is valid.";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ bool getNumber(QJsonValue value, double& out);
|
|||||||
bool getNumber(QJsonValue value, int64_t& out);
|
bool getNumber(QJsonValue value, int64_t& out);
|
||||||
bool getBool(QJsonValue value, bool& out);
|
bool getBool(QJsonValue value, bool& out);
|
||||||
|
|
||||||
bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString name);
|
bool parseXTokenResponse(QByteArray& data, Token& output, QString name);
|
||||||
bool parseMojangResponse(QByteArray& data, Katabasis::Token& output);
|
bool parseMojangResponse(QByteArray& data, Token& output);
|
||||||
|
|
||||||
bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output);
|
bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output);
|
||||||
bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output);
|
bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output);
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
#include "MSA.h"
|
|
||||||
|
|
||||||
#include "minecraft/auth/steps/EntitlementsStep.h"
|
|
||||||
#include "minecraft/auth/steps/GetSkinStep.h"
|
|
||||||
#include "minecraft/auth/steps/LauncherLoginStep.h"
|
|
||||||
#include "minecraft/auth/steps/MSAStep.h"
|
|
||||||
#include "minecraft/auth/steps/MinecraftProfileStep.h"
|
|
||||||
#include "minecraft/auth/steps/XboxAuthorizationStep.h"
|
|
||||||
#include "minecraft/auth/steps/XboxProfileStep.h"
|
|
||||||
#include "minecraft/auth/steps/XboxUserStep.h"
|
|
||||||
|
|
||||||
MSASilent::MSASilent(AccountData* data, QObject* parent) : AuthFlow(data, parent)
|
|
||||||
{
|
|
||||||
m_steps.append(makeShared<MSAStep>(m_data, MSAStep::Action::Refresh));
|
|
||||||
m_steps.append(makeShared<XboxUserStep>(m_data));
|
|
||||||
m_steps.append(makeShared<XboxAuthorizationStep>(m_data, &m_data->xboxApiToken, "http://xboxlive.com", "Xbox"));
|
|
||||||
m_steps.append(makeShared<XboxAuthorizationStep>(m_data, &m_data->mojangservicesToken, "rp://api.minecraftservices.com/", "Mojang"));
|
|
||||||
m_steps.append(makeShared<LauncherLoginStep>(m_data));
|
|
||||||
m_steps.append(makeShared<XboxProfileStep>(m_data));
|
|
||||||
m_steps.append(makeShared<EntitlementsStep>(m_data));
|
|
||||||
m_steps.append(makeShared<MinecraftProfileStep>(m_data));
|
|
||||||
m_steps.append(makeShared<GetSkinStep>(m_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
MSAInteractive::MSAInteractive(AccountData* data, QObject* parent) : AuthFlow(data, parent)
|
|
||||||
{
|
|
||||||
m_steps.append(makeShared<MSAStep>(m_data, MSAStep::Action::Login));
|
|
||||||
m_steps.append(makeShared<XboxUserStep>(m_data));
|
|
||||||
m_steps.append(makeShared<XboxAuthorizationStep>(m_data, &m_data->xboxApiToken, "http://xboxlive.com", "Xbox"));
|
|
||||||
m_steps.append(makeShared<XboxAuthorizationStep>(m_data, &m_data->mojangservicesToken, "rp://api.minecraftservices.com/", "Mojang"));
|
|
||||||
m_steps.append(makeShared<LauncherLoginStep>(m_data));
|
|
||||||
m_steps.append(makeShared<XboxProfileStep>(m_data));
|
|
||||||
m_steps.append(makeShared<EntitlementsStep>(m_data));
|
|
||||||
m_steps.append(makeShared<MinecraftProfileStep>(m_data));
|
|
||||||
m_steps.append(makeShared<GetSkinStep>(m_data));
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AuthFlow.h"
|
|
||||||
|
|
||||||
class MSAInteractive : public AuthFlow {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit MSAInteractive(AccountData* data, QObject* parent = 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
class MSASilent : public AuthFlow {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit MSASilent(AccountData* data, QObject* parent = 0);
|
|
||||||
};
|
|
@ -1,8 +0,0 @@
|
|||||||
#include "Offline.h"
|
|
||||||
|
|
||||||
#include "minecraft/auth/steps/OfflineStep.h"
|
|
||||||
|
|
||||||
OfflineLogin::OfflineLogin(AccountData* data, QObject* parent) : AuthFlow(data, parent)
|
|
||||||
{
|
|
||||||
m_steps.append(makeShared<OfflineStep>(m_data));
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AuthFlow.h"
|
|
||||||
|
|
||||||
class OfflineLogin : public AuthFlow {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit OfflineLogin(AccountData* data, QObject* parent = 0);
|
|
||||||
};
|
|
@ -37,12 +37,11 @@
|
|||||||
|
|
||||||
#include <QtNetworkAuth/qoauthhttpserverreplyhandler.h>
|
#include <QtNetworkAuth/qoauthhttpserverreplyhandler.h>
|
||||||
#include <QAbstractOAuth2>
|
#include <QAbstractOAuth2>
|
||||||
#include <QDesktopServices>
|
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(action)
|
MSAStep::MSAStep(AccountData* data, bool silent) : AuthStep(data), m_silent(silent)
|
||||||
{
|
{
|
||||||
m_clientId = APPLICATION->getMSAClientID();
|
m_clientId = APPLICATION->getMSAClientID();
|
||||||
|
|
||||||
@ -63,7 +62,7 @@ MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(ac
|
|||||||
m_data->msaToken.token = oauth2.token();
|
m_data->msaToken.token = oauth2.token();
|
||||||
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
|
emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
|
||||||
});
|
});
|
||||||
connect(&oauth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, this, &QDesktopServices::openUrl);
|
connect(&oauth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, this, &MSAStep::authorizeWithBrowser);
|
||||||
connect(&oauth2, &QOAuth2AuthorizationCodeFlow::requestFailed, this, [this](const QAbstractOAuth2::Error err) {
|
connect(&oauth2, &QOAuth2AuthorizationCodeFlow::requestFailed, this, [this](const QAbstractOAuth2::Error err) {
|
||||||
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft user authentication failed."));
|
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft user authentication failed."));
|
||||||
});
|
});
|
||||||
@ -82,30 +81,25 @@ QString MSAStep::describe()
|
|||||||
|
|
||||||
void MSAStep::perform()
|
void MSAStep::perform()
|
||||||
{
|
{
|
||||||
switch (m_action) {
|
if (m_silent) {
|
||||||
case Refresh: {
|
if (m_data->msaClientID != m_clientId) {
|
||||||
if (m_data->msaClientID != m_clientId) {
|
emit finished(AccountTaskState::STATE_DISABLED,
|
||||||
emit finished(AccountTaskState::STATE_DISABLED,
|
tr("Microsoft user authentication failed - client identification has changed."));
|
||||||
tr("Microsoft user authentication failed - client identification has changed."));
|
|
||||||
}
|
|
||||||
oauth2.setRefreshToken(m_data->msaToken.refresh_token);
|
|
||||||
oauth2.refreshAccessToken();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
case Login: {
|
oauth2.setRefreshToken(m_data->msaToken.refresh_token);
|
||||||
|
oauth2.refreshAccessToken();
|
||||||
|
} else {
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // QMultiMap param changed in 6.0
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // QMultiMap param changed in 6.0
|
||||||
oauth2.setModifyParametersFunction([](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* map) {
|
oauth2.setModifyParametersFunction([](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* map) {
|
||||||
#else
|
#else
|
||||||
oauth2.setModifyParametersFunction([](QAbstractOAuth::Stage stage, QMap<QString, QVariant>* map) {
|
oauth2.setModifyParametersFunction([](QAbstractOAuth::Stage stage, QMap<QString, QVariant>* map) {
|
||||||
#endif
|
#endif
|
||||||
map->insert("prompt", "select_account");
|
map->insert("prompt", "select_account");
|
||||||
map->insert("cobrandid", "8058f65d-ce06-4c30-9559-473c9275a65d");
|
map->insert("cobrandid", "8058f65d-ce06-4c30-9559-473c9275a65d");
|
||||||
});
|
});
|
||||||
|
|
||||||
*m_data = AccountData();
|
*m_data = AccountData();
|
||||||
m_data->msaClientID = m_clientId;
|
m_data->msaClientID = m_clientId;
|
||||||
oauth2.grant();
|
oauth2.grant();
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,18 +42,18 @@
|
|||||||
class MSAStep : public AuthStep {
|
class MSAStep : public AuthStep {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum Action { Refresh, Login };
|
explicit MSAStep(AccountData* data, bool silent = false);
|
||||||
|
|
||||||
public:
|
|
||||||
explicit MSAStep(AccountData* data, Action action);
|
|
||||||
virtual ~MSAStep() noexcept = default;
|
virtual ~MSAStep() noexcept = default;
|
||||||
|
|
||||||
void perform() override;
|
void perform() override;
|
||||||
|
|
||||||
QString describe() override;
|
QString describe() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void authorizeWithBrowser(const QUrl& url);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Action m_action;
|
bool m_silent;
|
||||||
QString m_clientId;
|
QString m_clientId;
|
||||||
QOAuth2AuthorizationCodeFlow oauth2;
|
QOAuth2AuthorizationCodeFlow oauth2;
|
||||||
};
|
};
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#include "OfflineStep.h"
|
|
||||||
|
|
||||||
OfflineStep::OfflineStep(AccountData* data) : AuthStep(data) {}
|
|
||||||
|
|
||||||
QString OfflineStep::describe()
|
|
||||||
{
|
|
||||||
return tr("Creating offline account.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void OfflineStep::perform()
|
|
||||||
{
|
|
||||||
emit finished(AccountTaskState::STATE_WORKING, tr("Created offline account."));
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
#include "minecraft/auth/AuthStep.h"
|
|
||||||
|
|
||||||
class OfflineStep : public AuthStep {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit OfflineStep(AccountData* data);
|
|
||||||
virtual ~OfflineStep() noexcept = default;
|
|
||||||
|
|
||||||
void perform() override;
|
|
||||||
|
|
||||||
QString describe() override;
|
|
||||||
};
|
|
@ -11,7 +11,7 @@
|
|||||||
#include "net/StaticHeaderProxy.h"
|
#include "net/StaticHeaderProxy.h"
|
||||||
#include "net/Upload.h"
|
#include "net/Upload.h"
|
||||||
|
|
||||||
XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Katabasis::Token* token, QString relyingParty, QString authorizationKind)
|
XboxAuthorizationStep::XboxAuthorizationStep(AccountData* data, Token* token, QString relyingParty, QString authorizationKind)
|
||||||
: AuthStep(data), m_token(token), m_relyingParty(relyingParty), m_authorizationKind(authorizationKind)
|
: AuthStep(data), m_token(token), m_relyingParty(relyingParty), m_authorizationKind(authorizationKind)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ void XboxAuthorizationStep::onRequestDone()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Katabasis::Token temp;
|
Token temp;
|
||||||
if (!Parsers::parseXTokenResponse(*m_response, temp, m_authorizationKind)) {
|
if (!Parsers::parseXTokenResponse(*m_response, temp, m_authorizationKind)) {
|
||||||
emit finished(AccountTaskState::STATE_FAILED_SOFT,
|
emit finished(AccountTaskState::STATE_FAILED_SOFT,
|
||||||
tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind));
|
tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind));
|
||||||
|
@ -9,7 +9,7 @@ class XboxAuthorizationStep : public AuthStep {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit XboxAuthorizationStep(AccountData* data, Katabasis::Token* token, QString relyingParty, QString authorizationKind);
|
explicit XboxAuthorizationStep(AccountData* data, Token* token, QString relyingParty, QString authorizationKind);
|
||||||
virtual ~XboxAuthorizationStep() noexcept = default;
|
virtual ~XboxAuthorizationStep() noexcept = default;
|
||||||
|
|
||||||
void perform() override;
|
void perform() override;
|
||||||
@ -23,7 +23,7 @@ class XboxAuthorizationStep : public AuthStep {
|
|||||||
void onRequestDone();
|
void onRequestDone();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Katabasis::Token* m_token;
|
Token* m_token;
|
||||||
QString m_relyingParty;
|
QString m_relyingParty;
|
||||||
QString m_authorizationKind;
|
QString m_authorizationKind;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ void XboxUserStep::onRequestDone()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Katabasis::Token temp;
|
Token temp;
|
||||||
if (!Parsers::parseXTokenResponse(*m_response, temp, "UToken")) {
|
if (!Parsers::parseXTokenResponse(*m_response, temp, "UToken")) {
|
||||||
qWarning() << "Could not parse user authentication response...";
|
qWarning() << "Could not parse user authentication response...";
|
||||||
emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication response could not be understood."));
|
emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication response could not be understood."));
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include "ui_MSALoginDialog.h"
|
#include "ui_MSALoginDialog.h"
|
||||||
|
|
||||||
#include "DesktopServices.h"
|
#include "DesktopServices.h"
|
||||||
#include "minecraft/auth/flows/AuthFlow.h"
|
#include "minecraft/auth/AuthFlow.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
@ -47,26 +47,24 @@
|
|||||||
MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MSALoginDialog)
|
MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MSALoginDialog)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
ui->progressBar->setVisible(false);
|
|
||||||
ui->actionButton->setVisible(false);
|
|
||||||
// ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
|
|
||||||
|
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
ui->cancel->setEnabled(false);
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
ui->link->setVisible(false);
|
||||||
|
ui->copy->setVisible(false);
|
||||||
|
|
||||||
|
connect(ui->cancel, &QPushButton::pressed, this, &QDialog::reject);
|
||||||
|
connect(ui->copy, &QPushButton::pressed, this, &MSALoginDialog::copyUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MSALoginDialog::exec()
|
int MSALoginDialog::exec()
|
||||||
{
|
{
|
||||||
setUserInputsEnabled(false);
|
|
||||||
ui->progressBar->setVisible(true);
|
|
||||||
|
|
||||||
// Setup the login task and start it
|
// Setup the login task and start it
|
||||||
m_account = MinecraftAccount::createBlankMSA();
|
m_account = MinecraftAccount::createBlankMSA();
|
||||||
m_loginTask = m_account->loginMSA();
|
m_loginTask = m_account->login();
|
||||||
connect(m_loginTask.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
|
connect(m_loginTask.get(), &Task::failed, this, &MSALoginDialog::onTaskFailed);
|
||||||
connect(m_loginTask.get(), &Task::succeeded, this, &MSALoginDialog::onTaskSucceeded);
|
connect(m_loginTask.get(), &Task::succeeded, this, &MSALoginDialog::onTaskSucceeded);
|
||||||
connect(m_loginTask.get(), &Task::status, this, &MSALoginDialog::onTaskStatus);
|
connect(m_loginTask.get(), &Task::status, this, &MSALoginDialog::onTaskStatus);
|
||||||
connect(m_loginTask.get(), &Task::progress, this, &MSALoginDialog::onTaskProgress);
|
connect(m_loginTask.get(), &AuthFlow::authorizeWithBrowser, this, &MSALoginDialog::authorizeWithBrowser);
|
||||||
m_loginTask->start();
|
m_loginTask->start();
|
||||||
|
|
||||||
return QDialog::exec();
|
return QDialog::exec();
|
||||||
@ -77,11 +75,6 @@ MSALoginDialog::~MSALoginDialog()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSALoginDialog::setUserInputsEnabled(bool enable)
|
|
||||||
{
|
|
||||||
ui->buttonBox->setEnabled(enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MSALoginDialog::onTaskFailed(const QString& reason)
|
void MSALoginDialog::onTaskFailed(const QString& reason)
|
||||||
{
|
{
|
||||||
// Set message
|
// Set message
|
||||||
@ -94,12 +87,7 @@ void MSALoginDialog::onTaskFailed(const QString& reason)
|
|||||||
processed += "<br />";
|
processed += "<br />";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui->label->setText(processed);
|
ui->message->setText(processed);
|
||||||
|
|
||||||
// Re-enable user-interaction
|
|
||||||
setUserInputsEnabled(true);
|
|
||||||
ui->progressBar->setVisible(false);
|
|
||||||
ui->actionButton->setVisible(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSALoginDialog::onTaskSucceeded()
|
void MSALoginDialog::onTaskSucceeded()
|
||||||
@ -109,22 +97,38 @@ void MSALoginDialog::onTaskSucceeded()
|
|||||||
|
|
||||||
void MSALoginDialog::onTaskStatus(const QString& status)
|
void MSALoginDialog::onTaskStatus(const QString& status)
|
||||||
{
|
{
|
||||||
ui->label->setText(status);
|
ui->message->setText(status);
|
||||||
}
|
ui->cancel->setEnabled(false);
|
||||||
|
ui->link->setVisible(false);
|
||||||
void MSALoginDialog::onTaskProgress(qint64 current, qint64 total)
|
ui->copy->setVisible(false);
|
||||||
{
|
|
||||||
ui->progressBar->setMaximum(total);
|
|
||||||
ui->progressBar->setValue(current);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public interface
|
// Public interface
|
||||||
MinecraftAccountPtr MSALoginDialog::newAccount(QWidget* parent, QString msg)
|
MinecraftAccountPtr MSALoginDialog::newAccount(QWidget* parent, QString msg)
|
||||||
{
|
{
|
||||||
MSALoginDialog dlg(parent);
|
MSALoginDialog dlg(parent);
|
||||||
dlg.ui->label->setText(msg);
|
dlg.ui->message->setText(msg);
|
||||||
if (dlg.exec() == QDialog::Accepted) {
|
if (dlg.exec() == QDialog::Accepted) {
|
||||||
return dlg.m_account;
|
return dlg.m_account;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MSALoginDialog::authorizeWithBrowser(const QUrl& url)
|
||||||
|
{
|
||||||
|
ui->cancel->setEnabled(true);
|
||||||
|
ui->link->setVisible(true);
|
||||||
|
ui->copy->setVisible(true);
|
||||||
|
DesktopServices::openUrl(url);
|
||||||
|
ui->link->setText(url.toDisplayString());
|
||||||
|
ui->message->setText(
|
||||||
|
tr("Browser opened to complete the login process."
|
||||||
|
"<br /><br />"
|
||||||
|
"If your browser hasn't opened, please manually open the bellow link in your browser:"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MSALoginDialog::copyUrl()
|
||||||
|
{
|
||||||
|
QClipboard* cb = QApplication::clipboard();
|
||||||
|
cb->setText(ui->link->text());
|
||||||
|
}
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
#include <QtCore/QEventLoop>
|
#include <QtCore/QEventLoop>
|
||||||
#include <QtWidgets/QDialog>
|
#include <QtWidgets/QDialog>
|
||||||
|
|
||||||
|
#include "minecraft/auth/AuthFlow.h"
|
||||||
#include "minecraft/auth/MinecraftAccount.h"
|
#include "minecraft/auth/MinecraftAccount.h"
|
||||||
#include "minecraft/auth/flows/AuthFlow.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MSALoginDialog;
|
class MSALoginDialog;
|
||||||
@ -37,13 +37,12 @@ class MSALoginDialog : public QDialog {
|
|||||||
private:
|
private:
|
||||||
explicit MSALoginDialog(QWidget* parent = 0);
|
explicit MSALoginDialog(QWidget* parent = 0);
|
||||||
|
|
||||||
void setUserInputsEnabled(bool enable);
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void onTaskFailed(const QString& reason);
|
void onTaskFailed(const QString& reason);
|
||||||
void onTaskSucceeded();
|
void onTaskSucceeded();
|
||||||
void onTaskStatus(const QString& status);
|
void onTaskStatus(const QString& status);
|
||||||
void onTaskProgress(qint64 current, qint64 total);
|
void authorizeWithBrowser(const QUrl& url);
|
||||||
|
void copyUrl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MSALoginDialog* ui;
|
Ui::MSALoginDialog* ui;
|
||||||
|
@ -21,11 +21,9 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="message">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string notr="true">Message label placeholder.
|
<string notr="true"/>
|
||||||
|
|
||||||
aaaaa</string>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="textFormat">
|
<property name="textFormat">
|
||||||
<enum>Qt::RichText</enum>
|
<enum>Qt::RichText</enum>
|
||||||
@ -39,36 +37,33 @@ aaaaa</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QProgressBar" name="progressBar">
|
<layout class="QHBoxLayout" name="linkLayout">
|
||||||
<property name="value">
|
|
||||||
<number>24</number>
|
|
||||||
</property>
|
|
||||||
<property name="textVisible">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="actionButton">
|
<widget class="QLineEdit" name="link">
|
||||||
<property name="text">
|
<property name="readOnly">
|
||||||
<string>Open page and copy code</string>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
<widget class="QPushButton" name="copy">
|
||||||
<property name="orientation">
|
<property name="text">
|
||||||
<enum>Qt::Horizontal</enum>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons">
|
<property name="icon">
|
||||||
<set>QDialogButtonBox::Cancel</set>
|
<iconset theme="copy"/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="cancel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -26,7 +26,7 @@ void OfflineLoginDialog::accept()
|
|||||||
|
|
||||||
// Setup the login task and start it
|
// Setup the login task and start it
|
||||||
m_account = MinecraftAccount::createOffline(ui->userTextBox->text());
|
m_account = MinecraftAccount::createOffline(ui->userTextBox->text());
|
||||||
m_loginTask = m_account->loginOffline();
|
m_loginTask = m_account->login();
|
||||||
connect(m_loginTask.get(), &Task::failed, this, &OfflineLoginDialog::onTaskFailed);
|
connect(m_loginTask.get(), &Task::failed, this, &OfflineLoginDialog::onTaskFailed);
|
||||||
connect(m_loginTask.get(), &Task::succeeded, this, &OfflineLoginDialog::onTaskSucceeded);
|
connect(m_loginTask.get(), &Task::succeeded, this, &OfflineLoginDialog::onTaskSucceeded);
|
||||||
connect(m_loginTask.get(), &Task::status, this, &OfflineLoginDialog::onTaskStatus);
|
connect(m_loginTask.get(), &Task::status, this, &OfflineLoginDialog::onTaskStatus);
|
||||||
|
Loading…
Reference in New Issue
Block a user