Refactor config API

This commit is contained in:
LordGrey
2024-08-01 23:07:18 +02:00
parent 4a5b0b6bf2
commit c86af5ce79
42 changed files with 1605 additions and 889 deletions

View File

@@ -405,20 +405,6 @@ bool API::saveSettings(const QJsonObject &data)
return isSaved;
}
bool API::restoreSettings(const QJsonObject &data)
{
bool isRestored {true};
if (!_adminAuthorized)
{
isRestored = false;
}
else
{
QMetaObject::invokeMethod(_hyperion, "restoreSettings", Qt::DirectConnection, Q_RETURN_ARG(bool, isRestored), Q_ARG(QJsonObject, data), Q_ARG(bool, true));
}
return isRestored;
}
bool API::updateHyperionPassword(const QString &password, const QString &newPassword)
{
bool isPwUpdated {true};

View File

@@ -10,18 +10,38 @@
"subcommand": {
"type" : "string",
"required" : true,
"enum" : ["getconfig","getschema","setconfig","restoreconfig","reload"]
},
"instance" : {
"type" : "integer",
"minimum": 0,
"maximum": 255
"enum" : ["getconfig","getconfig-old","getschema","setconfig","restoreconfig","reload"]
},
"tan" : {
"type" : "integer"
},
"global" : {
"types": {
"type": "array",
"required": false,
"items" : {
"type" : "string"
}
}
},
"instances" : {
"ids" : {
"type": "array",
"required": true,
"items" : {},
"minItems": 1
},
"types": {
"type": "array",
"required": false,
"items" :{
"type" : "string"
}
}
},
"config": {
"type" : "object"
"required": false,
"$ref": "schema-config-exchange"
}
},
"additionalProperties": false

View File

