mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 07:33:10 +02:00
Interface login through steam
This commit is contained in:
parent
45921a5c8d
commit
cea0e182c0
10 changed files with 275 additions and 17 deletions
BIN
interface/resources/images/steam-sign-in.png
Normal file
BIN
interface/resources/images/steam-sign-in.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
|
@ -203,24 +203,48 @@ ScrollingWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Row {
|
||||||
width: loginDialog.inputWidth
|
width: loginDialog.inputWidth
|
||||||
height: loginDialog.inputHeight
|
height: loginDialog.inputHeight
|
||||||
radius: height / 2
|
|
||||||
color: "#353535"
|
|
||||||
|
|
||||||
TextInput {
|
Rectangle {
|
||||||
anchors.fill: parent
|
width: loginDialog.inputWidth / 3
|
||||||
text: "Login"
|
height: loginDialog.inputHeight
|
||||||
color: "white"
|
radius: height / 2
|
||||||
horizontalAlignment: Text.AlignHCenter
|
color: "#353535"
|
||||||
|
|
||||||
|
TextInput {
|
||||||
|
anchors.fill: parent
|
||||||
|
text: "Login"
|
||||||
|
color: "white"
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
loginDialog.login(username.text, password.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
Image {
|
||||||
anchors.fill: parent
|
source: "../images/steam-sign-in.png"
|
||||||
cursorShape: Qt.PointingHandCursor
|
width: loginDialog.inputWidth / 3
|
||||||
onClicked: {
|
height: loginDialog.inputHeight
|
||||||
loginDialog.login(username.text, password.text)
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
right: parent.right
|
||||||
|
leftMargin: loginDialog.inputHeight / 4
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: {
|
||||||
|
loginDialog.loginThroughSteam()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,15 +86,16 @@
|
||||||
#include <PhysicsHelpers.h>
|
#include <PhysicsHelpers.h>
|
||||||
#include <plugins/PluginManager.h>
|
#include <plugins/PluginManager.h>
|
||||||
#include <plugins/CodecPlugin.h>
|
#include <plugins/CodecPlugin.h>
|
||||||
|
#include <RecordingScriptingInterface.h>
|
||||||
#include <RenderableWebEntityItem.h>
|
#include <RenderableWebEntityItem.h>
|
||||||
#include <RenderShadowTask.h>
|
#include <RenderShadowTask.h>
|
||||||
#include <RenderDeferredTask.h>
|
#include <RenderDeferredTask.h>
|
||||||
#include <ResourceCache.h>
|
#include <ResourceCache.h>
|
||||||
#include <SceneScriptingInterface.h>
|
#include <SceneScriptingInterface.h>
|
||||||
#include <RecordingScriptingInterface.h>
|
#include <ScriptEngines.h>
|
||||||
#include <ScriptCache.h>
|
#include <ScriptCache.h>
|
||||||
#include <SoundCache.h>
|
#include <SoundCache.h>
|
||||||
#include <ScriptEngines.h>
|
#include <steamworks-wrapper/SteamClient.h>
|
||||||
#include <Tooltip.h>
|
#include <Tooltip.h>
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
#include <UserActivityLogger.h>
|
#include <UserActivityLogger.h>
|
||||||
|
@ -2910,6 +2911,8 @@ void Application::idle(float nsecsElapsed) {
|
||||||
|
|
||||||
PROFILE_RANGE(__FUNCTION__);
|
PROFILE_RANGE(__FUNCTION__);
|
||||||
|
|
||||||
|
SteamClient::runCallbacks();
|
||||||
|
|
||||||
float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND;
|
float secondsSinceLastUpdate = nsecsElapsed / NSECS_PER_MSEC / MSECS_PER_SECOND;
|
||||||
|
|
||||||
// If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.
|
// If the offscreen Ui has something active that is NOT the root, then assume it has keyboard focus.
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
@ -20,12 +22,13 @@
|
||||||
#include <gl/OpenGLVersionChecker.h>
|
#include <gl/OpenGLVersionChecker.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include <steamworks-wrapper/SteamClient.h>
|
||||||
|
|
||||||
#include "AddressManager.h"
|
#include "AddressManager.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "UserActivityLogger.h"
|
#include "UserActivityLogger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#ifdef HAS_BUGSPLAT
|
#ifdef HAS_BUGSPLAT
|
||||||
#include <BuildInfo.h>
|
#include <BuildInfo.h>
|
||||||
|
@ -137,6 +140,8 @@ int main(int argc, const char* argv[]) {
|
||||||
// or in the main window ctor, before GL startup.
|
// or in the main window ctor, before GL startup.
|
||||||
Application::initPlugins(arguments);
|
Application::initPlugins(arguments);
|
||||||
|
|
||||||
|
SteamClient::init();
|
||||||
|
|
||||||
int exitCode;
|
int exitCode;
|
||||||
{
|
{
|
||||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||||
|
@ -202,6 +207,8 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
Application::shutdownPlugins();
|
Application::shutdownPlugins();
|
||||||
|
|
||||||
|
SteamClient::shutdown();
|
||||||
|
|
||||||
qCDebug(interfaceapp, "Normal exit.");
|
qCDebug(interfaceapp, "Normal exit.");
|
||||||
#if !defined(DEBUG) && !defined(Q_OS_LINUX)
|
#if !defined(DEBUG) && !defined(Q_OS_LINUX)
|
||||||
// HACK: exit immediately (don't handle shutdown callbacks) for Release build
|
// HACK: exit immediately (don't handle shutdown callbacks) for Release build
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
|
||||||
#include <NetworkingConstants.h>
|
#include <NetworkingConstants.h>
|
||||||
|
#include <steamworks-wrapper/SteamClient.h>
|
||||||
|
|
||||||
#include "AccountManager.h"
|
#include "AccountManager.h"
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
|
@ -82,6 +83,20 @@ void LoginDialog::login(const QString& username, const QString& password) {
|
||||||
DependencyManager::get<AccountManager>()->requestAccessToken(username, password);
|
DependencyManager::get<AccountManager>()->requestAccessToken(username, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoginDialog::loginThroughSteam() {
|
||||||
|
qDebug() << "Attempting to login through Steam";
|
||||||
|
setStatusText("Logging in...");
|
||||||
|
|
||||||
|
SteamClient::requestTicket([this](Ticket ticket) {
|
||||||
|
if (ticket.isNull()) {
|
||||||
|
setStatusText("Steam client not logged into an account");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DependencyManager::get<AccountManager>()->requestAccessTokenWithSteam(ticket);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void LoginDialog::openUrl(const QString& url) {
|
void LoginDialog::openUrl(const QString& url) {
|
||||||
qDebug() << url;
|
qDebug() << url;
|
||||||
QDesktopServices::openUrl(url);
|
QDesktopServices::openUrl(url);
|
||||||
|
|
|
@ -41,6 +41,7 @@ protected:
|
||||||
void handleLoginFailed();
|
void handleLoginFailed();
|
||||||
|
|
||||||
Q_INVOKABLE void login(const QString& username, const QString& password);
|
Q_INVOKABLE void login(const QString& username, const QString& password);
|
||||||
|
Q_INVOKABLE void loginThroughSteam();
|
||||||
Q_INVOKABLE void openUrl(const QString& url);
|
Q_INVOKABLE void openUrl(const QString& url);
|
||||||
private:
|
private:
|
||||||
QString _statusText;
|
QString _statusText;
|
||||||
|
|
|
@ -505,6 +505,29 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas
|
||||||
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
|
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) {
|
||||||
|
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||||
|
|
||||||
|
QNetworkRequest request;
|
||||||
|
request.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter());
|
||||||
|
|
||||||
|
QUrl grantURL = _authURL;
|
||||||
|
grantURL.setPath("/oauth/token");
|
||||||
|
|
||||||
|
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
||||||
|
|
||||||
|
QByteArray postData;
|
||||||
|
postData.append("grant_type=password&");
|
||||||
|
postData.append("ticket=" + QUrl::toPercentEncoding(authSessionTicket) + "&");
|
||||||
|
postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE);
|
||||||
|
|
||||||
|
request.setUrl(grantURL);
|
||||||
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
|
QNetworkReply* requestReply = networkAccessManager.post(request, postData);
|
||||||
|
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestAccessTokenFinished);
|
||||||
|
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
|
||||||
|
}
|
||||||
|
|
||||||
void AccountManager::requestAccessTokenFinished() {
|
void AccountManager::requestAccessTokenFinished() {
|
||||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||||
|
|
|
@ -96,6 +96,7 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void requestAccessToken(const QString& login, const QString& password);
|
void requestAccessToken(const QString& login, const QString& password);
|
||||||
|
void requestAccessTokenWithSteam(QByteArray authSessionTicket);
|
||||||
|
|
||||||
void requestAccessTokenFinished();
|
void requestAccessTokenFinished();
|
||||||
void requestProfileFinished();
|
void requestProfileFinished();
|
||||||
|
|
|
@ -11,9 +11,180 @@
|
||||||
|
|
||||||
#include "SteamClient.h"
|
#include "SteamClient.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <steam/steam_api.h>
|
#include <steam/steam_api.h>
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static const Ticket INVALID_TICKET = Ticket();
|
||||||
|
|
||||||
|
class SteamTicketRequests {
|
||||||
|
public:
|
||||||
|
SteamTicketRequests();
|
||||||
|
~SteamTicketRequests();
|
||||||
|
|
||||||
|
HAuthTicket startRequest(TicketRequestCallback callback);
|
||||||
|
void stopRequest(HAuthTicket authTicket);
|
||||||
|
|
||||||
|
STEAM_CALLBACK(SteamTicketRequests, onGetAuthSessionTicketResponse,
|
||||||
|
GetAuthSessionTicketResponse_t, _getAuthSessionTicketResponse);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void stopAll();
|
||||||
|
|
||||||
|
struct PendingTicket {
|
||||||
|
HAuthTicket authTicket;
|
||||||
|
Ticket ticket;
|
||||||
|
TicketRequestCallback callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<PendingTicket> _pendingTickets;
|
||||||
|
};
|
||||||
|
|
||||||
|
SteamTicketRequests::SteamTicketRequests() :
|
||||||
|
_getAuthSessionTicketResponse(this, &SteamTicketRequests::onGetAuthSessionTicketResponse)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SteamTicketRequests::~SteamTicketRequests() {
|
||||||
|
stopAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
HAuthTicket SteamTicketRequests::startRequest(TicketRequestCallback callback) {
|
||||||
|
static const uint32 MAX_TICKET_SIZE { 1024 };
|
||||||
|
uint32 ticketSize { 0 };
|
||||||
|
char ticket[MAX_TICKET_SIZE];
|
||||||
|
|
||||||
|
auto authTicket = SteamUser()->GetAuthSessionTicket(ticket, MAX_TICKET_SIZE, &ticketSize);
|
||||||
|
qDebug() << "Got Steam auth session ticket:" << authTicket;
|
||||||
|
|
||||||
|
if (authTicket == k_HAuthTicketInvalid) {
|
||||||
|
qWarning() << "Auth session ticket is invalid.";
|
||||||
|
callback(INVALID_TICKET);
|
||||||
|
} else {
|
||||||
|
PendingTicket pendingTicket{ authTicket, QByteArray(ticket, ticketSize).toHex(), callback };
|
||||||
|
_pendingTickets.push_back(pendingTicket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return authTicket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamTicketRequests::stopRequest(HAuthTicket authTicket) {
|
||||||
|
auto it = std::find_if(_pendingTickets.begin(), _pendingTickets.end(), [&authTicket](const PendingTicket& pendingTicket) {
|
||||||
|
return pendingTicket.authTicket == authTicket;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != _pendingTickets.end()) {
|
||||||
|
SteamUser()->CancelAuthTicket(it->authTicket);
|
||||||
|
it->callback(INVALID_TICKET);
|
||||||
|
_pendingTickets.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamTicketRequests::stopAll() {
|
||||||
|
auto steamUser = SteamUser();
|
||||||
|
if (steamUser) {
|
||||||
|
for (const auto& pendingTicket : _pendingTickets) {
|
||||||
|
steamUser->CancelAuthTicket(pendingTicket.authTicket);
|
||||||
|
pendingTicket.callback(INVALID_TICKET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pendingTickets.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamTicketRequests::onGetAuthSessionTicketResponse(GetAuthSessionTicketResponse_t* pCallback) {
|
||||||
|
auto authTicket = pCallback->m_hAuthTicket;
|
||||||
|
|
||||||
|
auto it = std::find_if(_pendingTickets.begin(), _pendingTickets.end(), [&authTicket](const PendingTicket& pendingTicket) {
|
||||||
|
return pendingTicket.authTicket == authTicket;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (it != _pendingTickets.end()) {
|
||||||
|
|
||||||
|
if (pCallback->m_eResult == k_EResultOK) {
|
||||||
|
qDebug() << "Got steam callback, auth session ticket is valid. Send it." << authTicket;
|
||||||
|
it->callback(it->ticket);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Steam auth session ticket callback encountered an error:" << pCallback->m_eResult;
|
||||||
|
it->callback(INVALID_TICKET);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pendingTickets.erase(it);
|
||||||
|
} else {
|
||||||
|
qWarning() << "Could not find steam auth session ticket in list of pending tickets:" << authTicket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static std::atomic_bool initialized { false };
|
||||||
|
static std::unique_ptr<SteamTicketRequests> steamTicketRequests;
|
||||||
|
|
||||||
|
bool SteamClient::init() {
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = SteamAPI_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!steamTicketRequests && initialized) {
|
||||||
|
steamTicketRequests.reset(new SteamTicketRequests());
|
||||||
|
}
|
||||||
|
|
||||||
|
return initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamClient::shutdown() {
|
||||||
|
if (initialized) {
|
||||||
|
SteamAPI_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (steamTicketRequests) {
|
||||||
|
steamTicketRequests.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamClient::runCallbacks() {
|
||||||
|
if (!initialized) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
qDebug() << "Steam not initialized";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto steamPipe = SteamAPI_GetHSteamPipe();
|
||||||
|
if (!steamPipe) {
|
||||||
|
qDebug() << "Could not get SteamPipe";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_RunCallbacks(steamPipe, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SteamClient::requestTicket(TicketRequestCallback callback) {
|
||||||
|
if (!initialized) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
qDebug() << "Steam not initialized";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
steamTicketRequests->startRequest(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,21 @@
|
||||||
#ifndef hifi_SteamClient_h
|
#ifndef hifi_SteamClient_h
|
||||||
#define hifi_SteamClient_h
|
#define hifi_SteamClient_h
|
||||||
|
|
||||||
class SteamClient {
|
#include <functional>
|
||||||
|
|
||||||
|
#include <QtCore/QByteArray>
|
||||||
|
|
||||||
|
using Ticket = QByteArray;
|
||||||
|
using TicketRequestCallback = std::function<void(Ticket)>;
|
||||||
|
|
||||||
|
class SteamClient {
|
||||||
|
public:
|
||||||
|
static bool init();
|
||||||
|
static void shutdown();
|
||||||
|
|
||||||
|
static void runCallbacks();
|
||||||
|
|
||||||
|
static void requestTicket(TicketRequestCallback callback);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue