From cc1b6f0cb2b70158114edbab2721137509c82c69 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 24 Jun 2016 11:42:56 -0700 Subject: [PATCH] add a permissions-grid row for friends-of-domain-owner --- domain-server/src/DomainGatekeeper.cpp | 44 ++++++++++++++++++- domain-server/src/DomainGatekeeper.h | 5 +++ .../src/DomainServerSettingsManager.cpp | 9 ++++ libraries/networking/src/AccountManager.cpp | 42 ++++++++++-------- libraries/networking/src/AccountManager.h | 4 +- libraries/networking/src/NodePermissions.cpp | 4 +- libraries/networking/src/NodePermissions.h | 1 + 7 files changed, 87 insertions(+), 22 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index a8b146e12b..90d0d0adca 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -142,6 +142,12 @@ NodePermissions DomainGatekeeper::applyPermissionsForUser(bool isLocalUser, userPerms |= _server->_settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn); qDebug() << "user-permissions: user is logged-into metavers, so:" << userPerms; + // if this user is a friend of the domain-owner, give them friend's permissions + if (_domainOwnerFriends.contains(verifiedUsername)) { + userPerms |= _server->_settingsManager.getStandardPermissionsForName(NodePermissions::standardNameFriends); + qDebug() << "user-permissions: user is friends with domain-owner, so:" << userPerms; + } + // if this user is a known member of a group, give them the implied permissions foreach (QUuid groupID, _server->_settingsManager.getKnownGroupIDs()) { if (groupID.isNull()) { @@ -275,6 +281,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect // ask for their public key right now to make sure we have it requestUserPublicKey(username); getGroupMemberships(username); // optimistically get started on group memberships + getDomainOwnerFriendsList(); return SharedNodePointer(); } @@ -284,6 +291,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect userPerms.setUserName(username); verifiedUsername = username; getGroupMemberships(username); + getDomainOwnerFriendsList(); } else if (!username.isEmpty()) { // they sent us a username, but it didn't check out requestUserPublicKey(username); @@ -717,5 +725,39 @@ void DomainGatekeeper::getIsGroupMemberJSONCallback(QNetworkReply& requestReply) } void DomainGatekeeper::getIsGroupMemberErrorCallback(QNetworkReply& requestReply) { - qDebug() << "getGroupID api call failed:" << requestReply.error(); + qDebug() << "getIsGroupMember api call failed:" << requestReply.error(); +} + +void DomainGatekeeper::getDomainOwnerFriendsList() { + JSONCallbackParameters callbackParams; + callbackParams.jsonCallbackReceiver = this; + callbackParams.jsonCallbackMethod = "getDomainOwnerFriendsListJSONCallback"; + callbackParams.errorCallbackReceiver = this; + callbackParams.errorCallbackMethod = "getDomainOwnerFriendsListErrorCallback"; + + const QString GET_FRIENDS_LIST_PATH = "api/v1/users"; + QUrlQuery query; + query.addQueryItem("filter", "friends"); + + DependencyManager::get()->sendRequest(GET_FRIENDS_LIST_PATH, AccountManagerAuth::Required, + QNetworkAccessManager::GetOperation, callbackParams, QByteArray(), + NULL, QVariantMap(), query); +} + +void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply) { + QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); + if (jsonObject["status"].toString() == "success") { + _domainOwnerFriends.clear(); + QJsonArray friends = jsonObject["data"].toObject()["users"].toArray(); + for (int i = 0; i < friends.size(); i++) { + QString friendUserName = friends.at(i).toObject()["username"].toString(); + _domainOwnerFriends[friendUserName] = true; + } + } else { + qDebug() << "getDomainOwnerFriendsList api call returned:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); + } +} + +void DomainGatekeeper::getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply) { + qDebug() << "getDomainOwnerFriendsList api call failed:" << requestReply.error(); } diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index bc8a569591..7d9cfe91e3 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -56,6 +56,9 @@ public slots: void getIsGroupMemberJSONCallback(QNetworkReply& requestReply); void getIsGroupMemberErrorCallback(QNetworkReply& requestReply); + void getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply); + void getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply); + signals: void killNode(SharedNodePointer node); void connectedNode(SharedNodePointer node); @@ -98,10 +101,12 @@ private: QHash _connectionTokenHash; QHash _userPublicKeys; QHash _inFlightPublicKeyRequests; // keep track of which we've already asked for + QHash _domainOwnerFriends; // keep track of friends of the domain owner NodePermissions applyPermissionsForUser(bool isLocalUser, NodePermissions userPerms, QString verifiedUsername); void getGroupMemberships(const QString& username); void getIsGroupMember(const QString& username, const QUuid groupID); + void getDomainOwnerFriendsList(); }; diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index d7fcf324e8..78a557ba5b 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -218,6 +218,8 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList new NodePermissions(NodePermissions::standardNameAnonymous)); _standardAgentPermissions[NodePermissions::standardNameLoggedIn].reset( new NodePermissions(NodePermissions::standardNameLoggedIn)); + _standardAgentPermissions[NodePermissions::standardNameFriends].reset( + new NodePermissions(NodePermissions::standardNameFriends)); if (isRestrictedAccess) { // only users in allow-users list can connect @@ -340,6 +342,7 @@ void DomainServerSettingsManager::unpackPermissions() { bool foundLocalhost = false; bool foundAnonymous = false; bool foundLoggedIn = false; + bool foundFriends = false; bool needPack = false; QVariant* standardPermissions = valueForKeyPath(_configMap.getUserConfig(), AGENT_STANDARD_PERMISSIONS_KEYPATH); @@ -368,6 +371,7 @@ void DomainServerSettingsManager::unpackPermissions() { foundLocalhost |= (id == NodePermissions::standardNameLocalhost); foundAnonymous |= (id == NodePermissions::standardNameAnonymous); foundLoggedIn |= (id == NodePermissions::standardNameLoggedIn); + foundFriends |= (id == NodePermissions::standardNameFriends); if (_standardAgentPermissions.contains(id)) { qDebug() << "duplicate name in standard permissions table: " << id; _standardAgentPermissions[id] |= perms; @@ -424,6 +428,11 @@ void DomainServerSettingsManager::unpackPermissions() { _standardAgentPermissions[perms->getID()] = perms; needPack = true; } + if (!foundFriends) { + NodePermissionsPointer perms { new NodePermissions(NodePermissions::standardNameFriends) }; + _standardAgentPermissions[perms->getID()] = perms; + needPack = true; + } if (needPack) { packPermissions(); diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index b6c5e691a6..d7976e2036 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -200,8 +200,9 @@ void AccountManager::sendRequest(const QString& path, const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart, - const QVariantMap& propertyMap) { - + const QVariantMap& propertyMap, + QUrlQuery query) { + if (thread() != QThread::currentThread()) { QMetaObject::invokeMethod(this, "sendRequest", Q_ARG(const QString&, path), @@ -213,9 +214,9 @@ void AccountManager::sendRequest(const QString& path, Q_ARG(QVariantMap, propertyMap)); return; } - + QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance(); - + QNetworkRequest networkRequest; networkRequest.setHeader(QNetworkRequest::UserAgentHeader, _userAgentGetter()); @@ -228,13 +229,17 @@ void AccountManager::sendRequest(const QString& path, } QUrl requestURL = _authURL; - + if (path.startsWith("/")) { requestURL.setPath(path); } else { requestURL.setPath("/" + path); } - + + if (!query.isEmpty()) { + requestURL.setQuery(query); + } + if (authType != AccountManagerAuth::None ) { if (hasValidAccessToken()) { networkRequest.setRawHeader(ACCESS_TOKEN_AUTHORIZATION_HEADER, @@ -245,22 +250,21 @@ void AccountManager::sendRequest(const QString& path, << path << "that requires authentication"; return; } - } } - + networkRequest.setUrl(requestURL); - + if (VERBOSE_HTTP_REQUEST_DEBUGGING) { qCDebug(networking) << "Making a request to" << qPrintable(requestURL.toString()); - + if (!dataByteArray.isEmpty()) { qCDebug(networking) << "The POST/PUT body -" << QString(dataByteArray); } } - + QNetworkReply* networkReply = NULL; - + switch (operation) { case QNetworkAccessManager::GetOperation: networkReply = networkAccessManager.get(networkRequest); @@ -273,7 +277,7 @@ void AccountManager::sendRequest(const QString& path, } else { networkReply = networkAccessManager.put(networkRequest, dataMultiPart); } - + // make sure dataMultiPart is destroyed when the reply is connect(networkReply, &QNetworkReply::destroyed, dataMultiPart, &QHttpMultiPart::deleteLater); } else { @@ -284,7 +288,7 @@ void AccountManager::sendRequest(const QString& path, networkReply = networkAccessManager.put(networkRequest, dataByteArray); } } - + break; case QNetworkAccessManager::DeleteOperation: networkReply = networkAccessManager.sendCustomRequest(networkRequest, "DELETE"); @@ -293,7 +297,7 @@ void AccountManager::sendRequest(const QString& path, // other methods not yet handled break; } - + if (networkReply) { if (!propertyMap.isEmpty()) { // we have properties to set on the reply so the user can check them after @@ -301,18 +305,18 @@ void AccountManager::sendRequest(const QString& path, networkReply->setProperty(qPrintable(propertyKey), propertyMap.value(propertyKey)); } } - - + + if (!callbackParams.isEmpty()) { // if we have information for a callback, insert the callbackParams into our local map _pendingCallbackMap.insert(networkReply, callbackParams); - + if (callbackParams.updateReciever && !callbackParams.updateSlot.isEmpty()) { callbackParams.updateReciever->connect(networkReply, SIGNAL(uploadProgress(qint64, qint64)), callbackParams.updateSlot.toStdString().c_str()); } } - + // if we ended up firing of a request, hook up to it now connect(networkReply, SIGNAL(finished()), SLOT(processReply())); } diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index d30a05fb2c..ef66164b12 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "NetworkAccessManager.h" @@ -67,7 +68,8 @@ public: const JSONCallbackParameters& callbackParams = JSONCallbackParameters(), const QByteArray& dataByteArray = QByteArray(), QHttpMultiPart* dataMultiPart = NULL, - const QVariantMap& propertyMap = QVariantMap()); + const QVariantMap& propertyMap = QVariantMap(), + QUrlQuery query = QUrlQuery()); void setIsAgent(bool isAgent) { _isAgent = isAgent; } diff --git a/libraries/networking/src/NodePermissions.cpp b/libraries/networking/src/NodePermissions.cpp index 9f77dd9d21..f0c25a764a 100644 --- a/libraries/networking/src/NodePermissions.cpp +++ b/libraries/networking/src/NodePermissions.cpp @@ -16,11 +16,13 @@ QString NodePermissions::standardNameLocalhost = QString("localhost"); QString NodePermissions::standardNameLoggedIn = QString("logged-in"); QString NodePermissions::standardNameAnonymous = QString("anonymous"); +QString NodePermissions::standardNameFriends = QString("friends"); QStringList NodePermissions::standardNames = QList() << NodePermissions::standardNameLocalhost << NodePermissions::standardNameLoggedIn - << NodePermissions::standardNameAnonymous; + << NodePermissions::standardNameAnonymous + << NodePermissions::standardNameFriends; NodePermissions::NodePermissions(QMap perms) { _id = perms["permissions_id"].toString(); diff --git a/libraries/networking/src/NodePermissions.h b/libraries/networking/src/NodePermissions.h index c2022bd7ff..7971d4e362 100644 --- a/libraries/networking/src/NodePermissions.h +++ b/libraries/networking/src/NodePermissions.h @@ -43,6 +43,7 @@ public: static QString standardNameLocalhost; static QString standardNameLoggedIn; static QString standardNameAnonymous; + static QString standardNameFriends; static QStringList standardNames; // the initializations here should match the defaults in describe-settings.json