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.h
|
||||
|
||||
minecraft/auth/flows/AuthFlow.cpp
|
||||
minecraft/auth/flows/AuthFlow.h
|
||||
minecraft/auth/flows/MSA.cpp
|
||||
minecraft/auth/flows/MSA.h
|
||||
minecraft/auth/flows/Offline.cpp
|
||||
minecraft/auth/flows/Offline.h
|
||||
minecraft/auth/AuthFlow.cpp
|
||||
minecraft/auth/AuthFlow.h
|
||||
|
||||
minecraft/auth/steps/OfflineStep.cpp
|
||||
minecraft/auth/steps/OfflineStep.h
|
||||
minecraft/auth/steps/EntitlementsStep.cpp
|
||||
minecraft/auth/steps/EntitlementsStep.h
|
||||
minecraft/auth/steps/GetSkinStep.cpp
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include <QUuid>
|
||||
|
||||
namespace {
|
||||
void tokenToJSONV3(QJsonObject& parent, Katabasis::Token t, const char* tokenName)
|
||||
void tokenToJSONV3(QJsonObject& parent, Token t, const char* tokenName)
|
||||
{
|
||||
if (!t.persistent) {
|
||||
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();
|
||||
if (tokenObject.isEmpty()) {
|
||||
return out;
|
||||
@ -94,7 +94,7 @@ Katabasis::Token tokenFromJSONV3(const QJsonObject& parent, const char* tokenNam
|
||||
auto token = tokenObject.value("token");
|
||||
if (token.isString()) {
|
||||
out.token = token.toString();
|
||||
out.validity = Katabasis::Validity::Assumed;
|
||||
out.validity = Validity::Assumed;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void entitlementToJSONV3(QJsonObject& parent, MinecraftEntitlement p)
|
||||
{
|
||||
if (p.validity == Katabasis::Validity::None) {
|
||||
if (p.validity == Validity::None) {
|
||||
return;
|
||||
}
|
||||
QJsonObject out;
|
||||
@ -271,7 +271,7 @@ bool entitlementFromJSONV3(const QJsonObject& parent, MinecraftEntitlement& out)
|
||||
}
|
||||
out.canPlayMinecraft = canPlayMinecraftV.toBool(false);
|
||||
out.ownsMinecraft = ownsMinecraftV.toBool(false);
|
||||
out.validity = Katabasis::Validity::Assumed;
|
||||
out.validity = Validity::Assumed;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -313,10 +313,10 @@ bool AccountData::resumeStateFromV3(QJsonObject data)
|
||||
|
||||
minecraftProfile = profileFromJSONV3(data, "profile");
|
||||
if (!entitlementFromJSONV3(data, minecraftEntitlement)) {
|
||||
if (minecraftProfile.validity != Katabasis::Validity::None) {
|
||||
if (minecraftProfile.validity != Validity::None) {
|
||||
minecraftEntitlement.canPlayMinecraft = true;
|
||||
minecraftEntitlement.ownsMinecraft = true;
|
||||
minecraftEntitlement.validity = Katabasis::Validity::Assumed;
|
||||
minecraftEntitlement.validity = Validity::Assumed;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,18 +44,6 @@
|
||||
#include <QString>
|
||||
#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 };
|
||||
|
||||
struct Token {
|
||||
@ -69,8 +57,6 @@ struct Token {
|
||||
bool persistent = true;
|
||||
};
|
||||
|
||||
} // namespace Katabasis
|
||||
|
||||
struct Skin {
|
||||
QString id;
|
||||
QString url;
|
||||
@ -90,7 +76,7 @@ struct Cape {
|
||||
struct MinecraftEntitlement {
|
||||
bool ownsMinecraft = false;
|
||||
bool canPlayMinecraft = false;
|
||||
Katabasis::Validity validity = Katabasis::Validity::None;
|
||||
Validity validity = Validity::None;
|
||||
};
|
||||
|
||||
struct MinecraftProfile {
|
||||
@ -99,7 +85,7 @@ struct MinecraftProfile {
|
||||
Skin skin;
|
||||
QString currentCape;
|
||||
QMap<QString, Cape> capes;
|
||||
Katabasis::Validity validity = Katabasis::Validity::None;
|
||||
Validity validity = Validity::None;
|
||||
};
|
||||
|
||||
enum class AccountType { MSA, Offline };
|
||||
@ -124,15 +110,15 @@ struct AccountData {
|
||||
AccountType type = AccountType::MSA;
|
||||
|
||||
QString msaClientID;
|
||||
Katabasis::Token msaToken;
|
||||
Katabasis::Token userToken;
|
||||
Katabasis::Token xboxApiToken;
|
||||
Katabasis::Token mojangservicesToken;
|
||||
Token msaToken;
|
||||
Token userToken;
|
||||
Token xboxApiToken;
|
||||
Token mojangservicesToken;
|
||||
|
||||
Katabasis::Token yggdrasilToken;
|
||||
Token yggdrasilToken;
|
||||
MinecraftProfile minecraftProfile;
|
||||
MinecraftEntitlement minecraftEntitlement;
|
||||
Katabasis::Validity validity_ = Katabasis::Validity::None;
|
||||
Validity validity_ = Validity::None;
|
||||
|
||||
// runtime only information (not saved with the account)
|
||||
QString internalId;
|
||||
|
@ -36,7 +36,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "MinecraftAccount.h"
|
||||
#include "minecraft/auth/flows/AuthFlow.h"
|
||||
#include "minecraft/auth/AuthFlow.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QObject>
|
||||
|
@ -3,27 +3,47 @@
|
||||
#include <QNetworkReply>
|
||||
#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 <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);
|
||||
}
|
||||
|
||||
void AuthFlow::succeed()
|
||||
{
|
||||
m_data->validity_ = Katabasis::Validity::Certain;
|
||||
m_data->validity_ = Validity::Certain;
|
||||
changeState(AccountTaskState::STATE_SUCCEEDED, tr("Finished all authentication steps"));
|
||||
}
|
||||
|
||||
void AuthFlow::executeTask()
|
||||
{
|
||||
if (m_currentStep) {
|
||||
emitFailed("No task");
|
||||
return;
|
||||
}
|
||||
changeState(AccountTaskState::STATE_WORKING, tr("Initializing"));
|
||||
nextStep();
|
||||
}
|
||||
@ -46,10 +66,9 @@ void AuthFlow::nextStep()
|
||||
|
||||
void AuthFlow::stepFinished(AccountTaskState resultingState, QString message)
|
||||
{
|
||||
if (changeState(resultingState, message)) {
|
||||
if (changeState(resultingState, message))
|
||||
nextStep();
|
||||
}
|
||||
}
|
||||
|
||||
bool AuthFlow::changeState(AccountTaskState newState, QString reason)
|
||||
{
|
@ -15,30 +15,26 @@ class AuthFlow : public Task {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AuthFlow(AccountData* data, QObject* parent = 0);
|
||||
explicit AuthFlow(AccountData* data, bool silent = false, QObject* parent = 0);
|
||||
virtual ~AuthFlow() = default;
|
||||
|
||||
Katabasis::Validity validity() { return m_data->validity_; };
|
||||
|
||||
void executeTask() override;
|
||||
|
||||
AccountTaskState taskState() { return m_taskState; }
|
||||
|
||||
signals:
|
||||
void activityChanged(Katabasis::Activity activity);
|
||||
void authorizeWithBrowser(const QUrl& url);
|
||||
|
||||
protected:
|
||||
void succeed();
|
||||
void nextStep();
|
||||
|
||||
protected slots:
|
||||
private slots:
|
||||
// NOTE: true -> non-terminal state, false -> terminal state
|
||||
bool changeState(AccountTaskState newState, QString reason = QString());
|
||||
|
||||
private slots:
|
||||
void stepFinished(AccountTaskState resultingState, QString message);
|
||||
|
||||
protected:
|
||||
private:
|
||||
AccountTaskState m_taskState = AccountTaskState::STATE_CREATED;
|
||||
QList<AuthStep::Ptr> m_steps;
|
||||
AuthStep::Ptr m_currentStep;
|
@ -50,11 +50,8 @@
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
#include "flows/MSA.h"
|
||||
#include "flows/Offline.h"
|
||||
#include "minecraft/auth/AccountData.h"
|
||||
#include "minecraft/auth/flows/AuthFlow.h"
|
||||
#include "tasks/Task.h"
|
||||
#include "minecraft/auth/AuthFlow.h"
|
||||
|
||||
MinecraftAccount::MinecraftAccount(QObject* parent) : QObject(parent)
|
||||
{
|
||||
@ -82,7 +79,7 @@ MinecraftAccountPtr MinecraftAccount::createOffline(const QString& username)
|
||||
auto account = makeShared<MinecraftAccount>();
|
||||
account->data.type = AccountType::Offline;
|
||||
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.extra["userName"] = username;
|
||||
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.minecraftProfile.id = uuidFromUsername(username).toString().remove(QRegularExpression("[{}-]"));
|
||||
account->data.minecraftProfile.name = username;
|
||||
account->data.minecraftProfile.validity = Katabasis::Validity::Certain;
|
||||
account->data.minecraftProfile.validity = Validity::Certain;
|
||||
return account;
|
||||
}
|
||||
|
||||
@ -122,23 +119,11 @@ QPixmap MinecraftAccount::getFace() const
|
||||
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);
|
||||
|
||||
m_currentTask.reset(new MSAInteractive(&data));
|
||||
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));
|
||||
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")); });
|
||||
@ -152,11 +137,7 @@ shared_qobject_ptr<AuthFlow> MinecraftAccount::refresh()
|
||||
return m_currentTask;
|
||||
}
|
||||
|
||||
if (data.type == AccountType::MSA) {
|
||||
m_currentTask.reset(new MSASilent(&data));
|
||||
} else {
|
||||
m_currentTask.reset(new OfflineLogin(&data));
|
||||
}
|
||||
m_currentTask.reset(new AuthFlow(&data, true, this));
|
||||
|
||||
connect(m_currentTask.get(), &Task::succeeded, this, &MinecraftAccount::authSucceeded);
|
||||
connect(m_currentTask.get(), &Task::failed, this, &MinecraftAccount::authFailed);
|
||||
@ -191,17 +172,17 @@ void MinecraftAccount::authFailed(QString reason)
|
||||
if (accountType() == AccountType::MSA) {
|
||||
data.msaToken.token = QString();
|
||||
data.msaToken.refresh_token = QString();
|
||||
data.msaToken.validity = Katabasis::Validity::None;
|
||||
data.validity_ = Katabasis::Validity::None;
|
||||
data.msaToken.validity = Validity::None;
|
||||
data.validity_ = Validity::None;
|
||||
} else {
|
||||
data.yggdrasilToken.token = QString();
|
||||
data.yggdrasilToken.validity = Katabasis::Validity::None;
|
||||
data.validity_ = Katabasis::Validity::None;
|
||||
data.yggdrasilToken.validity = Validity::None;
|
||||
data.validity_ = Validity::None;
|
||||
}
|
||||
emit changed();
|
||||
} break;
|
||||
case AccountTaskState::STATE_FAILED_GONE: {
|
||||
data.validity_ = Katabasis::Validity::None;
|
||||
data.validity_ = Validity::None;
|
||||
emit changed();
|
||||
} break;
|
||||
case AccountTaskState::STATE_CREATED:
|
||||
@ -231,13 +212,13 @@ bool MinecraftAccount::shouldRefresh() const
|
||||
return false;
|
||||
}
|
||||
switch (data.validity_) {
|
||||
case Katabasis::Validity::Certain: {
|
||||
case Validity::Certain: {
|
||||
break;
|
||||
}
|
||||
case Katabasis::Validity::None: {
|
||||
case Validity::None: {
|
||||
return false;
|
||||
}
|
||||
case Katabasis::Validity::Assumed: {
|
||||
case Validity::Assumed: {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include "AuthSession.h"
|
||||
#include "QObjectPtr.h"
|
||||
#include "Usable.h"
|
||||
#include "minecraft/auth/flows/AuthFlow.h"
|
||||
#include "minecraft/auth/AuthFlow.h"
|
||||
|
||||
class Task;
|
||||
class MinecraftAccount;
|
||||
@ -95,9 +95,7 @@ class MinecraftAccount : public QObject, public Usable {
|
||||
QJsonObject saveToJson() const;
|
||||
|
||||
public: /* manipulation */
|
||||
shared_qobject_ptr<AuthFlow> loginMSA();
|
||||
|
||||
shared_qobject_ptr<AuthFlow> loginOffline();
|
||||
shared_qobject_ptr<AuthFlow> login();
|
||||
|
||||
shared_qobject_ptr<AuthFlow> refresh();
|
||||
|
||||
|
@ -79,7 +79,7 @@ bool getBool(QJsonValue value, bool& out)
|
||||
// 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 << ":";
|
||||
qCDebug(authCredentials()) << data;
|
||||
@ -135,7 +135,7 @@ bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString nam
|
||||
qWarning() << "Missing uhs";
|
||||
return false;
|
||||
}
|
||||
output.validity = Katabasis::Validity::Certain;
|
||||
output.validity = Validity::Certain;
|
||||
qDebug() << name << "is valid.";
|
||||
return true;
|
||||
}
|
||||
@ -213,7 +213,7 @@ bool parseMinecraftProfile(QByteArray& data, MinecraftProfile& output)
|
||||
output.capes[capeOut.id] = capeOut;
|
||||
}
|
||||
output.currentCape = currentCape;
|
||||
output.validity = Katabasis::Validity::Certain;
|
||||
output.validity = Validity::Certain;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -388,7 +388,7 @@ bool parseMinecraftProfileMojang(QByteArray& data, MinecraftProfile& output)
|
||||
output.currentCape = capeOut.alias;
|
||||
}
|
||||
|
||||
output.validity = Katabasis::Validity::Certain;
|
||||
output.validity = Validity::Certain;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -422,7 +422,7 @@ bool parseMinecraftEntitlements(QByteArray& data, MinecraftEntitlement& output)
|
||||
output.ownsMinecraft = true;
|
||||
}
|
||||
}
|
||||
output.validity = Katabasis::Validity::Certain;
|
||||
output.validity = Validity::Certain;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -456,7 +456,7 @@ bool parseRolloutResponse(QByteArray& data, bool& result)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseMojangResponse(QByteArray& data, Katabasis::Token& output)
|
||||
bool parseMojangResponse(QByteArray& data, Token& output)
|
||||
{
|
||||
QJsonParseError jsonError;
|
||||
qDebug() << "Parsing Mojang response...";
|
||||
@ -488,7 +488,7 @@ bool parseMojangResponse(QByteArray& data, Katabasis::Token& output)
|
||||
qWarning() << "access_token is not valid";
|
||||
return false;
|
||||
}
|
||||
output.validity = Katabasis::Validity::Certain;
|
||||
output.validity = Validity::Certain;
|
||||
qDebug() << "Mojang response is valid.";
|
||||
return true;
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ bool getNumber(QJsonValue value, double& out);
|
||||
bool getNumber(QJsonValue value, int64_t& out);
|
||||
bool getBool(QJsonValue value, bool& out);
|
||||
|
||||
bool parseXTokenResponse(QByteArray& data, Katabasis::Token& output, QString name);
|
||||
bool parseMojangResponse(QByteArray& data, Katabasis::Token& output);
|
||||
bool parseXTokenResponse(QByteArray& data, Token& output, QString name);
|
||||
bool parseMojangResponse(QByteArray& data, Token& output);
|
||||
|
||||
bool parseMinecraftProfile(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 <QAbstractOAuth2>
|
||||
#include <QDesktopServices>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#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();
|
||||
|
||||
@ -63,7 +62,7 @@ MSAStep::MSAStep(AccountData* data, Action action) : AuthStep(data), m_action(ac
|
||||
m_data->msaToken.token = oauth2.token();
|
||||
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) {
|
||||
emit finished(AccountTaskState::STATE_FAILED_HARD, tr("Microsoft user authentication failed."));
|
||||
});
|
||||
@ -82,17 +81,14 @@ QString MSAStep::describe()
|
||||
|
||||
void MSAStep::perform()
|
||||
{
|
||||
switch (m_action) {
|
||||
case Refresh: {
|
||||
if (m_silent) {
|
||||
if (m_data->msaClientID != m_clientId) {
|
||||
emit finished(AccountTaskState::STATE_DISABLED,
|
||||
tr("Microsoft user authentication failed - client identification has changed."));
|
||||
}
|
||||
oauth2.setRefreshToken(m_data->msaToken.refresh_token);
|
||||
oauth2.refreshAccessToken();
|
||||
return;
|
||||
}
|
||||
case Login: {
|
||||
} else {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) // QMultiMap param changed in 6.0
|
||||
oauth2.setModifyParametersFunction([](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* map) {
|
||||
#else
|
||||
@ -105,7 +101,5 @@ void MSAStep::perform()
|
||||
*m_data = AccountData();
|
||||
m_data->msaClientID = m_clientId;
|
||||
oauth2.grant();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,18 +42,18 @@
|
||||
class MSAStep : public AuthStep {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Action { Refresh, Login };
|
||||
|
||||
public:
|
||||
explicit MSAStep(AccountData* data, Action action);
|
||||
explicit MSAStep(AccountData* data, bool silent = false);
|
||||
virtual ~MSAStep() noexcept = default;
|
||||
|
||||
void perform() override;
|
||||
|
||||
QString describe() override;
|
||||
|
||||
signals:
|
||||
void authorizeWithBrowser(const QUrl& url);
|
||||
|
||||
private:
|
||||
Action m_action;
|
||||
bool m_silent;
|
||||
QString m_clientId;
|
||||
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/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)
|
||||
{}
|
||||
|
||||
@ -72,7 +72,7 @@ void XboxAuthorizationStep::onRequestDone()
|
||||
return;
|
||||
}
|
||||
|
||||
Katabasis::Token temp;
|
||||
Token temp;
|
||||
if (!Parsers::parseXTokenResponse(*m_response, temp, m_authorizationKind)) {
|
||||
emit finished(AccountTaskState::STATE_FAILED_SOFT,
|
||||
tr("Could not parse authorization response for access to %1 services.").arg(m_authorizationKind));
|
||||
|
@ -9,7 +9,7 @@ class XboxAuthorizationStep : public AuthStep {
|
||||
Q_OBJECT
|
||||
|
||||
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;
|
||||
|
||||
void perform() override;
|
||||
@ -23,7 +23,7 @@ class XboxAuthorizationStep : public AuthStep {
|
||||
void onRequestDone();
|
||||
|
||||
private:
|
||||
Katabasis::Token* m_token;
|
||||
Token* m_token;
|
||||
QString m_relyingParty;
|
||||
QString m_authorizationKind;
|
||||
|
||||
|
@ -60,7 +60,7 @@ void XboxUserStep::onRequestDone()
|
||||
return;
|
||||
}
|
||||
|
||||
Katabasis::Token temp;
|
||||
Token temp;
|
||||
if (!Parsers::parseXTokenResponse(*m_response, temp, "UToken")) {
|
||||
qWarning() << "Could not parse user authentication response...";
|
||||
emit finished(AccountTaskState::STATE_FAILED_SOFT, tr("XBox user authentication response could not be understood."));
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "ui_MSALoginDialog.h"
|
||||
|
||||
#include "DesktopServices.h"
|
||||
#include "minecraft/auth/flows/AuthFlow.h"
|
||||
#include "minecraft/auth/AuthFlow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
@ -47,26 +47,24 @@
|
||||
MSALoginDialog::MSALoginDialog(QWidget* parent) : QDialog(parent), ui(new Ui::MSALoginDialog)
|
||||
{
|
||||
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);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||
ui->cancel->setEnabled(false);
|
||||
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()
|
||||
{
|
||||
setUserInputsEnabled(false);
|
||||
ui->progressBar->setVisible(true);
|
||||
|
||||
// Setup the login task and start it
|
||||
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::succeeded, this, &MSALoginDialog::onTaskSucceeded);
|
||||
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();
|
||||
|
||||
return QDialog::exec();
|
||||
@ -77,11 +75,6 @@ MSALoginDialog::~MSALoginDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MSALoginDialog::setUserInputsEnabled(bool enable)
|
||||
{
|
||||
ui->buttonBox->setEnabled(enable);
|
||||
}
|
||||
|
||||
void MSALoginDialog::onTaskFailed(const QString& reason)
|
||||
{
|
||||
// Set message
|
||||
@ -94,12 +87,7 @@ void MSALoginDialog::onTaskFailed(const QString& reason)
|
||||
processed += "<br />";
|
||||
}
|
||||
}
|
||||
ui->label->setText(processed);
|
||||
|
||||
// Re-enable user-interaction
|
||||
setUserInputsEnabled(true);
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->actionButton->setVisible(false);
|
||||
ui->message->setText(processed);
|
||||
}
|
||||
|
||||
void MSALoginDialog::onTaskSucceeded()
|
||||
@ -109,22 +97,38 @@ void MSALoginDialog::onTaskSucceeded()
|
||||
|
||||
void MSALoginDialog::onTaskStatus(const QString& status)
|
||||
{
|
||||
ui->label->setText(status);
|
||||
}
|
||||
|
||||
void MSALoginDialog::onTaskProgress(qint64 current, qint64 total)
|
||||
{
|
||||
ui->progressBar->setMaximum(total);
|
||||
ui->progressBar->setValue(current);
|
||||
ui->message->setText(status);
|
||||
ui->cancel->setEnabled(false);
|
||||
ui->link->setVisible(false);
|
||||
ui->copy->setVisible(false);
|
||||
}
|
||||
|
||||
// Public interface
|
||||
MinecraftAccountPtr MSALoginDialog::newAccount(QWidget* parent, QString msg)
|
||||
{
|
||||
MSALoginDialog dlg(parent);
|
||||
dlg.ui->label->setText(msg);
|
||||
dlg.ui->message->setText(msg);
|
||||
if (dlg.exec() == QDialog::Accepted) {
|
||||
return dlg.m_account;
|
||||
}
|
||||
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 <QtWidgets/QDialog>
|
||||
|
||||
#include "minecraft/auth/AuthFlow.h"
|
||||
#include "minecraft/auth/MinecraftAccount.h"
|
||||
#include "minecraft/auth/flows/AuthFlow.h"
|
||||
|
||||
namespace Ui {
|
||||
class MSALoginDialog;
|
||||
@ -37,13 +37,12 @@ class MSALoginDialog : public QDialog {
|
||||
private:
|
||||
explicit MSALoginDialog(QWidget* parent = 0);
|
||||
|
||||
void setUserInputsEnabled(bool enable);
|
||||
|
||||
protected slots:
|
||||
void onTaskFailed(const QString& reason);
|
||||
void onTaskSucceeded();
|
||||
void onTaskStatus(const QString& status);
|
||||
void onTaskProgress(qint64 current, qint64 total);
|
||||
void authorizeWithBrowser(const QUrl& url);
|
||||
void copyUrl();
|
||||
|
||||
private:
|
||||
Ui::MSALoginDialog* ui;
|
||||
|
@ -21,11 +21,9 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="message">
|
||||
<property name="text">
|
||||
<string notr="true">Message label placeholder.
|
||||
|
||||
aaaaa</string>
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
@ -39,36 +37,33 @@ aaaaa</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<layout class="QHBoxLayout" name="linkLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="link">
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionButton">
|
||||
<widget class="QPushButton" name="copy">
|
||||
<property name="text">
|
||||
<string>Open page and copy code</string>
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel</set>
|
||||
<property name="icon">
|
||||
<iconset theme="copy"/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -26,7 +26,7 @@ void OfflineLoginDialog::accept()
|
||||
|
||||
// Setup the login task and start it
|
||||
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::succeeded, this, &OfflineLoginDialog::onTaskSucceeded);
|
||||
connect(m_loginTask.get(), &Task::status, this, &OfflineLoginDialog::onTaskStatus);
|
||||
|
Loading…
Reference in New Issue
Block a user