From 206e35326462de92f9e47daded61b6f0c9f24829 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 22 May 2019 16:18:30 -0700 Subject: [PATCH 1/5] Pass tokens as params for automatic login --- interface/src/main.cpp | 18 +++++- libraries/networking/src/AccountManager.cpp | 63 +++++++++++++++++++++ libraries/networking/src/AccountManager.h | 5 ++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 9d8b733ba7..303d7f210b 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -83,6 +83,7 @@ int main(int argc, const char* argv[]) { QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run"); QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache ", "dir"); QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts ", "path"); + QCommandLineOption responseTokensOption("tokens", "set response tokens ", "json"); parser.addOption(urlOption); parser.addOption(noLauncherOption); @@ -93,6 +94,7 @@ int main(int argc, const char* argv[]) { parser.addOption(overrideAppLocalDataPathOption); parser.addOption(overrideScriptsPathOption); parser.addOption(allowMultipleInstancesOption); + parser.addOption(responseTokensOption); if (!parser.parse(arguments)) { std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam @@ -121,7 +123,7 @@ int main(int argc, const char* argv[]) { static const QString APPLICATION_CONFIG_FILENAME = "config.json"; QDir applicationDir(applicationPath); QFile configFile(applicationDir.filePath(APPLICATION_CONFIG_FILENAME)); - + bool isConfigFileValid = false; if (configFile.exists()) { if (!configFile.open(QIODevice::ReadOnly)) { qWarning() << "Found application config, but could not open it"; @@ -136,6 +138,7 @@ int main(int argc, const char* argv[]) { static const QString LAUNCHER_PATH_KEY = "launcherPath"; QString launcherPath = doc.object()[LAUNCHER_PATH_KEY].toString(); if (!launcherPath.isEmpty()) { + isConfigFileValid = true; if (!parser.isSet(noLauncherOption)) { qDebug() << "Found a launcherPath in application config. Starting launcher."; QProcess launcher; @@ -146,6 +149,7 @@ int main(int argc, const char* argv[]) { qDebug() << "Found a launcherPath in application config, but the launcher" " has been suppressed. Continuing normal execution."; } + configFile.close(); } } } @@ -398,6 +402,18 @@ int main(int argc, const char* argv[]) { printSystemInformation(); + if (isConfigFileValid || parser.isSet(responseTokensOption)) { + auto accountManager = DependencyManager::get(); + if (!accountManager.isNull()) { + if (parser.isSet(responseTokensOption)) { + QString tokens = QString(parser.value(responseTokensOption)); + accountManager->setAccessTokens(tokens); + } else if (isConfigFileValid) { + accountManager->setConfigFileURL(configFile.fileName()); + } + } + } + QTranslator translator; translator.load("i18n/interface_en"); app.installTranslator(&translator); diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 226433e388..014ae62aff 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -97,6 +97,7 @@ void AccountManager::logout() { // remove this account from the account settings file removeAccountFromFile(); + saveLoginStatus(false); emit logoutComplete(); // the username has changed to blank @@ -650,6 +651,39 @@ void AccountManager::refreshAccessToken() { } } +void AccountManager::setAccessTokens(const QString& response) { + QJsonDocument jsonResponse = QJsonDocument::fromJson(response.toUtf8()); + const QJsonObject& rootObject = jsonResponse.object(); + + if (!rootObject.contains("error")) { + // construct an OAuthAccessToken from the json object + + if (!rootObject.contains("access_token") || !rootObject.contains("expires_in") + || !rootObject.contains("token_type")) { + // TODO: error handling - malformed token response + qCDebug(networking) << "Received a response for password grant that is missing one or more expected values."; + } else { + // clear the path from the response URL so we have the right root URL for this access token + QUrl rootURL = rootObject.contains("url") ? rootObject["url"].toString() : _authURL; + rootURL.setPath(""); + + qCDebug(networking) << "Storing an account with access-token for" << qPrintable(rootURL.toString()); + + _accountInfo = DataServerAccountInfo(); + _accountInfo.setAccessTokenFromJSON(rootObject); + emit loginComplete(rootURL); + + persistAccountToFile(); + + requestProfile(); + } + } else { + // TODO: error handling + qCDebug(networking) << "Error in response for password grant -" << rootObject["error_description"].toString(); + emit loginFailed(); + } +} + void AccountManager::requestAccessTokenFinished() { QNetworkReply* requestReply = reinterpret_cast(sender()); @@ -895,3 +929,32 @@ void AccountManager::handleKeypairGenerationError() { void AccountManager::setLimitedCommerce(bool isLimited) { _limitedCommerce = isLimited; } + +void AccountManager::saveLoginStatus(bool isLoggedIn) { + if (_configFileURL.isValid()) { + QFile configFile(_configFileURL.toString()); + configFile.open(QIODevice::ReadOnly | QIODevice::Text); + QJsonParseError error; + QJsonDocument jsonDocument = QJsonDocument::fromJson(configFile.readAll(), &error); + configFile.close(); + QString launcherPath; + if (error.error == QJsonParseError::NoError) { + QJsonObject rootObject = jsonDocument.object(); + if (rootObject.contains("loggedIn")) { + rootObject["loggedIn"] = isLoggedIn; + } + if (rootObject.contains("laucherPath")) { + launcherPath = rootObject["launcherPath"].isString(); + } + } + configFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + configFile.write(jsonDocument.toJson()); + configFile.close(); + if (!isLoggedIn && !launcherPath.isEmpty()) { + QProcess launcher; + launcher.setProgram(launcherPath); + launcher.startDetached(); + qApp->quit(); + } + } +} \ No newline at end of file diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 8732042e93..3fcbff4f99 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -102,6 +102,10 @@ public: bool getLimitedCommerce() { return _limitedCommerce; } void setLimitedCommerce(bool isLimited); + void setAccessTokens(const QString& response); + void setConfigFileURL(const QUrl& fileURL) { _configFileURL = fileURL; } + void saveLoginStatus(bool isLoggedIn); + public slots: void requestAccessToken(const QString& login, const QString& password); void requestAccessTokenWithSteam(QByteArray authSessionTicket); @@ -162,6 +166,7 @@ private: QUuid _sessionID { QUuid::createUuid() }; bool _limitedCommerce { false }; + QUrl _configFileURL; }; #endif // hifi_AccountManager_h From 6d824ff22d1931342a53e55b9ea0fdc22575a98a Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Wed, 22 May 2019 20:27:42 -0700 Subject: [PATCH 2/5] Fix logout --- interface/src/main.cpp | 18 ++++++++++-------- libraries/networking/src/AccountManager.cpp | 14 ++++++++------ libraries/networking/src/AccountManager.h | 4 ++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 303d7f210b..80d88c9303 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -122,8 +122,10 @@ int main(int argc, const char* argv[]) { static const QString APPLICATION_CONFIG_FILENAME = "config.json"; QDir applicationDir(applicationPath); - QFile configFile(applicationDir.filePath(APPLICATION_CONFIG_FILENAME)); - bool isConfigFileValid = false; + QString configFileName = applicationDir.filePath(APPLICATION_CONFIG_FILENAME); + QFile configFile(configFileName); + QString launcherPath; + if (configFile.exists()) { if (!configFile.open(QIODevice::ReadOnly)) { qWarning() << "Found application config, but could not open it"; @@ -136,9 +138,8 @@ int main(int argc, const char* argv[]) { qWarning() << "Found application config, but could not parse it: " << error.errorString(); } else { static const QString LAUNCHER_PATH_KEY = "launcherPath"; - QString launcherPath = doc.object()[LAUNCHER_PATH_KEY].toString(); + launcherPath = doc.object()[LAUNCHER_PATH_KEY].toString(); if (!launcherPath.isEmpty()) { - isConfigFileValid = true; if (!parser.isSet(noLauncherOption)) { qDebug() << "Found a launcherPath in application config. Starting launcher."; QProcess launcher; @@ -402,15 +403,16 @@ int main(int argc, const char* argv[]) { printSystemInformation(); - if (isConfigFileValid || parser.isSet(responseTokensOption)) { + if (!launcherPath.isEmpty() || parser.isSet(responseTokensOption)) { auto accountManager = DependencyManager::get(); if (!accountManager.isNull()) { + if (!launcherPath.isEmpty()) { + accountManager->setConfigFileURL(configFileName); + } if (parser.isSet(responseTokensOption)) { QString tokens = QString(parser.value(responseTokensOption)); accountManager->setAccessTokens(tokens); - } else if (isConfigFileValid) { - accountManager->setConfigFileURL(configFile.fileName()); - } + } } } diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 014ae62aff..3a7d3e0a67 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -674,7 +674,7 @@ void AccountManager::setAccessTokens(const QString& response) { emit loginComplete(rootURL); persistAccountToFile(); - + saveLoginStatus(true); requestProfile(); } } else { @@ -931,8 +931,8 @@ void AccountManager::setLimitedCommerce(bool isLimited) { } void AccountManager::saveLoginStatus(bool isLoggedIn) { - if (_configFileURL.isValid()) { - QFile configFile(_configFileURL.toString()); + if (!_configFileURL.isEmpty()) { + QFile configFile(_configFileURL); configFile.open(QIODevice::ReadOnly | QIODevice::Text); QJsonParseError error; QJsonDocument jsonDocument = QJsonDocument::fromJson(configFile.readAll(), &error); @@ -940,12 +940,14 @@ void AccountManager::saveLoginStatus(bool isLoggedIn) { QString launcherPath; if (error.error == QJsonParseError::NoError) { QJsonObject rootObject = jsonDocument.object(); + if (rootObject.contains("launcherPath")) { + launcherPath = rootObject["launcherPath"].toString(); + } if (rootObject.contains("loggedIn")) { rootObject["loggedIn"] = isLoggedIn; } - if (rootObject.contains("laucherPath")) { - launcherPath = rootObject["launcherPath"].isString(); - } + jsonDocument = QJsonDocument(rootObject); + } configFile.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); configFile.write(jsonDocument.toJson()); diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 3fcbff4f99..c2187f79cb 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -103,7 +103,7 @@ public: void setLimitedCommerce(bool isLimited); void setAccessTokens(const QString& response); - void setConfigFileURL(const QUrl& fileURL) { _configFileURL = fileURL; } + void setConfigFileURL(const QString& fileURL) { _configFileURL = fileURL; } void saveLoginStatus(bool isLoggedIn); public slots: @@ -166,7 +166,7 @@ private: QUuid _sessionID { QUuid::createUuid() }; bool _limitedCommerce { false }; - QUrl _configFileURL; + QString _configFileURL; }; #endif // hifi_AccountManager_h From 8db3d03772fad935013f3ba8cda22e91fd807a5c Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 23 May 2019 10:21:47 -0700 Subject: [PATCH 3/5] add display name as param --- interface/src/Application.cpp | 10 ++++++++++ interface/src/Application.h | 4 ++++ interface/src/main.cpp | 24 ++++++++++++++---------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0dba4498d5..ca171aa8b9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -9355,6 +9355,16 @@ void Application::showUrlHandler(const QUrl& url) { }); } +void Application::forceDisplayName(const QString& displayName) { + getMyAvatar()->setDisplayName(displayName); +} +void Application::forceLogginWithTokens(const QString& tokens) { + DependencyManager::get()->setAccessTokens(tokens); +} +void Application::setConfigFileURL(const QString& fileUrl) { + DependencyManager::get()->setConfigFileURL(fileUrl); +} + #if defined(Q_OS_ANDROID) void Application::beforeEnterBackground() { auto nodeList = DependencyManager::get(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 210039beba..2eac2bc885 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -356,6 +356,10 @@ public: void openDirectory(const QString& path); + void forceDisplayName(const QString& displayName); + void forceLogginWithTokens(const QString& tokens); + void setConfigFileURL(const QString& fileUrl); + signals: void svoImportRequested(const QString& url); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 80d88c9303..140b79584c 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -84,6 +84,7 @@ int main(int argc, const char* argv[]) { QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache ", "dir"); QCommandLineOption overrideScriptsPathOption(SCRIPTS_SWITCH, "set scripts ", "path"); QCommandLineOption responseTokensOption("tokens", "set response tokens ", "json"); + QCommandLineOption displayNameOption("displayName", "set user display name ", "string"); parser.addOption(urlOption); parser.addOption(noLauncherOption); @@ -95,6 +96,7 @@ int main(int argc, const char* argv[]) { parser.addOption(overrideScriptsPathOption); parser.addOption(allowMultipleInstancesOption); parser.addOption(responseTokensOption); + parser.addOption(displayNameOption); if (!parser.parse(arguments)) { std::cout << parser.errorText().toStdString() << std::endl; // Avoid Qt log spam @@ -403,16 +405,18 @@ int main(int argc, const char* argv[]) { printSystemInformation(); - if (!launcherPath.isEmpty() || parser.isSet(responseTokensOption)) { - auto accountManager = DependencyManager::get(); - if (!accountManager.isNull()) { - if (!launcherPath.isEmpty()) { - accountManager->setConfigFileURL(configFileName); - } - if (parser.isSet(responseTokensOption)) { - QString tokens = QString(parser.value(responseTokensOption)); - accountManager->setAccessTokens(tokens); - } + auto appPointer = dynamic_cast(&app); + if (appPointer) { + if (parser.isSet(displayNameOption)) { + QString displayName = QString(parser.value(displayNameOption)); + appPointer->forceDisplayName(displayName); + } + if (!launcherPath.isEmpty()) { + appPointer->setConfigFileURL(configFileName); + } + if (parser.isSet(responseTokensOption)) { + QString tokens = QString(parser.value(responseTokensOption)); + appPointer->forceLogginWithTokens(tokens); } } From 42c1f4be33dd215d34c57d2b13b99f67d21e4f3b Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 23 May 2019 17:07:06 -0700 Subject: [PATCH 4/5] fix typo and entry on first run when --url is set --- interface/src/Application.cpp | 20 +++++++++++++------- interface/src/Application.h | 4 +++- interface/src/main.cpp | 5 ++++- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ca171aa8b9..5432577223 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3800,10 +3800,14 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { // If this is a first run we short-circuit the address passed in if (_firstRun.get()) { - DependencyManager::get()->goToEntry(); - sentTo = SENT_TO_ENTRY; - _firstRun.set(false); - + if (!_overrideEntry) { + DependencyManager::get()->goToEntry(); + sentTo = SENT_TO_ENTRY; + } else { + DependencyManager::get()->loadSettings(addressLookupString); + sentTo = SENT_TO_PREVIOUS_LOCATION; + } + _firstRun.set(false); } else { QString goingTo = ""; if (addressLookupString.isEmpty()) { @@ -3819,7 +3823,7 @@ void Application::handleSandboxStatus(QNetworkReply* reply) { DependencyManager::get()->loadSettings(addressLookupString); sentTo = SENT_TO_PREVIOUS_LOCATION; } - + UserActivityLogger::getInstance().logAction("startup_sent_to", { { "sent_to", sentTo }, { "sandbox_is_running", sandboxIsRunning }, @@ -9354,11 +9358,13 @@ void Application::showUrlHandler(const QUrl& url) { } }); } - +void Application::overrideEntry(){ + _overrideEntry = true; +} void Application::forceDisplayName(const QString& displayName) { getMyAvatar()->setDisplayName(displayName); } -void Application::forceLogginWithTokens(const QString& tokens) { +void Application::forceLoginWithTokens(const QString& tokens) { DependencyManager::get()->setAccessTokens(tokens); } void Application::setConfigFileURL(const QString& fileUrl) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 2eac2bc885..837fb8eae6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -356,8 +356,9 @@ public: void openDirectory(const QString& path); + void overrideEntry(); void forceDisplayName(const QString& displayName); - void forceLogginWithTokens(const QString& tokens); + void forceLoginWithTokens(const QString& tokens); void setConfigFileURL(const QString& fileUrl); signals: @@ -832,5 +833,6 @@ private: bool _resumeAfterLoginDialogActionTaken_WasPostponed { false }; bool _resumeAfterLoginDialogActionTaken_SafeToRun { false }; bool _startUpFinished { false }; + bool _overrideEntry { false }; }; #endif // hifi_Application_h diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 140b79584c..7fc4a5b651 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -407,6 +407,9 @@ int main(int argc, const char* argv[]) { auto appPointer = dynamic_cast(&app); if (appPointer) { + if (parser.isSet(urlOption)) { + appPointer->overrideEntry(); + } if (parser.isSet(displayNameOption)) { QString displayName = QString(parser.value(displayNameOption)); appPointer->forceDisplayName(displayName); @@ -416,7 +419,7 @@ int main(int argc, const char* argv[]) { } if (parser.isSet(responseTokensOption)) { QString tokens = QString(parser.value(responseTokensOption)); - appPointer->forceLogginWithTokens(tokens); + appPointer->forceLoginWithTokens(tokens); } } From 050682c84cc90f1c9cc573d25574374b5bdd63a8 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Thu, 23 May 2019 19:53:37 -0700 Subject: [PATCH 5/5] Keep logged in after first run --- interface/src/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5432577223..a0cb790958 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -9366,6 +9366,7 @@ void Application::forceDisplayName(const QString& displayName) { } void Application::forceLoginWithTokens(const QString& tokens) { DependencyManager::get()->setAccessTokens(tokens); + Setting::Handle(KEEP_ME_LOGGED_IN_SETTING_NAME, true).set(true); } void Application::setConfigFileURL(const QString& fileUrl) { DependencyManager::get()->setConfigFileURL(fileUrl);