stephb9959
2023-01-26 21:14:57 -08:00
parent d5e0687ade
commit 0b35942ef6
8 changed files with 902 additions and 398 deletions

View File

@@ -43,8 +43,8 @@ find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
find_package(Poco REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite)
find_package(nlohmann_json REQUIRED)
find_package(nlohmann_json_schema_validator REQUIRED)
find_package(fmt REQUIRED)
find_package(valijson REQUIRED)
if(SMALL_BUILD)
find_package(Poco REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite)
@@ -210,6 +210,5 @@ target_link_libraries(owprov PUBLIC
${MySQL_LIBRARIES}
${ZLIB_LIBRARIES}
CppKafka::cppkafka
fmt::fmt
nlohmann_json_schema_validator)
fmt::fmt)

2
build
View File

@@ -1 +1 @@
6
10

View File

@@ -87,8 +87,8 @@ namespace OpenWifi{
}
auto Config=RawObject->get("configuration").toString();
Poco::JSON::Object Answer;
std::string Error;
auto Res = ValidateUCentralConfiguration(Config,Error);
std::vector<std::string> Error;
auto Res = ValidateUCentralConfiguration(Config,Error, GetBoolParameter("strict",true));
Answer.set("valid",Res);
Answer.set("error", Error);
return ReturnObject(Answer);
@@ -124,9 +124,9 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidDeviceTypes);
}
RESTAPI::Errors::msg Error;
if(!ValidateConfigBlock(NewObject,Error)) {
return BadRequest(Error);
std::vector<std::string> Errors;
if(!ValidateConfigBlock(NewObject,Errors)) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
if(DB_.CreateRecord(NewObject)) {
@@ -171,9 +171,9 @@ namespace OpenWifi{
if(!NewObject.deviceTypes.empty())
Existing.deviceTypes = NewObject.deviceTypes;
RESTAPI::Errors::msg Error;
if(!ValidateConfigBlock( NewObject,Error)) {
return BadRequest(Error);
std::vector<std::string> Errors;
if(!ValidateConfigBlock( NewObject,Errors)) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
if(RawObject->has("configuration")) {

View File

@@ -406,7 +406,7 @@ namespace OpenWifi {
return EntityDB::RootUUID();
}
inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, RESTAPI::Errors::msg & Error) {
inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, std::vector<std::string> &Errors) {
static const std::vector<std::string> SectionNames{ "globals", "interfaces", "metrics", "radios", "services",
"unit", "definitions", "ethernet", "switch", "config-raw",
"third-party" };
@@ -414,8 +414,7 @@ namespace OpenWifi {
for(const auto &i:Config.configuration) {
Poco::JSON::Parser P;
if(i.name.empty()) {
std::cout << "Name is empty" << std::endl;
Error = RESTAPI::Errors::NameMustBeSet;
Errors.push_back("Name is empty");
return false;
}
@@ -424,25 +423,23 @@ namespace OpenWifi {
auto N = Blocks->getNames();
for (const auto &j: N) {
if (std::find(SectionNames.cbegin(), SectionNames.cend(), j) == SectionNames.cend()) {
Error = RESTAPI::Errors::UnknownConfigurationSection;
Errors.push_back("Unknown block name");
return false;
}
}
} catch (const Poco::JSON::JSONException &E ) {
Error = RESTAPI::Errors::InvalidJSONDocument;
Errors.push_back("Invalid JSON document");
return false;
}
try {
std::string ErrorText;
if (ValidateUCentralConfiguration(i.configuration, ErrorText)) {
if (ValidateUCentralConfiguration(i.configuration, Errors,true)) {
// std::cout << "Block: " << i.name << " is valid" << std::endl;
} else {
Error = RESTAPI::Errors::ConfigBlockInvalid ;
return false;
}
} catch(...) {
std::cout << "Exception in validation" << std::endl;
Errors.push_back("Invalid configuration caused an exception");
return false;
}
@@ -450,12 +447,11 @@ namespace OpenWifi {
return true;
}
template <typename Type> std::map<std::string,std::string> CreateObjects(Type & NewObject, RESTAPIHandler & R, RESTAPI::Errors::msg & Error) {
template <typename Type> std::map<std::string,std::string> CreateObjects(Type & NewObject, RESTAPIHandler & R, std::vector<std::string> & Errors) {
std::map<std::string,std::string> Result;
auto createObjects = R.GetParameter("createObjects","");
if(!createObjects.empty()) {
std::cout << "createObjects: " << createObjects << std::endl;
Poco::JSON::Parser P;
auto Objects = P.parse(createObjects).extract<Poco::JSON::Object::Ptr>();
if(Objects->isArray("objects")) {
@@ -467,7 +463,6 @@ namespace OpenWifi {
ProvObjects::Location LC;
if (LC.from_json(LocationDetails)) {
if constexpr(std::is_same_v<Type,ProvObjects::Venue>) {
std::cout << "Location decoded: " << LC.info.name << std::endl;
std::string ParentEntity = FindParentEntity(NewObject);
ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, LC.info);
LC.entity = ParentEntity;
@@ -479,7 +474,6 @@ namespace OpenWifi {
}
}
if constexpr(std::is_same_v<Type,ProvObjects::Operator>) {
std::cout << "Location decoded: " << LC.info.name << std::endl;
std::string ParentEntity = FindParentEntity(NewObject);
ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, LC.info);
LC.entity = ParentEntity;
@@ -491,7 +485,7 @@ namespace OpenWifi {
}
}
} else {
Error = RESTAPI::Errors::InvalidJSONDocument;
Errors.push_back("Invalid JSON document");
break;
}
} else if (Object->has("contact")) {
@@ -507,10 +501,9 @@ namespace OpenWifi {
ProvObjects::DeviceConfiguration DC;
if(DC.from_json(ConfigurationDetails)) {
if constexpr(std::is_same_v<Type, ProvObjects::InventoryTag>) {
if(!ValidateConfigBlock(DC,Error)) {
if(!ValidateConfigBlock(DC,Errors)) {
break;
}
std::cout << "Configuration decoded: " << DC.info.name << std::endl;
ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, DC.info);
if (StorageService()->ConfigurationDB().CreateRecord(DC)) {
NewObject.deviceConfiguration = DC.info.id;
@@ -518,7 +511,7 @@ namespace OpenWifi {
}
}
} else {
Error = RESTAPI::Errors::InvalidJSONDocument;
Errors.push_back("Invalid JSON document");
break;
}
}

View File

@@ -239,10 +239,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
}
RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
if(Error.err_num != 0) {
return BadRequest(Error);
std::vector<std::string> Errors;
auto ObjectsCreated = CreateObjects(NewObject,*this,Errors);
if(!Errors.empty()) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
if(DB_.CreateRecord(NewObject)) {
@@ -396,10 +396,10 @@ namespace OpenWifi{
Existing.state = NewObject.state;
}
RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
if(Error.err_num != 0) {
return BadRequest(Error);
std::vector<std::string> Errors;
auto ObjectsCreated = CreateObjects(NewObject,*this,Errors);
if(!Errors.empty()) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
if(!ObjectsCreated.empty()) {

View File

@@ -185,9 +185,10 @@ namespace OpenWifi{
NewObject.children.clear();
RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
std::vector<std::string> Errors;
auto ObjectsCreated = CreateObjects(NewObject,*this,Errors);
if(Error.err_num != 0) {
return BadRequest(Error);
return BadRequest(RESTAPI::Errors::InternalError);
}
if(DB_.CreateRecord(NewObject)) {
@@ -355,10 +356,10 @@ namespace OpenWifi{
NewObject.parent = Existing.parent;
NewObject.entity = Existing.entity;
RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
if(Error.err_num != 0) {
return BadRequest(Error);
std::vector<std::string> Errors;
auto ObjectsCreated = CreateObjects(NewObject,*this,Errors);
if(!Errors.empty()) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid);
}
if(!ObjectsCreated.empty()) {

File diff suppressed because it is too large Load Diff

View File

@@ -4,11 +4,15 @@
#pragma once
#include <nlohmann/json-schema.hpp>
#include "framework/SubSystemServer.h"
using nlohmann::json;
using nlohmann::json_schema::json_validator;
#include <valijson/adapters/poco_json_adapter.hpp>
#include <valijson/utils/poco_json_utils.hpp>
#include <valijson/schema.hpp>
#include <valijson/schema_parser.hpp>
#include <valijson/validator.hpp>
#include <valijson/constraints/constraint.hpp>
#include <valijson/constraints/constraint_visitor.hpp>
namespace OpenWifi {
class ConfigurationValidator : public SubSystemServer {
@@ -19,8 +23,7 @@ namespace OpenWifi {
return instance_;
}
bool Validate(const std::string &C, std::string &Error);
static void my_format_checker(const std::string &format, const std::string &value);
bool Validate(const std::string &C, std::vector<std::string> &Errors, bool Strict);
int Start() override;
void Stop() override;
void reinitialize(Poco::Util::Application &self) override;
@@ -29,7 +32,10 @@ namespace OpenWifi {
bool Initialized_=false;
bool Working_=false;
void Init();
nlohmann::json RootSchema_;
std::unique_ptr<valijson::Schema> RootSchema_;
std::unique_ptr<valijson::SchemaParser> SchemaParser_;
std::unique_ptr<valijson::adapters::PocoJsonAdapter> PocoJsonAdapter_;
Poco::JSON::Object::Ptr SchemaDocPtr_;
ConfigurationValidator():
SubSystemServer("ConfigValidator", "CFG-VALIDATOR", "config.validator") {
@@ -37,6 +43,6 @@ namespace OpenWifi {
};
inline auto ConfigurationValidator() { return ConfigurationValidator::instance(); }
inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); }
inline bool ValidateUCentralConfiguration(const std::string &C, std::vector<std::string> &Error, bool strict) { return ConfigurationValidator::instance()->Validate(C, Error, strict); }
}