From 40f2d364877c7566cf04f4530ae8f137362cf746 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 20 Jun 2016 11:38:38 -0700 Subject: [PATCH 1/3] fix hosts/tags in domain-server settings --- domain-server/resources/describe-settings.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index bad24dd3a1..dce6c3449f 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -116,6 +116,7 @@ "name": "hosts", "label": "Hosts", "type": "table", + "can_add_new_rows": true, "help": "Usernames of hosts who can reliably show your domain to new visitors.", "numbered": false, "columns": [ @@ -130,6 +131,7 @@ "name": "tags", "label": "Tags", "type": "table", + "can_add_new_rows": true, "help": "Common categories under which your domain falls.", "numbered": false, "columns": [ From 25b21dacda246e7ff691bdf4db9cf67d8b57cbd0 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 20 Jun 2016 12:57:32 -0700 Subject: [PATCH 2/3] clean domain metadata and update acl --- domain-server/src/DomainMetadata.cpp | 156 +++++++++++++++++++-------- domain-server/src/DomainMetadata.h | 60 ++++++----- domain-server/src/DomainServer.cpp | 30 ++---- domain-server/src/DomainServer.h | 8 +- 4 files changed, 154 insertions(+), 100 deletions(-) diff --git a/domain-server/src/DomainMetadata.cpp b/domain-server/src/DomainMetadata.cpp index 26d2bb87ce..d3eb7a97b0 100644 --- a/domain-server/src/DomainMetadata.cpp +++ b/domain-server/src/DomainMetadata.cpp @@ -10,16 +10,18 @@ #include "DomainMetadata.h" -#include +#include #include +#include #include +#include "DomainServer.h" #include "DomainServerNodeData.h" const QString DomainMetadata::USERS = "users"; -const QString DomainMetadata::USERS_NUM_TOTAL = "num_users"; -const QString DomainMetadata::USERS_NUM_ANON = "num_anon_users"; -const QString DomainMetadata::USERS_HOSTNAMES = "user_hostnames"; +const QString DomainMetadata::Users::NUM_TOTAL = "num_users"; +const QString DomainMetadata::Users::NUM_ANON = "num_anon_users"; +const QString DomainMetadata::Users::HOSTNAMES = "user_hostnames"; // users metadata will appear as (JSON): // { "num_users": Number, // "num_anon_users": Number, @@ -27,25 +29,20 @@ const QString DomainMetadata::USERS_HOSTNAMES = "user_hostnames"; // } const QString DomainMetadata::DESCRIPTORS = "descriptors"; -const QString DomainMetadata::DESCRIPTORS_DESCRIPTION = "description"; -const QString DomainMetadata::DESCRIPTORS_CAPACITY = "capacity"; // parsed from security -const QString DomainMetadata::DESCRIPTORS_RESTRICTION = "restriction"; // parsed from ACL -const QString DomainMetadata::DESCRIPTORS_MATURITY = "maturity"; -const QString DomainMetadata::DESCRIPTORS_HOSTS = "hosts"; -const QString DomainMetadata::DESCRIPTORS_TAGS = "tags"; +const QString DomainMetadata::Descriptors::DESCRIPTION = "description"; +const QString DomainMetadata::Descriptors::CAPACITY = "capacity"; // parsed from security +const QString DomainMetadata::Descriptors::HOURS = "hours"; +const QString DomainMetadata::Descriptors::RESTRICTION = "restriction"; // parsed from ACL +const QString DomainMetadata::Descriptors::MATURITY = "maturity"; +const QString DomainMetadata::Descriptors::HOSTS = "hosts"; +const QString DomainMetadata::Descriptors::TAGS = "tags"; // descriptors metadata will appear as (JSON): -// { "capacity": Number, -// TODO: "hours": String, // UTF-8 representation of the week, split into 15" segments +// { "description": String, // capped description +// "capacity": Number, +// "hours": String, // UTF-8 representation of the week, split into 15" segments // "restriction": String, // enum of either open, hifi, or acl // "maturity": String, // enum corresponding to ESRB ratings // "hosts": [ String ], // capped list of usernames -// "description": String, // capped description -// TODO: "img": { -// "src": String, -// "type": String, -// "size": Number, -// "updated_at": Number, -// }, // "tags": [ String ], // capped list of tags // } @@ -54,36 +51,103 @@ const QString DomainMetadata::DESCRIPTORS_TAGS = "tags"; // // it is meant to be sent to and consumed by an external API -DomainMetadata::DomainMetadata() { +DomainMetadata::DomainMetadata(QObject* domainServer) : QObject(domainServer) { _metadata[USERS] = {}; _metadata[DESCRIPTORS] = {}; + + assert(dynamic_cast(domainServer)); + DomainServer* server = static_cast(domainServer); + + // update the metadata when a user (dis)connects + connect(server, &DomainServer::userConnected, this, &DomainMetadata::usersChanged); + connect(server, &DomainServer::userDisconnected, this, &DomainMetadata::usersChanged); + + // update the metadata when security changes + connect(&server->_settingsManager, &DomainServerSettingsManager::updateNodePermissions, + this, static_cast(&DomainMetadata::securityChanged)); + + // initialize the descriptors + descriptorsChanged(); } -void DomainMetadata::setDescriptors(QVariantMap& settings) { +QJsonObject DomainMetadata::get() { + maybeUpdateUsers(); + return QJsonObject::fromVariantMap(_metadata); +} + +QJsonObject DomainMetadata::get(const QString& group) { + maybeUpdateUsers(); + return QJsonObject::fromVariantMap(_metadata[group].toMap()); +} + +void DomainMetadata::descriptorsChanged() { const QString CAPACITY = "security.maximum_user_capacity"; + auto settings = static_cast(parent())->_settingsManager.getSettingsMap(); const QVariant* capacityVariant = valueForKeyPath(settings, CAPACITY); unsigned int capacity = capacityVariant ? capacityVariant->toUInt() : 0; - // TODO: Keep parity with ACL development. - const QString RESTRICTION = "security.restricted_access"; - const QString RESTRICTION_OPEN = "open"; - // const QString RESTRICTION_HIFI = "hifi"; - const QString RESTRICTION_ACL = "acl"; - const QVariant* isRestrictedVariant = valueForKeyPath(settings, RESTRICTION); - bool isRestricted = isRestrictedVariant ? isRestrictedVariant->toBool() : false; - QString restriction = isRestricted ? RESTRICTION_ACL : RESTRICTION_OPEN; + auto descriptors = settings[DESCRIPTORS].toMap(); + descriptors[Descriptors::CAPACITY] = capacity; + _metadata[DESCRIPTORS] = descriptors; - QVariantMap descriptors = settings[DESCRIPTORS].toMap(); - descriptors[DESCRIPTORS_CAPACITY] = capacity; - descriptors[DESCRIPTORS_RESTRICTION] = restriction; + // update overwritten fields + securityChanged(false); + +#if DEV_BUILD || PR_BUILD + qDebug() << "Domain metadata descriptors set:" << _metadata[DESCRIPTORS]; +#endif + + sendDescriptors(); +} + +void DomainMetadata::securityChanged(bool send) { + const QString RESTRICTION_OPEN = "open"; + const QString RESTRICTION_ANON = "anon"; + const QString RESTRICTION_HIFI = "hifi"; + const QString RESTRICTION_ACL = "acl"; + + QString restriction; + + const auto& settingsManager = static_cast(parent())->_settingsManager; + bool hasAnonymousAccess = + settingsManager.getStandardPermissionsForName(NodePermissions::standardNameAnonymous).canConnectToDomain; + bool hasHifiAccess = + settingsManager.getStandardPermissionsForName(NodePermissions::standardNameLoggedIn).canConnectToDomain; + if (hasAnonymousAccess) { + restriction = hasHifiAccess ? RESTRICTION_OPEN : RESTRICTION_ANON; + } else if (hasHifiAccess) { + restriction = RESTRICTION_HIFI; + } else { + restriction = RESTRICTION_ACL; + } + + auto descriptors = _metadata[DESCRIPTORS].toMap(); + descriptors[Descriptors::RESTRICTION] = restriction; _metadata[DESCRIPTORS] = descriptors; #if DEV_BUILD || PR_BUILD - qDebug() << "Domain metadata descriptors set:" << descriptors; + qDebug() << "Domain metadata restriction set:" << restriction; +#endif + + if (send) { + sendDescriptors(); + } +} + +void DomainMetadata::usersChanged() { + ++_tic; + +#if DEV_BUILD || PR_BUILD + qDebug() << "Domain metadata users change detected"; #endif } -void DomainMetadata::updateUsers() { +void DomainMetadata::maybeUpdateUsers() { + if (_lastTic == _tic) { + return; + } + _lastTic = _tic; + static const QString DEFAULT_HOSTNAME = "*"; auto nodeList = DependencyManager::get(); @@ -113,20 +177,26 @@ void DomainMetadata::updateUsers() { }); QVariantMap users = { - { USERS_NUM_TOTAL, numConnected }, - { USERS_NUM_ANON, numConnectedAnonymously }, - { USERS_HOSTNAMES, userHostnames }}; + { Users::NUM_TOTAL, numConnected }, + { Users::NUM_ANON, numConnectedAnonymously }, + { Users::HOSTNAMES, userHostnames }}; _metadata[USERS] = users; + ++_tic; #if DEV_BUILD || PR_BUILD qDebug() << "Domain metadata users updated:" << users; #endif } -void DomainMetadata::usersChanged() { - ++_tic; - -#if DEV_BUILD || PR_BUILD - qDebug() << "Domain metadata users change detected"; -#endif +void DomainMetadata::sendDescriptors() { + QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(get(DESCRIPTORS)).toJson(QJsonDocument::Compact))); + const QUuid& domainID = DependencyManager::get()->getSessionUUID(); + if (!domainID.isNull()) { + static const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; + DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), + AccountManagerAuth::Required, + QNetworkAccessManager::PutOperation, + JSONCallbackParameters(), + domainUpdateJSON.toUtf8()); + } } diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index 7d58d43182..86918f5c78 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -19,46 +19,48 @@ class DomainMetadata : public QObject { Q_OBJECT +public: + using Tic = uint32_t; + static const QString USERS; - static const QString USERS_NUM_TOTAL; - static const QString USERS_NUM_ANON; - static const QString USERS_HOSTNAMES; + class Users { + public: + static const QString NUM_TOTAL; + static const QString NUM_ANON; + static const QString HOSTNAMES; + }; static const QString DESCRIPTORS; - static const QString DESCRIPTORS_DESCRIPTION; - static const QString DESCRIPTORS_CAPACITY; - static const QString DESCRIPTORS_HOURS; - static const QString DESCRIPTORS_RESTRICTION; - static const QString DESCRIPTORS_MATURITY; - static const QString DESCRIPTORS_HOSTS; - static const QString DESCRIPTORS_TAGS; - static const QString DESCRIPTORS_IMG; - static const QString DESCRIPTORS_IMG_SRC; - static const QString DESCRIPTORS_IMG_TYPE; - static const QString DESCRIPTORS_IMG_SIZE; - static const QString DESCRIPTORS_IMG_UPDATED_AT; + class Descriptors { + public: + static const QString DESCRIPTION; + static const QString CAPACITY; + static const QString HOURS; + static const QString RESTRICTION; + static const QString MATURITY; + static const QString HOSTS; + static const QString TAGS; + }; -public: - DomainMetadata(); + DomainMetadata(QObject* domainServer); + DomainMetadata() = delete; - // Returns the last set metadata - // If connected users have changed, metadata may need to be updated - // this should be checked by storing tic = getTic() between calls - // and testing it for equality before the next get (tic == getTic()) - QJsonObject get() { return QJsonObject::fromVariantMap(_metadata); } - QJsonObject getUsers() { return QJsonObject::fromVariantMap(_metadata[USERS].toMap()); } - QJsonObject getDescriptors() { return QJsonObject::fromVariantMap(_metadata[DESCRIPTORS].toMap()); } - - uint32_t getTic() { return _tic; } - - void setDescriptors(QVariantMap& settings); - void updateUsers(); + // Get cached metadata + QJsonObject get(); + QJsonObject get(const QString& group); public slots: + void descriptorsChanged(); + void securityChanged(bool send); + void securityChanged() { securityChanged(true); } void usersChanged(); protected: + void maybeUpdateUsers(); + void sendDescriptors(); + QVariantMap _metadata; + uint32_t _lastTic{ -1 }; uint32_t _tic{ 0 }; }; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 1f666455c6..223cab61da 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -94,10 +94,6 @@ DomainServer::DomainServer(int argc, char* argv[]) : qRegisterMetaType("DomainServerWebSessionData"); qRegisterMetaTypeStreamOperators("DomainServerWebSessionData"); - // update the metadata when a user (dis)connects - connect(this, &DomainServer::userConnected, &_metadata, &DomainMetadata::usersChanged); - connect(this, &DomainServer::userDisconnected, &_metadata, &DomainMetadata::usersChanged); - // make sure we hear about newly connected nodes from our gatekeeper connect(&_gatekeeper, &DomainGatekeeper::connectedNode, this, &DomainServer::handleConnectedNode); @@ -108,9 +104,6 @@ DomainServer::DomainServer(int argc, char* argv[]) : connect(&_settingsManager, &DomainServerSettingsManager::updateNodePermissions, &_gatekeeper, &DomainGatekeeper::updateNodePermissions); - // update the metadata with current descriptors - _metadata.setDescriptors(_settingsManager.getSettingsMap()); - if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth()) { // we either read a certificate and private key or were not passed one // and completed login or did not need to @@ -125,17 +118,9 @@ DomainServer::DomainServer(int argc, char* argv[]) : _gatekeeper.preloadAllowedUserPublicKeys(); optionallyGetTemporaryName(args); - - // send metadata descriptors - QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(_metadata.getDescriptors()).toJson(QJsonDocument::Compact))); - const QUuid& domainID = DependencyManager::get()->getSessionUUID(); - static const QString DOMAIN_UPDATE = "/api/v1/domains/%1"; - DependencyManager::get()->sendRequest(DOMAIN_UPDATE.arg(uuidStringWithoutCurlyBraces(domainID)), - AccountManagerAuth::Required, - QNetworkAccessManager::PutOperation, - JSONCallbackParameters(), - domainUpdateJSON.toUtf8()); } + + _metadata = new DomainMetadata(this); } DomainServer::~DomainServer() { @@ -1111,14 +1096,11 @@ void DomainServer::sendHeartbeatToMetaverse(const QString& networkAddress) { NodePermissions anonymousPermissions = _settingsManager.getPermissionsForName(NodePermissions::standardNameAnonymous); domainObject[RESTRICTED_ACCESS_FLAG] = !anonymousPermissions.canConnectToDomain; - // Add the metadata to the heartbeat - static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; - auto tic = _metadata.getTic(); - if (_metadataTic != tic) { - _metadataTic = tic; - _metadata.updateUsers(); + if (_metadata) { + // Add the metadata to the heartbeat + static const QString DOMAIN_HEARTBEAT_KEY = "heartbeat"; + domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata->get(DomainMetadata::USERS); } - domainObject[DOMAIN_HEARTBEAT_KEY] = _metadata.getUsers(); QString domainUpdateJSON = QString("{\"domain\":%1}").arg(QString(QJsonDocument(domainObject).toJson(QJsonDocument::Compact))); diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index bdcc36c1ac..c742dbc9b3 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -172,13 +172,12 @@ private: DomainServerSettingsManager _settingsManager; - DomainMetadata _metadata; - uint32_t _metadataTic{ 0 }; - HifiSockAddr _iceServerSocket; std::unique_ptr _iceServerHeartbeatPacket; - QTimer* _iceHeartbeatTimer { nullptr }; // this looks like it dangles when created but it's parented to the DomainServer + // These will be parented to this, they are not dangling + DomainMetadata* _metadata { nullptr }; + QTimer* _iceHeartbeatTimer { nullptr }; QList _iceServerAddresses; QSet _failedIceServerAddresses; @@ -190,6 +189,7 @@ private: bool _hasAccessToken { false }; friend class DomainGatekeeper; + friend class DomainMetadata; }; From cfe9ac32d4ff761fe07817959e9f89a19a0c4535 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Mon, 20 Jun 2016 14:46:20 -0700 Subject: [PATCH 3/3] fix narrowing warning by casting -1 --- domain-server/src/DomainMetadata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainMetadata.h b/domain-server/src/DomainMetadata.h index 86918f5c78..0bfd6c611b 100644 --- a/domain-server/src/DomainMetadata.h +++ b/domain-server/src/DomainMetadata.h @@ -60,7 +60,7 @@ protected: void sendDescriptors(); QVariantMap _metadata; - uint32_t _lastTic{ -1 }; + uint32_t _lastTic{ (uint32_t)-1 }; uint32_t _tic{ 0 }; };