Fixing ConfigurationValidator to not crash.

This commit is contained in:
stephb9959
2021-10-30 15:30:49 -07:00
parent a8079b04c8
commit dc326ea00e
21 changed files with 619 additions and 73 deletions

View File

@@ -61,6 +61,8 @@ add_executable(owprov
src/framework/RESTAPI_protocol.h
src/framework/StorageClass.h
src/framework/uCentral_Protocol.h
src/framework/ConfigurationValidator.cpp
src/framework/ConfigurationValidator.h
src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp
@@ -98,12 +100,14 @@ add_executable(owprov
src/SerialNumberCache.h src/SerialNumberCache.cpp
src/SecurityDBProxy.cpp src/SecurityDBProxy.h
src/APConfig.cpp src/APConfig.h
src/ConfigurationValidator.cpp src/ConfigurationValidator.h
src/AutoDiscovery.cpp src/AutoDiscovery.h
src/SDK_stubs.cpp src/SDK_stubs.h
src/ConfigSanityChecker.cpp src/ConfigSanityChecker.h
src/TagServer.cpp src/TagServer.h
src/RESTAPI/RESTAPI_db_helpers.h)
src/RESTAPI/RESTAPI_db_helpers.h
src/JobController.cpp src/JobController.h
src/JobRegistrations.cpp
src/storage/storage_jobs.cpp src/storage/storage_jobs.h)
target_link_libraries(owprov PUBLIC
${Poco_LIBRARIES} ${MySQL_LIBRARIES}

2
build
View File

@@ -1 +1 @@
9
19

View File

@@ -15,8 +15,9 @@
#include "StorageService.h"
#include "SecurityDBProxy.h"
#include "AutoDiscovery.h"
#include "ConfigurationValidator.h"
#include "framework/ConfigurationValidator.h"
#include "SerialNumberCache.h"
#include "JobController.h"
namespace OpenWifi {
class Daemon *Daemon::instance_ = nullptr;
@@ -33,7 +34,8 @@ namespace OpenWifi {
ConfigurationValidator(),
SerialNumberCache(),
SecurityDBProxy(),
AutoDiscovery()
AutoDiscovery(),
JobController()
});
}
return instance_;

37
src/JobController.cpp Normal file
View File

@@ -0,0 +1,37 @@
//
// Created by stephane bourque on 2021-10-28.
//
#include "JobController.h"
namespace OpenWifi {
void RegisterJobTypes();
int JobController::Start() {
RegisterJobTypes();
if(!Running_)
Thr_.start(*this);
return 0;
}
void JobController::Stop() {
if(Running_) {
Running_ = false;
Thr_.join();
}
}
void JobController::run() {
Running_ = true ;
while(Running_) {
Poco::Thread::trySleep(2000);
}
}
}

142
src/JobController.h Normal file
View File

