Error Framework update

This commit is contained in:
stephb9959
2022-05-07 20:18:40 -07:00
parent 84cf98d6a8
commit 75a3e57e9d
25 changed files with 307 additions and 252 deletions

2
build
View File

@@ -1 +1 @@
115 117

View File

@@ -81,13 +81,13 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
const auto & RawObject = ParsedBody_;
std::string Arg; std::string Arg;
if(HasParameter("validateOnly",Arg) && Arg=="true") { if(HasParameter("validateOnly",Arg) && Arg=="true") {
auto Body = ParseStream(); if(!RawObject->has("configuration")) {
if(!Body->has("configuration")) { return BadRequest(RESTAPI::Errors::MustHaveConfigElement);
return BadRequest("Must have 'configuration' element.");
} }
auto Config=Body->get("configuration").toString(); auto Config=RawObject->get("configuration").toString();
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
std::string Error; std::string Error;
auto Res = ValidateUCentralConfiguration(Config,Error); auto Res = ValidateUCentralConfiguration(Config,Error);
@@ -97,7 +97,6 @@ namespace OpenWifi{
} }
ProvObjects::DeviceConfiguration NewObject; ProvObjects::DeviceConfiguration NewObject;
auto RawObject = ParseStream();
if (!NewObject.from_json(RawObject)) { if (!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
@@ -123,9 +122,9 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); return BadRequest(RESTAPI::Errors::InvalidDeviceTypes);
} }
std::string Error; RESTAPI::Errors::msg Error;
if(!ValidateConfigBlock(NewObject,Error)) { if(!ValidateConfigBlock(NewObject,Error)) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid + ", error: " + Error); return BadRequest(Error);
} }
if(DB_.CreateRecord(NewObject)) { if(DB_.CreateRecord(NewObject)) {
@@ -150,7 +149,7 @@ namespace OpenWifi{
} }
ProvObjects::DeviceConfiguration NewConfig; ProvObjects::DeviceConfiguration NewConfig;
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
if (!NewConfig.from_json(RawObject)) { if (!NewConfig.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
@@ -166,9 +165,9 @@ namespace OpenWifi{
if(!NewConfig.deviceTypes.empty()) if(!NewConfig.deviceTypes.empty())
Existing.deviceTypes = NewConfig.deviceTypes; Existing.deviceTypes = NewConfig.deviceTypes;
std::string Error; RESTAPI::Errors::msg Error;
if(!ValidateConfigBlock( NewConfig,Error)) { if(!ValidateConfigBlock( NewConfig,Error)) {
return BadRequest(RESTAPI::Errors::ConfigBlockInvalid + ", error: " + Error); return BadRequest(Error);
} }
if(RawObject->has("configuration")) { if(RawObject->has("configuration")) {

View File

@@ -79,7 +79,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto Obj = ParseStream(); const auto & Obj = ParsedBody_;
ProvObjects::Contact NewObject; ProvObjects::Contact NewObject;
if (!NewObject.from_json(Obj)) { if (!NewObject.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -121,7 +121,7 @@ namespace OpenWifi{
return NotFound(); return NotFound();
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::Contact NewObject; ProvObjects::Contact NewObject;
if (!NewObject.from_json(RawObject)) { if (!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -170,7 +170,7 @@ namespace OpenWifi {
AddExtendedInfo(E,Obj); AddExtendedInfo(E,Obj);
ObjArr.add(Obj); ObjArr.add(Obj);
} else { } else {
return R.BadRequest(RESTAPI::Errors::UnknownId + i); return R.BadRequest(RESTAPI::Errors::UnknownId);
} }
} }
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
@@ -189,7 +189,7 @@ namespace OpenWifi {
AddExtendedInfo(E,Obj); AddExtendedInfo(E,Obj);
ObjArr.add(Obj); ObjArr.add(Obj);
} else { } else {
return R.BadRequest(RESTAPI::Errors::UnknownId + i); return R.BadRequest(RESTAPI::Errors::UnknownId);
} }
} }
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
@@ -359,17 +359,13 @@ namespace OpenWifi {
} }
template <typename db_type, typename Member> void RemoveMembership( db_type & DB, Member T, const std::string & Obj, const std::string &Id) { template <typename db_type, typename Member> void RemoveMembership( db_type & DB, Member T, const std::string & Obj, const std::string &Id) {
std::cout << __LINE__ << std::endl;
if(!Obj.empty()) if(!Obj.empty())
DB.ManipulateVectorMember(T, "id", Obj, Id, false); DB.ManipulateVectorMember(T, "id", Obj, Id, false);
std::cout << __LINE__ << std::endl;
} }
template <typename db_type, typename Member> void AddMembership( db_type & DB, Member T, const std::string & Obj, const std::string &Id) { template <typename db_type, typename Member> void AddMembership( db_type & DB, Member T, const std::string & Obj, const std::string &Id) {
std::cout << __LINE__ << std::endl;
if(!Obj.empty()) if(!Obj.empty())
DB.ManipulateVectorMember(T, "id", Obj, Id, true); DB.ManipulateVectorMember(T, "id", Obj, Id, true);
std::cout << __LINE__ << std::endl;
} }
template <typename db_type, typename Member> void ManageMembership( db_type & DB, Member T, const std::string & From, const std::string & To, const std::string &Id) { template <typename db_type, typename Member> void ManageMembership( db_type & DB, Member T, const std::string & From, const std::string & To, const std::string &Id) {
@@ -378,22 +374,14 @@ namespace OpenWifi {
} }
template <typename db_type, typename Member> void ManageMembership( db_type & DB, Member T, const Types::UUIDvec_t & From, const Types::UUIDvec_t & To, const std::string &Id) { template <typename db_type, typename Member> void ManageMembership( db_type & DB, Member T, const Types::UUIDvec_t & From, const Types::UUIDvec_t & To, const std::string &Id) {
std::cout << __LINE__ << std::endl;
if(From!=To) { if(From!=To) {
std::cout << __LINE__ << std::endl;
for (const auto &i: From) { for (const auto &i: From) {
std::cout << __LINE__ << std::endl;
RemoveMembership(DB, T, i, Id); RemoveMembership(DB, T, i, Id);
std::cout << __LINE__ << std::endl;
} }
for (const auto &i: To) { for (const auto &i: To) {
std::cout << __LINE__ << std::endl;
AddMembership(DB, T, i, Id); AddMembership(DB, T, i, Id);
std::cout << __LINE__ << std::endl;
} }
std::cout << __LINE__ << std::endl;
} }
std::cout << __LINE__ << std::endl;
} }
template <typename Member, typename Rec, typename db_type > bool CreateMove(const Poco::JSON::Object::Ptr & RawObj, const char *fieldname, Member T, Rec & Existing, std::string &From, std::string &To, db_type & TheDB) { template <typename Member, typename Rec, typename db_type > bool CreateMove(const Poco::JSON::Object::Ptr & RawObj, const char *fieldname, Member T, Rec & Existing, std::string &From, std::string &To, db_type & TheDB) {
@@ -416,7 +404,7 @@ namespace OpenWifi {
return EntityDB::RootUUID(); return EntityDB::RootUUID();
} }
inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, std::string & Error) { inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, RESTAPI::Errors::msg & Error) {
static const std::vector<std::string> SectionNames{ "globals", "interfaces", "metrics", "radios", "services", "unit" }; static const std::vector<std::string> SectionNames{ "globals", "interfaces", "metrics", "radios", "services", "unit" };
for(const auto &i:Config.configuration) { for(const auto &i:Config.configuration) {
@@ -432,20 +420,21 @@ namespace OpenWifi {
auto N = Blocks->getNames(); auto N = Blocks->getNames();
for (const auto &j: N) { for (const auto &j: N) {
if (std::find(SectionNames.cbegin(), SectionNames.cend(), j) == SectionNames.cend()) { if (std::find(SectionNames.cbegin(), SectionNames.cend(), j) == SectionNames.cend()) {
Error = "Unknown section: " + j; Error = RESTAPI::Errors::UnknownConfigurationSection;
return false; return false;
} }
} }
} catch (const Poco::JSON::JSONException &E ) { } catch (const Poco::JSON::JSONException &E ) {
Error = "Block: " + i.name + " failed parsing: " + E.message(); Error = RESTAPI::Errors::InvalidJSONDocument;
return false; return false;
} }
try { try {
if (ValidateUCentralConfiguration(i.configuration, Error)) { std::string ErrorText;
if (ValidateUCentralConfiguration(i.configuration, ErrorText)) {
// std::cout << "Block: " << i.name << " is valid" << std::endl; // std::cout << "Block: " << i.name << " is valid" << std::endl;
} else { } else {
Error = "Block: " + i.name + " Rejected config:" + i.configuration ; Error = RESTAPI::Errors::ConfigBlockInvalid ;
return false; return false;
} }
} catch(...) { } catch(...) {
@@ -457,7 +446,7 @@ namespace OpenWifi {
return true; return true;
} }
template <typename Type> std::map<std::string,std::string> CreateObjects(Type & NewObject, RESTAPIHandler & R, std::string &ErrorText) { template <typename Type> std::map<std::string,std::string> CreateObjects(Type & NewObject, RESTAPIHandler & R, RESTAPI::Errors::msg & Error) {
std::map<std::string,std::string> Result; std::map<std::string,std::string> Result;
auto createObjects = R.GetParameter("createObjects",""); auto createObjects = R.GetParameter("createObjects","");
@@ -498,7 +487,7 @@ namespace OpenWifi {
} }
} }
} else { } else {
ErrorText = RESTAPI::Errors::InvalidJSONDocument; Error = RESTAPI::Errors::InvalidJSONDocument;
break; break;
} }
} else if (Object->has("contact")) { } else if (Object->has("contact")) {
@@ -514,7 +503,7 @@ namespace OpenWifi {
ProvObjects::DeviceConfiguration DC; ProvObjects::DeviceConfiguration DC;
if(DC.from_json(ConfigurationDetails)) { if(DC.from_json(ConfigurationDetails)) {
if constexpr(std::is_same_v<Type, ProvObjects::InventoryTag>) { if constexpr(std::is_same_v<Type, ProvObjects::InventoryTag>) {
if(!ValidateConfigBlock(DC,ErrorText)) { if(!ValidateConfigBlock(DC,Error)) {
break; break;
} }
std::cout << "Configuration decoded: " << DC.info.name << std::endl; std::cout << "Configuration decoded: " << DC.info.name << std::endl;
@@ -525,7 +514,7 @@ namespace OpenWifi {
} }
} }
} else { } else {
ErrorText = RESTAPI::Errors::InvalidJSONDocument; Error = RESTAPI::Errors::InvalidJSONDocument;
break; break;
} }
} }
@@ -589,7 +578,7 @@ namespace OpenWifi {
return false; return false;
} }
template <typename DBType> bool ValidDbId(const Types::UUID_t &uuid, DBType & DB, bool AllowEmpty , const std::string &Error , RESTAPIHandler & H) { template <typename DBType> bool ValidDbId(const Types::UUID_t &uuid, DBType & DB, bool AllowEmpty , const RESTAPI::Errors::msg &Error , RESTAPIHandler & H) {
if(!AllowEmpty && uuid.empty()) { if(!AllowEmpty && uuid.empty()) {
H.BadRequest(Error); H.BadRequest(Error);
return false; return false;
@@ -655,7 +644,7 @@ namespace OpenWifi {
Updated.to_json(Answer); Updated.to_json(Answer);
return H.ReturnObject(Answer); return H.ReturnObject(Answer);
} else { } else {
H.InternalError("Record could not be updated."); H.InternalError(RESTAPI::Errors::RecordNotUpdated);
} }
} }
@@ -667,7 +656,7 @@ namespace OpenWifi {
Updated.to_json(Answer); Updated.to_json(Answer);
return H.ReturnObject(Answer); return H.ReturnObject(Answer);
} else { } else {
H.InternalError("Record could not be created."); H.InternalError(RESTAPI::Errors::RecordNotCreated);
} }
} }

