From 970798705c458c163b5d61c88a22905014a68a74 Mon Sep 17 00:00:00 2001 From: Wayne Chen Date: Fri, 4 Jan 2019 16:55:03 -0800 Subject: [PATCH] improving flow from Oculus API to login dialog wip --- .../qml/LoginDialog/LinkAccountBody.qml | 14 +- .../qml/LoginDialog/LoggingInBody.qml | 6 +- interface/src/ui/LoginDialog.cpp | 48 ++++++- libraries/networking/src/AccountManager.cpp | 6 +- libraries/networking/src/AccountManager.h | 2 +- .../src/plugins/OculusPlatformPlugin.h | 5 +- .../oculusPlatform/src/OculusAPIPlugin.cpp | 131 ++++++++++-------- plugins/oculusPlatform/src/OculusAPIPlugin.h | 4 +- 8 files changed, 137 insertions(+), 79 deletions(-) diff --git a/interface/resources/qml/LoginDialog/LinkAccountBody.qml b/interface/resources/qml/LoginDialog/LinkAccountBody.qml index 97cc370639..f467bfe5d1 100644 --- a/interface/resources/qml/LoginDialog/LinkAccountBody.qml +++ b/interface/resources/qml/LoginDialog/LinkAccountBody.qml @@ -394,10 +394,10 @@ Item { buttonGlyphSize: 24 buttonGlyphRightMargin: 10 onClicked: { - // if (loginDialog.isOculusRunning()) { - // linkAccountBody.withOculus = true; - // loginDialog.loginThroughSteam(); - // } else + if (loginDialog.isOculusRunning()) { + linkAccountBody.withOculus = true; + loginDialog.loginThroughOculus(); + } else if (loginDialog.isSteamRunning()) { linkAccountBody.withSteam = true; loginDialog.loginThroughSteam(); @@ -527,6 +527,9 @@ Item { }); } } + onLoginFailed: { + console.log("login failed"); + } } Component.onCompleted: { @@ -539,9 +542,6 @@ Item { Qt.callLater(function() { emailField.forceActiveFocus(); }); - if (loginDialog.isOculusRunning()) { - print(loginDialog.getLoggedInUserID()); - } } Keys.onPressed: { diff --git a/interface/resources/qml/LoginDialog/LoggingInBody.qml b/interface/resources/qml/LoginDialog/LoggingInBody.qml index fe307c91fc..0cdee9856b 100644 --- a/interface/resources/qml/LoginDialog/LoggingInBody.qml +++ b/interface/resources/qml/LoginDialog/LoggingInBody.qml @@ -252,7 +252,11 @@ Item { console.log("Login Failed") loggingInSpinner.visible = false; var errorString = ""; - if (loggingInBody.linkSteam && loggingInBody.withSteam) { + if (loggingInBody.withOculus) { + loggingInGlyph.visible = false; + errorString = "Your Oculus authentication has failed. Please make sure you are logged into Oculus and try again."; + bodyLoader.setSource("CompleteProfileBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": false, "errorString": errorString }); + } else if (loggingInBody.linkSteam && loggingInBody.withSteam) { errorString = "Username or password is incorrect."; bodyLoader.setSource("LinkAccountBody.qml", { "loginDialog": loginDialog, "root": root, "bodyLoader": bodyLoader, "withSteam": loggingInBody.withSteam, "linkSteam": loggingInBody.linkSteam, "errorString": errorString }); } else if (loggingInBody.withSteam) { diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index c241ee28e9..dd40c10800 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -126,11 +126,13 @@ void LoginDialog::login(const QString& username, const QString& password) const void LoginDialog::loginThroughOculus() { qDebug() << "Attempting to login through Oculus"; if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) { - oculusPlatform->requestTicket([this](Ticket ticket) { - if (ticket.isNull()) { + oculusPlatform->requestTicket([this](QString nonce, QString userID) { + if (nonce.isEmpty() || userID.isEmpty()) { emit handleLoginFailed(); return; } + + DependencyManager::get()->requestAccessTokenWithOculus(nonce, userID); }); } } @@ -138,11 +140,26 @@ void LoginDialog::loginThroughOculus() { void LoginDialog::linkOculus() { qDebug() << "Attempting to link Oculus account"; if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) { - oculusPlatform->requestTicket([this](Ticket ticket) { - if (ticket.isNull()) { + oculusPlatform->requestTicket([this](QString nonce, QString userID) { + if (nonce.isEmpty() || userID.isEmpty()) { emit handleLoginFailed(); return; } + + JSONCallbackParameters callbackParams; + callbackParams.callbackReceiver = this; + callbackParams.jsonCallbackMethod = "linkCompleted"; + callbackParams.errorCallbackMethod = "linkFailed"; + const QString LINK_OCULUS_PATH = "api/v1/user/oculus/link"; + + QJsonObject payload; + payload.insert("oculus_nonce", QJsonValue::fromVariant(QVariant(nonce))); + payload.insert("oculus_user_id", QJsonValue::fromVariant(QVariant(userID))); + + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(LINK_OCULUS_PATH, AccountManagerAuth::Required, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); }); } } @@ -150,11 +167,30 @@ void LoginDialog::linkOculus() { void LoginDialog::createAccountFromOculus(QString username) { qDebug() << "Attempting to create account from Oculus info"; if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) { - oculusPlatform->requestTicket([this](Ticket ticket) { - if (ticket.isNull()) { + oculusPlatform->requestTicket([this, username](QString nonce, QString userID) { + if (nonce.isEmpty() || userID.isEmpty()) { emit handleLoginFailed(); return; } + + JSONCallbackParameters callbackParams; + callbackParams.callbackReceiver = this; + callbackParams.jsonCallbackMethod = "createCompleted"; + callbackParams.errorCallbackMethod = "createFailed"; + + const QString CREATE_ACCOUNT_FROM_OCULUS_PATH = "api/v1/user/oculus/create"; + + QJsonObject payload; + payload.insert("oculus_nonce", QJsonValue::fromVariant(QVariant(nonce))); + payload.insert("oculus_user_id", QJsonValue::fromVariant(QVariant(userID))); + if (!username.isEmpty()) { + payload.insert("username", QJsonValue::fromVariant(QVariant(username))); + } + + auto accountManager = DependencyManager::get(); + accountManager->sendRequest(CREATE_ACCOUNT_FROM_OCULUS_PATH, AccountManagerAuth::None, + QNetworkAccessManager::PostOperation, callbackParams, + QJsonDocument(payload).toJson()); }); } } diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 2570b18b48..38d286d131 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -586,7 +586,7 @@ void AccountManager::requestAccessTokenWithSteam(QByteArray authSessionTicket) { connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError))); } -void AccountManager::requestAccessTokenWithOculus(QByteArray authSessionTicket) { +void AccountManager::requestAccessTokenWithOculus(const QString& nonce, const QString& userID) { QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); QNetworkRequest request; @@ -597,8 +597,8 @@ void AccountManager::requestAccessTokenWithOculus(QByteArray authSessionTicket) QByteArray postData; postData.append("grant_type=password&"); - postData.append("oculus_nonce=" + QUrl::toPercentEncoding(authSessionTicket) + "&"); - postData.append("oculus_user_id=" + QUrl::toPercentEncoding(authSessionTicket) + "&"); + postData.append("oculus_nonce=" + nonce + "&"); + postData.append("oculus_user_id=" + userID + "&"); postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE); request.setUrl(grantURL); diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 7fdf3a36b2..748dc27252 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -104,7 +104,7 @@ public: public slots: void requestAccessToken(const QString& login, const QString& password); void requestAccessTokenWithSteam(QByteArray authSessionTicket); - void requestAccessTokenWithOculus(QByteArray authSessionTicket); + void requestAccessTokenWithOculus(const QString& nonce, const QString& userID); void requestAccessTokenWithAuthCode(const QString& authCode, const QString& clientId, const QString& clientSecret, const QString& redirectUri); void refreshAccessToken(); diff --git a/libraries/plugins/src/plugins/OculusPlatformPlugin.h b/libraries/plugins/src/plugins/OculusPlatformPlugin.h index ed797292bb..3fe585eb75 100644 --- a/libraries/plugins/src/plugins/OculusPlatformPlugin.h +++ b/libraries/plugins/src/plugins/OculusPlatformPlugin.h @@ -12,8 +12,7 @@ #include -using Ticket = QByteArray; -using TicketRequestCallback = std::function; +using OculusTicketRequestCallback = std::function; class OculusPlatformPlugin { @@ -27,7 +26,7 @@ public: virtual void runCallbacks() = 0; - virtual void requestTicket(TicketRequestCallback callback) = 0; + virtual void requestTicket(OculusTicketRequestCallback callback) = 0; virtual QString getUserProof() = 0; diff --git a/plugins/oculusPlatform/src/OculusAPIPlugin.cpp b/plugins/oculusPlatform/src/OculusAPIPlugin.cpp index 8c1a63ab56..f95617d195 100644 --- a/plugins/oculusPlatform/src/OculusAPIPlugin.cpp +++ b/plugins/oculusPlatform/src/OculusAPIPlugin.cpp @@ -20,17 +20,9 @@ #include #include "OculusHelpers.h" -static const Ticket INVALID_TICKET = Ticket(); static std::atomic_bool initialized { false }; static ovrSession session { nullptr }; -class OculusCallbackManager { -public: - OculusCallbackManager(); -}; - -static OculusCallbackManager oculusCallbackManager; - bool OculusAPIPlugin::init() { if (session) { return initialized; @@ -52,17 +44,30 @@ bool OculusAPIPlugin::init() { } else { qCDebug(oculusLog) << "Performing Oculus Platform entitlement check"; ovr_Entitlement_GetIsViewerEntitled(); + QTimer timer; + timer.start(1000); using namespace std::chrono_literals; - std::this_thread::sleep_for(100ms); - auto message = ovr_PopMessage(); - if (ovr_Message_GetType(message) == ovrMessage_Entitlement_GetIsViewerEntitled && ovr_Message_IsError(message)) { - qDebug() << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); + std::this_thread::sleep_for(50ms); + while (auto message = ovr_PopMessage()) { + if (timer.remainingTime() == 0) { + qCDebug(oculusLog) << "login user id timeout after 1 second"; + break; + } + switch (ovr_Message_GetType(message)) { + case ovrMessage_Entitlement_GetIsViewerEntitled: + if (ovr_Message_IsError(message)) { + qDebug() << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); + } + initialized = true; + default: + ovr_FreeMessage(message); + break; + } } } } #endif - initialized = true; return initialized; } @@ -72,14 +77,14 @@ void OculusAPIPlugin::shutdown() { void OculusAPIPlugin::runCallbacks() { } -void OculusAPIPlugin::requestTicket(TicketRequestCallback callback) { +void OculusAPIPlugin::requestTicket(OculusTicketRequestCallback callback) { if (!initialized) { if (!ovr_IsPlatformInitialized()) { init(); } else { qWarning() << "Oculus is not running"; - callback(INVALID_TICKET); + callback("", ""); return; } } @@ -89,73 +94,87 @@ void OculusAPIPlugin::requestTicket(TicketRequestCallback callback) { return; } - auto userProof = requestUserProof(); - if (userProof == "") { - qWarning() << "User proof unavailable."; - callback(INVALID_TICKET); - return; - } else { - oculusCallbackManager; - } + auto userProof = getUserProof(); + auto userID = getLoggedInUserID(); + callback(userProof, userID); + return; } bool OculusAPIPlugin::isRunning() { return initialized; } -QString OculusAPIPlugin::requestUserProof() { +QString OculusAPIPlugin::getUserProof() { if (initialized) { QTimer timer; - timer.start(1000); + timer.start(5000); auto request = ovr_User_GetUserProof(); ovrMessageHandle message { nullptr }; - while (message = ovr_PopMessage()) { - if (message == nullptr) { - break; - } else if (!timer.isActive()) { - qCDebug(oculusLog) << "login user id timeout after 1 second"; + bool messageNotReceived = true; + while (timer.isActive() && messageNotReceived) { + message = ovr_PopMessage(); + if (timer.remainingTime() == 0) { + qCDebug(oculusLog) << "user proof timeout after 5 seconds"; return ""; - } else if (ovr_Message_GetType(message) == ovrMessage_User_GetUserProof) { - if (!ovr_Message_IsError(message)) { - ovrUserProofHandle userProof = ovr_Message_GetUserProof(message); - QString nonce = ovr_UserProof_GetNonce(userProof); - qCDebug(oculusLog) << "User nonce: " << nonce; - return nonce; - } else { - qDebug() << "Error getting user proof: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); - return ""; + } + if (message != nullptr) { + switch (ovr_Message_GetType(message)) { + case ovrMessage_User_GetUserProof: + messageNotReceived = false; + if (!ovr_Message_IsError(message)) { + ovrUserProofHandle userProof = ovr_Message_GetUserProof(message); + QString nonce = ovr_UserProof_GetNonce(userProof); + ovr_FreeMessage(message); + return nonce; + } else { + qDebug() << "Error getting user proof: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); + ovr_FreeMessage(message); + return ""; + } + break; + default: + ovr_FreeMessage(message); + break; } } } - return ""; } + return ""; } QString OculusAPIPlugin::getLoggedInUserID() { if (initialized) { QTimer timer; - timer.start(1000); + timer.start(5000); auto request = ovr_User_GetLoggedInUser(); ovrMessageHandle message { nullptr }; - while (message = ovr_PopMessage()) { - if (message == nullptr) { - break; - } else if (!timer.isActive()) { - qCDebug(oculusLog) << "login user id timeout after 1 second"; + bool messageNotReceived = true; + while (messageNotReceived) { + if (timer.remainingTime() == 0) { + qCDebug(oculusLog) << "login user id timeout after 5 seconds"; return ""; - } else if (ovr_Message_GetType(message) == ovrMessage_User_GetLoggedInUser) { - if (!ovr_Message_IsError(message)) { - ovrUserHandle user = ovr_Message_GetUser(message); - qCDebug(oculusLog) << "UserID: " << ovr_User_GetID(user) << ", Oculus ID: " << ovr_User_GetOculusID(user); - return ovr_User_GetOculusID(user); - } else { - qDebug() << "Error getting user id: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); - return ""; - } + } + switch (ovr_Message_GetType(message)) { + case ovrMessage_User_GetLoggedInUser: + messageNotReceived = false; + if (!ovr_Message_IsError(message)) { + ovrUserHandle user = ovr_Message_GetUser(message); + ovr_FreeMessage(message); + qCDebug(oculusLog) << "UserID: " << ovr_User_GetID(user) << ", Oculus ID: " << QString(ovr_User_GetOculusID(user)); + return QString(ovr_User_GetOculusID(user)); + } else { + qDebug() << "Error getting user id: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message))); + ovr_FreeMessage(message); + return ""; + } + break; + default: + ovr_FreeMessage(message); + break; } } - return ""; } + return ""; } QString OculusAPIPlugin::getOculusVRBuildID() { diff --git a/plugins/oculusPlatform/src/OculusAPIPlugin.h b/plugins/oculusPlatform/src/OculusAPIPlugin.h index 7c8bb9617e..86343d361c 100644 --- a/plugins/oculusPlatform/src/OculusAPIPlugin.h +++ b/plugins/oculusPlatform/src/OculusAPIPlugin.h @@ -18,9 +18,9 @@ public: void runCallbacks() override; - void requestTicket(TicketRequestCallback callback) override; + void requestTicket(OculusTicketRequestCallback callback) override; - QString requestUserProof() override; + QString getUserProof() override; QString getLoggedInUserID() override; QString getOculusVRBuildID() override;