mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-07-30 11:50:10 +02:00
207 lines
No EOL
9.1 KiB
C++
207 lines
No EOL
9.1 KiB
C++
//
|
|
// DomainServerSettingsManager.cpp
|
|
// domain-server/src
|
|
//
|
|
// Created by Stephen Birarda on 2014-06-24.
|
|
// Copyright 2014 High Fidelity, Inc.
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
#include <QtCore/QCoreApplication>
|
|
#include <QtCore/QFile>
|
|
#include <QtCore/QJsonArray>
|
|
#include <QtCore/QJsonObject>
|
|
#include <QtCore/QUrl>
|
|
#include <QtCore/QUrlQuery>
|
|
|
|
#include <Assignment.h>
|
|
#include <HTTPConnection.h>
|
|
|
|
#include "DomainServerSettingsManager.h"
|
|
|
|
const QString SETTINGS_DESCRIPTION_RELATIVE_PATH = "/resources/web/settings/describe.json";
|
|
const QString SETTINGS_JSON_FILE_RELATIVE_PATH = "/resources/settings.json";
|
|
|
|
DomainServerSettingsManager::DomainServerSettingsManager() :
|
|
_descriptionObject(),
|
|
_settingsMap()
|
|
{
|
|
// load the description object from the settings description
|
|
QFile descriptionFile(QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH);
|
|
descriptionFile.open(QIODevice::ReadOnly);
|
|
|
|
_descriptionObject = QJsonDocument::fromJson(descriptionFile.readAll()).object();
|
|
|
|
// load the existing config file to get the current values
|
|
QFile configFile(QCoreApplication::applicationDirPath() + SETTINGS_JSON_FILE_RELATIVE_PATH);
|
|
|
|
if (configFile.exists()) {
|
|
configFile.open(QIODevice::ReadOnly);
|
|
|
|
_settingsMap = QJsonDocument::fromJson(configFile.readAll()).toVariant().toMap();
|
|
}
|
|
}
|
|
|
|
const QString DESCRIPTION_SETTINGS_KEY = "settings";
|
|
const QString SETTING_DEFAULT_KEY = "default";
|
|
|
|
bool DomainServerSettingsManager::handlePublicHTTPRequest(HTTPConnection* connection, const QUrl &url) {
|
|
if (connection->requestOperation() == QNetworkAccessManager::GetOperation && url.path() == "/settings.json") {
|
|
// 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);
|
|
|
|
QJsonObject responseObject;
|
|
|
|
if (typeValue.isEmpty()) {
|
|
// combine the description object and our current settings map
|
|
responseObject["descriptions"] = _descriptionObject;
|
|
responseObject["values"] = QJsonDocument::fromVariant(_settingsMap).object();
|
|
} else {
|
|
// convert the string type value to a QJsonValue
|
|
QJsonValue queryType = 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 QString& group, _descriptionObject.keys()) {
|
|
QJsonObject groupObject = _descriptionObject[group].toObject();
|
|
QJsonObject groupSettingsObject = groupObject[DESCRIPTION_SETTINGS_KEY].toObject();
|
|
|
|
QJsonObject groupResponseObject;
|
|
|
|
|
|
foreach(const QString& settingKey, groupSettingsObject.keys()) {
|
|
QJsonObject settingObject = groupSettingsObject[settingKey].toObject();
|
|
|
|
QJsonArray affectedTypesArray = settingObject[AFFECTED_TYPES_JSON_KEY].toArray();
|
|
if (affectedTypesArray.isEmpty()) {
|
|
affectedTypesArray = groupObject[AFFECTED_TYPES_JSON_KEY].toArray();
|
|
}
|
|
|
|
if (affectedTypesArray.contains(queryType)) {
|
|
// this is a setting we should include in the responseObject
|
|
|
|
// we need to check if the settings map has a value for this setting
|
|
QVariant variantValue;
|
|
QVariant settingsMapGroupValue = _settingsMap.value(group);
|
|
|
|
if (!settingsMapGroupValue.isNull()) {
|
|
variantValue = settingsMapGroupValue.toMap().value(settingKey);
|
|
}
|
|
|
|
if (variantValue.isNull()) {
|
|
// no value for this setting, pass the default
|
|
groupResponseObject[settingKey] = settingObject[SETTING_DEFAULT_KEY];
|
|
} else {
|
|
groupResponseObject[settingKey] = QJsonValue::fromVariant(variantValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!groupResponseObject.isEmpty()) {
|
|
// set this group's object to the constructed object
|
|
responseObject[group] = groupResponseObject;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(responseObject).toJson(), "application/json");
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection *connection, const QUrl &url) {
|
|
if (connection->requestOperation() == QNetworkAccessManager::PostOperation && url.path() == "/settings.json") {
|
|
// this is a POST operation to change one or more settings
|
|
QJsonDocument postedDocument = QJsonDocument::fromJson(connection->requestContent());
|
|
QJsonObject postedObject = postedDocument.object();
|
|
|
|
// we recurse one level deep below each group for the appropriate setting
|
|
recurseJSONObjectAndOverwriteSettings(postedObject, _settingsMap, _descriptionObject);
|
|
|
|
// 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");
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
const QString SETTING_DESCRIPTION_TYPE_KEY = "type";
|
|
|
|
void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject,
|
|
QVariantMap& settingsVariant,
|
|
QJsonObject descriptionObject) {
|
|
foreach(const QString& key, postedObject.keys()) {
|
|
|
|
QJsonValue rootValue = postedObject[key];
|
|
|
|
// we don't continue if this key is not present in our descriptionObject
|
|
if (descriptionObject.contains(key)) {
|
|
if (rootValue.isString()) {
|
|
if (rootValue.toString().isEmpty()) {
|
|
// this is an empty value, clear it in settings variant so the default is sent
|
|
settingsVariant.remove(key);
|
|
} else {
|
|
if (descriptionObject[key].toObject().contains(SETTING_DESCRIPTION_TYPE_KEY)) {
|
|
// for now this means that this is a double, so set it as a double
|
|
settingsVariant[key] = rootValue.toString().toDouble();
|
|
} else {
|
|
settingsVariant[key] = rootValue.toString();
|
|
}
|
|
}
|
|
} else if (rootValue.isBool()) {
|
|
settingsVariant[key] = rootValue.toBool();
|
|
} else if (rootValue.isObject()) {
|
|
// there's a JSON Object to explore, so attempt to recurse into it
|
|
QJsonObject nextDescriptionObject = descriptionObject[key].toObject();
|
|
|
|
if (nextDescriptionObject.contains(DESCRIPTION_SETTINGS_KEY)) {
|
|
if (!settingsVariant.contains(key)) {
|
|
// we don't have a map below this key yet, so set it up now
|
|
settingsVariant[key] = QVariantMap();
|
|
}
|
|
|
|
QVariantMap& thisMap = *reinterpret_cast<QVariantMap*>(settingsVariant[key].data());
|
|
|
|
recurseJSONObjectAndOverwriteSettings(rootValue.toObject(),
|
|
thisMap,
|
|
nextDescriptionObject[DESCRIPTION_SETTINGS_KEY].toObject());
|
|
|
|
if (thisMap.isEmpty()) {
|
|
// we've cleared all of the settings below this value, so remove this one too
|
|
settingsVariant.remove(key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
QByteArray DomainServerSettingsManager::getJSONSettingsMap() const {
|
|
return QJsonDocument::fromVariant(_settingsMap).toJson();
|
|
}
|
|
|
|
void DomainServerSettingsManager::persistToFile() {
|
|
QFile settingsFile(QCoreApplication::applicationDirPath() + SETTINGS_JSON_FILE_RELATIVE_PATH);
|
|
|
|
if (settingsFile.open(QIODevice::WriteOnly)) {
|
|
settingsFile.write(getJSONSettingsMap());
|
|
} else {
|
|
qCritical("Could not write to JSON settings file. Unable to persist settings.");
|
|
}
|
|
} |