mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 12:42:58 +02:00
add domain settings backup and restore to web interface
This commit is contained in:
parent
2f6b079d80
commit
11fe279f6f
9 changed files with 316 additions and 45 deletions
|
@ -2,16 +2,6 @@ $(document).ready(function(){
|
||||||
|
|
||||||
Settings.afterReloadActions = function() {};
|
Settings.afterReloadActions = function() {};
|
||||||
|
|
||||||
function showSpinnerAlert(title) {
|
|
||||||
swal({
|
|
||||||
title: title,
|
|
||||||
text: '<div class="spinner" style="color:black;"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>',
|
|
||||||
html: true,
|
|
||||||
showConfirmButton: false,
|
|
||||||
allowEscapeKey: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var frm = $('#upload-form');
|
var frm = $('#upload-form');
|
||||||
frm.submit(function (ev) {
|
frm.submit(function (ev) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
|
|
@ -430,3 +430,7 @@ ul.nav li.dropdown ul.dropdown-menu .divider {
|
||||||
.advanced-settings-section {
|
.advanced-settings-section {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#restore-settings-button {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title">domain-server is restarting</h4>
|
<h4 class="modal-title">Domain Server is restarting</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<h5>This page will automatically refresh in <span id="refresh-time">3 seconds</span>.</h5>
|
<h5>This page will automatically refresh in <span id="refresh-time">3 seconds</span>.</h5>
|
||||||
|
|
|
@ -92,6 +92,16 @@ var viewHelpers = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showSpinnerAlert(title) {
|
||||||
|
swal({
|
||||||
|
title: title,
|
||||||
|
text: '<div class="spinner" style="color:black;"><div class="bounce1"></div><div class="bounce2"></div><div class="bounce3"></div></div>',
|
||||||
|
html: true,
|
||||||
|
showConfirmButton: false,
|
||||||
|
allowEscapeKey: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function reloadSettings(callback) {
|
function reloadSettings(callback) {
|
||||||
$.getJSON(Settings.endpoint, function(data){
|
$.getJSON(Settings.endpoint, function(data){
|
||||||
_.extend(data, viewHelpers);
|
_.extend(data, viewHelpers);
|
||||||
|
|
|
@ -82,11 +82,16 @@ $(document).ready(function(){
|
||||||
|
|
||||||
// for domain settings, we add a dummy "Places" group that we fill
|
// for domain settings, we add a dummy "Places" group that we fill
|
||||||
// via the API - add it to the dropdown menu in the right spot
|
// via the API - add it to the dropdown menu in the right spot
|
||||||
if (index == 0) {
|
// which is after "Metaverse / Networking"
|
||||||
|
if (group.name == "metaverse") {
|
||||||
$settingsDropdown.append("<li role='separator' class='divider'></li>");
|
$settingsDropdown.append("<li role='separator' class='divider'></li>");
|
||||||
$settingsDropdown.append(makeGroupDropdownElement({ html_id: 'places', label: 'Places' }, "/settings/"));
|
$settingsDropdown.append(makeGroupDropdownElement({ html_id: 'places', label: 'Places' }, "/settings/"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// append a link for the "Settings Backup" panel
|
||||||
|
$settingsDropdown.append("<li role='separator' class='divider'></li>");
|
||||||
|
$settingsDropdown.append(makeGroupDropdownElement({ html_id: 'settings_backup', label: 'Settings Backup'}, "/settings"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -97,7 +97,13 @@ var DOMAIN_ID_TYPE_FULL = 2;
|
||||||
var DOMAIN_ID_TYPE_UNKNOWN = 3;
|
var DOMAIN_ID_TYPE_UNKNOWN = 3;
|
||||||
|
|
||||||
function domainIDIsSet() {
|
function domainIDIsSet() {
|
||||||
return Settings.data.values.metaverse.id.length > 0;
|
if (typeof Settings.data.values.metaverse !== 'undefined' &&
|
||||||
|
typeof Settings.data.values.metaverse.id !== 'undefined') {
|
||||||
|
|
||||||
|
return Settings.data.values.metaverse.id.length > 0;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCurrentDomainIDType() {
|
function getCurrentDomainIDType() {
|
||||||
|
|
|
@ -19,6 +19,10 @@ $(document).ready(function(){
|
||||||
1: {
|
1: {
|
||||||
html_id: 'places',
|
html_id: 'places',
|
||||||
label: 'Places'
|
label: 'Places'
|
||||||
|
},
|
||||||
|
"-1": {
|
||||||
|
html_id: 'settings_backup',
|
||||||
|
label: 'Settings Backup'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +39,9 @@ $(document).ready(function(){
|
||||||
setupDomainNetworkingSettings();
|
setupDomainNetworkingSettings();
|
||||||
// setupDomainLabelSetting();
|
// setupDomainLabelSetting();
|
||||||
|
|
||||||
if (Settings.data.values.metaverse.id.length > 0) {
|
setupSettingsBackup();
|
||||||
|
|
||||||
|
if (domainIDIsSet()) {
|
||||||
// now, ask the API for what places, if any, point to this domain
|
// now, ask the API for what places, if any, point to this domain
|
||||||
reloadDomainInfo();
|
reloadDomainInfo();
|
||||||
|
|
||||||
|
@ -150,7 +156,13 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
function accessTokenIsSet() {
|
function accessTokenIsSet() {
|
||||||
return Settings.data.values.metaverse.access_token.length > 0;
|
if (typeof Settings.data.values.metaverse !== 'undefined' &&
|
||||||
|
typeof Settings.data.values.metaverse.access_token !== 'undefined') {
|
||||||
|
|
||||||
|
return Settings.data.values.metaverse.access_token.length > 0;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getShareName(callback) {
|
function getShareName(callback) {
|
||||||
|
@ -182,7 +194,7 @@ $(document).ready(function(){
|
||||||
|
|
||||||
if (action == "share") {
|
if (action == "share") {
|
||||||
// figure out if we already have a stored domain ID
|
// figure out if we already have a stored domain ID
|
||||||
if (Settings.data.values.metaverse.id.length > 0) {
|
if (domainIDIsSet()) {
|
||||||
// we need to ask the API what a shareable name for this domain is
|
// we need to ask the API what a shareable name for this domain is
|
||||||
getShareName(function(success, shareName){
|
getShareName(function(success, shareName){
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -674,7 +686,7 @@ $(document).ready(function(){
|
||||||
$("#" + Settings.PLACES_TABLE_ID).after(errorEl);
|
$("#" + Settings.PLACES_TABLE_ID).after(errorEl);
|
||||||
|
|
||||||
// do we have a domain ID?
|
// do we have a domain ID?
|
||||||
if (Settings.data.values.metaverse.id.length == 0) {
|
if (!domainIDIsSet()) {
|
||||||
// we don't have a domain ID - add a button to offer the user a chance to get a temporary one
|
// we don't have a domain ID - add a button to offer the user a chance to get a temporary one
|
||||||
var temporaryPlaceButton = dynamicButton(Settings.GET_TEMPORARY_NAME_BTN_ID, 'Get a temporary place name');
|
var temporaryPlaceButton = dynamicButton(Settings.GET_TEMPORARY_NAME_BTN_ID, 'Get a temporary place name');
|
||||||
$('#' + Settings.PLACES_TABLE_ID).after(temporaryPlaceButton);
|
$('#' + Settings.PLACES_TABLE_ID).after(temporaryPlaceButton);
|
||||||
|
@ -1023,4 +1035,70 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var RESTORE_SETTINGS_UPLOAD_ID = 'restore-settings-button';
|
||||||
|
var RESTORE_SETTINGS_FILE_ID = 'restore-settings-file';
|
||||||
|
|
||||||
|
// when the restore button is clicked, AJAX send the settings file to DS
|
||||||
|
// to restore its settings
|
||||||
|
$('body').on('click', '#' + RESTORE_SETTINGS_UPLOAD_ID, function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var files = $('#' + RESTORE_SETTINGS_FILE_ID).prop('files');
|
||||||
|
|
||||||
|
var fileFormData = new FormData();
|
||||||
|
fileFormData.append('restore-file', files[0]);
|
||||||
|
|
||||||
|
showSpinnerAlert("Restoring Settings");
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/settings/restore',
|
||||||
|
type: 'POST',
|
||||||
|
processData: false,
|
||||||
|
contentType: false,
|
||||||
|
dataType: 'json',
|
||||||
|
data: fileFormData
|
||||||
|
}).done(function(data, textStatus, jqXHR) {
|
||||||
|
swal.close();
|
||||||
|
showRestartModal();
|
||||||
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||||
|
showErrorMessage(
|
||||||
|
"Error",
|
||||||
|
"There was a problem restoring domain settings.\n"
|
||||||
|
+ "Please ensure that your current domain settings are valid and try again."
|
||||||
|
);
|
||||||
|
|
||||||
|
reloadSettings();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('body').on('change', '#' + RESTORE_SETTINGS_FILE_ID, function() {
|
||||||
|
if ($(this).val()) {
|
||||||
|
$('#' + RESTORE_SETTINGS_UPLOAD_ID).attr('disabled', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupSettingsBackup() {
|
||||||
|
// construct the HTML needed for the settings backup panel
|
||||||
|
var html = "<div class='form-group'>";
|
||||||
|
|
||||||
|
html += "<label class='control-label'>Save Your Settings Configuration</label>";
|
||||||
|
html += "<span class='help-block'>Download this domain's settings to quickly configure another domain or to restore them later</span>";
|
||||||
|
html += "<a href='/settings/backup.json' class='btn btn-primary'>Download Domain Settings</a>";
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
html += "<div class='form-group'>";
|
||||||
|
html += "<label class='control-label'>Upload a Settings Configuration</label>";
|
||||||
|
html += "<span class='help-block'>Upload a settings configuration to quickly configure this domain";
|
||||||
|
html += "<br/>Note: Your domain's settings will be replaced by the settings you upload</span>";
|
||||||
|
|
||||||
|
html += "<input id='restore-settings-file' name='restore-settings' type='file'>";
|
||||||
|
html += "<button type='button' id='" + RESTORE_SETTINGS_UPLOAD_ID + "' disabled='true' class='btn btn-primary'>Upload Domain Settings</button>";
|
||||||
|
|
||||||
|
html += "</div>";
|
||||||
|
|
||||||
|
$('#settings_backup .panel-body').html(html);
|
||||||
|
|
||||||
|
// add an upload button to the footer to kick off the upload form
|
||||||
|
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -174,7 +174,7 @@ void DomainServerSettingsManager::processSettingsRequestPacket(QSharedPointer<Re
|
||||||
Assignment::Type type;
|
Assignment::Type type;
|
||||||
message->readPrimitive(&type);
|
message->readPrimitive(&type);
|
||||||
|
|
||||||
QJsonObject responseObject = responseObjectForType(QString::number(type));
|
QJsonObject responseObject = settingsResponseObjectForType(QString::number(type));
|
||||||
auto json = QJsonDocument(responseObject).toJson();
|
auto json = QJsonDocument(responseObject).toJson();
|
||||||
|
|
||||||
auto packetList = NLPacketList::create(PacketType::DomainSettings, QByteArray(), true, true);
|
auto packetList = NLPacketList::create(PacketType::DomainSettings, QByteArray(), true, true);
|
||||||
|
@ -1079,6 +1079,8 @@ QVariant DomainServerSettingsManager::valueOrDefaultValueForKeyPath(const QStrin
|
||||||
|
|
||||||
bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection *connection, const QUrl &url) {
|
bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection *connection, const QUrl &url) {
|
||||||
if (connection->requestOperation() == QNetworkAccessManager::PostOperation) {
|
if (connection->requestOperation() == QNetworkAccessManager::PostOperation) {
|
||||||
|
static const QString SETTINGS_RESTORE_PATH = "/settings/restore";
|
||||||
|
|
||||||
if (url.path() == SETTINGS_PATH_JSON || url.path() == CONTENT_SETTINGS_PATH_JSON) {
|
if (url.path() == SETTINGS_PATH_JSON || url.path() == CONTENT_SETTINGS_PATH_JSON) {
|
||||||
// this is a POST operation to change one or more settings
|
// this is a POST operation to change one or more settings
|
||||||
QJsonDocument postedDocument = QJsonDocument::fromJson(connection->requestContent());
|
QJsonDocument postedDocument = QJsonDocument::fromJson(connection->requestContent());
|
||||||
|
@ -1107,10 +1109,39 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
|
||||||
emit settingsUpdated();
|
emit settingsUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (url.path() == SETTINGS_RESTORE_PATH) {
|
||||||
|
// this is an JSON settings file restore, ask the HTTPConnection to parse the data
|
||||||
|
QList<FormData> formData = connection->parseFormData();
|
||||||
|
|
||||||
|
bool wasRestoreSuccessful = false;
|
||||||
|
|
||||||
|
if (formData.size() > 0 && formData[0].second.size() > 0) {
|
||||||
|
// take the posted file and convert it to a QJsonObject
|
||||||
|
auto postedDocument = QJsonDocument::fromJson(formData[0].second);
|
||||||
|
if (postedDocument.isObject()) {
|
||||||
|
wasRestoreSuccessful = restoreSettingsFromObject(postedDocument.object(), DomainSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wasRestoreSuccessful) {
|
||||||
|
// respond with a 200 for success
|
||||||
|
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()));
|
||||||
|
} else {
|
||||||
|
// respond with a 400 for failure
|
||||||
|
connection->respond(HTTPConnection::StatusCode400);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
|
} else if (connection->requestOperation() == QNetworkAccessManager::GetOperation) {
|
||||||
static const QString SETTINGS_MENU_GROUPS_PATH = "/settings-menu-groups.json";
|
static const QString SETTINGS_MENU_GROUPS_PATH = "/settings-menu-groups.json";
|
||||||
|
static const QString SETTINGS_BACKUP_PATH = "/settings/backup.json";
|
||||||
|
|
||||||
if (url.path() == SETTINGS_PATH_JSON || url.path() == CONTENT_SETTINGS_PATH_JSON) {
|
if (url.path() == SETTINGS_PATH_JSON || url.path() == CONTENT_SETTINGS_PATH_JSON) {
|
||||||
|
|
||||||
|
@ -1127,7 +1158,10 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
|
||||||
? _domainSettingsDescription : _contentSettingsDescription;
|
? _domainSettingsDescription : _contentSettingsDescription;
|
||||||
|
|
||||||
// grab a domain settings object for all types, filtered for the right class of settings
|
// grab a domain settings object for all types, filtered for the right class of settings
|
||||||
rootObject[SETTINGS_RESPONSE_VALUE_KEY] = responseObjectForType("", true, forDomainSettings, forContentSettings);
|
// and exclude default values
|
||||||
|
rootObject[SETTINGS_RESPONSE_VALUE_KEY] = settingsResponseObjectForType("", true,
|
||||||
|
forDomainSettings, forContentSettings,
|
||||||
|
false);
|
||||||
|
|
||||||
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json");
|
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json");
|
||||||
|
|
||||||
|
@ -1136,14 +1170,152 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
|
||||||
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(_settingsMenuGroups).toJson(), "application/json");
|
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(_settingsMenuGroups).toJson(), "application/json");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} else if (url.path() == SETTINGS_BACKUP_PATH) {
|
||||||
|
// grab the settings backup as an authenticated user
|
||||||
|
// for the domain settings type only, excluding hidden and default values
|
||||||
|
auto currentDomainSettingsJSON = settingsResponseObjectForType("", true, true, false, false);
|
||||||
|
|
||||||
|
// setup headers that tell the client to download the file wth a special name
|
||||||
|
Headers downloadHeaders;
|
||||||
|
downloadHeaders.insert("Content-Transfer-Encoding", "binary");
|
||||||
|
|
||||||
|
// create a timestamped filename for the backup
|
||||||
|
const QString DATETIME_FORMAT { "yyyy-MM-dd_HH-mm-ss" };
|
||||||
|
auto backupFilename = "ds-settings-" + QDateTime::currentDateTime().toString(DATETIME_FORMAT) + ".json";
|
||||||
|
|
||||||
|
downloadHeaders.insert("Content-Disposition",
|
||||||
|
QString("attachment; filename=\"%1\"").arg(backupFilename).toLocal8Bit());
|
||||||
|
|
||||||
|
connection->respond(HTTPConnection::StatusCode200, QJsonDocument(currentDomainSettingsJSON).toJson(),
|
||||||
|
"application/force-download", downloadHeaders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& typeValue, bool isAuthenticated,
|
bool DomainServerSettingsManager::restoreSettingsFromObject(QJsonObject settingsToRestore, SettingsType settingsType) {
|
||||||
bool includeDomainSettings, bool includeContentSettings) {
|
QJsonArray& filteredDescriptionArray = settingsType == DomainSettings
|
||||||
|
? _domainSettingsDescription : _contentSettingsDescription;
|
||||||
|
|
||||||
|
// grab a copy of the current config before restore, so that we can back out if something bad happens during
|
||||||
|
QVariantMap preRestoreConfig = _configMap.getConfig();
|
||||||
|
|
||||||
|
bool shouldCancelRestore = false;
|
||||||
|
|
||||||
|
// enumerate through the settings in the description
|
||||||
|
// if we have one in the restore then use it, otherwise clear it from current settings
|
||||||
|
foreach(const QJsonValue& descriptionGroupValue, filteredDescriptionArray) {
|
||||||
|
QJsonObject descriptionGroupObject = descriptionGroupValue.toObject();
|
||||||
|
QString groupKey = descriptionGroupObject[DESCRIPTION_NAME_KEY].toString();
|
||||||
|
QJsonArray descriptionGroupSettings = descriptionGroupObject[DESCRIPTION_SETTINGS_KEY].toArray();
|
||||||
|
|
||||||
|
// grab the matching group from the restore so we can look at its settings
|
||||||
|
QJsonObject restoreGroup;
|
||||||
|
QVariantMap* configGroupMap = nullptr;
|
||||||
|
|
||||||
|
if (groupKey.isEmpty()) {
|
||||||
|
// this is for a setting at the root, use the full object as our restore group
|
||||||
|
restoreGroup = settingsToRestore;
|
||||||
|
|
||||||
|
// the variant map for this "group" is just the config map since there's no group
|
||||||
|
configGroupMap = &_configMap.getConfig();
|
||||||
|
} else {
|
||||||
|
if (settingsToRestore.contains(groupKey)) {
|
||||||
|
restoreGroup = settingsToRestore[groupKey].toObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// grab the variant for the group
|
||||||
|
auto groupMapVariant = _configMap.valueForKeyPath(groupKey);
|
||||||
|
|
||||||
|
// if it existed, double check that it is a map - any other value is unexpected and should cancel a restore
|
||||||
|
if (groupMapVariant) {
|
||||||
|
if (groupMapVariant->canConvert<QVariantMap>()) {
|
||||||
|
configGroupMap = static_cast<QVariantMap*>(groupMapVariant->data());
|
||||||
|
} else {
|
||||||
|
shouldCancelRestore = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(const QJsonValue& descriptionSettingValue, descriptionGroupSettings) {
|
||||||
|
const QString VALUE_HIDDEN_FLAG_KEY = "value-hidden";
|
||||||
|
|
||||||
|
QJsonObject descriptionSettingObject = descriptionSettingValue.toObject();
|
||||||
|
|
||||||
|
// we'll override this setting with the default or what is in the restore as long as it isn't hidden
|
||||||
|
if (!descriptionSettingObject[VALUE_HIDDEN_FLAG_KEY].toBool()) {
|
||||||
|
|
||||||
|
QString settingName = descriptionSettingObject[DESCRIPTION_NAME_KEY].toString();
|
||||||
|
|
||||||
|
// check if we have a matching setting for this in the restore
|
||||||
|
QJsonValue restoreValue;
|
||||||
|
if (restoreGroup.contains(settingName)) {
|
||||||
|
restoreValue = restoreGroup[settingName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// we should create the value for this key path in our current config map
|
||||||
|
// if we had value in the restore file
|
||||||
|
bool shouldCreateIfMissing = !restoreValue.isNull();
|
||||||
|
|
||||||
|
// get a QVariant pointer to this setting in our config map
|
||||||
|
QString fullSettingKey = !groupKey.isEmpty()
|
||||||
|
? groupKey + "." + settingName : settingName;
|
||||||
|
|
||||||
|
QVariant* variantValue = _configMap.valueForKeyPath(fullSettingKey, shouldCreateIfMissing);
|
||||||
|
|
||||||
|
if (restoreValue.isNull()) {
|
||||||
|
if (variantValue && !variantValue->isNull() && configGroupMap) {
|
||||||
|
// we didn't have a value to restore, but there might be a value in the config map
|
||||||
|
// so we need to remove the value in the config map which will set it back to the default
|
||||||
|
qDebug() << "Removing" << fullSettingKey << "from settings since it is not in the restored JSON";
|
||||||
|
configGroupMap->remove(settingName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we have a value to restore, use update setting to set it
|
||||||
|
|
||||||
|
// we might need to re-grab config group map in case it didn't exist when we looked for it before
|
||||||
|
// but was created by the call to valueForKeyPath before
|
||||||
|
if (!configGroupMap) {
|
||||||
|
auto groupMapVariant = _configMap.valueForKeyPath(groupKey);
|
||||||
|
if (groupMapVariant && groupMapVariant->canConvert<QVariantMap>()) {
|
||||||
|
configGroupMap = static_cast<QVariantMap*>(groupMapVariant->data());
|
||||||
|
} else {
|
||||||
|
shouldCancelRestore = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Updating setting" << fullSettingKey << "from restored JSON";
|
||||||
|
|
||||||
|
updateSetting(settingName, restoreValue, *configGroupMap, descriptionSettingObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldCancelRestore) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldCancelRestore) {
|
||||||
|
// if we cancelled the restore, go back to our state before and return false
|
||||||
|
qDebug() << "Restore cancelled, settings have not been changed";
|
||||||
|
_configMap.getConfig() = preRestoreConfig;
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// restore completed, persist the new settings
|
||||||
|
qDebug() << "Restore completed, persisting restored settings to file";
|
||||||
|
persistToFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject DomainServerSettingsManager::settingsResponseObjectForType(const QString& typeValue, bool isAuthenticated,
|
||||||
|
bool includeDomainSettings,
|
||||||
|
bool includeContentSettings,
|
||||||
|
bool includeDefaults) {
|
||||||
QJsonObject responseObject;
|
QJsonObject responseObject;
|
||||||
|
|
||||||
if (!typeValue.isEmpty() || isAuthenticated) {
|
if (!typeValue.isEmpty() || isAuthenticated) {
|
||||||
|
@ -1152,6 +1324,7 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
||||||
|
|
||||||
const QString AFFECTED_TYPES_JSON_KEY = "assignment-types";
|
const QString AFFECTED_TYPES_JSON_KEY = "assignment-types";
|
||||||
|
|
||||||
|
// only enumerate the requested settings type (domain setting or content setting)
|
||||||
QJsonArray& filteredDescriptionArray = _descriptionArray;
|
QJsonArray& filteredDescriptionArray = _descriptionArray;
|
||||||
if (includeDomainSettings && !includeContentSettings) {
|
if (includeDomainSettings && !includeContentSettings) {
|
||||||
filteredDescriptionArray = _domainSettingsDescription;
|
filteredDescriptionArray = _domainSettingsDescription;
|
||||||
|
@ -1159,7 +1332,7 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
||||||
filteredDescriptionArray = _contentSettingsDescription;
|
filteredDescriptionArray = _contentSettingsDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
// enumerate the groups in the description object to find which settings to pass
|
// enumerate the groups in the potentially filtered object to find which settings to pass
|
||||||
foreach(const QJsonValue& groupValue, filteredDescriptionArray) {
|
foreach(const QJsonValue& groupValue, filteredDescriptionArray) {
|
||||||
QJsonObject groupObject = groupValue.toObject();
|
QJsonObject groupObject = groupValue.toObject();
|
||||||
QString groupKey = groupObject[DESCRIPTION_NAME_KEY].toString();
|
QString groupKey = groupObject[DESCRIPTION_NAME_KEY].toString();
|
||||||
|
@ -1174,7 +1347,6 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
||||||
QJsonObject settingObject = settingValue.toObject();
|
QJsonObject settingObject = settingValue.toObject();
|
||||||
|
|
||||||
// consider this setting as long as it isn't hidden
|
// consider this setting as long as it isn't hidden
|
||||||
// and we've been asked to include this type (domain setting or content setting)
|
|
||||||
if (!settingObject[VALUE_HIDDEN_FLAG_KEY].toBool()) {
|
if (!settingObject[VALUE_HIDDEN_FLAG_KEY].toBool()) {
|
||||||
QJsonArray affectedTypesArray = settingObject[AFFECTED_TYPES_JSON_KEY].toArray();
|
QJsonArray affectedTypesArray = settingObject[AFFECTED_TYPES_JSON_KEY].toArray();
|
||||||
if (affectedTypesArray.isEmpty()) {
|
if (affectedTypesArray.isEmpty()) {
|
||||||
|
@ -1183,8 +1355,6 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
||||||
|
|
||||||
if (affectedTypesArray.contains(queryType) ||
|
if (affectedTypesArray.contains(queryType) ||
|
||||||
(queryType.isNull() && isAuthenticated)) {
|
(queryType.isNull() && isAuthenticated)) {
|
||||||
// this is a setting we should include in the responseObject
|
|
||||||
|
|
||||||
QString settingName = settingObject[DESCRIPTION_NAME_KEY].toString();
|
QString settingName = settingObject[DESCRIPTION_NAME_KEY].toString();
|
||||||
|
|
||||||
// we need to check if the settings map has a value for this setting
|
// we need to check if the settings map has a value for this setting
|
||||||
|
@ -1200,28 +1370,31 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty
|
||||||
variantValue = _configMap.value(settingName);
|
variantValue = _configMap.value(settingName);
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonValue result;
|
// final check for inclusion, either we include default values
|
||||||
|
// or we don't but this isn't a default value
|
||||||
|
if (includeDefaults || !variantValue.isNull()) {
|
||||||
|
QJsonValue result;
|
||||||
|
|
||||||
if (variantValue.isNull()) {
|
if (variantValue.isNull()) {
|
||||||
// no value for this setting, pass the default
|
// no value for this setting, pass the default
|
||||||
if (settingObject.contains(SETTING_DEFAULT_KEY)) {
|
if (settingObject.contains(SETTING_DEFAULT_KEY)) {
|
||||||
result = settingObject[SETTING_DEFAULT_KEY];
|
result = settingObject[SETTING_DEFAULT_KEY];
|
||||||
|
} else {
|
||||||
|
// users are allowed not to provide a default for string values
|
||||||
|
// if so we set to the empty string
|
||||||
|
result = QString("");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// users are allowed not to provide a default for string values
|
result = QJsonValue::fromVariant(variantValue);
|
||||||
// if so we set to the empty string
|
|
||||||
result = QString("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
if (!groupKey.isEmpty()) {
|
||||||
result = QJsonValue::fromVariant(variantValue);
|
// this belongs in the group object
|
||||||
}
|
groupResponseObject[settingName] = result;
|
||||||
|
} else {
|
||||||
if (!groupKey.isEmpty()) {
|
// this is a value that should be at the root
|
||||||
// this belongs in the group object
|
responseObject[settingName] = result;
|
||||||
groupResponseObject[settingName] = result;
|
}
|
||||||
} else {
|
|
||||||
// this is a value that should be at the root
|
|
||||||
responseObject[settingName] = result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1266,6 +1439,8 @@ void DomainServerSettingsManager::updateSetting(const QString& key, const QJsonV
|
||||||
settingMap[key] = sanitizedValue;
|
settingMap[key] = sanitizedValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (newValue.isDouble()) {
|
||||||
|
settingMap[key] = newValue.toDouble();
|
||||||
} else if (newValue.isBool()) {
|
} else if (newValue.isBool()) {
|
||||||
settingMap[key] = newValue.toBool();
|
settingMap[key] = newValue.toBool();
|
||||||
} else if (newValue.isObject()) {
|
} else if (newValue.isObject()) {
|
||||||
|
|
|
@ -130,8 +130,9 @@ private:
|
||||||
QStringList _argumentList;
|
QStringList _argumentList;
|
||||||
|
|
||||||
QJsonArray filteredDescriptionArray(bool isContentSettings);
|
QJsonArray filteredDescriptionArray(bool isContentSettings);
|
||||||
QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false,
|
QJsonObject settingsResponseObjectForType(const QString& typeValue, bool isAuthenticated = false,
|
||||||
bool includeDomainSettings = true, bool includeContentSettings = true);
|
bool includeDomainSettings = true, bool includeContentSettings = true,
|
||||||
|
bool includeDefaults = true);
|
||||||
bool recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, SettingsType settingsType);
|
bool recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, SettingsType settingsType);
|
||||||
|
|
||||||
void updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
|
void updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
|
||||||
|
@ -142,6 +143,8 @@ private:
|
||||||
|
|
||||||
void splitSettingsDescription();
|
void splitSettingsDescription();
|
||||||
|
|
||||||
|
bool restoreSettingsFromObject(QJsonObject settingsToRestore, SettingsType settingsType);
|
||||||
|
|
||||||
double _descriptionVersion;
|
double _descriptionVersion;
|
||||||
|
|
||||||
QJsonArray _descriptionArray;
|
QJsonArray _descriptionArray;
|
||||||
|
|
Loading…
Reference in a new issue