diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index f85766105e..968d56ca84 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -296,7 +296,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect QString verifiedUsername; if (!username.isEmpty() && verifyUserSignature(username, usernameSignature, nodeConnection.senderSockAddr)) { - // they are sent us a username and the signature verifies it + // they sent us a username and the signature verifies it userPerms.setUserName(username); verifiedUsername = username; getGroupMemberships(username); @@ -699,6 +699,7 @@ void DomainGatekeeper::getGroupMemberships(const QString& username) { // loop through the groups mentioned on the settings page and ask if this user is in each. The replies // will be received asynchronously and permissions will be updated as the answers come in. QList groupIDs = _server->_settingsManager.getGroupIDs() + _server->_settingsManager.getBlacklistGroupIDs(); + // TODO -- use alternative that allows checking entire group list in one call foreach (QUuid groupID, groupIDs) { if (groupID.isNull()) { continue; @@ -789,3 +790,23 @@ void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requ void DomainGatekeeper::getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply) { qDebug() << "getDomainOwnerFriendsList api call failed:" << requestReply.error(); } + +void DomainGatekeeper::refreshGroupsCache() { + // if agents are connected to this domain, refresh our cached information about groups and memberships in such. + + getDomainOwnerFriendsList(); + + int agentCount = 0; + auto nodeList = DependencyManager::get(); + nodeList->eachNode([&](const SharedNodePointer& node) { + if (!node->getPermissions().isAssignment) { + // this node is an agent + getGroupMemberships(node->getPermissions().getUserName()); + agentCount++; + } + }); + + if (agentCount > 0) { + _server->_settingsManager.apiRefreshGroupInformation(); + } +} diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index 7d9cfe91e3..a5ff5d90a7 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -59,6 +59,8 @@ public slots: void getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply); void getDomainOwnerFriendsListErrorCallback(QNetworkReply& requestReply); + void refreshGroupsCache(); + signals: void killNode(SharedNodePointer node); void connectedNode(SharedNodePointer node); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index b7c61b600a..e1ee4906a2 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "DomainServerNodeData.h" #include "NodeConnectionData.h" @@ -108,6 +109,8 @@ DomainServer::DomainServer(int argc, char* argv[]) : connect(&_settingsManager, &DomainServerSettingsManager::updateNodePermissions, &_gatekeeper, &DomainGatekeeper::updateNodePermissions); + setupGroupCacheRefresh(); + // if we were given a certificate/private key or oauth credentials they must succeed if (!(optionallyReadX509KeyAndCertificate() && optionallySetupOAuth())) { return; @@ -2328,3 +2331,14 @@ void DomainServer::randomizeICEServerAddress(bool shouldTriggerHostLookup) { // immediately send an update to the metaverse API when our ice-server changes sendICEServerAddressToMetaverseAPI(); } + +void DomainServer::setupGroupCacheRefresh() { + const int REFRESH_GROUPS_INTERVAL_MSECS = 15 * MSECS_PER_SECOND; + + if (!_metaverseGroupCacheTimer) { + // setup a timer to refresh this server's cached group details + _metaverseGroupCacheTimer = new QTimer { this }; + connect(_metaverseGroupCacheTimer, &QTimer::timeout, &_gatekeeper, &DomainGatekeeper::refreshGroupsCache); + _metaverseGroupCacheTimer->start(REFRESH_GROUPS_INTERVAL_MSECS); + } +} diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 138cb9ca2d..4004333789 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -41,7 +41,7 @@ class DomainServer : public QCoreApplication, public HTTPSRequestHandler { public: DomainServer(int argc, char* argv[]); ~DomainServer(); - + static int const EXIT_CODE_REBOOT; bool handleHTTPRequest(HTTPConnection* connection, const QUrl& url, bool skipSubHandler = false); @@ -64,7 +64,7 @@ public slots: void processNodeDisconnectRequestPacket(QSharedPointer message); void processICEServerHeartbeatDenialPacket(QSharedPointer message); void processICEServerHeartbeatACK(QSharedPointer message); - + private slots: void aboutToQuit(); @@ -74,7 +74,7 @@ private slots: void performIPAddressUpdate(const HifiSockAddr& newPublicSockAddr); void sendHeartbeatToMetaverse() { sendHeartbeatToMetaverse(QString()); } void sendHeartbeatToIceServer(); - + void handleConnectedNode(SharedNodePointer newNode); void handleTempDomainSuccess(QNetworkReply& requestReply); @@ -96,7 +96,7 @@ signals: void iceServerChanged(); void userConnected(); void userDisconnected(); - + private: const QUuid& getID(); @@ -136,7 +136,7 @@ private: SharedAssignmentPointer deployableAssignmentForRequest(const Assignment& requestAssignment); void refreshStaticAssignmentAndAddToQueue(SharedAssignmentPointer& assignment); void addStaticAssignmentsToQueue(); - + QUrl oauthRedirectURL(); QUrl oauthAuthorizationURL(const QUuid& stateUUID = QUuid::createUuid()); @@ -151,7 +151,9 @@ private: QJsonObject jsonForSocket(const HifiSockAddr& socket); QJsonObject jsonObjectForNode(const SharedNodePointer& node); - + + void setupGroupCacheRefresh(); + DomainGatekeeper _gatekeeper; HTTPManager _httpManager; @@ -184,6 +186,7 @@ private: DomainMetadata* _metadata { nullptr }; QTimer* _iceHeartbeatTimer { nullptr }; QTimer* _metaverseHeartbeatTimer { nullptr }; + QTimer* _metaverseGroupCacheTimer { nullptr }; QList _iceServerAddresses; QSet _failedIceServerAddresses; diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 3f44b9a293..b9715240ca 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -515,10 +515,6 @@ void DomainServerSettingsManager::unpackPermissions() { packPermissions(); } - // attempt to retrieve any missing group-IDs, etc - apiRefreshGroupInformation(); - - #ifdef WANT_DEBUG qDebug() << "--------------- permissions ---------------------"; QList> permissionsSets; @@ -1136,8 +1132,6 @@ bool DomainServerSettingsManager::setGroupID(const QString& groupName, const QUu } void DomainServerSettingsManager::apiRefreshGroupInformation() { - const int STALE_DATA_AGE = 600; // seconds - if (!DependencyManager::get()->hasAuthEndpoint()) { // can't yet. return; @@ -1152,11 +1146,8 @@ void DomainServerSettingsManager::apiRefreshGroupInformation() { apiGetGroupID(groupName); } - quint64 now = usecTimestampNow(); foreach (QUuid groupID, _groupNames.keys()) { - if (now - _groupRanksLastFetched[groupID] > STALE_DATA_AGE * USECS_PER_SECOND) { - apiGetGroupRanks(groupID); - } + apiGetGroupRanks(groupID); } } diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 52e4b02e26..f59d76bd1e 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -80,6 +80,10 @@ public: void recordGroupMembership(const QString& name, const QUuid groupID, int rank); int isGroupMember(const QString& name, const QUuid& groupID); // returns rank or -1 if not a member + // calls http api to refresh group information + void apiRefreshGroupInformation(); + + signals: void updateNodePermissions(); @@ -113,7 +117,6 @@ private: void validateDescriptorsMap(); // these cause calls to metaverse's group api - void apiRefreshGroupInformation(); void apiGetGroupID(const QString& groupName); void apiGetGroupRanks(const QUuid& groupID);