mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-04-07 13:12:39 +02:00
Tidy networking code
This commit is contained in:
parent
dfbad4efc0
commit
43b6e77235
5 changed files with 54 additions and 49 deletions
|
@ -85,9 +85,9 @@
|
|||
"backup": false
|
||||
},
|
||||
{
|
||||
"name": "oauth2_url_base",
|
||||
"label": "Authentication URL Base",
|
||||
"help": "The URL base that the Interface will use to login via OAuth2.",
|
||||
"name": "oauth2_url_path",
|
||||
"label": "Authentication URL",
|
||||
"help": "The URL that the Interface will use to login via OAuth2.",
|
||||
"advanced": true
|
||||
},
|
||||
{
|
||||
|
|
|
@ -450,7 +450,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
|
|||
}
|
||||
|
||||
const QString AUTHENTICATION_ENAABLED = "authentication.enable_oauth2";
|
||||
const QString AUTHENTICATION_OAUTH2_URL_BASE = "authentication.oauth2_url_base";
|
||||
const QString AUTHENTICATION_OAUTH2_URL_PATH = "authentication.oauth2_url_path";
|
||||
const QString AUTHENTICATION_WORDPRESS_URL_BASE = "authentication.wordpress_url_base";
|
||||
const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity";
|
||||
const QString MAXIMUM_USER_CAPACITY_REDIRECT_LOCATION = "security.maximum_user_capacity_redirect_location";
|
||||
|
@ -548,10 +548,9 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
|||
if (!userPerms.can(NodePermissions::Permission::canConnectToDomain)) {
|
||||
if (domainHasLogin()) {
|
||||
QString domainAuthURL;
|
||||
auto domainAuthURLVariant = _server->_settingsManager.valueForKeyPath(AUTHENTICATION_OAUTH2_URL_BASE);
|
||||
auto domainAuthURLVariant = _server->_settingsManager.valueForKeyPath(AUTHENTICATION_OAUTH2_URL_PATH);
|
||||
if (domainAuthURLVariant.canConvert<QString>()) {
|
||||
domainAuthURL = domainAuthURLVariant.toString();
|
||||
qDebug() << "Domain authorization URL:" << domainAuthURL;
|
||||
}
|
||||
sendConnectionDeniedPacket("You lack the required permissions to connect to this domain.",
|
||||
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::NotAuthorizedDomain, domainAuthURL);
|
||||
|
@ -1220,7 +1219,7 @@ bool DomainGatekeeper::domainHasLogin() {
|
|||
// The domain may have its own users and groups in a WordPress site.
|
||||
// ####### TODO: Add checks of any further domain server settings used.
|
||||
return _server->_settingsManager.valueForKeyPath(AUTHENTICATION_ENAABLED).toBool()
|
||||
&& !_server->_settingsManager.valueForKeyPath(AUTHENTICATION_OAUTH2_URL_BASE).toString().isEmpty()
|
||||
&& !_server->_settingsManager.valueForKeyPath(AUTHENTICATION_OAUTH2_URL_PATH).toString().isEmpty()
|
||||
&& !_server->_settingsManager.valueForKeyPath(AUTHENTICATION_WORDPRESS_URL_BASE).toString().isEmpty();
|
||||
}
|
||||
|
||||
|
@ -1233,7 +1232,7 @@ void DomainGatekeeper::requestDomainUser(const QString& username, const QString&
|
|||
}
|
||||
|
||||
if (_inFlightDomainUserIdentityRequests.contains(username)) {
|
||||
// Domain identify request for this username is already flight.
|
||||
// Domain identify request for this username is already in progress.
|
||||
return;
|
||||
}
|
||||
_inFlightDomainUserIdentityRequests.insert(username, QPair<QString, QString>(accessToken, refreshToken));
|
||||
|
@ -1248,9 +1247,9 @@ void DomainGatekeeper::requestDomainUser(const QString& username, const QString&
|
|||
}
|
||||
|
||||
// Get data pertaining to "me", the user who generated the access token.
|
||||
// ####### TODO: Confirm API_ROUTE w.r.t. OAuth2 plugin's capabilities.
|
||||
QString API_ROUTE = "wp/v2/users/me?context=edit&_fields=id,username,roles";
|
||||
QUrl domainUserURL = apiBase + API_ROUTE;
|
||||
// ####### TODO: Confirm API route and data w.r.t. OAuth2 plugin's capabilities. [plugin]
|
||||
const QString WORDPRESS_USER_ROUTE = "wp/v2/users/me?context=edit&_fields=id,username,roles";
|
||||
QUrl domainUserURL = apiBase + WORDPRESS_USER_ROUTE;
|
||||
|
||||
// ####### TODO: Append a random key to check in response?
|
||||
|
||||
|
@ -1258,7 +1257,6 @@ void DomainGatekeeper::requestDomainUser(const QString& username, const QString&
|
|||
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
// ####### TODO: WordPress plugin's authorization requirements.
|
||||
request.setRawHeader(QByteArray("Authorization"), QString("Bearer " + accessToken).toUtf8());
|
||||
|
||||
QByteArray formData; // No data to send.
|
||||
|
@ -1278,12 +1276,13 @@ void DomainGatekeeper::requestDomainUserFinished() {
|
|||
|
||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
||||
const QJsonObject& rootObject = jsonResponse.object();
|
||||
|
||||
auto httpStatus = requestReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (200 <= httpStatus && httpStatus < 300) {
|
||||
// Success.
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
||||
const QJsonObject& rootObject = jsonResponse.object();
|
||||
// ####### Expected response:
|
||||
// ####### TODO: Verify Expected response. [plugin]
|
||||
/*
|
||||
{
|
||||
id: 2,
|
||||
|
@ -1292,22 +1291,24 @@ void DomainGatekeeper::requestDomainUserFinished() {
|
|||
}
|
||||
*/
|
||||
|
||||
// ####### TODO: Handle invalid / unexpected response.
|
||||
|
||||
QString username = rootObject["username"].toString().toLower();
|
||||
// ####### TODO: Handle invalid username or one that isn't in the _inFlight list.
|
||||
|
||||
if (_inFlightDomainUserIdentityRequests.contains(username)) {
|
||||
// Success! Verified user.
|
||||
_verifiedDomainUserIdentities.insert(username, _inFlightDomainUserIdentityRequests.value(username));
|
||||
_inFlightDomainUserIdentityRequests.remove(username);
|
||||
} else {
|
||||
// Unexpected response.
|
||||
// ####### TODO
|
||||
// Failure.
|
||||
qDebug() << "Unexpected username in response for user details -" << username;
|
||||
}
|
||||
|
||||
// ####### TODO: Handle roles if available. [plugin]
|
||||
|
||||
} else {
|
||||
// Failure.
|
||||
|
||||
// ####### TODO: Error fields to report. [plugin]
|
||||
qDebug() << "Error in response for user details -" << rootObject["error"].toString();
|
||||
|
||||
// ####### TODO: Is this the best way to handle _inFlightDomainUserIdentityRequests?
|
||||
// If there's a brief network glitch will it recover?
|
||||
// Perhaps clear on a timer? Cancel timer upon subsequent successful responses?
|
||||
|
|
|
@ -155,7 +155,7 @@ private:
|
|||
void requestDomainUser(const QString& username, const QString& accessToken, const QString& refreshToken);
|
||||
|
||||
typedef QHash<QString, QPair<QString, QString>> DomainUserIdentities; // <domainUserName, <access_token, refresh_token>>
|
||||
DomainUserIdentities _inFlightDomainUserIdentityRequests; // Keep track of domain user identity requests in progress.
|
||||
DomainUserIdentities _inFlightDomainUserIdentityRequests; // Domain user identity requests currently in progress.
|
||||
DomainUserIdentities _verifiedDomainUserIdentities; // Verified domain users.
|
||||
|
||||
void getDomainGroupMemberships(const QString& domainUserName);
|
||||
|
|
|
@ -60,7 +60,12 @@ void DomainAccountManager::setAuthURL(const QUrl& authURL) {
|
|||
|
||||
qCDebug(networking) << "AccountManager URL for authenticated requests has been changed to" << qPrintable(_authURL.toString());
|
||||
|
||||
// ####### TODO: See AccountManager::setAuthURL().
|
||||
_access_token = "";
|
||||
_refresh_token = "";
|
||||
|
||||
// ####### TODO: Restore and refresh OAuth2 tokens if have them for this domain.
|
||||
|
||||
// ####### TODO: Handle "keep me logged in".
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,9 +89,7 @@ void DomainAccountManager::requestAccessToken(const QString& username, const QSt
|
|||
formData.append("scope=" + DOMAIN_ACCOUNT_MANAGER_REQUESTED_SCOPE);
|
||||
// ####### TODO: Include state?
|
||||
|
||||
QUrl domainAuthURL = _authURL;
|
||||
domainAuthURL.setPath("/token"); // ####### TODO: miniOrange-mandated URL. ####### TODO: Should this be included in the server settings value?
|
||||
request.setUrl(domainAuthURL);
|
||||
request.setUrl(_authURL);
|
||||
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
|
||||
|
@ -96,40 +99,40 @@ void DomainAccountManager::requestAccessToken(const QString& username, const QSt
|
|||
}
|
||||
|
||||
void DomainAccountManager::requestAccessTokenFinished() {
|
||||
|
||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
||||
const QJsonObject& rootObject = jsonResponse.object();
|
||||
|
||||
// ####### TODO: Test HTTP response codes rather than object contains "error".
|
||||
// #### reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200
|
||||
if (!rootObject.contains("error")) {
|
||||
// ####### TODO: Process response scope?
|
||||
// ####### TODO: Process response state?
|
||||
auto httpStatus = requestReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||
if (200 <= httpStatus && httpStatus < 300) {
|
||||
|
||||
// ####### TODO: Check that token type == "Bearer"?
|
||||
// ####### TODO: Process response state?
|
||||
// ####### TODO: Process response scope?
|
||||
|
||||
if (!rootObject.contains("access_token")
|
||||
// ####### TODO: Does WordPRess plugin provide "expires_in"?
|
||||
// If so, handle here, or is it just the domain server that needs to use it?
|
||||
//|| !rootObject.contains("expires_in")
|
||||
|| !rootObject.contains("token_type")) {
|
||||
if (rootObject.contains("access_token")) {
|
||||
// Success.
|
||||
|
||||
qCDebug(networking) << "Received a response for password grant that is missing one or more expected values.";
|
||||
emit loginFailed();
|
||||
|
||||
} else {
|
||||
|
||||
// clear the path from the response URL so we have the right root URL for this access token
|
||||
QUrl rootURL = requestReply->url();
|
||||
rootURL.setPath("");
|
||||
|
||||
qCDebug(networking) << "Storing a domain account with access-token for" << qPrintable(rootURL.toString());
|
||||
setAccessTokenFromJSON(rootObject);
|
||||
setTokensFromJSON(rootObject, rootURL);
|
||||
|
||||
emit loginComplete(rootURL);
|
||||
emit loginComplete();
|
||||
|
||||
} else {
|
||||
// Failure.
|
||||
qCDebug(networking) << "Received a response for password grant that is missing one or more expected values.";
|
||||
emit loginFailed();
|
||||
}
|
||||
|
||||
} else {
|
||||
qCDebug(networking) << "Error in response for password grant -" << rootObject["error_description"].toString();
|
||||
// Failure.
|
||||
|
||||
// ####### TODO: Error object fields to report. [plugin]
|
||||
qCDebug(networking) << "Error in response for password grant -" << rootObject["error"].toString();
|
||||
emit loginFailed();
|
||||
}
|
||||
}
|
||||
|
@ -171,13 +174,14 @@ bool DomainAccountManager::hasValidAccessToken() {
|
|||
|
||||
}
|
||||
|
||||
void DomainAccountManager::setAccessTokenFromJSON(const QJsonObject& jsonObject) {
|
||||
void DomainAccountManager::setTokensFromJSON(const QJsonObject& jsonObject, const QUrl& url) {
|
||||
_access_token = jsonObject["access_token"].toString();
|
||||
_refresh_token = jsonObject["refresh_token"].toString();
|
||||
|
||||
// ####### TODO: Enable and use these.
|
||||
// ####### TODO: Protect these per AccountManager?
|
||||
/*
|
||||
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));
|
||||
|
|
|
@ -37,7 +37,7 @@ public slots:
|
|||
void requestAccessTokenFinished();
|
||||
signals:
|
||||
void authRequired();
|
||||
void loginComplete(const QUrl& authURL);
|
||||
void loginComplete();
|
||||
void loginFailed();
|
||||
void logoutComplete();
|
||||
void newTokens();
|
||||
|
@ -47,7 +47,7 @@ private slots:
|
|||
private:
|
||||
bool hasValidAccessToken();
|
||||
bool accessTokenIsExpired();
|
||||
void setAccessTokenFromJSON(const QJsonObject&);
|
||||
void setTokensFromJSON(const QJsonObject&, const QUrl& url);
|
||||
void sendInterfaceAccessTokenToServer();
|
||||
|
||||
QUrl _authURL;
|
||||
|
|
Loading…
Reference in a new issue