@@ -39,6 +39,7 @@
// auth manager
#include <hyperion/AuthManager.h>
#include <db/ConfigImportExport.h>
#ifdef ENABLE_MDNS
// mDNS discover
@@ -697,7 +698,11 @@ void JsonAPI::handleConfigCommand(const QJsonObject& message, const JsonApiComma
handleSchemaGetCommand(message, cmd);
break;
case SubCommand::GetConfig:
case SubCommand::GetConfig:
handleConfigGetCommand(message, cmd);
break;
case SubCommand::GetConfigOld:
sendSuccessDataReply(_hyperion->getQJsonConfig(), cmd);
break;
@@ -722,45 +727,130 @@ void JsonAPI::handleConfigCommand(const QJsonObject& message, const JsonApiComma
void JsonAPI::handleConfigSetCommand(const QJsonObject &message, const JsonApiCommand& cmd)
{
if (message.contains("config"))
if (DBManager::isReadOnly())
{
QJsonObject config = message["config"].toObject();
if (API::isHyperionEnabled())
{
if ( API::saveSettings(config) ) {
sendSuccessReply(cmd);
} else {
sendErrorReply("Save settings failed", cmd);
sendErrorReply("Database Error", {"Hyperion is running in read-only mode","Configuration updates are not possible"}, cmd);
return;
}
QJsonObject config = message["config"].toObject();
QJsonObject schema = QJsonFactory::readSchema(":schema-config-exchange");
QPair<bool, QStringList> validationResult = JsonUtils::validate("setConfig", config, schema, _log);
if (!validationResult.first)
{
sendErrorReply("Invalid JSON configuration data provided!", validationResult.second, cmd);
return;
}
// TODO: Implement new setconfig schema
if (config.contains("global") || config.contains("instances"))
{
Warning(_log, "New set config schema is not yet supported!");
config.remove("global");
config.remove("instanceIds");
config.remove("instances");
}
if (config.isEmpty())
{
sendErrorReply("Update configuration failed", {"No configuration data provided!"}, cmd);
return;
}
if (API::isHyperionEnabled())
{
if ( API::saveSettings(config) ) {
sendSuccessReply(cmd);
} else {
sendErrorReply("Save settings failed", cmd);
}
}
else
{
sendErrorReply("Updating the configuration while Hyperion is disabled is not possible", cmd);
}
}
void JsonAPI::handleConfigGetCommand(const QJsonObject &message, const JsonApiCommand& cmd)
{
bool addGlobalConfig {false};
QStringList globalFilterTypes;
if (message.contains("global"))
{
addGlobalConfig = true;
const QJsonObject globalConfig = message["global"].toObject();
const QJsonArray globalTypes = globalConfig["types"].toArray();
for (const QJsonValue &type : globalTypes) {
if (type.isString()) {
globalFilterTypes.append(type.toString());
}
}
else
{
sendErrorReply("Saving configuration while Hyperion is disabled isn't possible", cmd);
}
QList<quint8> instanceListFilter;
QStringList instanceFilterTypes;
bool addInstanceConfig {false};
if (message.contains("instances"))
{
addInstanceConfig = true;
const QJsonObject instances = message["instances"].toObject();
const QJsonArray instanceIds = instances["ids"].toArray();
for (const QJsonValue &idx : instanceIds) {
if (idx.isDouble()) {
instanceListFilter.append(static_cast<quint8>(idx.toInt()));
}
}
const QJsonArray instanceTypes = instances["types"].toArray();
for (const QJsonValue &type : instanceTypes) {
if (type.isString()) {
instanceFilterTypes.append(type.toString());
}
}
}
if (!addGlobalConfig && ! addInstanceConfig)
{
addGlobalConfig = true;
}
const QJsonObject settings = JsonInfo::getConfiguration(instanceListFilter, addGlobalConfig, instanceFilterTypes, globalFilterTypes);
if (!settings.empty())
{
sendSuccessDataReply(settings, cmd);
}
else
{
sendErrorReply("Generating full config failed", cmd);
}
}
void JsonAPI::handleConfigRestoreCommand(const QJsonObject &message, const JsonApiCommand& cmd)
{
if (message.contains("config"))
QJsonObject config = message["config"].toObject();
if (API::isHyperionEnabled())
{
QJsonObject config = message["config"].toObject();
if (API::isHyperionEnabled())
ConfigImportExport configImport;
QPair<bool, QStringList> result = configImport.setConfiguration(config);
if (result.first)
{
if ( API::restoreSettings(config) )
{
sendSuccessReply(cmd);
}
else
{
sendErrorReply("Restore settings failed", cmd);
}
QString infoMsg {"Restarting after importing configuration successfully."};
sendSuccessDataReply(infoMsg, cmd);
Info(_log, "%s", QSTRING_CSTR(infoMsg));
emit signalEvent(Event::Restart);
}
else
{
sendErrorReply("Restoring configuration while Hyperion is disabled is not possible", cmd);
sendErrorReply("Restore configuration failed", result.second, cmd);
}
}
else
{
sendErrorReply("Restoring configuration while Hyperion is disabled is not possible", cmd);
}
}
void JsonAPI::handleSchemaGetCommand(const QJsonObject& /*message*/, const JsonApiCommand& cmd)
@@ -1156,7 +1246,7 @@ void JsonAPI::handleInstanceCommand(const QJsonObject &message, const JsonApiCom
{
QString replyMsg;
const quint8 &inst = static_cast<quint8>(message["instance"].toInt());
const quint8 inst = static_cast<quint8>(message["instance"].toInt());
const QString &name = message["name"].toString();
switch (cmd.subCommand) {
@@ -1191,7 +1281,6 @@ void JsonAPI::handleInstanceCommand(const QJsonObject &message, const JsonApiCom
break;
case SubCommand::DeleteInstance:
handleConfigRestoreCommand(message, cmd);
if (API::deleteInstance(inst, replyMsg))
{
sendSuccessReply(cmd);
@@ -1213,7 +1302,7 @@ void JsonAPI::handleInstanceCommand(const QJsonObject &message, const JsonApiCom
if (cmd.subCommand == SubCommand::CreateInstance) {
replyMsg = API::createInstance(name);
} else {
replyMsg = setInstanceName(inst, name);
replyMsg = API::setInstanceName(inst, name);
}
if (replyMsg.isEmpty()) {

View File

@@ -1,3 +1,4 @@
#include <db/ConfigImportExport.h>
#include <api/JsonInfo.h>
#include <api/API.h>
@@ -498,8 +499,8 @@ QJsonObject JsonInfo::getSystemInfo(const Hyperion* hyperion)
hyperionInfo["gitremote"] = QString(HYPERION_GIT_REMOTE);
hyperionInfo["time"] = QString(__DATE__ " " __TIME__);
hyperionInfo["id"] = AuthManager::getInstance()->getID();
hyperionInfo["rootPath"] = HyperionIManager::getInstance()->getRootPath();
hyperionInfo["readOnlyMode"] = hyperion->getReadOnlyMode();
hyperionInfo["configDatabaseFile"] = DBManager::getFileInfo().absoluteFilePath();
hyperionInfo["readOnlyMode"] = DBManager::isReadOnly();
QCoreApplication* app = QCoreApplication::instance();
hyperionInfo["isGuiMode"] = qobject_cast<QApplication*>(app) != nullptr;
@@ -618,3 +619,9 @@ QJsonArray JsonInfo::discoverScreenInputs(const QJsonObject& params) const
return screenInputs;
}
QJsonObject JsonInfo::getConfiguration(const QList<quint8>& instancesfilter, bool addGlobalConfig, const QStringList& instanceFilteredTypes, const QStringList& globalFilterTypes )
{
ConfigImportExport configExport;
return configExport.getConfiguration(instancesfilter, addGlobalConfig, instanceFilteredTypes, globalFilterTypes );
}