From 9bb5add1ca8e1bf290c378930da660f8efe51ca4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 18 Aug 2020 11:42:35 +1200 Subject: [PATCH 1/7] Don't display domain login status in title bar unless relevant --- interface/src/Application.cpp | 26 ++++--- .../networking/src/DomainAccountManager.cpp | 73 ++++++++++++++----- .../networking/src/DomainAccountManager.h | 15 +++- libraries/networking/src/DomainHandler.cpp | 20 ++++- libraries/networking/src/NodeList.cpp | 21 ++---- 5 files changed, 108 insertions(+), 47 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cc2aed7f53..f97c48fbdf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1352,10 +1352,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(accountManager.data(), &AccountManager::usernameChanged, this, &Application::updateWindowTitle); auto domainAccountManager = DependencyManager::get(); - connect(domainAccountManager.data(), &DomainAccountManager::authRequired, dialogsManager.data(), - &DialogsManager::showDomainLoginDialog); - connect(domainAccountManager.data(), &DomainAccountManager::loginComplete, this, - &Application::updateWindowTitle); + connect(domainAccountManager.data(), &DomainAccountManager::authRequired, + dialogsManager.data(), &DialogsManager::showDomainLoginDialog); + connect(domainAccountManager.data(), &DomainAccountManager::authRequired, this, &Application::updateWindowTitle); + connect(domainAccountManager.data(), &DomainAccountManager::loginComplete, this, &Application::updateWindowTitle); // ####### TODO: Connect any other signals from domainAccountManager. // use our MyAvatar position and quat for address manager path @@ -7084,6 +7084,7 @@ void Application::updateWindowTitle() const { auto domainAccountManager = DependencyManager::get(); auto isInErrorState = nodeList->getDomainHandler().isInErrorState(); bool isMetaverseLoggedIn = accountManager->isLoggedIn(); + bool hasDomainLogIn = domainAccountManager->hasLogIn(); bool isDomainLoggedIn = domainAccountManager->isLoggedIn(); QString authedDomain = domainAccountManager->getAuthedDomain(); @@ -7115,20 +7116,23 @@ void Application::updateWindowTitle() const { QString metaverseDetails; if (isMetaverseLoggedIn) { - metaverseDetails = "Metaverse: Logged in as " + metaverseUsername; + metaverseDetails = " (Metaverse: Logged in as " + metaverseUsername + ")"; } else { - metaverseDetails = "Metaverse: Not Logged In"; + metaverseDetails = " (Metaverse: Not Logged In)"; } QString domainDetails; - if (currentPlaceName == authedDomain && isDomainLoggedIn) { - domainDetails = "Domain: Logged in as " + domainUsername; + if (hasDomainLogIn) { + if (currentPlaceName == authedDomain && isDomainLoggedIn) { + domainDetails = " (Domain: Logged in as " + domainUsername + ")"; + } else { + domainDetails = " (Domain: Not Logged In)"; + } } else { - domainDetails = "Domain: Not Logged In"; + domainDetails = ""; } - QString title = QString() + currentPlaceName + connectionStatus + " (" + metaverseDetails + ") (" + domainDetails + ")" - + buildVersion; + QString title = currentPlaceName + connectionStatus + metaverseDetails + domainDetails + buildVersion; #ifndef WIN32 // crashes with vs2013/win32 diff --git a/libraries/networking/src/DomainAccountManager.cpp b/libraries/networking/src/DomainAccountManager.cpp index 928b581a5b..6475d50cbb 100644 --- a/libraries/networking/src/DomainAccountManager.cpp +++ b/libraries/networking/src/DomainAccountManager.cpp @@ -39,29 +39,54 @@ Setting::Handle domainAccessTokenExpiresIn {"private/domainAccessTokenExpir Setting::Handle domainAccessTokenType {"private/domainAccessTokenType", "" }; */ -DomainAccountManager::DomainAccountManager() : - _authURL(), - _username(), - _access_token(), - _refresh_token(), - _domain_name() -{ +DomainAccountManager::DomainAccountManager() { connect(this, &DomainAccountManager::loginComplete, this, &DomainAccountManager::sendInterfaceAccessTokenToServer); } -void DomainAccountManager::setAuthURL(const QUrl& authURL) { - if (_authURL != authURL) { - _authURL = authURL; +void DomainAccountManager::setDomainURL(const QUrl& domainURL) { - qCDebug(networking) << "AccountManager URL for authenticated requests has been changed to" << qPrintable(_authURL.toString()); - - _access_token = ""; - _refresh_token = ""; - - // ####### TODO: Restore and refresh OAuth2 tokens if have them for this domain. - - // ####### TODO: Handle "keep me logged in". + if (domainURL == _domainURL) { + return; } + + _domainURL = domainURL; + qCDebug(networking) << "DomainAccountManager domain URL has been changed to" << qPrintable(_domainURL.toString()); + + // Restore OAuth2 authorization if have it for this domain. + if (_domainURL == _previousDomainURL) { + _authURL = _previousAuthURL; + _clientID = _previousClientID; + _username = _previousUsername; + _access_token = _previousAccessToken; + _refresh_token = _previousRefreshToken; + _domain_name = _previousDomainName; + // ####### TODO: Refresh OAuth2 access token if necessary. + } else { + _authURL.clear(); + _clientID.clear(); + _username.clear(); + _access_token.clear(); + _refresh_token.clear(); + _domain_name.clear(); + } + +} + +void DomainAccountManager::setAuthURL(const QUrl& authURL) { + if (_authURL == authURL) { + return; + } + + _authURL = authURL; + qCDebug(networking) << "DomainAccountManager URL for authenticated requests has been changed to" + << qPrintable(_authURL.toString()); + + _access_token = ""; + _refresh_token = ""; +} + +bool DomainAccountManager::hasLogIn() { + return !_authURL.isEmpty(); } bool DomainAccountManager::isLoggedIn() { @@ -115,6 +140,18 @@ void DomainAccountManager::requestAccessTokenFinished() { QUrl rootURL = requestReply->url(); rootURL.setPath(""); setTokensFromJSON(rootObject, rootURL); + + // Remember domain login for the current Interface session. + _previousDomainURL = _domainURL; + _previousAuthURL = _authURL; + _previousClientID = _clientID; + _previousUsername = _username; + _previousAccessToken = _access_token; + _previousRefreshToken = _refresh_token; + _previousDomainName = _domain_name; + + // ####### TODO: Handle "keep me logged in". + emit loginComplete(); } else { // Failure. diff --git a/libraries/networking/src/DomainAccountManager.h b/libraries/networking/src/DomainAccountManager.h index 31226d6990..765217549d 100644 --- a/libraries/networking/src/DomainAccountManager.h +++ b/libraries/networking/src/DomainAccountManager.h @@ -23,6 +23,7 @@ class DomainAccountManager : public QObject, public Dependency { public: DomainAccountManager(); + void setDomainURL(const QUrl& domainURL); void setAuthURL(const QUrl& authURL); void setClientID(const QString& clientID) { _clientID = clientID; } @@ -31,6 +32,7 @@ public: QString getRefreshToken() { return _refresh_token; } QString getAuthedDomain() { return _domain_name; } + bool hasLogIn(); bool isLoggedIn(); Q_INVOKABLE bool checkAndSignalForAccessToken(); @@ -55,12 +57,23 @@ private: void setTokensFromJSON(const QJsonObject&, const QUrl& url); void sendInterfaceAccessTokenToServer(); + QUrl _domainURL; QUrl _authURL; QString _clientID; - QString _username; // ####### TODO: Store elsewhere? + + QString _username; QString _access_token; // ####... "" QString _refresh_token; // ####... "" QString _domain_name; // ####... "" + + // ####### TODO: Handle more than one domain. + QUrl _previousDomainURL; + QUrl _previousAuthURL; + QString _previousClientID; + QString _previousUsername; + QString _previousAccessToken; + QString _previousRefreshToken; + QString _previousDomainName; }; #endif // hifi_DomainAccountManager_h diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index c1a24748f4..ea4c0a00cb 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -241,6 +241,8 @@ void DomainHandler::setURLAndID(QUrl domainURL, QUuid domainID) { } } + DependencyManager::get()->setDomainURL(_domainURL); + emit domainURLChanged(_domainURL); if (_sockAddr.getPort() != domainPort) { @@ -584,18 +586,28 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointergenerateNewUserKeypair(); _connectionDenialsSinceKeypairRegen = 0; } + + // Server with domain login will prompt for domain login, not metaverse, so reset domain values if asked for metaverse. + auto domainAccountManager = DependencyManager::get(); + domainAccountManager->setAuthURL(QUrl()); + domainAccountManager->setClientID(QString()); + } else if (reasonSuggestsDomainLogin(reasonCode)) { qCWarning(networking) << "Make sure you are logged in to the domain."; - auto accountManager = DependencyManager::get(); + auto domainAccountManager = DependencyManager::get(); if (!extraInfo.isEmpty()) { auto extraInfoComponents = extraInfo.split("|"); - accountManager->setAuthURL(extraInfoComponents.value(0)); - accountManager->setClientID(extraInfoComponents.value(1)); + domainAccountManager->setAuthURL(extraInfoComponents.value(0)); + domainAccountManager->setClientID(extraInfoComponents.value(1)); + } else { + // Shouldn't occur, but just in case. + domainAccountManager->setAuthURL(QUrl()); + domainAccountManager->setClientID(QString()); } if (!_hasCheckedForDomainAccessToken) { - accountManager->checkAndSignalForAccessToken(); + domainAccountManager->checkAndSignalForAccessToken(); _hasCheckedForDomainAccessToken = true; } diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index e02a8dd56e..64663def22 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -476,33 +476,28 @@ void NodeList::sendDomainServerCheckIn() { packetStream << _ownerType.load() << publicSockAddr << localSockAddr << _nodeTypesOfInterest.toList(); packetStream << DependencyManager::get()->getPlaceName(); - // ####### TODO: Also send if need to send new domainLogin data? if (!domainIsConnected) { + + // Metaverse account. DataServerAccountInfo& accountInfo = accountManager->getAccountInfo(); packetStream << accountInfo.getUsername(); - // if this is a connect request, and we can present a username signature, send it along if (requiresUsernameSignature && accountManager->getAccountInfo().hasPrivateKey()) { const QByteArray& usernameSignature = accountManager->getAccountInfo().getUsernameSignature(connectionToken); packetStream << usernameSignature; } else { - // ####### TODO: Only append if are going to send domain username? packetStream << QString(""); // Placeholder in case have domain username. } - } else { - // ####### TODO: Only append if are going to send domainUsername? - packetStream << QString("") << QString(""); // Placeholders in case have domain username. - } - // Send domain domain login data from Interface to domain server. - if (_hasDomainAccountManager) { - auto domainAccountManager = DependencyManager::get(); - if (!domainAccountManager->getUsername().isEmpty()) { - packetStream << domainAccountManager->getUsername(); - if (!domainAccountManager->getAccessToken().isEmpty()) { + // Domain account. + if (_hasDomainAccountManager) { + auto domainAccountManager = DependencyManager::get(); + if (!domainAccountManager->getUsername().isEmpty() && !domainAccountManager->getAccessToken().isEmpty()) { + packetStream << domainAccountManager->getUsername(); packetStream << (domainAccountManager->getAccessToken() + ":" + domainAccountManager->getRefreshToken()); } } + } flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SendDSCheckIn); From bf60cf5b4c1780dc0d51409dd25d2a106b2d5f68 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 18 Aug 2020 16:33:47 +1200 Subject: [PATCH 2/7] Tidying --- interface/src/Application.cpp | 4 +-- .../networking/src/DomainAccountManager.cpp | 36 ++++++++++--------- .../networking/src/DomainAccountManager.h | 17 +++++---- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f97c48fbdf..c0eb8072cc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7086,7 +7086,7 @@ void Application::updateWindowTitle() const { bool isMetaverseLoggedIn = accountManager->isLoggedIn(); bool hasDomainLogIn = domainAccountManager->hasLogIn(); bool isDomainLoggedIn = domainAccountManager->isLoggedIn(); - QString authedDomain = domainAccountManager->getAuthedDomain(); + QString authedDomainName = domainAccountManager->getAuthedDomainName(); QString buildVersion = " - Vircadia - " + (BuildInfo::BUILD_TYPE == BuildInfo::BuildType::Stable ? QString("Version") : QString("Build")) @@ -7123,7 +7123,7 @@ void Application::updateWindowTitle() const { QString domainDetails; if (hasDomainLogIn) { - if (currentPlaceName == authedDomain && isDomainLoggedIn) { + if (currentPlaceName == authedDomainName && isDomainLoggedIn) { domainDetails = " (Domain: Logged in as " + domainUsername + ")"; } else { domainDetails = " (Domain: Not Logged In)"; diff --git a/libraries/networking/src/DomainAccountManager.cpp b/libraries/networking/src/DomainAccountManager.cpp index 6475d50cbb..04baacd560 100644 --- a/libraries/networking/src/DomainAccountManager.cpp +++ b/libraries/networking/src/DomainAccountManager.cpp @@ -57,17 +57,19 @@ void DomainAccountManager::setDomainURL(const QUrl& domainURL) { _authURL = _previousAuthURL; _clientID = _previousClientID; _username = _previousUsername; - _access_token = _previousAccessToken; - _refresh_token = _previousRefreshToken; - _domain_name = _previousDomainName; + _accessToken = _previousAccessToken; + _refreshToken = _previousRefreshToken; + _authedDomainName = _previousAuthedDomainName; + // ####### TODO: Refresh OAuth2 access token if necessary. + } else { _authURL.clear(); _clientID.clear(); _username.clear(); - _access_token.clear(); - _refresh_token.clear(); - _domain_name.clear(); + _accessToken.clear(); + _refreshToken.clear(); + _authedDomainName.clear(); } } @@ -81,8 +83,8 @@ void DomainAccountManager::setAuthURL(const QUrl& authURL) { qCDebug(networking) << "DomainAccountManager URL for authenticated requests has been changed to" << qPrintable(_authURL.toString()); - _access_token = ""; - _refresh_token = ""; + _accessToken = ""; + _refreshToken = ""; } bool DomainAccountManager::hasLogIn() { @@ -96,8 +98,8 @@ bool DomainAccountManager::isLoggedIn() { void DomainAccountManager::requestAccessToken(const QString& username, const QString& password) { _username = username; - _access_token = ""; - _refresh_token = ""; + _accessToken = ""; + _refreshToken = ""; QNetworkRequest request; @@ -136,7 +138,7 @@ void DomainAccountManager::requestAccessTokenFinished() { if (rootObject.contains("access_token")) { // Success. auto nodeList = DependencyManager::get(); - _domain_name = nodeList->getDomainHandler().getHostname(); + _authedDomainName = nodeList->getDomainHandler().getHostname(); QUrl rootURL = requestReply->url(); rootURL.setPath(""); setTokensFromJSON(rootObject, rootURL); @@ -146,9 +148,9 @@ void DomainAccountManager::requestAccessTokenFinished() { _previousAuthURL = _authURL; _previousClientID = _clientID; _previousUsername = _username; - _previousAccessToken = _access_token; - _previousRefreshToken = _refresh_token; - _previousDomainName = _domain_name; + _previousAccessToken = _accessToken; + _previousRefreshToken = _refreshToken; + _previousAuthedDomainName = _authedDomainName; // ####### TODO: Handle "keep me logged in". @@ -183,7 +185,7 @@ bool DomainAccountManager::accessTokenIsExpired() { bool DomainAccountManager::hasValidAccessToken() { // ###### TODO: wire this up to actually retrieve a token (based on session or storage) and confirm that it is in fact valid and relevant to the current domain. // QString currentDomainAccessToken = domainAccessToken.get(); - QString currentDomainAccessToken = _access_token; + QString currentDomainAccessToken = _accessToken; // if (currentDomainAccessToken.isEmpty() || accessTokenIsExpired()) { if (currentDomainAccessToken.isEmpty()) { @@ -205,8 +207,8 @@ bool DomainAccountManager::hasValidAccessToken() { } void DomainAccountManager::setTokensFromJSON(const QJsonObject& jsonObject, const QUrl& url) { - _access_token = jsonObject["access_token"].toString(); - _refresh_token = jsonObject["refresh_token"].toString(); + _accessToken = jsonObject["access_token"].toString(); + _refreshToken = jsonObject["refresh_token"].toString(); // ####### TODO: Enable and use these? // ####### TODO: Protect these per AccountManager? diff --git a/libraries/networking/src/DomainAccountManager.h b/libraries/networking/src/DomainAccountManager.h index 765217549d..b27c9ce0bf 100644 --- a/libraries/networking/src/DomainAccountManager.h +++ b/libraries/networking/src/DomainAccountManager.h @@ -27,10 +27,10 @@ public: void setAuthURL(const QUrl& authURL); void setClientID(const QString& clientID) { _clientID = clientID; } - QString getUsername() { return _username; } - QString getAccessToken() { return _access_token; } - QString getRefreshToken() { return _refresh_token; } - QString getAuthedDomain() { return _domain_name; } + const QString& getUsername() { return _username; } + const QString& getAccessToken() { return _accessToken; } + const QString& getRefreshToken() { return _refreshToken; } + const QString& getAuthedDomainName() { return _authedDomainName; } bool hasLogIn(); bool isLoggedIn(); @@ -39,7 +39,6 @@ public: public slots: void requestAccessToken(const QString& username, const QString& password); - void requestAccessTokenFinished(); signals: @@ -62,9 +61,9 @@ private: QString _clientID; QString _username; - QString _access_token; // ####... "" - QString _refresh_token; // ####... "" - QString _domain_name; // ####... "" + QString _accessToken; + QString _refreshToken; + QString _authedDomainName; // ####### TODO: Handle more than one domain. QUrl _previousDomainURL; @@ -73,7 +72,7 @@ private: QString _previousUsername; QString _previousAccessToken; QString _previousRefreshToken; - QString _previousDomainName; + QString _previousAuthedDomainName; }; #endif // hifi_DomainAccountManager_h From 662b2bfc5e9904bd028ea0822a2ff72fba96423f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 20 Aug 2020 12:32:03 +1200 Subject: [PATCH 3/7] Handle log in for multiple domains with domain login --- .../networking/src/DomainAccountManager.cpp | 93 ++++++------------- .../networking/src/DomainAccountManager.h | 40 ++++---- 2 files changed, 45 insertions(+), 88 deletions(-) diff --git a/libraries/networking/src/DomainAccountManager.cpp b/libraries/networking/src/DomainAccountManager.cpp index 04baacd560..e2eec7a13e 100644 --- a/libraries/networking/src/DomainAccountManager.cpp +++ b/libraries/networking/src/DomainAccountManager.cpp @@ -29,77 +29,56 @@ const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false; -// ####### TODO: Enable and use these? -// ####### TODO: Add storing domain URL and check against it when retrieving values? -// ####### TODO: Add storing _authURL and check against it when retrieving values? -/* -Setting::Handle domainAccessToken {"private/domainAccessToken", "" }; -Setting::Handle domainAccessRefreshToken {"private/domainAccessToken", "" }; -Setting::Handle domainAccessTokenExpiresIn {"private/domainAccessTokenExpiresIn", -1 }; -Setting::Handle domainAccessTokenType {"private/domainAccessTokenType", "" }; -*/ - DomainAccountManager::DomainAccountManager() { connect(this, &DomainAccountManager::loginComplete, this, &DomainAccountManager::sendInterfaceAccessTokenToServer); } void DomainAccountManager::setDomainURL(const QUrl& domainURL) { + qDebug() << "####### DomainAccountManager::setDomainURL()" << domainURL; - if (domainURL == _domainURL) { + if (domainURL == _currentAuth.domainURL) { + qDebug() << "####... Early return"; return; } - _domainURL = domainURL; - qCDebug(networking) << "DomainAccountManager domain URL has been changed to" << qPrintable(_domainURL.toString()); + qCDebug(networking) << "DomainAccountManager domain URL has been changed to" << qPrintable(domainURL.toString()); // Restore OAuth2 authorization if have it for this domain. - if (_domainURL == _previousDomainURL) { - _authURL = _previousAuthURL; - _clientID = _previousClientID; - _username = _previousUsername; - _accessToken = _previousAccessToken; - _refreshToken = _previousRefreshToken; - _authedDomainName = _previousAuthedDomainName; - - // ####### TODO: Refresh OAuth2 access token if necessary. - + if (_knownAuths.contains(domainURL)) { + _currentAuth = _knownAuths.value(domainURL); } else { - _authURL.clear(); - _clientID.clear(); - _username.clear(); - _accessToken.clear(); - _refreshToken.clear(); - _authedDomainName.clear(); + _currentAuth = DomainAccountDetails(); + _currentAuth.domainURL = domainURL; } } void DomainAccountManager::setAuthURL(const QUrl& authURL) { - if (_authURL == authURL) { + if (authURL == _currentAuth.authURL) { return; } - _authURL = authURL; + _currentAuth.authURL = authURL; qCDebug(networking) << "DomainAccountManager URL for authenticated requests has been changed to" - << qPrintable(_authURL.toString()); + << qPrintable(_currentAuth.authURL.toString()); - _accessToken = ""; - _refreshToken = ""; + _currentAuth.accessToken = ""; + _currentAuth.refreshToken = ""; } bool DomainAccountManager::hasLogIn() { - return !_authURL.isEmpty(); + return !_currentAuth.authURL.isEmpty(); } bool DomainAccountManager::isLoggedIn() { - return !_authURL.isEmpty() && hasValidAccessToken(); + return !_currentAuth.authURL.isEmpty() && hasValidAccessToken(); } void DomainAccountManager::requestAccessToken(const QString& username, const QString& password) { - _username = username; - _accessToken = ""; - _refreshToken = ""; + _currentAuth.username = username; + _currentAuth.accessToken = ""; + _currentAuth.refreshToken = ""; QNetworkRequest request; @@ -113,9 +92,9 @@ void DomainAccountManager::requestAccessToken(const QString& username, const QSt formData.append("grant_type=password&"); formData.append("username=" + QUrl::toPercentEncoding(username) + "&"); formData.append("password=" + QUrl::toPercentEncoding(password) + "&"); - formData.append("client_id=" + _clientID); + formData.append("client_id=" + _currentAuth.clientID); - request.setUrl(_authURL); + request.setUrl(_currentAuth.authURL); request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); @@ -138,19 +117,13 @@ void DomainAccountManager::requestAccessTokenFinished() { if (rootObject.contains("access_token")) { // Success. auto nodeList = DependencyManager::get(); - _authedDomainName = nodeList->getDomainHandler().getHostname(); + _currentAuth.authedDomainName = nodeList->getDomainHandler().getHostname(); QUrl rootURL = requestReply->url(); rootURL.setPath(""); setTokensFromJSON(rootObject, rootURL); // Remember domain login for the current Interface session. - _previousDomainURL = _domainURL; - _previousAuthURL = _authURL; - _previousClientID = _clientID; - _previousUsername = _username; - _previousAccessToken = _accessToken; - _previousRefreshToken = _refreshToken; - _previousAuthedDomainName = _authedDomainName; + _knownAuths.insert(_currentAuth.domainURL, _currentAuth); // ####### TODO: Handle "keep me logged in". @@ -176,22 +149,19 @@ void DomainAccountManager::sendInterfaceAccessTokenToServer() { bool DomainAccountManager::accessTokenIsExpired() { // ####### TODO: accessTokenIsExpired() return true; - /* - return domainAccessTokenExpiresIn.get() != -1 && domainAccessTokenExpiresIn.get() <= QDateTime::currentMSecsSinceEpoch(); - */ } bool DomainAccountManager::hasValidAccessToken() { // ###### TODO: wire this up to actually retrieve a token (based on session or storage) and confirm that it is in fact valid and relevant to the current domain. // QString currentDomainAccessToken = domainAccessToken.get(); - QString currentDomainAccessToken = _accessToken; + QString currentDomainAccessToken = _currentAuth.accessToken; // if (currentDomainAccessToken.isEmpty() || accessTokenIsExpired()) { if (currentDomainAccessToken.isEmpty()) { if (VERBOSE_HTTP_REQUEST_DEBUGGING) { qCDebug(networking) << "An access token is required for requests to" - << qPrintable(_authURL.toString()); + << qPrintable(_currentAuth.authURL.toString()); } return false; @@ -207,17 +177,8 @@ bool DomainAccountManager::hasValidAccessToken() { } void DomainAccountManager::setTokensFromJSON(const QJsonObject& jsonObject, const QUrl& url) { - _accessToken = jsonObject["access_token"].toString(); - _refreshToken = jsonObject["refresh_token"].toString(); - - // ####### TODO: Enable and use these? - // ####### TODO: Protect these per AccountManager? - // ######: TODO: clientID needed? - // qCDebug(networking) << "Storing a domain account with access-token for" << qPrintable(url.toString()); - // domainAccessToken.set(jsonObject["access_token"].toString()); - // domainAccessRefreshToken.set(jsonObject["refresh_token"].toString()); - // domainAccessTokenExpiresIn.set(QDateTime::currentMSecsSinceEpoch() + (jsonObject["expires_in"].toDouble() * 1000)); - // domainAccessTokenType.set(jsonObject["token_type"].toString()); + _currentAuth.accessToken = jsonObject["access_token"].toString(); + _currentAuth.refreshToken = jsonObject["refresh_token"].toString(); } bool DomainAccountManager::checkAndSignalForAccessToken() { @@ -232,7 +193,7 @@ bool DomainAccountManager::checkAndSignalForAccessToken() { // Emit a signal so somebody can call back to us and request an access token given a user name and password. // Dialog can be hidden immediately after showing if we've just teleported to the domain, unless the signal is delayed. - auto domain = _authURL.host(); + auto domain = _currentAuth.authURL.host(); QTimer::singleShot(500, this, [this, domain] { emit this->authRequired(domain); }); diff --git a/libraries/networking/src/DomainAccountManager.h b/libraries/networking/src/DomainAccountManager.h index b27c9ce0bf..08ebe59882 100644 --- a/libraries/networking/src/DomainAccountManager.h +++ b/libraries/networking/src/DomainAccountManager.h @@ -18,6 +18,17 @@ #include +struct DomainAccountDetails { + QUrl domainURL; + QUrl authURL; + QString clientID; + QString username; + QString accessToken; + QString refreshToken; + QString authedDomainName; +}; + + class DomainAccountManager : public QObject, public Dependency { Q_OBJECT public: @@ -25,12 +36,12 @@ public: void setDomainURL(const QUrl& domainURL); void setAuthURL(const QUrl& authURL); - void setClientID(const QString& clientID) { _clientID = clientID; } + void setClientID(const QString& clientID) { _currentAuth.clientID = clientID; } - const QString& getUsername() { return _username; } - const QString& getAccessToken() { return _accessToken; } - const QString& getRefreshToken() { return _refreshToken; } - const QString& getAuthedDomainName() { return _authedDomainName; } + const QString& getUsername() { return _currentAuth.username; } + const QString& getAccessToken() { return _currentAuth.accessToken; } + const QString& getRefreshToken() { return _currentAuth.refreshToken; } + const QString& getAuthedDomainName() { return _currentAuth.authedDomainName; } bool hasLogIn(); bool isLoggedIn(); @@ -56,23 +67,8 @@ private: void setTokensFromJSON(const QJsonObject&, const QUrl& url); void sendInterfaceAccessTokenToServer(); - QUrl _domainURL; - QUrl _authURL; - QString _clientID; - - QString _username; - QString _accessToken; - QString _refreshToken; - QString _authedDomainName; - - // ####### TODO: Handle more than one domain. - QUrl _previousDomainURL; - QUrl _previousAuthURL; - QString _previousClientID; - QString _previousUsername; - QString _previousAccessToken; - QString _previousRefreshToken; - QString _previousAuthedDomainName; + DomainAccountDetails _currentAuth; + QHash _knownAuths; // }; #endif // hifi_DomainAccountManager_h From 6926cd205a0ca7d83b7f185829b14a88bc0d0912 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 20 Aug 2020 17:12:57 +1200 Subject: [PATCH 4/7] Ignore residual "connection denied" packets from previous domain --- libraries/networking/src/DomainHandler.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index ea4c0a00cb..d85264e333 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -529,6 +529,12 @@ bool DomainHandler::reasonSuggestsDomainLogin(ConnectionRefusedReason reasonCode } void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer message) { + + // Ignore any residual packets from previous domain. + if (message->getSenderSockAddr().getAddress().toString() != _domainURL.host()) { + return; + } + // we're hearing from this domain-server, don't need to refresh API info _apiRefreshTimer.stop(); From 29e5bfdb940a8c7c24add6dc5c3f6f0412e1e2c5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 23 Aug 2020 14:34:10 +1200 Subject: [PATCH 5/7] Ignore residual "connection denied" packets from previous domain --- libraries/networking/src/DomainHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index d85264e333..6a47d74864 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -531,7 +531,7 @@ bool DomainHandler::reasonSuggestsDomainLogin(ConnectionRefusedReason reasonCode void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer message) { // Ignore any residual packets from previous domain. - if (message->getSenderSockAddr().getAddress().toString() != _domainURL.host()) { + if (!message->getSenderSockAddr().getAddress().isEqual(_sockAddr.getAddress())) { return; } From 67100b5a200c7eca8f52282db394da7383459c8b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 23 Aug 2020 15:56:27 +1200 Subject: [PATCH 6/7] Display domain login menu item only on domains that have domain login --- interface/src/Menu.cpp | 6 ++++++ libraries/networking/src/DomainAccountManager.cpp | 3 +++ libraries/networking/src/DomainAccountManager.h | 1 + 3 files changed, 10 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 64cdf98239..4ee3865600 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -43,6 +43,7 @@ #include "avatar/AvatarManager.h" #include "avatar/AvatarPackager.h" #include "AvatarBookmarks.h" +#include "DomainAccountManager.h" #include "MainWindow.h" #include "render/DrawStatus.h" #include "scripting/MenuScriptingInterface.h" @@ -73,6 +74,7 @@ const char* EXCLUSION_GROUP_KEY = "exclusionGroup"; Menu::Menu() { auto dialogsManager = DependencyManager::get(); auto accountManager = DependencyManager::get(); + auto domainAccountManager = DependencyManager::get(); // File/Application menu ---------------------------------- MenuWrapper* fileMenu = addMenu("File"); @@ -89,11 +91,15 @@ Menu::Menu() { } auto domainLogin = addActionToQMenuAndActionHash(fileMenu, "Domain: Log In"); + domainLogin->setVisible(false); connect(domainLogin, &QAction::triggered, [] { auto dialogsManager = DependencyManager::get(); dialogsManager->setDomainLoginState(); dialogsManager->showDomainLoginDialog(); }); + connect(domainAccountManager.data(), &DomainAccountManager::hasLogInChanged, [domainLogin](bool hasLogIn) { + domainLogin->setVisible(hasLogIn); + }); // File > Quit addActionToQMenuAndActionHash(fileMenu, MenuOption::Quit, Qt::CTRL | Qt::Key_Q, qApp, SLOT(quit()), QAction::QuitRole); diff --git a/libraries/networking/src/DomainAccountManager.cpp b/libraries/networking/src/DomainAccountManager.cpp index e2eec7a13e..d257994bea 100644 --- a/libraries/networking/src/DomainAccountManager.cpp +++ b/libraries/networking/src/DomainAccountManager.cpp @@ -51,6 +51,7 @@ void DomainAccountManager::setDomainURL(const QUrl& domainURL) { _currentAuth.domainURL = domainURL; } + emit hasLogInChanged(hasLogIn()); } void DomainAccountManager::setAuthURL(const QUrl& authURL) { @@ -64,6 +65,8 @@ void DomainAccountManager::setAuthURL(const QUrl& authURL) { _currentAuth.accessToken = ""; _currentAuth.refreshToken = ""; + + emit hasLogInChanged(hasLogIn()); } bool DomainAccountManager::hasLogIn() { diff --git a/libraries/networking/src/DomainAccountManager.h b/libraries/networking/src/DomainAccountManager.h index 08ebe59882..6a1da84aff 100644 --- a/libraries/networking/src/DomainAccountManager.h +++ b/libraries/networking/src/DomainAccountManager.h @@ -53,6 +53,7 @@ public slots: void requestAccessTokenFinished(); signals: + void hasLogInChanged(bool hasLogIn); void authRequired(const QString& domain); void loginComplete(); void loginFailed(); From eb8ae74245c17e375f92398fb5f58953b5bc9b02 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sun, 23 Aug 2020 16:06:16 +1200 Subject: [PATCH 7/7] Tidying --- libraries/networking/src/DomainAccountManager.cpp | 3 --- libraries/networking/src/DomainAccountManager.h | 2 -- 2 files changed, 5 deletions(-) diff --git a/libraries/networking/src/DomainAccountManager.cpp b/libraries/networking/src/DomainAccountManager.cpp index d257994bea..23c52143f6 100644 --- a/libraries/networking/src/DomainAccountManager.cpp +++ b/libraries/networking/src/DomainAccountManager.cpp @@ -34,10 +34,7 @@ DomainAccountManager::DomainAccountManager() { } void DomainAccountManager::setDomainURL(const QUrl& domainURL) { - qDebug() << "####### DomainAccountManager::setDomainURL()" << domainURL; - if (domainURL == _currentAuth.domainURL) { - qDebug() << "####... Early return"; return; } diff --git a/libraries/networking/src/DomainAccountManager.h b/libraries/networking/src/DomainAccountManager.h index 6a1da84aff..03c56d9215 100644 --- a/libraries/networking/src/DomainAccountManager.h +++ b/libraries/networking/src/DomainAccountManager.h @@ -60,8 +60,6 @@ signals: void logoutComplete(); void newTokens(); -private slots: - private: bool hasValidAccessToken(); bool accessTokenIsExpired();