@@ -0,0 +1,142 @@
//
// Created by stephane bourque on 2021-10-28.
//
#ifndef OWPROV_JOBCONTROLLER_H
#define OWPROV_JOBCONTROLLER_H
#include <vector>
#include <utility>
#include <functional>
#include "framework/MicroService.h"
namespace OpenWifi {
class Job {
public:
struct Parameter {
std::string name;
std::string value;
inline void to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"name",name);
RESTAPI_utils::field_to_json(Obj,"value",value);
}
inline bool from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"name",name);
RESTAPI_utils::field_from_json(Obj,"value",value);
return true;
} catch (...) {
}
return false;
}
};
struct Status {
Types::UUID_t UUID;
uint64_t Start = 0 ;
uint64_t Progress = 0 ;
uint64_t Completed = 0 ;
std::string CurrentDisplay;
};
struct Result {
int Error=0;
std::string Reason;
};
typedef std::vector<Parameter> Parameters;
typedef std::vector<Parameters> ParametersVec;
typedef std::function<bool(const Parameters &Parameters, Result &Result, bool &Retry)> WorkerFunction;
typedef std::vector<Status> Statuses;
Job(std::string Title,
std::string Description,
std::string RegisteredName,
ParametersVec Parameters,
bool Parallel=true) :
Title_(std::move(Title)),
Description_(std::move(Description)),
RegisteredName_(std::move(RegisteredName)),
Parameters_(std::move(Parameters)),
Parallel_(Parallel)
{
UUID_ = MicroService::instance().CreateUUID();
}
[[nodiscard]] inline const Types::UUID_t & ID() const { return UUID_; }
private:
Types::UUID_t UUID_;
std::string Title_;
std::string Description_;
std::string RegisteredName_;
ParametersVec Parameters_;
bool Parallel_=true;
};
class JobRegistry {
public:
static JobRegistry *instance() {
if (instance_ == nullptr) {
instance_ = new JobRegistry;
}
return instance_;
}
inline void RegisterJobType( const std::string & JobType, Job::WorkerFunction Function) {
JobTypes_[JobType] = std::move(Function);
}
inline bool Execute(const std::string &JobType, const Job::Parameters & Params, Job::Result &Result, bool & Retry) {
auto Hint = JobTypes_.find(JobType);
if(Hint != end(JobTypes_)) {
Hint->second(Params, Result, Retry);
return true;
}
return false;
}
private:
static JobRegistry *instance_;
std::map<std::string,Job::WorkerFunction> JobTypes_;
};
inline JobRegistry * JobRegistry() { return JobRegistry::instance(); }
inline class JobRegistry * JobRegistry::instance_ = nullptr;
class JobController : public SubSystemServer, Poco::Runnable {
public:
static JobController *instance() {
if (instance_ == nullptr) {
instance_ = new JobController;
}
return instance_;
}
int Start() override;
void Stop() override;
void run() override;
inline void wakeup() { Thr_.wakeUp(); }
bool JobList(Job::Statuses & Statuses);
private:
static JobController *instance_;
Poco::Thread Thr_;
std::atomic_bool Running_=false;
JobController() noexcept:
SubSystemServer("JobController", "JOB-SVR", "job")
{
}
};
inline JobController * JobController() { return JobController::instance(); }
inline class JobController * JobController::instance_ = nullptr;
}
#endif //OWPROV_JOBCONTROLLER_H

11
src/JobRegistrations.cpp Normal file
View File

@@ -0,0 +1,11 @@
//
// Created by stephane bourque on 2021-10-28.
//
namespace OpenWifi {
void RegisterJobTypes() {
}
}

View File

