From 352fb344bd6df0c5ef2450775a03d06679cb6e6a Mon Sep 17 00:00:00 2001 From: stephb9959 Date: Sun, 22 Aug 2021 16:21:25 -0700 Subject: [PATCH] Fixed UpdateDeviceTypes. --- CMakeLists.txt | 5 +- README.md | 15 +++- build | 2 +- openapi/ow_prov.yaml | 63 +++++++-------- src/RESTAPI_ProvObjects.cpp | 22 +++--- src/RESTAPI_ProvObjects.h | 11 ++- src/RESTAPI_SecurityObjects.h | 4 +- src/RESTAPI_contact_handler.cpp | 10 --- src/RESTAPI_entity_handler.cpp | 25 +++--- src/RESTAPI_inventory_handler.cpp | 77 ++++++------------- src/StorageService.cpp | 122 +++++++++++++++++++++--------- src/StorageService.h | 14 ++-- src/orm.h | 8 ++ src/storage_contact.cpp | 9 +-- src/storage_contact.h | 1 - src/storage_inventory.cpp | 24 +++--- src/storage_inventory.h | 2 + src/storage_location.cpp | 15 ++-- src/storage_location.h | 1 - src/storage_mysql.cpp | 44 ----------- src/storage_pgql.cpp | 45 ----------- src/storage_policies.cpp | 6 +- src/storage_policies.h | 1 + src/storage_setup.cpp | 82 ++++++++++++++++++++ src/storage_sqlite.cpp | 26 ------- 25 files changed, 319 insertions(+), 315 deletions(-) delete mode 100644 src/storage_mysql.cpp delete mode 100644 src/storage_pgql.cpp create mode 100644 src/storage_setup.cpp delete mode 100644 src/storage_sqlite.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d4c7135..38c7598 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,7 +69,6 @@ add_executable(owprov src/StorageService.cpp src/StorageService.h src/SubSystemServer.cpp src/SubSystemServer.h src/RESTAPI_ProvObjects.cpp src/RESTAPI_ProvObjects.h - src/storage_pgql.cpp src/storage_mysql.cpp src/storage_sqlite.cpp src/storage_entity.cpp src/storage_entity.h src/storage_policies.cpp src/storage_policies.h src/OpenWifiTypes.h @@ -84,9 +83,9 @@ add_executable(owprov src/RESTAPI_inventory_handler.cpp src/RESTAPI_inventory_handler.h src/RESTAPI_managementPolicy_handler.cpp src/RESTAPI_managementPolicy_handler.h src/RESTAPI_inventory_list_handler.cpp src/RESTAPI_inventory_list_handler.h - src/dbhelpers.h src/RESTAPI_entity_list_handler.cpp src/RESTAPI_entity_list_handler.h - src/storage_management_roles.cpp src/storage_management_roles.h) + src/storage_management_roles.cpp src/storage_management_roles.h + src/storage_setup.cpp) target_link_libraries(owprov PUBLIC ${Poco_LIBRARIES} ${MySQL_LIBRARIES} diff --git a/README.md b/README.md index 822ffb8..9650860 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,20 @@ You must use the query command parameters to modify other properties ## Inventory Tags ### Creation rules - Entity must point to an existing non-root entity -- If you associate a venue, it must exist +- If you associate a venue, it must exist. +- You must use an existing device type. Device type cannot be empty. +- Name, description, notes are allowed. + +### Modification rules +- You can modify the device type to another valid one. + +## Venue +### Creation rules +- If you include an entity, the parent must bot be set +- if you include a parent, the entity must not be set +- You cannot have children upon creation. +- You may include an array of devices UUIDs +- Topology and design cannot be set ### Modification rules diff --git a/build b/build index a5c750f..dc7b54a 100644 --- a/build +++ b/build @@ -1 +1 @@ -27 \ No newline at end of file +33 \ No newline at end of file diff --git a/openapi/ow_prov.yaml b/openapi/ow_prov.yaml index 8c9c286..cbbf880 100644 --- a/openapi/ow_prov.yaml +++ b/openapi/ow_prov.yaml @@ -126,6 +126,12 @@ components: type: array items: $ref: '#/components/schemas/ManagementPolicyEntry' + inUse: + type: array + items: + type: string + format: uuid + example: each uuid is preceded by ent, or ven to say that the elemenet is entity or venue # uuids: ent: Entity: @@ -291,17 +297,12 @@ components: contact: type: string format: uuid - venues: + inUse: type: array items: type: string format: uuid - entities: - type: array - items: - type: string - format: uuid - + example: each uuid is preceded by ent, or ven to say that the elemenet is entity or venue # uuids: con: Contact: @@ -346,34 +347,29 @@ components: type: string accessPIN: type: string - venues: - type: array - items: - type: string - format: uuid - entities: + inUse: type: array items: type: string format: uuid - # uuids: svc: - ServiceConfiguration: + DeviceConfigurationElement: type: object properties: - id: + name: + type: string + description: + type: string + weight: + type: integer + configuration: type: string - format: uuid - managementPolicy: - $ref: '#/components/schemas/ManagementPolicy' - # uuids: cfg: DeviceConfiguration: type: object properties: - id: - type: string - format: uuid + allOf: + $ref: '#/components/schemas/ObjectInfo' managementPolicy: $ref: '#/components/schemas/ManagementPolicy' deviceTypes: @@ -381,7 +377,14 @@ components: items: type: string configuration: - type: string + type: array + items: + $ref: '#/components/schemas/DeviceConfigurationElement' + inUse: + type: array + items: + type: string + format: uuid InventoryTag: type: object @@ -398,16 +401,16 @@ components: entity: type: string format: uuid - subEntity: - type: string - format: uuid - subVenue: - type: string - format: uuid qrCode: type: string geoCode: type: string + location: + type: string + format: uuid + contact: + type: string + format: uuid InventoryTagList: type: object diff --git a/src/RESTAPI_ProvObjects.cpp b/src/RESTAPI_ProvObjects.cpp index e4a4cf8..97a2879 100644 --- a/src/RESTAPI_ProvObjects.cpp +++ b/src/RESTAPI_ProvObjects.cpp @@ -54,12 +54,14 @@ namespace OpenWifi::ProvObjects { void ManagementPolicy::to_json(Poco::JSON::Object &Obj) const { info.to_json(Obj); RESTAPI_utils::field_to_json(Obj, "entries", entries); + RESTAPI_utils::field_to_json(Obj, "inUse", inUse); } bool ManagementPolicy::from_json(const Poco::JSON::Object::Ptr &Obj) { try { info.from_json(Obj); RESTAPI_utils::field_from_json(Obj, "entries", entries); + RESTAPI_utils::field_from_json(Obj, "inUse", inUse); return true; } catch(...) { @@ -184,9 +186,8 @@ namespace OpenWifi::ProvObjects { RESTAPI_utils::field_to_json( Obj,"country",country); RESTAPI_utils::field_to_json( Obj,"phones",phones); RESTAPI_utils::field_to_json( Obj,"mobiles",mobiles); - RESTAPI_utils::field_to_json( Obj,"venues",venues); - RESTAPI_utils::field_to_json( Obj,"entities",entities); RESTAPI_utils::field_to_json( Obj,"geoCode",geoCode); + RESTAPI_utils::field_to_json( Obj,"inUse",inUse); } bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) { @@ -203,9 +204,8 @@ namespace OpenWifi::ProvObjects { RESTAPI_utils::field_from_json( Obj,"country",country); RESTAPI_utils::field_from_json( Obj,"phones",phones); RESTAPI_utils::field_from_json( Obj,"mobiles",mobiles); - RESTAPI_utils::field_from_json( Obj,"venues",venues); - RESTAPI_utils::field_from_json( Obj,"entities",entities); RESTAPI_utils::field_from_json( Obj,"geoCode",geoCode); + RESTAPI_utils::field_from_json( Obj,"inUse",inUse); return true; } catch (...) { @@ -227,8 +227,7 @@ namespace OpenWifi::ProvObjects { RESTAPI_utils::field_to_json( Obj,"primaryEmail",primaryEmail); RESTAPI_utils::field_to_json( Obj,"secondaryEmail",secondaryEmail); RESTAPI_utils::field_to_json( Obj,"accessPIN",accessPIN); - RESTAPI_utils::field_to_json( Obj,"venues",venues); - RESTAPI_utils::field_to_json( Obj,"entities",entities); + RESTAPI_utils::field_to_json( Obj,"inUse",inUse); } bool Contact::from_json(const Poco::JSON::Object::Ptr &Obj) { @@ -248,8 +247,7 @@ namespace OpenWifi::ProvObjects { RESTAPI_utils::field_from_json( Obj,"primaryEmail",primaryEmail); RESTAPI_utils::field_from_json( Obj,"secondaryEmail",secondaryEmail); RESTAPI_utils::field_from_json( Obj,"accessPIN",accessPIN); - RESTAPI_utils::field_from_json( Obj,"venues",venues); - RESTAPI_utils::field_from_json( Obj,"entities",entities); + RESTAPI_utils::field_from_json( Obj,"inUse",inUse); return true; } catch (...) { @@ -278,12 +276,12 @@ namespace OpenWifi::ProvObjects { RESTAPI_utils::field_to_json(Obj, "serialNumber", serialNumber); RESTAPI_utils::field_to_json(Obj, "venue", venue); RESTAPI_utils::field_to_json(Obj, "entity", entity); - RESTAPI_utils::field_to_json(Obj, "subEntity", subEntity); - RESTAPI_utils::field_to_json(Obj, "subVenue", subVenue); RESTAPI_utils::field_to_json(Obj, "subscriber", subscriber); RESTAPI_utils::field_to_json(Obj, "deviceType", deviceType); RESTAPI_utils::field_to_json(Obj, "qrCode", qrCode); RESTAPI_utils::field_to_json(Obj, "geoCode", geoCode); + RESTAPI_utils::field_to_json(Obj, "location", location); + RESTAPI_utils::field_to_json(Obj, "contact", contact); } bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) { @@ -292,12 +290,12 @@ namespace OpenWifi::ProvObjects { RESTAPI_utils::field_from_json( Obj,"serialNumber",serialNumber); RESTAPI_utils::field_from_json( Obj,"venue",venue); RESTAPI_utils::field_from_json( Obj,"entity",entity); - RESTAPI_utils::field_from_json( Obj,"subEntity",subEntity); - RESTAPI_utils::field_from_json( Obj,"subVenue",subVenue); RESTAPI_utils::field_from_json( Obj,"subscriber",subscriber); RESTAPI_utils::field_from_json( Obj,"deviceType",deviceType); RESTAPI_utils::field_from_json(Obj, "qrCode", qrCode); RESTAPI_utils::field_from_json( Obj,"geoCode",geoCode); + RESTAPI_utils::field_from_json( Obj,"location",location); + RESTAPI_utils::field_from_json( Obj,"contact",contact); return true; } catch(...) { diff --git a/src/RESTAPI_ProvObjects.h b/src/RESTAPI_ProvObjects.h index 39de481..e8e7c76 100644 --- a/src/RESTAPI_ProvObjects.h +++ b/src/RESTAPI_ProvObjects.h @@ -35,6 +35,7 @@ namespace OpenWifi::ProvObjects { struct ManagementPolicy { ObjectInfo info; std::vector entries; + Types::StringVec inUse; void to_json(Poco::JSON::Object &Obj) const; bool from_json(const Poco::JSON::Object::Ptr &Obj); @@ -142,9 +143,8 @@ namespace OpenWifi::ProvObjects { std::string country; Types::StringVec phones; Types::StringVec mobiles; - Types::StringVec venues; - Types::StringVec entities; std::string geoCode; + Types::StringVec inUse; void to_json(Poco::JSON::Object &Obj) const; bool from_json(const Poco::JSON::Object::Ptr &Obj); @@ -204,8 +204,7 @@ namespace OpenWifi::ProvObjects { std::string primaryEmail; std::string secondaryEmail; std::string accessPIN; - Types::StringVec venues; - Types::StringVec entities; + Types::StringVec inUse; void to_json(Poco::JSON::Object &Obj) const; bool from_json(const Poco::JSON::Object::Ptr &Obj); @@ -234,12 +233,12 @@ namespace OpenWifi::ProvObjects { std::string serialNumber; std::string venue; std::string entity; - std::string subEntity; - std::string subVenue; std::string subscriber; std::string deviceType; std::string qrCode; std::string geoCode; + std::string location; + std::string contact; void to_json(Poco::JSON::Object &Obj) const; bool from_json(const Poco::JSON::Object::Ptr &Obj); diff --git a/src/RESTAPI_SecurityObjects.h b/src/RESTAPI_SecurityObjects.h index 9ab885e..b422dbd 100644 --- a/src/RESTAPI_SecurityObjects.h +++ b/src/RESTAPI_SecurityObjects.h @@ -116,9 +116,9 @@ namespace OpenWifi::SecurityObjects { struct SystemEndpoint { std::string type; uint64_t id = 0; - std::string vendor; + std::string vendor{"OpenWiFi"}; std::string uri; - std::string authenticationType; + std::string authenticationType{"internal_v1"}; void to_json(Poco::JSON::Object &Obj) const; bool from_json(const Poco::JSON::Object::Ptr &Obj); }; diff --git a/src/RESTAPI_contact_handler.cpp b/src/RESTAPI_contact_handler.cpp index 1eda0a2..4d9970d 100644 --- a/src/RESTAPI_contact_handler.cpp +++ b/src/RESTAPI_contact_handler.cpp @@ -81,19 +81,9 @@ namespace OpenWifi{ C.info.id = Daemon()->CreateUUID(); C.info.created = C.info.modified = std::time(nullptr); - if(C.entities.empty() || C.entities.size()!=1) { - BadRequest(Request, Response, "A contact must have a single entity set."); - return; - } - std::string f{RESTAPI::Protocol::ID}; - if(!Storage()->EntityDB().Exists("id",C.entities[0])) { - BadRequest(Request, Response, "Unknown entity: " + C.entities[0] ); - return; - } if(Storage()->ContactDB().CreateRecord(C)) { - Storage()->EntityDB().AddContact("id",C.entities[0],C.info.id); Poco::JSON::Object Answer; C.to_json(Answer); ReturnObject(Request, Answer, Response); diff --git a/src/RESTAPI_entity_handler.cpp b/src/RESTAPI_entity_handler.cpp index ae29897..69d4713 100644 --- a/src/RESTAPI_entity_handler.cpp +++ b/src/RESTAPI_entity_handler.cpp @@ -214,18 +214,19 @@ namespace OpenWifi{ if(Storage()->EntityDB().UpdateRecord("id",UUID,LocalObject)) { for(const auto &i:Request) { std::string Child{i.second}; - if(i.first == "addContact") { - Storage()->EntityDB().AddContact("id", UUID, Child); - Storage()->ContactDB().AddEntity("id",Child,UUID); - } else if (i.first == "delContact") { - Storage()->EntityDB().DeleteContact("id", UUID, Child); - Storage()->ContactDB().DeleteEntity("id",Child,UUID); - } else if (i.first == "addLocation") { - Storage()->EntityDB().AddLocation("id", UUID, Child); - Storage()->LocationDB().AddEntity("id",Child,UUID); - } else if (i.first == "delLocation") { - Storage()->EntityDB().DeleteLocation("id", UUID, Child); - Storage()->LocationDB().DeleteEntity("id",Child,UUID); + auto UUID_parts = Utils::Split(Child,':'); + if(i.first=="add" && UUID_parts[0] == "con") { + Storage()->EntityDB().AddContact("id", UUID, UUID_parts[1]); + Storage()->ContactDB().AddInUse("id",UUID_parts[1],UUID); + } else if (i.first == "del" && UUID_parts[0] == "con") { + Storage()->EntityDB().DeleteContact("id", UUID, UUID_parts[1]); + Storage()->ContactDB().DeleteInUse("id",UUID_parts[1],UUID); + } else if (i.first == "add" && UUID_parts[0] == "loc") { + Storage()->EntityDB().AddLocation("id", UUID, UUID_parts[1]); + Storage()->LocationDB().AddInUse("id",UUID_parts[1],UUID); + } else if (i.first == "del" && UUID_parts[0] == "loc") { + Storage()->EntityDB().DeleteLocation("id", UUID, UUID_parts[1]); + Storage()->LocationDB().DeleteInUse("id",UUID_parts[1],UUID); } } Poco::JSON::Object Answer; diff --git a/src/RESTAPI_inventory_handler.cpp b/src/RESTAPI_inventory_handler.cpp index 15872fa..b3f0911 100644 --- a/src/RESTAPI_inventory_handler.cpp +++ b/src/RESTAPI_inventory_handler.cpp @@ -71,15 +71,6 @@ namespace OpenWifi{ return; } - if(!IT.entity.empty()) - Storage()->EntityDB().DeleteChild(RESTAPI::Protocol::ID,IT.entity,IT.info.id); - if(!IT.subEntity.empty()) - Storage()->EntityDB().DeleteChild(RESTAPI::Protocol::ID,IT.subEntity,IT.info.id); - if(!IT.venue.empty()) - Storage()->EntityDB().DeleteChild(RESTAPI::Protocol::ID,IT.venue,IT.info.id); - if(!IT.subVenue.empty()) - Storage()->EntityDB().DeleteChild(RESTAPI::Protocol::ID,IT.subVenue,IT.info.id); - Storage()->InventoryDB().DeleteRecord(RESTAPI::Protocol::ID, IT.info.id); OK(Request, Response); return; @@ -111,7 +102,17 @@ namespace OpenWifi{ return; } - if(IT.entity.empty() || OpenWifi::EntityDB::IsRoot(IT.entity) || !Storage()->InventoryDB().Exists("id",IT.entity)) { + if(IT.info.name.empty()) { + BadRequest(Request, Response, "Name cannot be empty."); + return; + } + + if(IT.deviceType.empty() || !Storage()->IsAcceptableDeviceType(IT.deviceType)) { + BadRequest(Request, Response, "DeviceType: '" + IT.deviceType + "' does not exist."); + return; + } + + if(IT.entity.empty() || OpenWifi::EntityDB::IsRoot(IT.entity) || !Storage()->EntityDB().Exists("id",IT.entity)) { BadRequest(Request, Response, "Device must be associated with a non-root and existing entity. UUID="+IT.entity); return; } @@ -122,13 +123,9 @@ namespace OpenWifi{ } IT.info.modified = IT.info.created = std::time(nullptr); - IT.subEntity = IT.subVenue = ""; IT.info.id = Daemon()->CreateUUID(); if(Storage()->InventoryDB().CreateRecord(IT)) { - Storage()->EntityDB().AddChild("id",IT.entity,IT.info.id); - if(!IT.venue.empty()) - Storage()->VenueDB().AddChild("id",IT.venue,IT.info.id); Poco::JSON::Object Answer; IT.to_json(Answer); ReturnObject(Request, Answer, Response); @@ -163,12 +160,21 @@ namespace OpenWifi{ SecurityObjects::append_from_json(RawObject, UserInfo_.userinfo, ExistingObject.info.notes); } - if(RawObject->has("name")) + if(RawObject->has("name") && !RawObject->get("name").toString().empty()) ExistingObject.info.name = RawObject->get("name").toString(); if(RawObject->has("description")) ExistingObject.info.description = RawObject->get("description").toString(); ExistingObject.info.modified = std::time(nullptr); + if(RawObject->has("deviceType")) { + std::string DeviceType{RawObject->get("deviceType").toString()}; + if(!Storage()->IsAcceptableDeviceType(DeviceType)) { + BadRequest(Request, Response, "DeviceType: '" + DeviceType + "' does not exist."); + return; + } + ExistingObject.deviceType = DeviceType; + } + // if we are changing venues... if(RawObject->has("entity")) { std::string Entity{RawObject->get("entity").toString()}; @@ -176,22 +182,7 @@ namespace OpenWifi{ BadRequest(Request, Response, "Entity association does not exist."); return; } - if(Entity!=ExistingObject.entity) { - Storage()->EntityDB().DeleteChild("id", ExistingObject.entity, ExistingObject.info.id); - Storage()->EntityDB().AddChild("id",Entity,ExistingObject.info.id); - } - } - - if(RawObject->has("subEntity")) { - std::string subEntity{RawObject->get("subEntity").toString()}; - if(!Storage()->EntityDB().Exists("id",subEntity)) { - BadRequest(Request, Response, "subEntity association does not exist."); - return; - } - if(subEntity!=ExistingObject.entity) { - Storage()->EntityDB().DeleteChild("id", ExistingObject.subEntity, ExistingObject.info.id); - Storage()->EntityDB().AddChild("id",subEntity,ExistingObject.info.id); - } + ExistingObject.entity = Entity; } if(RawObject->has("venue")) { @@ -200,29 +191,7 @@ namespace OpenWifi{ BadRequest(Request, Response, "Venue association does not exist."); return; } - if(Venue!=ExistingObject.venue) { - if(!ExistingObject.venue.empty()) - Storage()->VenueDB().DeleteChild("id", ExistingObject.venue, ExistingObject.info.id); - Storage()->VenueDB().AddChild("id",Venue,ExistingObject.info.id); - } - } - - if(RawObject->has("subVenue")) { - std::string subVenue{RawObject->get("subVenue").toString()}; - if(!Storage()->VenueDB().Exists("id",subVenue)) { - BadRequest(Request, Response, "Venue association does not exist."); - return; - } - if(subVenue!=ExistingObject.subVenue) { - if(!ExistingObject.subVenue.empty()) - Storage()->VenueDB().DeleteChild("id", ExistingObject.subVenue, ExistingObject.info.id); - Storage()->VenueDB().AddChild("id",subVenue,ExistingObject.info.id); - } - } - - if(RawObject->has("deviceType")) { - std::string DeviceType{RawObject->get("deviceType").toString()}; - ExistingObject.deviceType = DeviceType; + ExistingObject.venue = Venue; } if(Storage()->InventoryDB().UpdateRecord("id", ExistingObject.info.id, ExistingObject)) { diff --git a/src/StorageService.cpp b/src/StorageService.cpp index 5a6defe..b319b88 100644 --- a/src/StorageService.cpp +++ b/src/StorageService.cpp @@ -19,11 +19,6 @@ namespace OpenWifi { class Storage *Storage::instance_ = nullptr; - Storage::Storage() noexcept: - SubSystemServer("Storage", "STORAGE-SVR", "storage") - { - } - int Storage::Start() { SubMutexGuard Guard(Mutex_); @@ -152,48 +147,101 @@ namespace OpenWifi { bool Storage::Validate(const Poco::URI::QueryParameters &P, std::string &Error) { for(const auto &i:P) { - if(i.first == "addContact" || i.first == "delContact") { - if(!ContactDB_->Exists("id",i.second)) { - Error = "Unknown contact UUID: " + i.second; - break; - } + auto uuid_parts = Utils::Split(i.second,':'); + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "con") + if(!ContactDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown contact UUID: " + i.second; + break; + } } - if(i.first == "addLocation" || i.first == "delLocation") { - if(!LocationDB_->Exists("id",i.second)) { - Error = "Unknown Location UUID: " + i.second; - break; - } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "loc") + if(!LocationDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown location UUID: " + i.second; + break; + } } - if(i.first == "addEntity" || i.first == "delEntity") { - if(!EntityDB_->Exists("id",i.second)) { - Error = "Unknown Entity UUID: " + i.second; - break; - } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "ent") + if(!EntityDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown entity UUID: " + i.second; + break; + } } - if(i.first == "addVenue" || i.first == "delVenue") { - if(!VenueDB_->Exists("id",i.second)) { - Error = "Unknown Venue UUID: " + i.second; - break; - } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "ven") + if(!VenueDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown venue UUID: " + i.second; + break; + } } - if(i.first == "addManager" || i.first == "delManager") { - /* - if(!VenueDB_->Exists("id",i.second)) { - Error = "Unknown Manager UUID: " + i.second; - break; - }*/ - } - if(i.first == "addDevice" || i.first == "delDevice") { - if(!InventoryDB_->Exists("id",i.second)) { - Error = "Unknown Inventory UUID: " + i.second; - break; - } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "dev") + if(!InventoryDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown device UUID: " + i.second; + break; + } } + } if(Error.empty()) return true; return false; + + } + + bool Storage::Validate(const Types::StringVec &P, std::string &Error) { + for(const auto &i:P) { + auto uuid_parts = Utils::Split(i,':'); + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "con") + if(!ContactDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown contact UUID: " + i; + break; + } + } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "loc") + if(!LocationDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown location UUID: " + i; + break; + } + } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "ent") + if(!EntityDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown entity UUID: " + i; + break; + } + } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "ven") + if(!VenueDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown venue UUID: " + i; + break; + } + } + + if(uuid_parts.size()==2) { + if(uuid_parts[0] == "dev") + if(!InventoryDB_->Exists("id",uuid_parts[1])) { + Error = "Unknown device UUID: " + i; + break; + } + } + } + if(Error.empty()) + return true; + return false; } } diff --git a/src/StorageService.h b/src/StorageService.h index f42debe..c90b290 100644 --- a/src/StorageService.h +++ b/src/StorageService.h @@ -44,10 +44,6 @@ class Storage : public SubSystemServer, Poco::Runnable { [[nodiscard]] std::string ConvertParams(const std::string &S) const; - int Setup_SQLite(); - int Setup_MySQL(); - int Setup_PostgreSQL(); - OpenWifi::EntityDB & EntityDB() { return *EntityDB_; }; OpenWifi::PolicyDB & PolicyDB() { return *PolicyDB_; }; OpenWifi::VenueDB & VenueDB() { return *VenueDB_; }; @@ -57,6 +53,7 @@ class Storage : public SubSystemServer, Poco::Runnable { OpenWifi::ManagementRoleDB & RolesDB() { return *RolesDB_; }; bool Validate(const Poco::URI::QueryParameters &P, std::string &Error); + bool Validate(const Types::StringVec &P, std::string &Error); inline bool IsAcceptableDeviceType(const std::string &D) const { return (DeviceTypes_.find(D)!=DeviceTypes_.end());}; @@ -83,7 +80,14 @@ class Storage : public SubSystemServer, Poco::Runnable { std::atomic_bool Running_=false; bool UpdateDeviceTypes(); - Storage() noexcept; + Storage() noexcept: + SubSystemServer("Storage", "STORAGE-SVR", "storage") + { + } + + int Setup_SQLite(); + int Setup_MySQL(); + int Setup_PostgreSQL(); }; inline Storage * Storage() { return Storage::instance(); } diff --git a/src/orm.h b/src/orm.h index 4a064b8..17c8ce3 100644 --- a/src/orm.h +++ b/src/orm.h @@ -535,6 +535,14 @@ namespace ORM { return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, false); } + inline bool AddInUse(const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { + return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, ChildUUID, true); + } + + inline bool DeleteInUse(const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { + return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, ChildUUID, false); + } + [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { if(From<1) From=1; if(Type==ORM::sqlite) { diff --git a/src/storage_contact.cpp b/src/storage_contact.cpp index c6b1e80..9fb78e5 100644 --- a/src/storage_contact.cpp +++ b/src/storage_contact.cpp @@ -30,8 +30,7 @@ namespace OpenWifi { ORM::Field{"primaryEmail",ORM::FieldType::FT_TEXT}, ORM::Field{"secondaryEmail",ORM::FieldType::FT_TEXT}, ORM::Field{"accessPIN",ORM::FieldType::FT_TEXT}, - ORM::Field{"venues",ORM::FieldType::FT_TEXT}, - ORM::Field{"entities",ORM::FieldType::FT_TEXT} + ORM::Field{"inUse",ORM::FieldType::FT_TEXT} }; static ORM::IndexVec ContactDB_Indexes{ @@ -66,8 +65,7 @@ template<> void ORM::DB< OpenWifi::ContactDBRecordType, OpenWifi::ProvObjects Out.primaryEmail = In.get<15>(); Out.secondaryEmail = In.get<16>(); Out.accessPIN = In.get<17>(); - OpenWifi::Types::from_string(In.get<18>(), Out.venues); - OpenWifi::Types::from_string(In.get<19>(), Out.entities); + OpenWifi::Types::from_string(In.get<18>(), Out.inUse); } template<> void ORM::DB< OpenWifi::ContactDBRecordType, OpenWifi::ProvObjects::Contact>::Convert(OpenWifi::ProvObjects::Contact &In, OpenWifi::ContactDBRecordType &Out) { @@ -89,6 +87,5 @@ template<> void ORM::DB< OpenWifi::ContactDBRecordType, OpenWifi::ProvObjects Out.set<15>(In.primaryEmail); Out.set<16>(In.secondaryEmail); Out.set<17>(In.accessPIN); - Out.set<18>(OpenWifi::Types::to_string(In.venues)); - Out.set<19>(OpenWifi::Types::to_string(In.entities)); + Out.set<18>(OpenWifi::Types::to_string(In.inUse)); } diff --git a/src/storage_contact.h b/src/storage_contact.h index 3d2d850..6614938 100644 --- a/src/storage_contact.h +++ b/src/storage_contact.h @@ -28,7 +28,6 @@ namespace OpenWifi { std::string, std::string, std::string, - std::string, std::string > ContactDBRecordType; diff --git a/src/storage_inventory.cpp b/src/storage_inventory.cpp index 6065358..f1be203 100644 --- a/src/storage_inventory.cpp +++ b/src/storage_inventory.cpp @@ -21,10 +21,12 @@ namespace OpenWifi { ORM::Field{"serialNumber",ORM::FieldType::FT_TEXT}, ORM::Field{"venue",ORM::FieldType::FT_TEXT}, ORM::Field{"entity",ORM::FieldType::FT_TEXT}, - ORM::Field{"subEntity",ORM::FieldType::FT_TEXT}, - ORM::Field{"subVenue",ORM::FieldType::FT_TEXT}, + ORM::Field{"subscriber",ORM::FieldType::FT_TEXT}, ORM::Field{"deviceType",ORM::FieldType::FT_TEXT}, - ORM::Field{"qrcode",ORM::FieldType::FT_TEXT} + ORM::Field{"qrcode",ORM::FieldType::FT_TEXT}, + ORM::Field{"geocode",ORM::FieldType::FT_TEXT}, + ORM::Field{"location",ORM::FieldType::FT_TEXT}, + ORM::Field{"contact",ORM::FieldType::FT_TEXT} }; static ORM::IndexVec InventoryDB_Indexes{ @@ -53,10 +55,12 @@ template<> void ORM::DB< OpenWifi::InventoryDBRecordType, OpenWifi::ProvObjec Out.serialNumber = In.get<6>(); Out.venue = In.get<7>(); Out.entity = In.get<8>(); - Out.subEntity = In.get<9>(); - Out.subVenue = In.get<10>(); - Out.deviceType = In.get<11>(); + Out.subscriber = In.get<9>(); + Out.deviceType = In.get<10>(); Out.qrCode = In.get<11>(); + Out.geoCode = In.get<12>(); + Out.location = In.get<13>(); + Out.contact = In.get<14>(); } template<> void ORM::DB< OpenWifi::InventoryDBRecordType, OpenWifi::ProvObjects::InventoryTag>::Convert(OpenWifi::ProvObjects::InventoryTag &In, OpenWifi::InventoryDBRecordType &Out) { @@ -69,8 +73,10 @@ template<> void ORM::DB< OpenWifi::InventoryDBRecordType, OpenWifi::ProvObjec Out.set<6>(In.serialNumber); Out.set<7>(In.venue); Out.set<8>(In.entity); - Out.set<9>(In.subEntity); - Out.set<10>(In.subVenue); - Out.set<11>(In.deviceType); + Out.set<9>(In.subscriber); + Out.set<10>(In.deviceType); Out.set<11>(In.qrCode); + Out.set<12>(In.geoCode); + Out.set<13>(In.location); + Out.set<14>(In.contact); } diff --git a/src/storage_inventory.h b/src/storage_inventory.h index 44b2fb3..1a11508 100644 --- a/src/storage_inventory.h +++ b/src/storage_inventory.h @@ -22,6 +22,8 @@ namespace OpenWifi { std::string, std::string, std::string, + std::string, + std::string, std::string > InventoryDBRecordType; diff --git a/src/storage_location.cpp b/src/storage_location.cpp index 6e720a0..ab31452 100644 --- a/src/storage_location.cpp +++ b/src/storage_location.cpp @@ -27,9 +27,8 @@ namespace OpenWifi { ORM::Field{"country",ORM::FieldType::FT_TEXT}, ORM::Field{"phones",ORM::FieldType::FT_TEXT}, ORM::Field{"mobiles",ORM::FieldType::FT_TEXT}, - ORM::Field{"venues",ORM::FieldType::FT_TEXT}, - ORM::Field{"entities",ORM::FieldType::FT_TEXT}, - ORM::Field{"geoCode",ORM::FieldType::FT_TEXT} + ORM::Field{"geoCode",ORM::FieldType::FT_TEXT}, + ORM::Field{"inUse",ORM::FieldType::FT_TEXT} }; static ORM::IndexVec LocationDB_Indexes{ @@ -60,9 +59,8 @@ template<> void ORM::DB(); OpenWifi::Types::from_string(In.get<13>(), Out.phones); OpenWifi::Types::from_string(In.get<14>(), Out.mobiles); - OpenWifi::Types::from_string(In.get<15>(), Out.venues); - OpenWifi::Types::from_string(In.get<16>(), Out.entities); - Out.geoCode = In.get<17>(); + Out.geoCode = In.get<15>(); + OpenWifi::Types::from_string(In.get<16>(), Out.inUse); } template<> void ::ORM::DB::Convert(OpenWifi::ProvObjects::Location &In, OpenWifi::LocationDBRecordType &Out) { @@ -81,8 +79,7 @@ template<> void ::ORM::DB(In.country); Out.set<13>(OpenWifi::Types::to_string(In.phones)); Out.set<14>(OpenWifi::Types::to_string(In.mobiles)); - Out.set<15>(OpenWifi::Types::to_string(In.venues)); - Out.set<16>(OpenWifi::Types::to_string(In.entities)); - Out.set<17>(In.geoCode); + Out.set<15>(In.geoCode); + Out.set<16>(OpenWifi::Types::to_string(In.inUse)); } diff --git a/src/storage_location.h b/src/storage_location.h index 2d4beee..920ddd7 100644 --- a/src/storage_location.h +++ b/src/storage_location.h @@ -26,7 +26,6 @@ namespace OpenWifi { std::string, std::string, std::string, - std::string, std::string > LocationDBRecordType; diff --git a/src/storage_mysql.cpp b/src/storage_mysql.cpp deleted file mode 100644 index ee546b0..0000000 --- a/src/storage_mysql.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// License type: BSD 3-Clause License -// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE -// -// Created by Stephane Bourque on 2021-03-04. -// Arilia Wireless Inc. -// - -#include "Daemon.h" -#include "StorageService.h" - -namespace OpenWifi { - -#ifdef SMALL_BUILD - int Service::Setup_MySQL() { instance()->exit(Poco::Util::Application::EXIT_CONFIG);} -#else - - int Storage::Setup_MySQL() { - - Logger_.notice("MySQL Storage enabled."); - auto NumSessions = Daemon()->ConfigGetInt("storage.type.mysql.maxsessions", 64); - auto IdleTime = Daemon()->ConfigGetInt("storage.type.mysql.idletime", 60); - auto Host = Daemon()->ConfigGetString("storage.type.mysql.host"); - auto Username = Daemon()->ConfigGetString("storage.type.mysql.username"); - auto Password = Daemon()->ConfigGetString("storage.type.mysql.password"); - auto Database = Daemon()->ConfigGetString("storage.type.mysql.database"); - auto Port = Daemon()->ConfigGetString("storage.type.mysql.port"); - - std::string ConnectionStr = - "host=" + Host + - ";user=" + Username + - ";password=" + Password + - ";db=" + Database + - ";port=" + Port + - ";compress=true;auto-reconnect=true"; - - MySQLConn_ = std::make_unique(); - MySQLConn_->registerConnector(); - Pool_ = std::make_unique(MySQLConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); - - return 0; - } -#endif -} \ No newline at end of file diff --git a/src/storage_pgql.cpp b/src/storage_pgql.cpp deleted file mode 100644 index 61add84..0000000 --- a/src/storage_pgql.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// License type: BSD 3-Clause License -// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE -// -// Created by Stephane Bourque on 2021-03-04. -// Arilia Wireless Inc. -// - -#include "Daemon.h" -#include "StorageService.h" - -namespace OpenWifi { - -#ifdef SMALL_BUILD - int Service::Setup_PostgreSQL() { instance()->exit(Poco::Util::Application::EXIT_CONFIG);} -#else - int Storage::Setup_PostgreSQL() { - Logger_.notice("PostgreSQL Storage enabled."); - - auto NumSessions = Daemon()->ConfigGetInt("storage.type.postgresql.maxsessions", 64); - auto IdleTime = Daemon()->ConfigGetInt("storage.type.postgresql.idletime", 60); - auto Host = Daemon()->ConfigGetString("storage.type.postgresql.host"); - auto Username = Daemon()->ConfigGetString("storage.type.postgresql.username"); - auto Password = Daemon()->ConfigGetString("storage.type.postgresql.password"); - auto Database = Daemon()->ConfigGetString("storage.type.postgresql.database"); - auto Port = Daemon()->ConfigGetString("storage.type.postgresql.port"); - auto ConnectionTimeout = Daemon()->ConfigGetString("storage.type.postgresql.connectiontimeout"); - - std::string ConnectionStr = - "host=" + Host + - " user=" + Username + - " password=" + Password + - " dbname=" + Database + - " port=" + Port + - " connect_timeout=" + ConnectionTimeout; - - PostgresConn_ = std::make_unique(); - PostgresConn_->registerConnector(); - Pool_ = std::make_unique(PostgresConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); - - return 0; - } -#endif - -} \ No newline at end of file diff --git a/src/storage_policies.cpp b/src/storage_policies.cpp index 8096f75..f9634de 100644 --- a/src/storage_policies.cpp +++ b/src/storage_policies.cpp @@ -18,7 +18,8 @@ namespace OpenWifi { ORM::Field{"notes",ORM::FieldType::FT_TEXT}, ORM::Field{"created",ORM::FieldType::FT_BIGINT}, ORM::Field{"modified",ORM::FieldType::FT_BIGINT}, - ORM::Field{"entries",ORM::FieldType::FT_TEXT} + ORM::Field{"entries",ORM::FieldType::FT_TEXT}, + ORM::Field{"inUse",ORM::FieldType::FT_TEXT} }; static ORM::IndexVec PolicyDB_Indexes{ @@ -41,8 +42,10 @@ template<> void ORM::DB< OpenWifi::PolicyDBRecordType, OpenWifi::ProvObjects: Out.info.created = In.get<4>(); Out.info.modified = In.get<5>(); Out.entries = OpenWifi::RESTAPI_utils::to_object_array(In.get<6>()); + OpenWifi::Types::from_string(In.get<7>(), Out.inUse); } + template<> void ORM::DB< OpenWifi::PolicyDBRecordType, OpenWifi::ProvObjects::ManagementPolicy>::Convert(OpenWifi::ProvObjects::ManagementPolicy &In, OpenWifi::PolicyDBRecordType &Out) { Out.set<0>(In.info.id); Out.set<1>(In.info.name); @@ -51,4 +54,5 @@ template<> void ORM::DB< OpenWifi::PolicyDBRecordType, OpenWifi::ProvObjects: Out.set<4>(In.info.created); Out.set<5>(In.info.modified); Out.set<6>(OpenWifi::RESTAPI_utils::to_string(In.entries)); + Out.set<7>(OpenWifi::Types::to_string(In.inUse)); } diff --git a/src/storage_policies.h b/src/storage_policies.h index 7945bbe..f18b815 100644 --- a/src/storage_policies.h +++ b/src/storage_policies.h @@ -16,6 +16,7 @@ namespace OpenWifi { std::string, uint64_t, uint64_t, + std::string, std::string > PolicyDBRecordType; diff --git a/src/storage_setup.cpp b/src/storage_setup.cpp new file mode 100644 index 0000000..03bcecf --- /dev/null +++ b/src/storage_setup.cpp @@ -0,0 +1,82 @@ +// +// Created by stephane bourque on 2021-08-22. +// + +#include "StorageService.h" +#include "Daemon.h" + +namespace OpenWifi { + +#ifdef SMALL_BUILD + int Service::Setup_MySQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } + int Service::Setup_PostgreSQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } +#else + + int Storage::Setup_SQLite() { + Logger_.notice("SQLite Storage enabled."); + auto DBName = Daemon()->DataDir() + "/" + Daemon()->ConfigGetString("storage.type.sqlite.db"); + auto NumSessions = Daemon()->ConfigGetInt("storage.type.sqlite.maxsessions", 64); + auto IdleTime = Daemon()->ConfigGetInt("storage.type.sqlite.idletime", 60); + SQLiteConn_ = std::make_unique(); + SQLiteConn_->registerConnector(); + Pool_ = std::make_unique(SQLiteConn_->name(), DBName, 4, NumSessions, IdleTime); + return 0; + } + + int Storage::Setup_MySQL() { + + Logger_.notice("MySQL Storage enabled."); + auto NumSessions = Daemon()->ConfigGetInt("storage.type.mysql.maxsessions", 64); + auto IdleTime = Daemon()->ConfigGetInt("storage.type.mysql.idletime", 60); + auto Host = Daemon()->ConfigGetString("storage.type.mysql.host"); + auto Username = Daemon()->ConfigGetString("storage.type.mysql.username"); + auto Password = Daemon()->ConfigGetString("storage.type.mysql.password"); + auto Database = Daemon()->ConfigGetString("storage.type.mysql.database"); + auto Port = Daemon()->ConfigGetString("storage.type.mysql.port"); + + std::string ConnectionStr = + "host=" + Host + + ";user=" + Username + + ";password=" + Password + + ";db=" + Database + + ";port=" + Port + + ";compress=true;auto-reconnect=true"; + + MySQLConn_ = std::make_unique(); + MySQLConn_->registerConnector(); + Pool_ = std::make_unique(MySQLConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); + + return 0; + } + + int Storage::Setup_PostgreSQL() { + Logger_.notice("PostgreSQL Storage enabled."); + + auto NumSessions = Daemon()->ConfigGetInt("storage.type.postgresql.maxsessions", 64); + auto IdleTime = Daemon()->ConfigGetInt("storage.type.postgresql.idletime", 60); + auto Host = Daemon()->ConfigGetString("storage.type.postgresql.host"); + auto Username = Daemon()->ConfigGetString("storage.type.postgresql.username"); + auto Password = Daemon()->ConfigGetString("storage.type.postgresql.password"); + auto Database = Daemon()->ConfigGetString("storage.type.postgresql.database"); + auto Port = Daemon()->ConfigGetString("storage.type.postgresql.port"); + auto ConnectionTimeout = Daemon()->ConfigGetString("storage.type.postgresql.connectiontimeout"); + + std::string ConnectionStr = + "host=" + Host + + " user=" + Username + + " password=" + Password + + " dbname=" + Database + + " port=" + Port + + " connect_timeout=" + ConnectionTimeout; + + PostgresConn_ = std::make_unique(); + PostgresConn_->registerConnector(); + Pool_ = std::make_unique(PostgresConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); + + return 0; + } + +#endif + +} + diff --git a/src/storage_sqlite.cpp b/src/storage_sqlite.cpp deleted file mode 100644 index 5115b49..0000000 --- a/src/storage_sqlite.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// -// License type: BSD 3-Clause License -// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE -// -// Created by Stephane Bourque on 2021-03-04. -// Arilia Wireless Inc. -// - -#include "Daemon.h" -#include "StorageService.h" - -namespace OpenWifi { - int Storage::Setup_SQLite() { - Logger_.notice("SQLite Storage enabled."); - - auto DBName = Daemon()->DataDir() + "/" + Daemon()->ConfigGetString("storage.type.sqlite.db"); - auto NumSessions = Daemon()->ConfigGetInt("storage.type.sqlite.maxsessions", 64); - auto IdleTime = Daemon()->ConfigGetInt("storage.type.sqlite.idletime", 60); - - SQLiteConn_ = std::make_unique(); - SQLiteConn_->registerConnector(); - Pool_ = std::make_unique(SQLiteConn_->name(), DBName, 4, NumSessions, IdleTime); - - return 0; - } -} \ No newline at end of file