View File

@@ -62,7 +62,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
auto Obj = ParseStream(); const auto & Obj = ParsedBody_;
ProvObjects::Entity NewEntity; ProvObjects::Entity NewEntity;
if (!NewEntity.from_json(Obj)) { if (!NewEntity.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -124,7 +124,7 @@ namespace OpenWifi{
return NotFound(); return NotFound();
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::Entity NewEntity; ProvObjects::Entity NewEntity;
if(!NewEntity.from_json(RawObject)) { if(!NewEntity.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -145,7 +145,7 @@ namespace OpenWifi{
Existing.sourceIP = NewEntity.sourceIP; Existing.sourceIP = NewEntity.sourceIP;
} }
std::string Error; RESTAPI::Errors::msg Error;
if(!StorageService()->Validate(Parameters_,Error)) { if(!StorageService()->Validate(Parameters_,Error)) {
return BadRequest(Error); return BadRequest(Error);
} }

View File

@@ -33,7 +33,7 @@ namespace OpenWifi{
void RESTAPI_entity_list_handler::DoPost() { void RESTAPI_entity_list_handler::DoPost() {
if (GetBoolParameter("setTree",false)) { if (GetBoolParameter("setTree",false)) {
auto FullTree = ParseStream(); const auto & FullTree = ParsedBody_;
DB_.ImportTree(FullTree); DB_.ImportTree(FullTree);
return OK(); return OK();
} }

View File

@@ -152,10 +152,10 @@ namespace OpenWifi{
} }
if(DB_.Exists(RESTAPI::Protocol::SERIALNUMBER,SerialNumber)) { if(DB_.Exists(RESTAPI::Protocol::SERIALNUMBER,SerialNumber)) {
return BadRequest(RESTAPI::Errors::SerialNumberExists + " (" + SerialNumber + ")"); return BadRequest(RESTAPI::Errors::SerialNumberExists);
} }
auto Obj = ParseStream(); const auto & Obj = ParsedBody_;
ProvObjects::InventoryTag NewObject; ProvObjects::InventoryTag NewObject;
if (!NewObject.from_json(Obj)) { if (!NewObject.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -205,10 +205,10 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
} }
std::string ErrorText; RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
auto ObjectsCreated = CreateObjects(NewObject,*this,ErrorText); auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
if(!ErrorText.empty()) { if(Error.err_num != 0) {
return BadRequest(ErrorText); return BadRequest(Error);
} }
if(DB_.CreateRecord(NewObject)) { if(DB_.CreateRecord(NewObject)) {
@@ -279,7 +279,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::InventoryTag NewObject; ProvObjects::InventoryTag NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -355,10 +355,10 @@ namespace OpenWifi{
Existing.state = NewObject.state; Existing.state = NewObject.state;
} }
std::string ErrorText; RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
auto ObjectsCreated = CreateObjects(Existing,*this,ErrorText); auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
if(!ErrorText.empty()) { if(Error.err_num != 0) {
return BadRequest(ErrorText); return BadRequest(Error);
} }
if(!ObjectsCreated.empty()) { if(!ObjectsCreated.empty()) {

View File

@@ -76,7 +76,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto Obj = ParseStream(); const auto & Obj = ParsedBody_;
ProvObjects::Location NewObject; ProvObjects::Location NewObject;
if (!NewObject.from_json(Obj)) { if (!NewObject.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -117,30 +117,23 @@ namespace OpenWifi{
return NotFound(); return NotFound();
} }
std::cout << __LINE__ << std::endl; const auto & RawObject = ParsedBody_;
auto RawObject = ParseStream();
std::cout << __LINE__ << std::endl;
ProvObjects::Location NewObject; ProvObjects::Location NewObject;
std::cout << __LINE__ << std::endl;
if (!NewObject.from_json(RawObject)) { if (!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
std::cout << __LINE__ << std::endl;
if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) { if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest( RESTAPI::Errors::NameMustBeSet); return BadRequest( RESTAPI::Errors::NameMustBeSet);
} }
std::cout << __LINE__ << std::endl;
std::string FromPolicy, ToPolicy; std::string FromPolicy, ToPolicy;
if(!CreateMove(RawObject,"managementPolicy",&LocationDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) if(!CreateMove(RawObject,"managementPolicy",&LocationDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB()))
return BadRequest(RESTAPI::Errors::EntityMustExist); return BadRequest(RESTAPI::Errors::EntityMustExist);
std::cout << __LINE__ << std::endl;
std::string FromEntity, ToEntity; std::string FromEntity, ToEntity;
if(!CreateMove(RawObject,"entity",&LocationDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) if(!CreateMove(RawObject,"entity",&LocationDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB()))
return BadRequest(RESTAPI::Errors::EntityMustExist); return BadRequest(RESTAPI::Errors::EntityMustExist);
std::cout << __LINE__ << std::endl;
AssignIfPresent(RawObject, "buildingName", Existing.buildingName); AssignIfPresent(RawObject, "buildingName", Existing.buildingName);
AssignIfPresent(RawObject, "city", Existing.city); AssignIfPresent(RawObject, "city", Existing.city);
@@ -148,10 +141,8 @@ namespace OpenWifi{
AssignIfPresent(RawObject, "postal", Existing.postal); AssignIfPresent(RawObject, "postal", Existing.postal);
AssignIfPresent(RawObject, "country", Existing.country); AssignIfPresent(RawObject, "country", Existing.country);
AssignIfPresent(RawObject, "geoCode", Existing.geoCode); AssignIfPresent(RawObject, "geoCode", Existing.geoCode);
std::cout << __LINE__ << std::endl;
if(RawObject->has("addressLines")) if(RawObject->has("addressLines"))
Existing.addressLines = NewObject.addressLines; Existing.addressLines = NewObject.addressLines;
std::cout << __LINE__ << std::endl;
if(RawObject->has("phones")) if(RawObject->has("phones"))
Existing.phones = NewObject.phones; Existing.phones = NewObject.phones;
if(RawObject->has("mobiles")) if(RawObject->has("mobiles"))
@@ -160,20 +151,14 @@ namespace OpenWifi{
if(RawObject->has("type")) if(RawObject->has("type"))
Existing.type = NewObject.type; Existing.type = NewObject.type;
std::cout << __LINE__ << std::endl;
if(DB_.UpdateRecord("id", UUID, Existing)) { if(DB_.UpdateRecord("id", UUID, Existing)) {
std::cout << __LINE__ << std::endl;
MoveUsage(StorageService()->PolicyDB(), DB_, FromPolicy, ToPolicy, Existing.info.id); MoveUsage(StorageService()->PolicyDB(), DB_, FromPolicy, ToPolicy, Existing.info.id);
std::cout << __LINE__ << std::endl;
ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::locations,FromEntity, ToEntity, Existing.info.id); ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::locations,FromEntity, ToEntity, Existing.info.id);
std::cout << __LINE__ << std::endl;
std::cout << __LINE__ << std::endl;
ProvObjects::Location NewObjectAdded; ProvObjects::Location NewObjectAdded;
DB_.GetRecord("id", UUID, NewObjectAdded); DB_.GetRecord("id", UUID, NewObjectAdded);
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
NewObjectAdded.to_json(Answer); NewObjectAdded.to_json(Answer);
std::cout << __LINE__ << std::endl;
return ReturnObject(Answer); return ReturnObject(Answer);
} }
InternalError(RESTAPI::Errors::RecordNotUpdated); InternalError(RESTAPI::Errors::RecordNotUpdated);

View File

@@ -76,7 +76,7 @@ namespace OpenWifi{
} }
ProvObjects::ManagementPolicy NewObject; ProvObjects::ManagementPolicy NewObject;
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
@@ -114,7 +114,7 @@ namespace OpenWifi{
} }
ProvObjects::ManagementPolicy NewPolicy; ProvObjects::ManagementPolicy NewPolicy;
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
if(!NewPolicy.from_json(RawObject)) { if(!NewPolicy.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }

View File

@@ -75,7 +75,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto RawObj = ParseStream(); const auto & RawObj = ParsedBody_;
ProvObjects::ManagementRole NewObject; ProvObjects::ManagementRole NewObject;
if (!NewObject.from_json(RawObj)) { if (!NewObject.from_json(RawObj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -114,7 +114,7 @@ namespace OpenWifi{
return NotFound(); return NotFound();
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::ManagementRole NewObject; ProvObjects::ManagementRole NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -35,7 +35,7 @@ namespace OpenWifi{
} }
if(UserInfo_.userinfo.id!=Existing.creator) { if(UserInfo_.userinfo.id!=Existing.creator) {
return UnAuthorized("You must be the creator of the map to delete it"); return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
} }
DB_.DeleteRecord("id", Existing.info.id); DB_.DeleteRecord("id", Existing.info.id);
@@ -55,7 +55,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::Map NewObject; ProvObjects::Map NewObject;
if (!NewObject.from_json(RawObject)) { if (!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -66,7 +66,7 @@ namespace OpenWifi{
} }
if(!ValidateVisibility(NewObject.visibility)) { if(!ValidateVisibility(NewObject.visibility)) {
return BadRequest("Invalid visibility attribute"); return BadRequest(RESTAPI::Errors::InvalidVisibilityAttribute);
} }
if(RawObject->has("entity")) { if(RawObject->has("entity")) {
@@ -101,7 +101,7 @@ namespace OpenWifi{
return NotFound(); return NotFound();
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::Map NewObject; ProvObjects::Map NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -113,7 +113,7 @@ namespace OpenWifi{
if(Existing.creator != UserInfo_.userinfo.id) { if(Existing.creator != UserInfo_.userinfo.id) {
if(Existing.visibility == "private") { if(Existing.visibility == "private") {
return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
} }
if(Existing.visibility == "select") { if(Existing.visibility == "select") {
for(const auto &i:Existing.access.list) { for(const auto &i:Existing.access.list) {

View File

@@ -44,7 +44,7 @@ namespace OpenWifi {
void RESTAPI_op_contact_handler::DoPost() { void RESTAPI_op_contact_handler::DoPost() {
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
OpContactDB::RecordName NewObject; OpContactDB::RecordName NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -68,7 +68,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
OpContactDB::RecordName UpdateObj; OpContactDB::RecordName UpdateObj;
if(!UpdateObj.from_json(RawObject)) { if(!UpdateObj.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -43,7 +43,7 @@ namespace OpenWifi {
void RESTAPI_op_location_handler::DoPost() { void RESTAPI_op_location_handler::DoPost() {
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
OpLocationDB::RecordName NewObject; OpLocationDB::RecordName NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -67,7 +67,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto RawObject = ParseStream(); const auto RawObject = ParsedBody_;
OpLocationDB::RecordName UpdateObj; OpLocationDB::RecordName UpdateObj;
if(!UpdateObj.from_json(RawObject)) { if(!UpdateObj.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -51,7 +51,7 @@ namespace OpenWifi {
void RESTAPI_operators_handler::DoPost() { void RESTAPI_operators_handler::DoPost() {
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::Operator NewObject; ProvObjects::Operator NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -103,7 +103,7 @@ namespace OpenWifi {
return ReturnObject(Answer); return ReturnObject(Answer);
} }
return InternalError("Failed creating operator."); return InternalError(RESTAPI::Errors::RecordNotCreated);
} }
void RESTAPI_operators_handler::DoPut() { void RESTAPI_operators_handler::DoPut() {
@@ -117,7 +117,7 @@ namespace OpenWifi {
return NotFound(); return NotFound();
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::Operator UpdatedObj; ProvObjects::Operator UpdatedObj;
if(!UpdatedObj.from_json(RawObject)) { if(!UpdatedObj.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -41,7 +41,7 @@ namespace OpenWifi {
} }
void RESTAPI_service_class_handler::DoPost() { void RESTAPI_service_class_handler::DoPost() {
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::ServiceClass NewObject; ProvObjects::ServiceClass NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -85,7 +85,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::ServiceClass UpdateObj; ProvObjects::ServiceClass UpdateObj;
if(!UpdateObj.from_json(RawObject)) { if(!UpdateObj.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -53,7 +53,7 @@ namespace OpenWifi {
for(const auto &i:SEs) { for(const auto &i:SEs) {
if(!i.deviceID.empty() && i.deviceID!=deviceID) { if(!i.deviceID.empty() && i.deviceID!=deviceID) {
return BadRequest("Invalid deviceID"); return BadRequest(RESTAPI::Errors::InvalidDeviceID);
} }
if (i.statusCode == ProvObjects::SignupStatusCodes::SignupWaitingForEmail || if (i.statusCode == ProvObjects::SignupStatusCodes::SignupWaitingForEmail ||
@@ -181,7 +181,7 @@ namespace OpenWifi {
return ReturnObject(Answer); return ReturnObject(Answer);
} }
return BadRequest("Not implemented"); return BadRequest(RESTAPI::Errors::NotImplemented);
} }
void RESTAPI_signup_handler::DoGet() { void RESTAPI_signup_handler::DoGet() {

View File

@@ -48,7 +48,7 @@ namespace OpenWifi {
void RESTAPI_sub_devices_handler::DoPost() { void RESTAPI_sub_devices_handler::DoPost() {
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
SubscriberDeviceDB::RecordName NewObject; SubscriberDeviceDB::RecordName NewObject;
if(!NewObject.from_json(RawObject)) { if(!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -71,7 +71,7 @@ namespace OpenWifi {
void RESTAPI_sub_devices_handler::DoPut() { void RESTAPI_sub_devices_handler::DoPut() {
auto uuid = GetBinding("uuid"); auto uuid = GetBinding("uuid");
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
SubscriberDeviceDB::RecordName UpdateObj; SubscriberDeviceDB::RecordName UpdateObj;
if(!UpdateObj.from_json(RawObject)) { if(!UpdateObj.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -53,7 +53,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto RawObj = ParseStream(); const auto & RawObj = ParsedBody_;
VariablesDB::RecordName NewObject; VariablesDB::RecordName NewObject;
if(!NewObject.from_json(RawObj)) { if(!NewObject.from_json(RawObj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -100,7 +100,7 @@ namespace OpenWifi {
return NotFound(); return NotFound();
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
VariablesDB::RecordName NewObj; VariablesDB::RecordName NewObj;
if(!NewObj.from_json(RawObject)) { if(!NewObj.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);

View File

@@ -116,7 +116,7 @@ namespace OpenWifi{
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
auto Obj = ParseStream(); const auto & Obj = ParsedBody_;
ProvObjects::Venue NewObject; ProvObjects::Venue NewObject;
if (!NewObject.from_json(Obj)) { if (!NewObject.from_json(Obj)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -176,11 +176,10 @@ namespace OpenWifi{
NewObject.children.clear(); NewObject.children.clear();
std::string ErrorText; RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
auto ObjectsToCreate = CreateObjects(NewObject, *this, ErrorText); auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
if(Error.err_num != 0) {
if(!ErrorText.empty()) { return BadRequest(Error);
return BadRequest(ErrorText);
} }
if(DB_.CreateRecord(NewObject)) { if(DB_.CreateRecord(NewObject)) {
@@ -247,7 +246,7 @@ namespace OpenWifi{
return ReturnObject(Answer); return ReturnObject(Answer);
} }
auto RawObject = ParseStream(); const auto & RawObject = ParsedBody_;
ProvObjects::Venue NewObject; ProvObjects::Venue NewObject;
if (!NewObject.from_json(RawObject)) { if (!NewObject.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
@@ -329,9 +328,11 @@ namespace OpenWifi{
std::string ErrorText; std::string ErrorText;
NewObject.parent = Existing.parent; NewObject.parent = Existing.parent;
NewObject.entity = Existing.entity; NewObject.entity = Existing.entity;
auto ObjectsCreated = CreateObjects(NewObject, *this, ErrorText);
if(!ErrorText.empty()) { RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS;
return BadRequest(ErrorText); auto ObjectsCreated = CreateObjects(NewObject,*this,Error);
if(Error.err_num != 0) {
return BadRequest(Error);
} }
if(!ObjectsCreated.empty()) { if(!ObjectsCreated.empty()) {

View File

@@ -31,7 +31,7 @@ namespace OpenWifi {
void DoPut() final; void DoPut() final;
void DoDelete() final; void DoDelete() final;
template <typename T> bool IdExists(T &DB, const std::string &Field, const std::string &Error) { template <typename T> bool IdExists(T &DB, const std::string &Field, const RESTAPI::Errors::msg &Error) {
if(!Field.empty() && !DB.Exists("id",Field)) { if(!Field.empty() && !DB.Exists("id",Field)) {
BadRequest(Error); BadRequest(Error);
return false; return false;

View File

@@ -112,22 +112,20 @@ namespace OpenWifi {
Logger().notice("Stopping."); Logger().notice("Stopping.");
} }
bool Storage::Validate(const Poco::URI::QueryParameters &P, std::string &Error) { bool Storage::Validate(const Poco::URI::QueryParameters &P, RESTAPI::Errors::msg &Error) {
for(const auto &i:P) { for(const auto &i:P) {
auto uuid_parts = Utils::Split(i.second,':'); auto uuid_parts = Utils::Split(i.second,':');
if(uuid_parts.size()==2) { if(uuid_parts.size()==2) {
auto F = ExistFunc_.find(uuid_parts[0]); auto F = ExistFunc_.find(uuid_parts[0]);
if(F!=ExistFunc_.end()) { if(F!=ExistFunc_.end()) {
if(!F->second("id", uuid_parts[1])) { if(!F->second("id", uuid_parts[1])) {
Error = "Unknown " + F->first + " UUID:" + uuid_parts[1] ; Error = RESTAPI::Errors::UnknownId;
break; return false;
} }
} }
} }
} }
if(Error.empty()) return true;
return true;
return false;
} }
bool Storage::ValidateSingle(const std::string &P, std::string & Error) { bool Storage::ValidateSingle(const std::string &P, std::string & Error) {

View File

@@ -63,7 +63,7 @@ namespace OpenWifi {
OpenWifi::OpLocationDB & OpLocationDB() { return *OpLocationDB_; }; OpenWifi::OpLocationDB & OpLocationDB() { return *OpLocationDB_; };
OpenWifi::OpContactDB & OpContactDB() { return *OpContactDB_; }; OpenWifi::OpContactDB & OpContactDB() { return *OpContactDB_; };
bool Validate(const Poco::URI::QueryParameters &P, std::string &Error); bool Validate(const Poco::URI::QueryParameters &P, RESTAPI::Errors::msg &Error);
bool Validate(const Types::StringVec &P, std::string &Error); bool Validate(const Types::StringVec &P, std::string &Error);
inline bool ValidatePrefix(const std::string &P) const { return ExistFunc_.find(P)!=ExistFunc_.end(); } inline bool ValidatePrefix(const std::string &P) const { return ExistFunc_.find(P)!=ExistFunc_.end(); }
bool ExpandInUse(const Types::StringVec &UUIDs, ExpandedListMap & Map, std::vector<std::string> & Errors); bool ExpandInUse(const Types::StringVec &UUIDs, ExpandedListMap & Map, std::vector<std::string> & Errors);

View File

@@ -1812,8 +1812,14 @@ namespace OpenWifi {
Poco::Thread::current()->setName("WebServerThread_" + std::to_string(TransactionId_)); Poco::Thread::current()->setName("WebServerThread_" + std::to_string(TransactionId_));
if(Request->getContentLength()>0) {
if(Request->getContentType().find("application/json")!=std::string::npos) {
ParsedBody_ = IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>();
}
}
if(RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(RequestIn,MyRates_.Interval, MyRates_.MaxCalls)) { if(RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(RequestIn,MyRates_.Interval, MyRates_.MaxCalls)) {
return UnAuthorized("Rate limit exceeded.",RATE_LIMIT_EXCEEDED); return UnAuthorized(RESTAPI::Errors::RATE_LIMIT_EXCEEDED);
} }
if (!ContinueProcessing()) if (!ContinueProcessing())
@@ -1822,16 +1828,16 @@ namespace OpenWifi {
bool Expired=false, Contacted=false; bool Expired=false, Contacted=false;
if (AlwaysAuthorize_ && !IsAuthorized(Expired, Contacted, SubOnlyService_)) { if (AlwaysAuthorize_ && !IsAuthorized(Expired, Contacted, SubOnlyService_)) {
if(Expired) if(Expired)
return UnAuthorized(RESTAPI::Errors::ExpiredToken, EXPIRED_TOKEN); return UnAuthorized(RESTAPI::Errors::EXPIRED_TOKEN);
if(Contacted) if(Contacted)
return UnAuthorized(RESTAPI::Errors::InvalidCredentials, INVALID_TOKEN); return UnAuthorized(RESTAPI::Errors::INVALID_TOKEN);
else else
return UnAuthorized(RESTAPI::Errors::InvalidCredentials, SECURITY_SERVICE_UNREACHABLE); return UnAuthorized(RESTAPI::Errors::SECURITY_SERVICE_UNREACHABLE);
} }
std::string Reason; std::string Reason;
if(!RoleIsAuthorized(RequestIn.getURI(), Request->getMethod(), Reason)) { if(!RoleIsAuthorized(RequestIn.getURI(), Request->getMethod(), Reason)) {
return UnAuthorized(Reason, ACCESS_DENIED); return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
} }
ParseParameters(); ParseParameters();
@@ -1853,10 +1859,10 @@ namespace OpenWifi {
[[nodiscard]] inline bool NeedAdditionalInfo() const { return QB_.AdditionalInfo; } [[nodiscard]] inline bool NeedAdditionalInfo() const { return QB_.AdditionalInfo; }
[[nodiscard]] inline const std::vector<std::string> & SelectedRecords() const { return QB_.Select; } [[nodiscard]] inline const std::vector<std::string> & SelectedRecords() const { return QB_.Select; }
[[nodiscard]] inline const Poco::JSON::Object::Ptr ParseStream() { /* [[nodiscard]] inline const Poco::JSON::Object::Ptr ParseStream() {
return IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>(); return IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>();
} }
*/
inline static bool ParseBindings(const std::string & Request, const std::list<std::string> & EndPoints, BindingMap &bindings) { inline static bool ParseBindings(const std::string & Request, const std::list<std::string> & EndPoints, BindingMap &bindings) {
bindings.clear(); bindings.clear();
@@ -2011,7 +2017,7 @@ namespace OpenWifi {
return false; return false;
} }
inline void SetCommonHeaders(bool CloseConnection=false) { inline void SetCommonHeaders(bool CloseConnection=false) {
Response->setVersion(Poco::Net::HTTPMessage::HTTP_1_1); Response->setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
Response->setChunkedTransferEncoding(true); Response->setChunkedTransferEncoding(true);
Response->setContentType("application/json"); Response->setContentType("application/json");
@@ -2032,21 +2038,6 @@ namespace OpenWifi {
} }
} }
/* inline void AddCORS() {
SetCommonHeaders();
auto Origin = Request->find("Origin");
if (Origin != Request->end()) {
Response->set("Access-Control-Allow-Origin", Origin->second);
Response->set("Vary", "Origin");
} else {
Response->set("Access-Control-Allow-Origin", "*");
}
Response->set("Access-Control-Allow-Headers", "*");
Response->set("Access-Control-Allow-Methods", MakeList(Methods_));
Response->set("Access-Control-Max-Age", "86400");
}
*/
inline void ProcessOptions() { inline void ProcessOptions() {
Response->setVersion(Poco::Net::HTTPMessage::HTTP_1_1); Response->setVersion(Poco::Net::HTTPMessage::HTTP_1_1);
Response->setChunkedTransferEncoding(true); Response->setChunkedTransferEncoding(true);
@@ -2077,17 +2068,17 @@ namespace OpenWifi {
SetCommonHeaders(CloseConnection); SetCommonHeaders(CloseConnection);
} }
inline void BadRequest(const std::string & Reason) { inline void BadRequest(const OpenWifi::RESTAPI::Errors::msg &E) {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST); PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Poco::JSON::Object ErrorObject; Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",400); ErrorObject.set("ErrorCode",400);
ErrorObject.set("ErrorDetails",Request->getMethod()); ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "Command is missing parameters or wrong values." : Reason) ; ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ;
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
} }
inline void BadRequest(uint64_t ErrorCode, const std::string & ErrorText) { /* inline void BadRequest(uint64_t ErrorCode, const std::string & ErrorText) {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST); PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Poco::JSON::Object ErrorObject; Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode", ErrorCode); ErrorObject.set("ErrorCode", ErrorCode);
@@ -2096,23 +2087,23 @@ namespace OpenWifi {
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
} }
*/
inline void InternalError(const std::string & Reason = "") { inline void InternalError(const OpenWifi::RESTAPI::Errors::msg &E) {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); PrepareResponse(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
Poco::JSON::Object ErrorObject; Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",500); ErrorObject.set("ErrorCode",500);
ErrorObject.set("ErrorDetails",Request->getMethod()); ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "Please try later or review the data submitted." : Reason) ; ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ;
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
} }
inline void UnAuthorized(const std::string & Reason = "", int Code = INVALID_CREDENTIALS ) { inline void UnAuthorized(const OpenWifi::RESTAPI::Errors::msg &E) {
PrepareResponse(Poco::Net::HTTPResponse::HTTP_FORBIDDEN); PrepareResponse(Poco::Net::HTTPResponse::HTTP_FORBIDDEN);
Poco::JSON::Object ErrorObject; Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",Code); ErrorObject.set("ErrorCode",E.err_num);
ErrorObject.set("ErrorDetails",Request->getMethod()); ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "No access allowed." : Reason) ; ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ;
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
} }
@@ -2122,7 +2113,8 @@ namespace OpenWifi {
Poco::JSON::Object ErrorObject; Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",404); ErrorObject.set("ErrorCode",404);
ErrorObject.set("ErrorDetails",Request->getMethod()); ErrorObject.set("ErrorDetails",Request->getMethod());
ErrorObject.set("ErrorDescription","This resource does not exist."); const auto & E = OpenWifi::RESTAPI::Errors::Error404;
ErrorObject.set("ErrorDescription",fmt::format("{}: {}",E.err_num,E.err_txt)) ;
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer); Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
Logger_.debug(fmt::format("RES-NOTFOUND: User='{}@{}' Method='{}' Path='{}", Logger_.debug(fmt::format("RES-NOTFOUND: User='{}@{}' Method='{}' Path='{}",
@@ -2261,28 +2253,28 @@ namespace OpenWifi {
return true; return true;
} }
inline bool IsAuthorized(bool & Expired, bool & Contacted, bool SubOnly = false ); inline bool IsAuthorized(bool & Expired, bool & Contacted, bool SubOnly = false );
inline void ReturnObject(Poco::JSON::Object &Object) { inline void ReturnObject(Poco::JSON::Object &Object) {
PrepareResponse(); PrepareResponse();
if(Request!= nullptr) { if(Request!= nullptr) {
// can we compress ??? // can we compress ???
auto AcceptedEncoding = Request->find("Accept-Encoding"); auto AcceptedEncoding = Request->find("Accept-Encoding");
if(AcceptedEncoding!=Request->end()) { if(AcceptedEncoding!=Request->end()) {
if( AcceptedEncoding->second.find("gzip")!=std::string::npos || if( AcceptedEncoding->second.find("gzip")!=std::string::npos ||
AcceptedEncoding->second.find("compress")!=std::string::npos) { AcceptedEncoding->second.find("compress")!=std::string::npos) {
Response->set("Content-Encoding", "gzip"); Response->set("Content-Encoding", "gzip");
std::ostream &Answer = Response->send(); std::ostream &Answer = Response->send();
Poco::DeflatingOutputStream deflater(Answer, Poco::DeflatingStreamBuf::STREAM_GZIP); Poco::DeflatingOutputStream deflater(Answer, Poco::DeflatingStreamBuf::STREAM_GZIP);
Poco::JSON::Stringifier::stringify(Object, deflater); Poco::JSON::Stringifier::stringify(Object, deflater);
deflater.close(); deflater.close();
return; return;
}
} }
} }
std::ostream &Answer = Response->send(); }
Poco::JSON::Stringifier::stringify(Object, Answer); std::ostream &Answer = Response->send();
} Poco::JSON::Stringifier::stringify(Object, Answer);
}
inline void ReturnCountOnly(uint64_t Count) { inline void ReturnCountOnly(uint64_t Count) {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
@@ -2372,6 +2364,7 @@ namespace OpenWifi {
RESTAPI_GenericServer & Server_; RESTAPI_GenericServer & Server_;
RateLimit MyRates_; RateLimit MyRates_;
uint64_t TransactionId_; uint64_t TransactionId_;
Poco::JSON::Object::Ptr ParsedBody_;
}; };
class RESTAPI_UnknownRequestHandler : public RESTAPIHandler { class RESTAPI_UnknownRequestHandler : public RESTAPIHandler {
@@ -4262,7 +4255,7 @@ namespace OpenWifi {
} }
inline void DoPost() final { inline void DoPost() final {
auto Obj = ParseStream(); const auto & Obj = ParsedBody_;
if (Obj->has(RESTAPI::Protocol::COMMAND)) { if (Obj->has(RESTAPI::Protocol::COMMAND)) {
auto Command = Poco::toLower(Obj->get(RESTAPI::Protocol::COMMAND).toString()); auto Command = Poco::toLower(Obj->get(RESTAPI::Protocol::COMMAND).toString());
if (Command == RESTAPI::Protocol::SETLOGLEVEL) { if (Command == RESTAPI::Protocol::SETLOGLEVEL) {

View File

@@ -25,6 +25,30 @@ namespace OpenWifi {
} }
}; };
struct WebNotificationSingleDeviceConfigurationChange {
std::string serialNumber;
uint64_t oldUUID;
uint64_t newUUID;
inline void to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"serialNumber", serialNumber);
RESTAPI_utils::field_to_json(Obj,"oldUUID", oldUUID);
RESTAPI_utils::field_to_json(Obj,"newUUID", newUUID);
}
inline bool from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"serialNumber", serialNumber);
RESTAPI_utils::field_from_json(Obj,"oldUUID", oldUUID);
RESTAPI_utils::field_from_json(Obj,"newUUID", newUUID);
return true;
} catch (...) {
}
return false;
}
};
struct WebNotificationSingleDeviceFirmwareChange { struct WebNotificationSingleDeviceFirmwareChange {
std::string serialNumber; std::string serialNumber;
std::string newFirmware; std::string newFirmware;
@@ -45,6 +69,15 @@ namespace OpenWifi {
} }
}; };
inline void WebSocketClientNotificationDeviceConfigurationChange(const std::string &SerialNumber, uint64_t oldUUID, uint64_t newUUID) {
WebSocketNotification<WebNotificationSingleDeviceConfigurationChange> N;
N.content.serialNumber = SerialNumber;
N.content.oldUUID = oldUUID;
N.content.newUUID = newUUID;
N.type = "device_configuration_upgrade";
WebSocketClientServer()->SendNotification(N);
}
inline void WebSocketClientNotificationDeviceFirmwareUpdated(const std::string &SerialNumber, const std::string &Firmware) { inline void WebSocketClientNotificationDeviceFirmwareUpdated(const std::string &SerialNumber, const std::string &Firmware) {
WebSocketNotification<WebNotificationSingleDeviceFirmwareChange> N; WebSocketNotification<WebNotificationSingleDeviceFirmwareChange> N;
N.content.serialNumber = SerialNumber; N.content.serialNumber = SerialNumber;

View File

@@ -18,92 +18,149 @@
#endif #endif
namespace OpenWifi::RESTAPI::Errors { namespace OpenWifi::RESTAPI::Errors {
static const std::string MissingUUID{"Missing UUID."}; struct msg { uint64_t err_num; std::string err_txt; };
static const std::string MissingSerialNumber{"Missing Serial Number."}; static const struct msg Error404{404,"Resource does not exist."};
static const std::string InternalError{"Internal error. Please try later."};
static const std::string InvalidJSONDocument{"Invalid JSON document."}; static const struct msg SUCCESS{0,"No error."};
static const std::string UnsupportedHTTPMethod{"Unsupported HTTP Method"}; static const struct msg PASSWORD_CHANGE_REQUIRED{1,"Password change required"};
static const std::string StillInUse{"Element still in use."}; static const struct msg INVALID_CREDENTIALS{2,"Invalid credentials."};
static const std::string CouldNotBeDeleted{"Element could not be deleted."}; static const struct msg PASSWORD_ALREADY_USED{3,"Password already used."};
static const std::string NameMustBeSet{"The name property must be set."}; static const struct msg USERNAME_PENDING_VERIFICATION{4,"Username pending verification."};
static const std::string ConfigBlockInvalid{"Configuration block type invalid."}; static const struct msg PASSWORD_INVALID{5,"Password is invalid"};
static const std::string UnknownId{"Unknown UUID."}; static const struct msg INTERNAL_ERROR{6,"Internal error."};
static const std::string InvalidDeviceTypes{"Unknown or invalid device type(s)."}; static const struct msg ACCESS_DENIED{7,"Access denied."};
static const std::string RecordNotCreated{"Record could not be created."}; static const struct msg INVALID_TOKEN{8,"Invalid token."};
static const std::string RecordNotUpdated{"Record could not be updated."}; static const struct msg EXPIRED_TOKEN{9,"Expired token."};
static const std::string UnknownManagementPolicyUUID{"Unknown management policy UUID."}; static const struct msg RATE_LIMIT_EXCEEDED{10,"Rate limit exceeded."};
static const std::string CannotDeleteRoot{"Root Entity cannot be removed, only modified."}; static const struct msg BAD_MFA_TRANSACTION{11,"Bad MFA transaction."};
static const std::string MustCreateRootFirst{"Root entity must be created first."}; static const struct msg MFA_FAILURE{12,"MFA failure."};
static const std::string ParentUUIDMustExist{"Parent UUID must exist."}; static const struct msg SECURITY_SERVICE_UNREACHABLE{13,"Security service is unreachable, try again later."};
static const std::string ConfigurationMustExist{"Configuration must exist."}; static const struct msg CANNOT_REFRESH_TOKEN{14,"Cannot refresh token."};
static const std::string MissingOrInvalidParameters{"Invalid or missing parameters."};
static const std::string UnknownSerialNumber{"Unknown Serial Number."}; static const struct msg MissingUUID{1000,"Missing UUID."};
static const std::string InvalidSerialNumber{"Invalid Serial Number."}; static const struct msg MissingSerialNumber{1001,"Missing Serial Number."};
static const std::string SerialNumberExists{"Serial Number already exists."}; static const struct msg InternalError{1002,"Internal error. Please try later."};
static const std::string ValidNonRootUUID{"Must be a non-root, and valid UUID."}; static const struct msg InvalidJSONDocument{1003,"Invalid JSON document."};
static const std::string VenueMustExist{"Venue does not exist."}; static const struct msg UnsupportedHTTPMethod{1004,"Unsupported HTTP Method"};
static const std::string NotBoth{"You cannot specify both Entity and Venue"}; static const struct msg StillInUse{1005,"Element still in use."};
static const std::string EntityMustExist{"Entity must exist."}; static const struct msg CouldNotBeDeleted{1006,"Element could not be deleted."};
static const std::string ParentOrEntityMustBeSet{"Parent or Entity must be set."}; static const struct msg NameMustBeSet{1007,"The name property must be set."};
static const std::string ContactMustExist{"Contact must exist."}; static const struct msg ConfigBlockInvalid{1008,"Configuration block type invalid."};
static const std::string LocationMustExist{"Location must exist."}; static const struct msg UnknownId{1009,"Unknown UUID."};
static const std::string OnlyWSSupported{"This endpoint only supports WebSocket."}; static const struct msg InvalidDeviceTypes{1010,"Unknown or invalid device type(s)."};
static const std::string SerialNumberMismatch{"Serial Number mismatch."}; static const struct msg RecordNotCreated{1011,"Record could not be created."};
static const std::string InvalidCommand{"Invalid command."}; static const struct msg RecordNotUpdated{1012,"Record could not be updated."};
static const std::string NoRecordsDeleted{"No records deleted."}; static const struct msg UnknownManagementPolicyUUID{1013,"Unknown management policy UUID."};
static const std::string DeviceNotConnected{"Device is not currently connected."}; static const struct msg CannotDeleteRoot{1014,"Root Entity cannot be removed, only modified."};
static const std::string CannotCreateWS{"Telemetry system could not create WS endpoint. Please try again."}; static const struct msg MustCreateRootFirst{1015,"Root entity must be created first."};
static const std::string BothDeviceTypeRevision{"Both deviceType and revision must be set."}; static const struct msg ParentUUIDMustExist{1016,"Parent UUID must exist."};
static const std::string IdOrSerialEmpty{"SerialNumber and Id must not be empty."}; static const struct msg ConfigurationMustExist{1017,"Configuration must exist."};
static const std::string MissingUserID{"Missing user ID."}; static const struct msg MissingOrInvalidParameters{1018,"Invalid or missing parameters."};
static const std::string IdMustBe0{"To create a user, you must set the ID to 0"}; static const struct msg UnknownSerialNumber{1019,"Unknown Serial Number."};
static const std::string InvalidUserRole{"Invalid userRole."}; static const struct msg InvalidSerialNumber{1020,"Invalid Serial Number."};
static const std::string InvalidEmailAddress{"Invalid email address."}; static const struct msg SerialNumberExists{1021,"Serial Number already exists."};
static const std::string PasswordRejected{"Password was rejected. This maybe an old password."}; static const struct msg ValidNonRootUUID{1022,"Must be a non-root, and valid UUID."};
static const std::string InvalidIPRanges{"Invalid IP range specifications."}; static const struct msg VenueMustExist{1023,"Venue does not exist."};
static const std::string InvalidLOrderBy{"Invalid orderBy specification."}; static const struct msg NotBoth{1024,"You cannot specify both Entity and Venue"};
static const std::string NeedMobileNumber{"You must provide at least one validated phone number."}; static const struct msg EntityMustExist{1025,"Entity must exist."};
static const std::string BadMFAMethod{"MFA only supports sms or email."}; static const struct msg ParentOrEntityMustBeSet{1026,"Parent or Entity must be set."};
static const std::string InvalidCredentials{"Invalid credentials (username/password)."}; static const struct msg ContactMustExist{1027,"Contact must exist."};
static const std::string InvalidPassword{"Password does not conform to basic password rules."}; static const struct msg LocationMustExist{1028,"Location must exist."};
static const std::string UserPendingVerification{"User access denied pending email verification."}; static const struct msg OnlyWSSupported{1029,"This endpoint only supports WebSocket."};
static const std::string PasswordMustBeChanged{"Password must be changed."}; static const struct msg SerialNumberMismatch{1030,"Serial Number mismatch."};
static const std::string UnrecognizedRequest{"Ill-formed request. Please consult documentation."}; static const struct msg InvalidCommand{1031,"Invalid command."};
static const std::string MissingAuthenticationInformation{"Missing authentication information."}; static const struct msg NoRecordsDeleted{1032,"No records deleted."};
static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."}; static const struct msg DeviceNotConnected{1033,"Device is not currently connected."};
static const std::string ExpiredToken{"Token has expired, user must login."}; static const struct msg CannotCreateWS{1034,"Telemetry system could not create WS endpoint. Please try again."};
static const std::string SubscriberMustExist{"Subscriber must exist."}; static const struct msg BothDeviceTypeRevision{1035,"Both deviceType and revision must be set."};
static const std::string AuthenticatorVerificationIncomplete{"Authenticator validation is not complete."}; static const struct msg IdOrSerialEmpty{1036,"SerialNumber and Id must not be empty."};
static const std::string SMSCouldNotBeSentRetry{"SMS could not be sent to validate device, try later or change the phone number."}; static const struct msg MissingUserID{1037,"Missing user ID."};
static const std::string SMSCouldNotValidate{"Code and number could not be validated"}; static const struct msg IdMustBe0{1038,"To create a user, you must set the ID to 0"};
static const std::string InvalidDeviceClass{"Invalid device class. Must be: any, venue, entity, or subscriber"}; static const struct msg InvalidUserRole{1039,"Invalid userRole."};
static const std::string SerialNumberAlreadyProvisioned{"This device has already been provisioned to a subscriber."}; static const struct msg InvalidEmailAddress{1040,"Invalid email address."};
static const std::string SerialNumberNotTheProperClass{"Device is not available to subscribers. It ahs been assigned to another class of devices."}; static const struct msg PasswordRejected{1041,"Password was rejected. This maybe an old password."};
static const std::string UserAlreadyExists{"Username already exists."}; static const struct msg InvalidIPRanges{1042,"Invalid IP range specifications."};
static const std::string NotImplemented{"Function not implemented."}; static const struct msg InvalidLOrderBy{1043,"Invalid orderBy specification."};
static const std::string VariableMustExist{"Specified variable does not exist."}; static const struct msg NeedMobileNumber{1044,"You must provide at least one validated phone number."};
static const std::string InvalidEntityType{"Invalid entity type."}; static const struct msg BadMFAMethod{1045,"MFA only supports sms or email."};
static const std::string CannotDeleteSubEntity{"Cannot delete the default subscriber entity."}; static const struct msg InvalidCredentials{1046,"Invalid credentials (username/password)."};
static const std::string OperatorIdMustExist{"Missing or bad Operator ID"}; static const struct msg InvalidPassword{1047,"Password does not conform to basic password rules."};
static const std::string CannotDeleteDefaultOperator{"Cannot delete the default operator."}; static const struct msg UserPendingVerification{1048,"User access denied pending email verification."};
static const std::string CannotCreateDefaultOperator{"Cannot create the default operator."}; static const struct msg PasswordMustBeChanged{1049,"Password must be changed."};
static const std::string InvalidRRM{"Invalid RRM value."}; static const struct msg UnrecognizedRequest{1050,"Ill-formed request. Please consult documentation."};
static const std::string InvalidIPAddresses{"Invalid IP addresses."}; static const struct msg MissingAuthenticationInformation{1051,"Missing authentication information."};
static const std::string InvalidBillingCode{"Empty of invalid billing code."}; static const struct msg InsufficientAccessRights{1052,"Insufficient access rights to complete the operation."};
static const std::string InvalidBillingPeriod{"Invalid billing period."}; static const struct msg ExpiredToken{1053,"Token has expired, user must login."};
static const std::string InvalidSubscriberId{"Invalid subscriber ID."}; static const struct msg SubscriberMustExist{1054,"Subscriber must exist."};
static const std::string InvalidContactId{"Invalid contact ID."}; static const struct msg AuthenticatorVerificationIncomplete{1055,"Authenticator validation is not complete."};
static const std::string InvalidLocationId{"Invalid location ID."}; static const struct msg SMSCouldNotBeSentRetry{1056,"SMS could not be sent to validate device, try later or change the phone number."};
static const std::string InvalidContactType{"Invalid contact type."}; static const struct msg SMSCouldNotValidate{1057,"Code and number could not be validated"};
static const std::string InvalidLocationType{"Invalid location type."}; static const struct msg InvalidDeviceClass{1058,"Invalid device class. Must be: any, venue, entity, or subscriber"};
static const std::string InvalidOperatorId{"Invalid operator ID."}; static const struct msg SerialNumberAlreadyProvisioned{1059,"This device has already been provisioned to a subscriber."};
static const std::string InvalidServiceClassId{"Invalid service class ID."}; static const struct msg SerialNumberNotTheProperClass{1060,"Device is not available to subscribers. It ahs been assigned to another class of devices."};
static const std::string InvalidSubscriberDeviceId{"Invalid subscriber device ID."}; static const struct msg UserAlreadyExists{1061,"Username already exists."};
static const std::string InvalidRegistrationOperatorId{"Invalid registration operator ID."}; static const struct msg NotImplemented{1062,"Function not implemented."};
static const std::string InvalidRegistrationOperatorName{"Invalid registration operator name."}; static const struct msg VariableMustExist{1063,"Specified variable does not exist."};
static const std::string RegistrationNameDuplicate{"Registration name must be unique."}; static const struct msg InvalidEntityType{1064,"Invalid entity type."};
static const std::string SMSMFANotEnabled{"SMS is not enabled in the security service."}; static const struct msg CannotDeleteSubEntity{1065,"Cannot delete the default subscriber entity."};
static const std::string EMailMFANotEnabled{"email is not enabled in the security service."}; static const struct msg OperatorIdMustExist{1066,"Missing or bad Operator ID"};
static const struct msg CannotDeleteDefaultOperator{1067,"Cannot delete the default operator."};
static const struct msg CannotCreateDefaultOperator{1068,"Cannot create the default operator."};
static const struct msg InvalidRRM{1069,"Invalid RRM value."};
static const struct msg InvalidIPAddresses{1070,"Invalid IP addresses."};
static const struct msg InvalidBillingCode{1071,"Empty of invalid billing code."};
static const struct msg InvalidBillingPeriod{1072,"Invalid billing period."};
static const struct msg InvalidSubscriberId{1073,"Invalid subscriber ID."};
static const struct msg InvalidContactId{1074,"Invalid contact ID."};
static const struct msg InvalidLocationId{1075,"Invalid location ID."};
static const struct msg InvalidContactType{1076,"Invalid contact type."};
static const struct msg InvalidLocationType{1077,"Invalid location type."};
static const struct msg InvalidOperatorId{1078,"Invalid operator ID."};
static const struct msg InvalidServiceClassId{1079,"Invalid service class ID."};
static const struct msg InvalidSubscriberDeviceId{1080,"Invalid subscriber device ID."};
static const struct msg InvalidRegistrationOperatorId{1081,"Invalid registration operator ID."};
static const struct msg InvalidRegistrationOperatorName{1082,"Invalid registration operator name."};
static const struct msg RegistrationNameDuplicate{1083,"Registration name must be unique."};
static const struct msg SMSMFANotEnabled{1084,"SMS is not enabled in the security service."};
static const struct msg EMailMFANotEnabled{1085,"email is not enabled in the security service."};
static const struct msg TOTInvalidCode{1086,"Invalid code."};
static const struct msg TOTInvalidIndex{1087,"Invalid index."};
static const struct msg TOTRepeatedCode{1088,"Code is repeated. Must be new code."};
static const struct msg TOTInvalidProtocol{1089,"Invalid protocol sequence."};
static const struct msg TOTNoSession{1090,"No validation session present."};
static const struct msg SignupAlreadySigned{1091,"Code is repeated. Must be new code."};
static const struct msg SignupEmailCheck{1092,"Waiting for email check completion."};
static const struct msg SignupWaitingForDevice{1093,"Waiting for device."};
static const struct msg SMSMissingPhoneNumber{1094,"Missing phone number"};
static const struct msg SMSTryLater{1095,"SMS could not be sent. Verify the number or try again later."};
static const struct msg SMSMissingChallenge{1096,"Missing 'challengeCode'"};
static const struct msg MustHaveConfigElement{1097,"Must have 'configuration' element."};
static const struct msg ModelIDListCannotBeEmpty{1098,"Model ID list cannot be empty."};
static const struct msg DefConfigNameExists{1099,"Configuration name already exists."};
static const struct msg SubNoDeviceActivated{1100,"No devices activated yet."};
static const struct msg SubConfigNotRefreshed{1101,"Configuration could not be refreshed."};
static const struct msg ProvServiceNotAvailable{1102,"Provisioning service not available yet."};
static const struct msg SSIDInvalidPassword{1103,"Invalid password length. Must be 8 characters or greater, and a maximum of 32 characters."};
static const struct msg InvalidStartingIPAddress{1104,"Invalid starting/ending IP address."};
static const struct msg SubnetFormatError{1105,"Subnet must be in format like 192.168.1.1/24"};
static const struct msg DeviceModeError{1106,"Device mode subnet must be of the form 192.168.1.1/24"};
static const struct msg BadDeviceMode{1107,"Mode must be bridge, nat, or manual"};
static const struct msg DefaultGatewayFormat{1108,"Default gateway must be in format like 192.168.1.1"};
static const struct msg PrimaryDNSFormat{1109,"Primary DNS must be an IP address i.e. 192.168.1.1"};
static const struct msg SecondaryDNSFormat{1110,"Secondary DNS must be an IP address i.e. 192.168.1.1"};
static const struct msg BadConnectionType{1111,"Internet Connection must be automatic, bridge, pppoe, or manual"};
static const struct msg InvalidDeviceID{1112,"Invalid deviceID"};
static const struct msg InvalidVisibilityAttribute{1113,"Invalid visibility attribute"};
static const struct msg UnknownConfigurationSection{1114,"Unknown section"};
} }
namespace OpenWifi::RESTAPI::Protocol { namespace OpenWifi::RESTAPI::Protocol {