@@ -12,7 +12,7 @@
#include "RESTObjects/RESTAPI_ProvObjects.h"
#include "StorageService.h"
#include "framework/RESTAPI_errors.h"
#include "ConfigurationValidator.h"
#include "framework/ConfigurationValidator.h"
#include "RESTAPI/RESTAPI_db_helpers.h"
namespace OpenWifi{
@@ -127,7 +127,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(C.info.name.empty()) {
if(!ProvObjects::CreateObjectInfo(Obj,UserInfo_.userinfo,C.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
@@ -135,11 +135,6 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::UnknownId);
}
C.info.modified = C.info.created = std::time(nullptr);
C.info.id = MicroService::instance().CreateUUID();
for(auto &i:C.info.notes)
i.createdBy = UserInfo_.userinfo.email;
C.inUse.clear();
if(C.deviceTypes.empty() || !StorageService()->AreAcceptableDeviceTypes(C.deviceTypes, true)) {
return BadRequest(RESTAPI::Errors::InvalidDeviceTypes);
@@ -175,6 +170,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!UpdateObjectInfo(ParsedObj, UserInfo_.userinfo, Existing.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
if(!NewConfig.deviceTypes.empty() && !StorageService()->AreAcceptableDeviceTypes(NewConfig.deviceTypes, true)) {
return BadRequest(RESTAPI::Errors::InvalidDeviceTypes);
}
@@ -188,8 +187,6 @@ namespace OpenWifi{
Existing.configuration = NewConfig.configuration;
}
UpdateObjectInfo(ParsedObj, UserInfo_.userinfo, Existing.info);
std::string MovePolicy;
bool MovingPolicy=false;
if(AssignIfPresent(ParsedObj,"managementPolicy",MovePolicy)) {

View File

@@ -88,6 +88,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!ProvObjects::CreateObjectInfo(Obj,UserInfo_.userinfo,NewObject.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
if(NewObject.entity.empty() || !StorageService()->EntityDB().Exists("id",NewObject.entity)) {
return BadRequest(RESTAPI::Errors::EntityMustExist);
}
@@ -96,8 +100,6 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
}
NewObject.info.id = MicroService::instance().CreateUUID();
NewObject.info.created = NewObject.info.modified = std::time(nullptr);
NewObject.inUse.clear();
if(DB_.CreateRecord(NewObject)) {
@@ -130,7 +132,9 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info);
if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
std::string MoveToPolicy, MoveFromPolicy;
bool MovingPolicy=false;

View File

@@ -73,14 +73,15 @@ namespace OpenWifi{
if (!NewEntity.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
NewEntity.info.modified = NewEntity.info.created = std::time(nullptr);
for(auto &i:NewEntity.info.notes)
i.createdBy = UserInfo_.userinfo.email;
if(!ProvObjects::CreateObjectInfo(Obj,UserInfo_.userinfo,NewEntity.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
// When creating an entity, it cannot have any relations other that parent, notes, name, description. Everything else
// must be conveyed through PUT.
NewEntity.info.id = (UUID==EntityDB::RootUUID()) ? UUID : MicroService::instance().CreateUUID() ;
NewEntity.info.id = (UUID==EntityDB::RootUUID()) ? UUID : MicroService::instance().CreateUUID();
if(UUID==EntityDB::RootUUID()) {
NewEntity.parent="";
} else if(NewEntity.parent.empty() || !DB_.Exists("id",NewEntity.parent)) {
@@ -143,6 +144,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
std::string NewManagementPolicy;
Types::UUIDvec_t NewConfiguration;
bool MovingConfiguration=false,
@@ -172,8 +177,6 @@ namespace OpenWifi{
Existing.sourceIP = NewEntity.sourceIP;
}
UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info);
std::string Error;
if(!StorageService()->Validate(Parameters_,Error)) {
return BadRequest(Error);

View File

@@ -157,7 +157,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(NewObject.info.name.empty()) {
if(!ProvObjects::CreateObjectInfo(Obj, UserInfo_.userinfo, NewObject.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
@@ -193,9 +193,6 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
}
NewObject.info.modified = NewObject.info.created = std::time(nullptr);
NewObject.info.id = MicroService::instance().CreateUUID();
if(DB_.CreateRecord(NewObject)) {
SerialNumberCache()->AddSerialNumber(SerialNumber);
if (!NewObject.venue.empty())
@@ -239,7 +236,9 @@ namespace OpenWifi{
}
}
UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info);
if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
std::string NewVenue, NewEntity, NewLocation, NewContact, NewConfiguration, NewPolicy;
bool MovingVenue=false,

View File

@@ -88,6 +88,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!ProvObjects::CreateObjectInfo(Obj, UserInfo_.userinfo, NewObject.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
if(NewObject.entity.empty() || !StorageService()->EntityDB().Exists("id",NewObject.entity)) {
return BadRequest(RESTAPI::Errors::EntityMustExist);
}
@@ -96,8 +100,6 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
}
NewObject.info.id = MicroService::instance().CreateUUID();
NewObject.info.created = NewObject.info.modified = std::time(nullptr);
NewObject.inUse.clear();
if(DB_.CreateRecord(NewObject)) {
@@ -126,6 +128,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
std::string MoveFromPolicy,MoveToPolicy;
bool MovingPolicy=false;
if(AssignIfPresent(RawObject,"managementPolicy",MoveToPolicy)) {
@@ -148,8 +154,6 @@ namespace OpenWifi{
Existing.entity = MoveToEntity;
}
UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info);
AssignIfPresent(RawObject, "buildingName", Existing.buildingName);
AssignIfPresent(RawObject, "city", Existing.city);
AssignIfPresent(RawObject, "state", Existing.state);

View File

@@ -78,18 +78,17 @@ namespace OpenWifi{
}
ProvObjects::ManagementPolicy NewPolicy;
auto NewObj = ParseStream();
if(!NewPolicy.from_json(NewObj)) {
auto NewObject = ParseStream();
if(!NewPolicy.from_json(NewObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(NewPolicy.info.name.empty()) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
if(!CreateObjectInfo(NewObject, UserInfo_.userinfo, NewPolicy.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
NewPolicy.inUse.clear();
NewPolicy.info.id = MicroService::instance().CreateUUID();
NewPolicy.info.created = NewPolicy.info.modified = std::time(nullptr);
if(DB_.CreateRecord(NewPolicy)) {
ProvObjects::ManagementPolicy Policy;
DB_.GetRecord("id",NewPolicy.info.id,Policy);
@@ -113,7 +112,9 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
UpdateObjectInfo(NewObject, UserInfo_.userinfo, Existing.info);
if(!UpdateObjectInfo(NewObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
if(!NewPolicy.entries.empty())
Existing.entries = NewPolicy.entries;

View File

@@ -85,13 +85,13 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!CreateObjectInfo(Obj, UserInfo_.userinfo, NewObject.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
if(!NewObject.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) {
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
}
NewObject.info.id = MicroService::instance().CreateUUID();
NewObject.info.created = NewObject.info.modified = std::time(nullptr);
std::string f{RESTAPI::Protocol::ID};
if(DB_.CreateRecord(NewObject)) {
if(!NewObject.managementPolicy.empty())
@@ -118,7 +118,9 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info);
if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
std::string NewPolicy,OldPolicy = Existing.managementPolicy;
AssignIfPresent(RawObject, "managementPolicy", NewPolicy);

View File

@@ -72,6 +72,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if(!CreateObjectInfo(Obj, UserInfo_.userinfo, NewObject.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
if(NewObject.parent.empty() && NewObject.entity.empty()) {
return BadRequest(RESTAPI::Errors::ParentOrEntityMustBeSet);
}
@@ -117,10 +121,6 @@ namespace OpenWifi{
}
NewObject.children.clear();
NewObject.info.modified = NewObject.info.created = std::time(nullptr);
NewObject.info.id = MicroService::instance().CreateUUID() ;
for(auto &i:NewObject.info.notes)
i.createdBy = UserInfo_.userinfo.email;
if(DB_.CreateShortCut(NewObject)) {
ProvObjects::Venue NewRecord;
@@ -145,7 +145,9 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info);
if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet);
}
AssignIfPresent(RawObject, "rrm",Existing.rrm);

View File

@@ -438,13 +438,47 @@ namespace OpenWifi::ProvObjects {
}
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) {
uint64_t Now = std::time(nullptr);
if(O->has("name"))
I.name = O->get("name").toString();
if(O->has("description"))
if(I.name.empty())
return false;
if(O->has("description"))
I.description = O->get("description").toString();
SecurityObjects::MergeNotes(O,U,I.notes);
I.modified = std::time(nullptr);
SecurityObjects::NoteInfoVec N;
for(auto &i:I.notes) {
if(i.note.empty())
continue;
N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note});
}
I.modified = Now;
return true;
}
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) {
uint64_t Now = std::time(nullptr);
if(O->has("name"))
I.name = O->get("name").toString();
if(I.name.empty())
return false;
if(O->has("description"))
I.description = O->get("description").toString();
SecurityObjects::NoteInfoVec N;
for(auto &i:I.notes) {
if(i.note.empty())
continue;
N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note});
}
I.notes = N;
I.modified = I.created = Now;
I.id = MicroService::instance().CreateUUID();
return true;
}
};

View File

@@ -325,6 +325,8 @@ namespace OpenWifi::ProvObjects {
};
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
};

View File

@@ -96,6 +96,69 @@ namespace OpenWifi {
}
}
},
"globals.wireless-multimedia.class-selector": {
"type": "array",
"items": {
"type": "string",
"enum": [
"CS1",
"CS2",
"CS3",
"CS4",
"CS5",
"CS6",
"AF11",
"AF12",
"AF13",
"AF21",
"AF22",
"AF23",
"AF31",
"AF32",
"AF33",
"AF41",
"AF42",
"AF43",
"DF",
"EF"
]
}
},
"globals.wireless-multimedia": {
"type": "object",
"properties": {
"UP0": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
},
"UP1": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
},
"UP2": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
},
"UP3": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
},
"UP4": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
},
"UP5": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
},
"UP6": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
},
"UP7": {
"$ref": "#/$defs/globals.wireless-multimedia.class-selector"
}
}
},
"globals.wireless-multimedia-profile": {
"type": "string",
"enum": [
"enterprise"
]
},
"globals": {
"type": "object",
"properties": {
@@ -112,6 +175,16 @@ namespace OpenWifi {
"examples": [
"fdca:1234:4567::/48"
]
},
"wireless-multimedia": {
"oneOf": [
{
"$ref": "#/$defs/globals.wireless-multimedia"
},
{
"$ref": "#/$defs/globals.wireless-multimedia-profile"
}
]
}
}
},
@@ -807,6 +880,7 @@ namespace OpenWifi {
"sae",
"sae-mixed",
"wpa3",
"wpa3-192",
"wpa3-mixed"
],
"examples": [
@@ -1143,8 +1217,11 @@ namespace OpenWifi {
"maxLength": 2
},
"domain-name": {
"type": "string",
"format": "hostname"
"type": "array",
"items": {
"type": "string",
"format": "hostname"
}
},
"nai-realm": {
"type": "array",
@@ -1265,6 +1342,25 @@ namespace OpenWifi {
}
]
}
},
"wan-metrics": {
"type": "object",
"properties": {
"info": {
"type": "string",
"enum": [
"up",
"down",
"testing"
]
},
"downlink": {
"type": "integer"
},
"uplink": {
"type": "integer"
}
}
}
}
},
@@ -1481,10 +1577,6 @@ namespace OpenWifi {
"type": "string",
"format": "ipv4",
"example": "192.168.100.1"
},
"vlan-id": {
"type": "integer",
"maximum": 4096
}
}
},
@@ -1842,9 +1934,13 @@ namespace OpenWifi {
"properties": {
"controller": {
"type": "string",
"uc-format": "cidr",
"format": "ip",
"example": "192.168.10.1"
},
"datapath-description": {
"type": "string",
"example": "Building 2, Floor 6, AP 2"
},
"mode": {
"type": "string",
"enum": [
@@ -1852,7 +1948,8 @@ namespace OpenWifi {
"ptcp",
"ssl",
"tcp"
]
],
"default": "ssl"
},
"ca-certificate": {
"type": "string"
@@ -1927,13 +2024,76 @@ namespace OpenWifi {
"service.quality-of-service": {
"type": "object",
"properties": {
"upload-rate": {
"select-ports": {
"type": "array",
"items": {
"type": "string",
"default": "WAN"
}
},
"bandwidth-up": {
"type": "integer",
"default": 0
},
"download-rate": {
"bandwidth-down": {
"type": "integer",
"default": 0
},
"classifier": {
"type": "array",
"items": {
"type": "object",
"properties": {
"dscp": {
"type": "string",
"enum": [
"CS0",
"CS1",
"CS2",
"CS3",
"CS4",
"CS5",
"CS6",
"CS7"
],
"default": "CS1"
},
"ports": {
"type": "array",
"items": {
"type": "object",
"properties": {
"protocol": {
"type": "string",
"enum": [
"any",
"tcp",
"udp"
],
"default": "any"
},
"port": {
"type": "integer"
},
"range-end": {
"type": "integer"
},
"reclassify": {
"type": "boolean",
"default": true
}
}
},
"dns": {
"type": "array",
"items": {
"type": "string",
"format": "fqdn"
}
}
}
}
}
}
}
},
@@ -2155,7 +2315,6 @@ namespace OpenWifi {
}
}
}
)"_json;
class ConfigurationValidator *ConfigurationValidator::instance_ = nullptr;
@@ -2164,13 +2323,13 @@ namespace OpenWifi {
if(Initialized_)
return;
std::string GitSchema;
if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
auto schema = json::parse(GitSchema);
Validator_->set_root_schema(schema);
Logger_.information("Using uCentral validation schema from GIT.");
} else {
std::string FileName{ MicroService::instance().DataDir() + "/ucentral.schema.json" };
try {
try {
if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
auto schema = json::parse(GitSchema);
Validator_->set_root_schema(schema);
Logger_.information("Using uCentral validation schema from GIT.");
} else {
std::string FileName{ MicroService::instance().DataDir() + "/ucentral.schema.json" };
std::ifstream input(FileName);
std::stringstream schema_file;
schema_file << input.rdbuf();
@@ -2178,10 +2337,10 @@ namespace OpenWifi {
auto schema = json::parse(schema_file.str());
Validator_->set_root_schema(schema);
Logger_.information("Using uCentral validation schema from local file.");
} catch (const Poco::Exception &E) {
Validator_->set_root_schema(DefaultUCentralSchema);
Logger_.information("Using uCentral validation from built-in default.");
}
} catch (const Poco::Exception &E) {
Validator_->set_root_schema(DefaultUCentralSchema);
Logger_.information("Using uCentral validation from built-in default.");
}
Initialized_ = Working_ = true;
}

View File

@@ -277,6 +277,31 @@ namespace OpenWifi::RESTAPI_utils {
return OS.str();
}
template<class T> std::string to_string(const std::vector<std::vector<T>> & ObjectArray) {
Poco::JSON::Array OutputArr;
if(ObjectArray.empty())
return "[]";
for(auto const &i:ObjectArray) {
Poco::JSON::Array InnerArr;
for(auto const &j:i) {
if constexpr(std::is_integral<T>::value) {
InnerArr.add(j);
} if constexpr(std::is_same_v<T,std::string>) {
InnerArr.add(j);
} else {
InnerArr.add(j);
Poco::JSON::Object O;
j.to_json(O);
InnerArr.add(O);
}
}
OutputArr.add(InnerArr);
}
std::ostringstream OS;
Poco::JSON::Stringifier::condense(OutputArr,OS);
return OS.str();
}
template<class T> std::string to_string(const T & Object) {
Poco::JSON::Object OutputObj;
Object.to_json(OutputObj);
@@ -321,7 +346,6 @@ namespace OpenWifi::RESTAPI_utils {
}
template<class T> std::vector<T> to_object_array(const std::string & ObjectString) {
std::vector<T> Result;
if(ObjectString.empty())
return Result;
@@ -341,6 +365,31 @@ namespace OpenWifi::RESTAPI_utils {
return Result;
}
template<class T> std::vector<std::vector<T>> to_array_of_array_of_object(const std::string & ObjectString) {
std::vector<std::vector<T>> Result;
if(ObjectString.empty())
return Result;
try {
Poco::JSON::Parser P1;
auto OutterArray = P1.parse(ObjectString).template extract<Poco::JSON::Array::Ptr>();
for (auto const &i : *OutterArray) {
Poco::JSON::Parser P2;
auto InnerArray = P2.parse(i).template extract<Poco::JSON::Array::Ptr>();
std::vector<T> InnerVector;
for(auto const &j: *InnerArray) {
auto Object = j.template extract<Poco::JSON::Object::Ptr>();
T Obj;
Obj.from_json(Object);
InnerVector.push_back(Obj);
}
Result.push_back(InnerVector);
}
} catch (...) {
}
return Result;
}
template<class T> T to_object(const std::string & ObjectString) {
T Result;

View File

@@ -0,0 +1,51 @@
//
// Created by stephane bourque on 2021-10-28.
//
#include "storage_jobs.h"
#include "framework/OpenWifiTypes.h"
#include "framework/MicroService.h"
namespace OpenWifi {
static ORM::FieldVec JobDB_Fields{
// object info
ORM::Field{"id",64, true},
ORM::Field{"name",ORM::FieldType::FT_TEXT},
ORM::Field{"description",ORM::FieldType::FT_TEXT},
ORM::Field{"type",ORM::FieldType::FT_TEXT},
ORM::Field{"progress",ORM::FieldType::FT_BIGINT},
ORM::Field{"total",ORM::FieldType::FT_BIGINT},
ORM::Field{"parameters",ORM::FieldType::FT_TEXT}
};
static ORM::IndexVec JobDB_Indexes{
{ std::string("job_name_index"),
ORM::IndexEntryVec{
{std::string("name"),
ORM::Indextype::ASC} } }
};
JobDB::JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) :
DB(T, "jobs", JobDB_Fields, JobDB_Indexes, P, L, "job") {}
}
template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(OpenWifi::JobDBRecordType &In, OpenWifi::JobRecord &Out) {
Out.id = In.get<0>();
Out.name = In.get<1>();
Out.description = In.get<2>();
Out.type = In.get<3>();
Out.progress = In.get<4>();
Out.total = In.get<5>();
Out.parameters = OpenWifi::RESTAPI_utils::to_array_of_array_of_object<OpenWifi::Job::Parameter>(In.get<3>());
}
template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(OpenWifi::JobRecord &In, OpenWifi::JobDBRecordType &Out) {
Out.set<0>(In.id);
Out.set<1>(In.name);
Out.set<2>(In.description);
Out.set<3>(In.type);
Out.set<4>(In.progress);
Out.set<5>(In.total);
Out.set<6>(OpenWifi::RESTAPI_utils::to_string(In.parameters));
}

View File

@@ -0,0 +1,43 @@
//
// Created by stephane bourque on 2021-10-28.
//
#ifndef OWPROV_STORAGE_JOBS_H
#define OWPROV_STORAGE_JOBS_H
#include "framework/orm.h"
#include "JobController.h"
namespace OpenWifi {
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
uint64_t,
uint64_t,
std::string
> JobDBRecordType;
struct JobRecord {
Types::UUID_t id;
std::string name;
std::string description;
std::string type;
uint64_t progress;
uint64_t total;
Job::ParametersVec parameters;
// void from_string(const std::string &S);
// std::string to_string() const;
};
class JobDB : public ORM::DB<JobDBRecordType, JobRecord> {
public:
JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
private:
};
}
#endif //OWPROV_STORAGE_JOBS_H