mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 09:54:14 +02:00
handle root key settings when updating
This commit is contained in:
parent
f0aeaa1af8
commit
c49d73ea35
3 changed files with 359 additions and 318 deletions
File diff suppressed because it is too large
Load diff
|
@ -39,31 +39,31 @@ DomainServerSettingsManager::DomainServerSettingsManager() :
|
|||
// load the description object from the settings description
|
||||
QFile descriptionFile(QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH);
|
||||
descriptionFile.open(QIODevice::ReadOnly);
|
||||
|
||||
|
||||
_descriptionArray = QJsonDocument::fromJson(descriptionFile.readAll()).array();
|
||||
}
|
||||
|
||||
void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList) {
|
||||
_configMap.loadMasterAndUserConfig(argumentList);
|
||||
|
||||
|
||||
// for now we perform a temporary transition from http-username and http-password to http_username and http_password
|
||||
const QVariant* oldUsername = valueForKeyPath(_configMap.getUserConfig(), "security.http-username");
|
||||
const QVariant* oldPassword = valueForKeyPath(_configMap.getUserConfig(), "security.http-password");
|
||||
|
||||
|
||||
if (oldUsername || oldPassword) {
|
||||
QVariantMap& settingsMap = *reinterpret_cast<QVariantMap*>(_configMap.getUserConfig()["security"].data());
|
||||
|
||||
|
||||
// remove old keys, move to new format
|
||||
if (oldUsername) {
|
||||
settingsMap["http_username"] = oldUsername->toString();
|
||||
settingsMap.remove("http-username");
|
||||
}
|
||||
|
||||
|
||||
if (oldPassword) {
|
||||
settingsMap["http_password"] = oldPassword->toString();
|
||||
settingsMap.remove("http-password");
|
||||
}
|
||||
|
||||
|
||||
// save the updated settings
|
||||
persistToFile();
|
||||
}
|
||||
|
@ -71,18 +71,18 @@ void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList
|
|||
|
||||
QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QString &keyPath) {
|
||||
const QVariant* foundValue = valueForKeyPath(_configMap.getMergedConfig(), keyPath);
|
||||
|
||||
|
||||
if (foundValue) {
|
||||
return *foundValue;
|
||||
} else {
|
||||
int dotIndex = keyPath.indexOf('.');
|
||||
|
||||
|
||||
QString groupKey = keyPath.mid(0, dotIndex);
|
||||
QString settingKey = keyPath.mid(dotIndex + 1);
|
||||
|
||||
|
||||
foreach(const QVariant& group, _descriptionArray.toVariantList()) {
|
||||
QVariantMap groupMap = group.toMap();
|
||||
|
||||
|
||||
if (groupMap[DESCRIPTION_NAME_KEY].toString() == groupKey) {
|
||||
foreach(const QVariant& setting, groupMap[DESCRIPTION_SETTINGS_KEY].toList()) {
|
||||
QVariantMap settingMap = setting.toMap();
|
||||
|
@ -90,12 +90,12 @@ QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QStrin
|
|||
return settingMap[SETTING_DEFAULT_KEY];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
@ -104,23 +104,23 @@ const QString SETTINGS_PATH = "/settings.json";
|
|||
bool DomainServerSettingsManager::handlePublicHTTPRequest(HTTPConnection* connection, const QUrl &url) {
|
||||
if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == SETTINGS_PATH) {
|
||||
// this is a GET operation for our settings
|
||||
|
||||
|
||||
// check if there is a query parameter for settings affecting a particular type of assignment
|
||||
const QString SETTINGS_TYPE_QUERY_KEY = "type";
|
||||
QUrlQuery settingsQuery(url);
|
||||
QString typeValue = settingsQuery.queryItemValue(SETTINGS_TYPE_QUERY_KEY);
|
||||
|
||||
|
||||
if (!typeValue.isEmpty()) {
|
||||
QJsonObject responseObject = responseObjectForType(typeValue);
|
||||
|
||||
|
||||
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(responseObject).toJson(), "application/json");
|
||||
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -129,82 +129,82 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
|
|||
// this is a POST operation to change one or more settings
|
||||
QJsonDocument postedDocument = QJsonDocument::fromJson(connection->requestContent());
|
||||
QJsonObject postedObject = postedDocument.object();
|
||||
|
||||
|
||||
qDebug() << "DomainServerSettingsManager postedObject -" << postedObject;
|
||||
|
||||
// we recurse one level deep below each group for the appropriate setting
|
||||
recurseJSONObjectAndOverwriteSettings(postedObject, _configMap.getUserConfig(), _descriptionArray);
|
||||
|
||||
recurseJSONObjectAndOverwriteSettings(postedObject, _configMap.getUserConfig());
|
||||
|
||||
// store whatever the current _settingsMap is to file
|
||||
persistToFile();
|
||||
|
||||
|
||||
// return success to the caller
|
||||
QString jsonSuccess = "{\"status\": \"success\"}";
|
||||
connection->respond(HTTPConnection::StatusCode200, jsonSuccess.toUtf8(), "application/json");
|
||||
|
||||
|
||||
// defer a restart to the domain-server, this gives our HTTPConnection enough time to respond
|
||||
const int DOMAIN_SERVER_RESTART_TIMER_MSECS = 1000;
|
||||
QTimer::singleShot(DOMAIN_SERVER_RESTART_TIMER_MSECS, qApp, SLOT(restart()));
|
||||
|
||||
|
||||
return true;
|
||||
} else if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == SETTINGS_PATH) {
|
||||
// setup a JSON Object with descriptions and non-omitted settings
|
||||
const QString SETTINGS_RESPONSE_DESCRIPTION_KEY = "descriptions";
|
||||
const QString SETTINGS_RESPONSE_VALUE_KEY = "values";
|
||||
const QString SETTINGS_RESPONSE_LOCKED_VALUES_KEY = "locked";
|
||||
|
||||
|
||||
QJsonObject rootObject;
|
||||
rootObject[SETTINGS_RESPONSE_DESCRIPTION_KEY] = _descriptionArray;
|
||||
rootObject[SETTINGS_RESPONSE_VALUE_KEY] = responseObjectForType("", true);
|
||||
rootObject[SETTINGS_RESPONSE_LOCKED_VALUES_KEY] = QJsonDocument::fromVariant(_configMap.getMasterConfig()).object();
|
||||
|
||||
|
||||
|
||||
|
||||
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json");
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& typeValue, bool isAuthenticated) {
|
||||
QJsonObject responseObject;
|
||||
|
||||
|
||||
if (!typeValue.isEmpty() || isAuthenticated) {
|
||||
// convert the string type value to a QJsonValue
|
||||
QJsonValue queryType = typeValue.isEmpty() ? QJsonValue() : QJsonValue(typeValue.toInt());
|
||||
|
||||
|
||||
const QString AFFECTED_TYPES_JSON_KEY = "assignment-types";
|
||||
|
||||
|
||||
// enumerate the groups in the description object to find which settings to pass
|
||||
foreach(const QJsonValue& groupValue, _descriptionArray) {
|
||||
QJsonObject groupObject = groupValue.toObject();
|
||||
QString groupKey = groupObject[DESCRIPTION_NAME_KEY].toString();
|
||||
QJsonArray groupSettingsArray = groupObject[DESCRIPTION_SETTINGS_KEY].toArray();
|
||||
|
||||
|
||||
QJsonObject groupResponseObject;
|
||||
|
||||
|
||||
foreach(const QJsonValue& settingValue, groupSettingsArray) {
|
||||
const QString VALUE_HIDDEN_FLAG_KEY = "value-hidden";
|
||||
|
||||
|
||||
QJsonObject settingObject = settingValue.toObject();
|
||||
|
||||
|
||||
if (!settingObject[VALUE_HIDDEN_FLAG_KEY].toBool()) {
|
||||
QJsonArray affectedTypesArray = settingObject[AFFECTED_TYPES_JSON_KEY].toArray();
|
||||
if (affectedTypesArray.isEmpty()) {
|
||||
affectedTypesArray = groupObject[AFFECTED_TYPES_JSON_KEY].toArray();
|
||||
}
|
||||
|
||||
|
||||
if (affectedTypesArray.contains(queryType) ||
|
||||
(queryType.isNull() && isAuthenticated)) {
|
||||
// this is a setting we should include in the responseObject
|
||||
|
||||
|
||||
QString settingName = settingObject[DESCRIPTION_NAME_KEY].toString();
|
||||
|
||||
|
||||
// we need to check if the settings map has a value for this setting
|
||||
QVariant variantValue;
|
||||
|
||||
|
||||
if (!groupKey.isEmpty()) {
|
||||
QVariant settingsMapGroupValue = _configMap.getMergedConfig().value(groupKey);
|
||||
|
||||
|
||||
if (!settingsMapGroupValue.isNull()) {
|
||||
variantValue = settingsMapGroupValue.toMap().value(settingName);
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
|||
}
|
||||
|
||||
QJsonValue result;
|
||||
|
||||
|
||||
if (variantValue.isNull()) {
|
||||
// no value for this setting, pass the default
|
||||
if (settingObject.contains(SETTING_DEFAULT_KEY)) {
|
||||
|
@ -223,7 +223,7 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
|||
// if so we set to the empty string
|
||||
result = QString("");
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
result = QJsonValue::fromVariant(variantValue);
|
||||
}
|
||||
|
@ -238,35 +238,16 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!groupKey.isEmpty() && !groupResponseObject.isEmpty()) {
|
||||
// set this group's object to the constructed object
|
||||
responseObject[groupKey] = groupResponseObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
bool DomainServerSettingsManager::settingExists(const QString& groupName, const QString& settingName,
|
||||
const QJsonArray& descriptionArray, QJsonObject& settingDescription) {
|
||||
foreach(const QJsonValue& groupValue, descriptionArray) {
|
||||
QJsonObject groupObject = groupValue.toObject();
|
||||
if (groupObject[DESCRIPTION_NAME_KEY].toString() == groupName) {
|
||||
|
||||
foreach(const QJsonValue& settingValue, groupObject[DESCRIPTION_SETTINGS_KEY].toArray()) {
|
||||
QJsonObject settingObject = settingValue.toObject();
|
||||
if (settingObject[DESCRIPTION_NAME_KEY].toString() == settingName) {
|
||||
settingDescription = settingObject;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
settingDescription = QJsonObject();
|
||||
return false;
|
||||
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
|
||||
|
@ -280,28 +261,31 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
|
|||
QString settingType = settingDescription[SETTING_DESCRIPTION_TYPE_KEY].toString();
|
||||
const QString INPUT_DOUBLE_TYPE = "double";
|
||||
const QString INPUT_INTEGER_TYPE = "int";
|
||||
|
||||
|
||||
if (settingType == INPUT_DOUBLE_TYPE) {
|
||||
settingMap[key] = newValue.toString().toDouble();
|
||||
} else if (settingType == INPUT_INTEGER_TYPE) {
|
||||
settingMap[key] = newValue.toString().toInt();
|
||||
} else {
|
||||
|
||||
qDebug() << "setting value at key" << key << "to string" << newValue.toString();
|
||||
settingMap[key] = newValue.toString();
|
||||
}
|
||||
}
|
||||
} else if (newValue.isBool()) {
|
||||
settingMap[key] = newValue.toBool();
|
||||
} else if (newValue.isObject()) {
|
||||
qDebug() << "updateSetting called with" << newValue.toObject();
|
||||
if (!settingMap.contains(key)) {
|
||||
// we don't have a map below this key yet, so set it up now
|
||||
settingMap[key] = QVariantMap();
|
||||
}
|
||||
|
||||
|
||||
QVariantMap& thisMap = *reinterpret_cast<QVariantMap*>(settingMap[key].data());
|
||||
foreach(const QString childKey, newValue.toObject().keys()) {
|
||||
|
||||
QJsonObject childDescriptionObject = settingDescription;
|
||||
|
||||
|
||||
// is this the key? if so we have the description already
|
||||
if (key != settingDescription[DESCRIPTION_NAME_KEY].toString()) {
|
||||
// otherwise find the description object for this childKey under columns
|
||||
|
@ -313,12 +297,12 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateSetting(childKey, newValue.toObject()[childKey], thisMap, childDescriptionObject);
|
||||
}
|
||||
|
||||
|
||||
if (settingMap[key].toMap().isEmpty()) {
|
||||
// we've cleared all of the settings below this value, so remove this one too
|
||||
settingMap.remove(key);
|
||||
|
@ -330,47 +314,105 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
|
|||
}
|
||||
}
|
||||
|
||||
void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject,
|
||||
QVariantMap& settingsVariant,
|
||||
const QJsonArray& descriptionArray) {
|
||||
// Iterate on the setting groups
|
||||
foreach(const QString& groupKey, postedObject.keys()) {
|
||||
QJsonValue groupValue = postedObject[groupKey];
|
||||
|
||||
if (!settingsVariant.contains(groupKey)) {
|
||||
// we don't have a map below this key yet, so set it up now
|
||||
settingsVariant[groupKey] = QVariantMap();
|
||||
QJsonObject DomainServerSettingsManager::settingDescriptionFromGroup(const QJsonObject& groupObject, const QString& settingName) {
|
||||
foreach(const QJsonValue& settingValue, groupObject[DESCRIPTION_SETTINGS_KEY].toArray()) {
|
||||
QJsonObject settingObject = settingValue.toObject();
|
||||
if (settingObject[DESCRIPTION_NAME_KEY].toString() == settingName) {
|
||||
return settingObject;
|
||||
}
|
||||
|
||||
// Iterate on the settings
|
||||
foreach(const QString& settingKey, groupValue.toObject().keys()) {
|
||||
QJsonValue settingValue = groupValue.toObject()[settingKey];
|
||||
|
||||
QJsonObject thisDescription;
|
||||
if (settingExists(groupKey, settingKey, descriptionArray, thisDescription)) {
|
||||
QVariantMap& thisMap = *reinterpret_cast<QVariantMap*>(settingsVariant[groupKey].data());
|
||||
updateSetting(settingKey, settingValue, thisMap, thisDescription);
|
||||
}
|
||||
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject,
|
||||
QVariantMap& settingsVariant) {
|
||||
// Iterate on the setting groups
|
||||
foreach(const QString& rootKey, postedObject.keys()) {
|
||||
QJsonValue rootValue = postedObject[rootKey];
|
||||
|
||||
if (!settingsVariant.contains(rootKey)) {
|
||||
// we don't have a map below this key yet, so set it up now
|
||||
settingsVariant[rootKey] = QVariantMap();
|
||||
}
|
||||
|
||||
QVariantMap& thisMap = settingsVariant;
|
||||
|
||||
QJsonObject groupDescriptionObject;
|
||||
|
||||
// we need to check the description array to see if this is a root setting or a group setting
|
||||
foreach(const QJsonValue& groupValue, _descriptionArray) {
|
||||
if (groupValue.toObject()[DESCRIPTION_NAME_KEY] == rootKey) {
|
||||
// we matched a group - keep this since we'll use it below to update the settings
|
||||
groupDescriptionObject = groupValue.toObject();
|
||||
|
||||
// change the map we will update to be the map for this group
|
||||
thisMap = *reinterpret_cast<QVariantMap*>(settingsVariant[rootKey].data());
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsVariant[groupKey].toMap().empty()) {
|
||||
|
||||
if (groupDescriptionObject.isEmpty()) {
|
||||
// this is a root value, so we can call updateSetting for it directly
|
||||
// first we need to find our description value for it
|
||||
|
||||
QJsonObject matchingDescriptionObject;
|
||||
|
||||
foreach(const QJsonValue& groupValue, _descriptionArray) {
|
||||
// find groups with root values (they don't have a group name)
|
||||
QJsonObject groupObject = groupValue.toObject();
|
||||
if (!groupObject.contains(DESCRIPTION_NAME_KEY)) {
|
||||
// this is a group with root values - check if our setting is in here
|
||||
matchingDescriptionObject = settingDescriptionFromGroup(groupObject, rootKey);
|
||||
|
||||
if (!matchingDescriptionObject.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!matchingDescriptionObject.isEmpty()) {
|
||||
updateSetting(rootKey, rootValue, thisMap, matchingDescriptionObject);
|
||||
qDebug() << "This map is" << thisMap << "after call to update setting";
|
||||
} else {
|
||||
qDebug() << "Setting for root key" << rootKey << "does not exist - cannot update setting.";
|
||||
}
|
||||
} else {
|
||||
// this is a group - iterate on the settings in the group
|
||||
foreach(const QString& settingKey, rootValue.toObject().keys()) {
|
||||
// make sure this particular setting exists and we have a description object for it
|
||||
QJsonObject matchingDescriptionObject = settingDescriptionFromGroup(groupDescriptionObject, settingKey);
|
||||
|
||||
// if we matched the setting then update the value
|
||||
if (!matchingDescriptionObject.isEmpty()) {
|
||||
QJsonValue settingValue = rootValue.toObject()[settingKey];
|
||||
updateSetting(settingKey, settingValue, thisMap, matchingDescriptionObject);
|
||||
} else {
|
||||
qDebug() << "Could not find description for setting" << settingKey << "in group" << rootKey <<
|
||||
"- cannot update setting.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsVariant[rootKey].toMap().empty()) {
|
||||
// we've cleared all of the settings below this value, so remove this one too
|
||||
settingsVariant.remove(groupKey);
|
||||
settingsVariant.remove(rootKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DomainServerSettingsManager::persistToFile() {
|
||||
|
||||
|
||||
// make sure we have the dir the settings file is supposed to live in
|
||||
QFileInfo settingsFileInfo(_configMap.getUserConfigFilename());
|
||||
|
||||
|
||||
if (!settingsFileInfo.dir().exists()) {
|
||||
settingsFileInfo.dir().mkpath(".");
|
||||
}
|
||||
|
||||
|
||||
QFile settingsFile(_configMap.getUserConfigFilename());
|
||||
|
||||
|
||||
if (settingsFile.open(QIODevice::WriteOnly)) {
|
||||
settingsFile.write(QJsonDocument::fromVariant(_configMap.getUserConfig()).toJson());
|
||||
} else {
|
||||
|
|
|
@ -24,21 +24,20 @@ public:
|
|||
DomainServerSettingsManager();
|
||||
bool handlePublicHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
||||
bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url);
|
||||
|
||||
|
||||
void setupConfigMap(const QStringList& argumentList);
|
||||
QVariant valueOrDefaultValueForKeyPath(const QString& keyPath);
|
||||
|
||||
|
||||
QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); }
|
||||
private:
|
||||
QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false);
|
||||
void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant,
|
||||
const QJsonArray& descriptionArray);
|
||||
bool settingExists(const QString& groupName, const QString& settingName,
|
||||
const QJsonArray& descriptionArray, QJsonObject& settingDescription);
|
||||
void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant);
|
||||
|
||||
void updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
|
||||
const QJsonObject& settingDescription);
|
||||
QJsonObject settingDescriptionFromGroup(const QJsonObject& groupObject, const QString& settingName);
|
||||
void persistToFile();
|
||||
|
||||
|
||||
QJsonArray _descriptionArray;
|
||||
HifiConfigVariantMap _configMap;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue