diff --git a/CMakeLists.txt b/CMakeLists.txt index 563d4ef..2e6e208 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.13) -project(ucentraltopo VERSION 0.1.0) +project(owprov VERSION 2.1.0) set(CMAKE_CXX_STANDARD 17) @@ -48,7 +48,7 @@ endif() include_directories(/usr/local/include /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include) -add_executable( ucentraltopo +add_executable(owprov build src/Daemon.cpp src/Daemon.h src/Dashboard.h src/Dashboard.cpp @@ -56,7 +56,6 @@ add_executable( ucentraltopo src/Utils.h src/Utils.cpp src/RESTAPI_utils.cpp src/RESTAPI_utils.h src/RESTAPI_SecurityObjects.h src/RESTAPI_SecurityObjects.h - src/RESTAPI_TopoObjects.cpp src/RESTAPI_TopoObjects.h src/ALBHealthCheckServer.h src/AuthClient.cpp src/AuthClient.h src/KafkaManager.cpp src/KafkaManager.h @@ -69,12 +68,18 @@ add_executable( ucentraltopo src/RESTAPI_InternalServer.h src/RESTAPI_InternalServer.cpp 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_tables.cpp + src/storage_entity.cpp src/storage_entity.h + src/storage_policies.cpp src/storage_policies.h src/uCentralTypes.h - ) + src/storage_venue.cpp src/storage_venue.h + src/storage_location.cpp src/storage_location.h + src/storage_contact.cpp src/storage_contact.h + src/RESTAPI_entity_handler.cpp src/RESTAPI_entity_handler.h + src/storage_inventory.cpp src/storage_inventory.h) -target_link_libraries(ucentraltopo PUBLIC +target_link_libraries(owprov PUBLIC ${Poco_LIBRARIES} ${MySQL_LIBRARIES} ${Boost_LIBRARIES} ${ZLIB_LIBRARIES} ${AWSSDK_LINK_LIBRARIES} diff --git a/README.md b/README.md index 93416d6..316f83c 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ -# ucentral-topo \ No newline at end of file +# OpenWiFi Provisioning + diff --git a/build b/build new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/build @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/openapi/ow_prov.yaml b/openapi/ow_prov.yaml new file mode 100644 index 0000000..491a54b --- /dev/null +++ b/openapi/ow_prov.yaml @@ -0,0 +1,539 @@ +openapi: 3.0.1 +info: + title: OpenWiFi Provisioning Model + description: Definitions and APIs to manages an OpenWiFi network. + version: 2.1.0 + license: + name: BSD3 + +servers: + - url: 'https://localhost:16005/api/v1' + +security: + - bearerAuth: [] + - ApiKeyAuth: [] + +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: X-API-KEY + bearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + + responses: + NotFound: + description: The specified resource was not found. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + ErrorDetails: + type: string + ErrorDescription: + type: string + + Unauthorized: + description: The requested does not have sufficient rights to perform the operation. + content: + application/json: + schema: + properties: + ErrorCode: + type: integer + ErrorDetails: + type: string + ErrorDescription: + type: string + + Success: + description: The requested operation was performed. + content: + application/json: + schema: + properties: + Operation: + type: string + Details: + type: string + Code: + type: integer + + schemas: + + ObjectInfo: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + notes: + type: array + items: + $ref: '#/components/schemas/NoteInfo' + created: + type: integer + format: int64 + modified: + type: integer + format: int64 + + # uuids: mpe: + ManagementPolicyEntry: + type: object + properties: + users: + type: array + items: + type: string + resources: + description: this is a list of UUID and UUID Patterns to control by this policy + type: array + items: + type: string + access: + type: array + items: + type: string + enum: + - NOACCESS + - READ + - MODIFY + - DELETE + - LIST + - CREATE + - FULL + policy: + description: A JSON document describing the policy + type: string + + # uuids: mpp: + ManagementPolicy: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + entries: + type: array + items: + $ref: '#/components/schemas/ManagementPolicyEntry' + + # uuids: ent: + Entity: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + parent: + description: If empty, then this is the root entity, otherwise this points to a parent entity + type: string + format: uuid + children: + type: array + items: + type: string + format: uuid + managers: + description: The list of UUID of the management groups allowed to manage this entity + type: array + items: + type: string + format: uuid + contacts: + description: The list of UUID of the contacts for the entity + type: array + items: + type: string + format: uuid + locations: + description: The list of UUID of the locations associated with thit entiry + type: array + items: + type: string + format: uuid + managementPolicy: + type: string + format: uuid + + DiGraphEntry: + type: object + properties: + parent: + type: string + format: uuid + child: + type: string + format: uuid + + DiGraph: + type: array + items: + $ref: '#/components/schemas/DiGraphEntry' + + # uuids: ven: + Venue: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + owner: + type: string + format: uuid + parent: + type: string + format: uuid + children: + type: array + items: + type: string + format: uuid + managers: + type: array + items: + type: string + format: uuid + managementPolicy: + type: string + format: uuid + devices: + type: array + items: + type: string + format: uuid + topology: + $ref: '#/components/schemas/DiGraph' + design: + type: string + + # uuids: mgg: + ManagementGroup: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + managementPolicy: + $ref: '#/components/schemas/ManagementPolicy' + managers: + type: array + items: + type: string + format: uuid + + # uuids: loc: + Location: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + type: + type: string + enum: + - SERVICE + - EQUIPMENT + - AUTO + - MANUAL + - SPECIAL + - UNKNOWN + - CORPORATE + buildingName: + type: string + addressLines: + type: array + items: + type: string + city: + type: string + state: + type: string + postal: + type: string + country: + type: string + telephones: + type: array + items: + type: string + contact: + type: string + format: uuid + + # uuids: con: + Contact: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + type: + type: string + enum: + - SUBSCRIBER + - USER + - INSTALLER + - CSR + - MANAGER + - BUSINESSOWNER + - TECHNICIAN + - CORPORATE + title: + type: string + salutation: + type: string + firstname: + type: string + lastname: + type: string + initials: + type: string + visual: + type: string + mobiles: + type: array + items: + type: string + phones: + type: array + items: + type: string + location: + type: string + format: uuid + primaryEmail: + type: string + secondaryEmail: + type: string + accessPIN: + type: string + + # uuids: svc: + ServiceConfiguration: + type: object + properties: + id: + type: string + format: uuid + managementPolicy: + $ref: '#/components/schemas/ManagementPolicy' + + # uuids: cfg: + DeviceConfiguration: + type: object + properties: + id: + type: string + format: uuid + managementPolicy: + $ref: '#/components/schemas/ManagementPolicy' + deviceTypes: + type: array + items: + type: string + configuration: + type: string + + InventoryTag: + type: object + properties: + allOf: + $ref: '#/components/schemas/ObjectInfo' + serialNumber: + type: string + venue: + type: string + format: uuid + entity: + type: string + format: uuid + subEntity: + type: string + format: uuid + subVenue: + type: string + format: uuid + + ######################################################################################### + ## + ## These are endpoints that all services in the OPenWiFI stack must provide + ## + ######################################################################################### + AnyPayload: + type: object + properties: + Document: + type: string + + StringList: + type: object + properties: + list: + type: array + items: + type: string + + TagValuePair: + type: object + properties: + tag: + type: string + value: + type: string + + TagValuePairList: + type: object + properties: + tagList: + type: array + items: + $ref: '#/components/schemas/TagValuePair' + + TagIntPair: + type: object + properties: + tag: + type: string + value: + type: integer + format: int64 + + TagIntPairList: + type: object + properties: + tagList: + type: array + items: + $ref: '#/components/schemas/TagIntPair' + + SystemCommandDetails: + type: object + properties: + command: + type: string + enum: + - setloglevels + - getloglevels + - getSubSystemNames + - getLogLevelNames + - stats + parameters: + oneOf: + - $ref: '#/components/schemas/StringList' + - $ref: '#/components/schemas/TagValuePairList' + + SystemCommandResults: + type: object + oneOf: + - $ref: '#/components/schemas/StringList' + - $ref: '#/components/schemas/TagValuePairList' + + NoteInfo: + type: object + properties: + created: + type: integer + format: int64 + createdBy: + type: string + note: + type: string + + Dashboard: + type: object + properties: + snapshot: + type: integer + format: int64 + tenants: + $ref: '#/components/schemas/TagIntPairList' + +paths: + /entity: + get: + tags: + - Entities + operationId: getEntities + summary: Retrieve the list of entities + + + + + + ######################################################################################### + ## + ## These are endpoints that all services in the OpenWiFi stack must provide + ## + ######################################################################################### + /dashboard: + get: + tags: + - Dashboards + summary: Get the last version of the dashboard + operationId: getDeviceDashboard + responses: + 200: + $ref: '#/components/schemas/Dashboard' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + /system: + post: + tags: + - System Commands + summary: Perform some systeme wide commands + operationId: systemCommand + requestBody: + description: Command details + content: + application/json: + schema: + $ref: '#/components/schemas/SystemCommandDetails' + responses: + 200: + description: Successfull command execution + content: + application/json: + schema: + $ref: '#/components/schemas/SystemCommandResults' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + get: + tags: + - System Commands + summary: Retrieve different values from the running service. + operationId: getSystemCommand + parameters: + - in: query + description: Get a value + name: command + schema: + type: string + enum: + - version + - times + required: true + + responses: + 200: + description: Successfull command execution + content: + application/json: + schema: + $ref: '#/components/schemas/TagValuePair' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + + diff --git a/ucentralprov.properties b/ow_prov.properties similarity index 71% rename from ucentralprov.properties rename to ow_prov.properties index adef00a..58d5f5f 100644 --- a/ucentralprov.properties +++ b/ow_prov.properties @@ -1,35 +1,34 @@ # -# uCentral protocol server for devices. This is where you point # all your devices. You can replace the * for address by the specific # address of one of your interfaces # # # REST API access # -ucentralfws.restapi.host.0.backlog = 100 -ucentralfws.restapi.host.0.security = relaxed -ucentralfws.restapi.host.0.rootca = $UCENTRALTOPO_ROOT/certs/restapi-ca.pem -ucentralfws.restapi.host.0.address = * -ucentralfws.restapi.host.0.port = 16005 -ucentralfws.restapi.host.0.cert = $UCENTRALTOPO_ROOT/certs/restapi-cert.pem -ucentralfws.restapi.host.0.key = $UCENTRALTOPO_ROOT/certs/restapi-key.pem -ucentralfws.restapi.host.0.key.password = mypassword +owprov.restapi.host.0.backlog = 100 +owprov.restapi.host.0.security = relaxed +owprov.restapi.host.0.rootca = $OWPROV_ROOT/certs/restapi-ca.pem +owprov.restapi.host.0.address = * +owprov.restapi.host.0.port = 16005 +owprov.restapi.host.0.cert = $OWPROV_ROOT/certs/restapi-cert.pem +owprov.restapi.host.0.key = $OWPROV_ROOT/certs/restapi-key.pem +owprov.restapi.host.0.key.password = mypassword -ucentral.internal.restapi.host.0.backlog = 100 -ucentral.internal.restapi.host.0.security = relaxed -ucentral.internal.restapi.host.0.rootca = $UCENTRALTOPO_ROOT/certs/restapi-ca.pem -ucentral.internal.restapi.host.0.address = * -ucentral.internal.restapi.host.0.port = 17005 -ucentral.internal.restapi.host.0.cert = $UCENTRALTOPO_ROOT/certs/restapi-cert.pem -ucentral.internal.restapi.host.0.key = $UCENTRALTOPO_ROOT/certs/restapi-key.pem -ucentral.internal.restapi.host.0.key.password = mypassword +owprov.internal.restapi.host.0.backlog = 100 +owprov.internal.restapi.host.0.security = relaxed +owprov.internal.restapi.host.0.rootca = $OWPROV_ROOT/certs/restapi-ca.pem +owprov.internal.restapi.host.0.address = * +owprov.internal.restapi.host.0.port = 17005 +owprov.internal.restapi.host.0.cert = $OWPROV_ROOT/certs/restapi-cert.pem +owprov.internal.restapi.host.0.key = $OWPROV_ROOT/certs/restapi-key.pem +owprov.internal.restapi.host.0.key.password = mypassword # # Generic section that all microservices must have # -ucentral.service.key = $UCENTRALTOPO_ROOT/certs/restapi-key.pem +ucentral.service.key = $OWPROV_ROOT/certs/restapi-key.pem ucentral.service.key.password = mypassword -ucentral.system.data = $UCENTRALTOPO_ROOT/data +ucentral.system.data = $OWPROV_ROOT/data ucentral.system.debug = false ucentral.system.uri.private = https://localhost:17005 ucentral.system.uri.public = https://ucentral.dpaas.arilia.com:16005 @@ -48,8 +47,8 @@ alb.port = 16104 # # Kafka # -ucentral.kafka.group.id = topology -ucentral.kafka.client.id = topology1 +ucentral.kafka.group.id = prov +ucentral.kafka.client.id = prov1 ucentral.kafka.enable = true ucentral.kafka.brokerlist = a1.arilia.com:9092 # ucentral.kafka.brokerlist = debfarm1-node-c.arilia.com:9092 @@ -66,7 +65,7 @@ storage.type = sqlite #storage.type = mysql #storage.type = odbc -storage.type.sqlite.db = firmware.db +storage.type.sqlite.db = prov.db storage.type.sqlite.idletime = 120 storage.type.sqlite.maxsessions = 128 @@ -103,7 +102,7 @@ logging.channels.c1.formatter = f1 # This is where the logs will be written. This path MUST exist logging.channels.c2.class = FileChannel -logging.channels.c2.path = $UCENTRALTOPO_ROOT/logs/log +logging.channels.c2.path = $OWPROV_ROOT/logs/log logging.channels.c2.formatter.class = PatternFormatter logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t logging.channels.c2.rotation = 20 M diff --git a/set_env.sh b/set_env.sh index e756885..710ab3c 100755 --- a/set_env.sh +++ b/set_env.sh @@ -1,4 +1,4 @@ #!/bin/bash -export UCENTRALPROV_CONFIG=`pwd` -export UCENTRALPROV_ROOT=`pwd` +export OWPROV_CONFIG=`pwd` +export OWPROV_ROOT=`pwd` diff --git a/src/Daemon.h b/src/Daemon.h index 6a4befa..4caea01 100644 --- a/src/Daemon.h +++ b/src/Daemon.h @@ -31,10 +31,10 @@ namespace uCentral { - static const char * vDAEMON_PROPERTIES_FILENAME = "ucentraltopo.properties"; - static const char * vDAEMON_ROOT_ENV_VAR = "UCENTRALTOPO_ROOT"; - static const char * vDAEMON_CONFIG_ENV_VAR = "UCENTRALTOPO_CONFIG"; - static const char * vDAEMON_APP_NAME = uSERVICE_TOPOLOGY.c_str(); + static const char * vDAEMON_PROPERTIES_FILENAME = "ow_prov.properties"; + static const char * vDAEMON_ROOT_ENV_VAR = "OWPROV_ROOT"; + static const char * vDAEMON_CONFIG_ENV_VAR = "OWPROV_CONFIG"; + static const char * vDAEMON_APP_NAME = uSERVICE_PROVISIONING.c_str(); static const uint64_t vDAEMON_BUS_TIMER = 10000; class Daemon : public MicroService { @@ -49,10 +49,10 @@ namespace uCentral { void initialize(Poco::Util::Application &self); static Daemon *instance(); - inline TopoDashboard & GetDashboard() { return DB_; } + inline OpenWifi::TopoDashboard & GetDashboard() { return DB_; } private: static Daemon *instance_; - TopoDashboard DB_; + OpenWifi::TopoDashboard DB_; }; diff --git a/src/Dashboard.cpp b/src/Dashboard.cpp index eaec35b..c14a0e1 100644 --- a/src/Dashboard.cpp +++ b/src/Dashboard.cpp @@ -5,7 +5,7 @@ #include "Dashboard.h" #include "StorageService.h" -namespace uCentral { +namespace OpenWifi { void TopoDashboard::Create() { uint64_t Now = std::time(nullptr); if(LastRun_==0 || (Now-LastRun_)>120) { diff --git a/src/Dashboard.h b/src/Dashboard.h index 94b163b..589482a 100644 --- a/src/Dashboard.h +++ b/src/Dashboard.h @@ -6,16 +6,16 @@ #define UCENTRALGW_DASHBOARD_H #include "uCentralTypes.h" -#include "RESTAPI_TopoObjects.h" +#include "RESTAPI_ProvObjects.h" -namespace uCentral { +namespace OpenWifi { class TopoDashboard { public: void Create(); - const TopoObjects::Report & Report() const { return DB_;} + const ProvObjects::Report & Report() const { return DB_;} inline void Reset() { LastRun_=0; DB_.reset(); } private: - TopoObjects::Report DB_; + ProvObjects::Report DB_; uint64_t LastRun_=0; }; } diff --git a/src/MicroService.h b/src/MicroService.h index 7dd02e8..1ae8dfa 100644 --- a/src/MicroService.h +++ b/src/MicroService.h @@ -33,7 +33,7 @@ namespace uCentral { static const std::string uSERVICE_GATEWAY{"ucentralgw"}; static const std::string uSERVICE_FIRMWARE{ "ucentralfws"}; static const std::string uSERVICE_TOPOLOGY{ "ucentraltopo"}; - static const std::string uSERVICE_PROVISIONING{ "ucentralprov"}; + static const std::string uSERVICE_PROVISIONING{ "owprov"}; class MyErrorHandler : public Poco::ErrorHandler { public: diff --git a/src/RESTAPI_InternalServer.cpp b/src/RESTAPI_InternalServer.cpp index fce636d..3d48231 100644 --- a/src/RESTAPI_InternalServer.cpp +++ b/src/RESTAPI_InternalServer.cpp @@ -14,7 +14,7 @@ namespace uCentral { class RESTAPI_InternalServer *RESTAPI_InternalServer::instance_ = nullptr; - RESTAPI_InternalServer::RESTAPI_InternalServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "ucentral.internal.restapi") + RESTAPI_InternalServer::RESTAPI_InternalServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "owprov.internal.restapi") { } diff --git a/src/RESTAPI_ProvObjects.cpp b/src/RESTAPI_ProvObjects.cpp new file mode 100644 index 0000000..9c6fd68 --- /dev/null +++ b/src/RESTAPI_ProvObjects.cpp @@ -0,0 +1,314 @@ +// +// Created by stephane bourque on 2021-08-04. +// + +#include "RESTAPI_ProvObjects.h" +#include "RESTAPI_utils.h" + +using uCentral::RESTAPI_utils::field_from_json; +using uCentral::RESTAPI_utils::field_to_json; + +namespace OpenWifi::ProvObjects { + + void ObjectInfo::to_json(Poco::JSON::Object &Obj) const { + uCentral::RESTAPI_utils::field_to_json(Obj,"id",id); + uCentral::RESTAPI_utils::field_to_json(Obj,"name",name); + uCentral::RESTAPI_utils::field_to_json(Obj,"description",description); + uCentral::RESTAPI_utils::field_to_json(Obj,"created",created); + uCentral::RESTAPI_utils::field_to_json(Obj,"modified",modified); + uCentral::RESTAPI_utils::field_to_json(Obj,"notes",notes); + } + + bool ObjectInfo::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + uCentral::RESTAPI_utils::field_from_json(Obj,"id",id); + uCentral::RESTAPI_utils::field_from_json(Obj,"name",name); + uCentral::RESTAPI_utils::field_from_json(Obj,"description",description); + uCentral::RESTAPI_utils::field_from_json(Obj,"created",created); + uCentral::RESTAPI_utils::field_from_json(Obj,"modified",modified); + uCentral::RESTAPI_utils::field_from_json(Obj,"notes",notes); + return true; + } catch(...) { + + } + return false; + } + + void ManagementPolicyEntry::to_json(Poco::JSON::Object &Obj) const { + uCentral::RESTAPI_utils::field_to_json( Obj,"users",users); + uCentral::RESTAPI_utils::field_to_json( Obj,"resources",resources); + uCentral::RESTAPI_utils::field_to_json( Obj,"access",access); + uCentral::RESTAPI_utils::field_to_json( Obj,"policy",policy); + } + + bool ManagementPolicyEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + uCentral::RESTAPI_utils::field_from_json( Obj,"users",users); + uCentral::RESTAPI_utils::field_from_json( Obj,"resources",resources); + uCentral::RESTAPI_utils::field_from_json( Obj,"access",access); + uCentral::RESTAPI_utils::field_from_json( Obj,"policy",policy); + return true; + } catch(...) { + + } + return false; + } + + void ManagementPolicy::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json(Obj, "entries", entries); + } + + bool ManagementPolicy::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + uCentral::RESTAPI_utils::field_from_json(Obj, "entries", entries); + return true; + } catch(...) { + + } + return false; + } + + void Entity::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_to_json( Obj,"venues",venues); + uCentral::RESTAPI_utils::field_to_json( Obj,"children",children); + uCentral::RESTAPI_utils::field_to_json( Obj,"managers",managers); + uCentral::RESTAPI_utils::field_to_json( Obj,"contacts",contacts); + uCentral::RESTAPI_utils::field_to_json( Obj,"locations",locations); + uCentral::RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); + } + + bool Entity::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + uCentral::RESTAPI_utils::field_from_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_from_json( Obj,"venues",venues); + uCentral::RESTAPI_utils::field_from_json( Obj,"children",children); + uCentral::RESTAPI_utils::field_from_json( Obj,"managers",managers); + uCentral::RESTAPI_utils::field_from_json( Obj,"contacts",contacts); + uCentral::RESTAPI_utils::field_from_json( Obj,"locations",locations); + uCentral::RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); + return true; + } catch(...) { + + } + return false; + } + + void DiGraphEntry::to_json(Poco::JSON::Object &Obj) const { + uCentral::RESTAPI_utils::field_to_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_to_json( Obj,"child",child); + } + + bool DiGraphEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + uCentral::RESTAPI_utils::field_from_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_from_json( Obj,"child",child); + return true; + } catch (...) { + + } + return false; + } + + void Venue::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_to_json( Obj,"owner",owner); + uCentral::RESTAPI_utils::field_to_json( Obj,"children",children); + uCentral::RESTAPI_utils::field_to_json( Obj,"managers",managers); + uCentral::RESTAPI_utils::field_to_json( Obj,"devices",devices); + uCentral::RESTAPI_utils::field_to_json( Obj,"topology",topology); + uCentral::RESTAPI_utils::field_to_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_to_json( Obj,"design",design); + uCentral::RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); + } + + bool Venue::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + uCentral::RESTAPI_utils::field_from_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_from_json( Obj,"owner",owner); + uCentral::RESTAPI_utils::field_from_json( Obj,"children",children); + uCentral::RESTAPI_utils::field_from_json( Obj,"managers",managers); + uCentral::RESTAPI_utils::field_from_json( Obj,"devices",devices); + uCentral::RESTAPI_utils::field_from_json( Obj,"topology",topology); + uCentral::RESTAPI_utils::field_from_json( Obj,"parent",parent); + uCentral::RESTAPI_utils::field_from_json( Obj,"design",design); + uCentral::RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); + return true; + } catch (...) { + + } + return false; + } + + void ManagementGroup::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json( Obj,"managers",managers); + managementPolicy.to_json(Obj); + } + + bool ManagementGroup::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + uCentral::RESTAPI_utils::field_from_json( Obj,"managers",managers); + managementPolicy.from_json(Obj); + return true; + } catch (...) { + + } + return false; + } + + void Location::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json( Obj,"type",OpenWifi::ProvObjects::to_string(type)); + uCentral::RESTAPI_utils::field_to_json( Obj,"buildingName",buildingName); + uCentral::RESTAPI_utils::field_to_json( Obj,"addressLines",addressLines); + uCentral::RESTAPI_utils::field_to_json( Obj,"city",city); + uCentral::RESTAPI_utils::field_to_json( Obj,"state",state); + uCentral::RESTAPI_utils::field_to_json( Obj,"postal",postal); + uCentral::RESTAPI_utils::field_to_json( Obj,"country",country); + uCentral::RESTAPI_utils::field_to_json( Obj,"telephones",telephones); + uCentral::RESTAPI_utils::field_to_json( Obj,"contact",contact); + } + + bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + std::string tmp_type; + uCentral::RESTAPI_utils::field_from_json( Obj,"type", tmp_type); + type = location_from_string(tmp_type); + uCentral::RESTAPI_utils::field_from_json( Obj,"buildingName",buildingName); + uCentral::RESTAPI_utils::field_from_json( Obj,"addressLines",addressLines); + uCentral::RESTAPI_utils::field_from_json( Obj,"city",city); + uCentral::RESTAPI_utils::field_from_json( Obj,"state",state); + uCentral::RESTAPI_utils::field_from_json( Obj,"postal",postal); + uCentral::RESTAPI_utils::field_from_json( Obj,"country",country); + uCentral::RESTAPI_utils::field_from_json( Obj,"telephones",telephones); + uCentral::RESTAPI_utils::field_from_json( Obj,"contact",contact); + return true; + } catch (...) { + + } + return false; + } + + void Contact::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json( Obj,"type", to_string(type)); + uCentral::RESTAPI_utils::field_to_json( Obj,"title",title); + uCentral::RESTAPI_utils::field_to_json( Obj,"salutation",salutation); + uCentral::RESTAPI_utils::field_to_json( Obj,"firstname",firstname); + uCentral::RESTAPI_utils::field_to_json( Obj,"lastname",lastname); + uCentral::RESTAPI_utils::field_to_json( Obj,"initials",initials); + uCentral::RESTAPI_utils::field_to_json( Obj,"visual",visual); + uCentral::RESTAPI_utils::field_to_json( Obj,"mobiles",mobiles); + uCentral::RESTAPI_utils::field_to_json( Obj,"phones",phones); + uCentral::RESTAPI_utils::field_to_json( Obj,"location",location); + uCentral::RESTAPI_utils::field_to_json( Obj,"primaryEmail",primaryEmail); + uCentral::RESTAPI_utils::field_to_json( Obj,"secondaryEmail",secondaryEmail); + uCentral::RESTAPI_utils::field_to_json( Obj,"accessPIN",accessPIN); + } + + bool Contact::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + std::string tmp_type; + uCentral::RESTAPI_utils::field_from_json( Obj,"type", tmp_type); + type = contact_from_string(tmp_type); + uCentral::RESTAPI_utils::field_from_json( Obj,"title",title); + uCentral::RESTAPI_utils::field_from_json( Obj,"salutation",salutation); + uCentral::RESTAPI_utils::field_from_json( Obj,"firstname",firstname); + uCentral::RESTAPI_utils::field_from_json( Obj,"lastname",lastname); + uCentral::RESTAPI_utils::field_from_json( Obj,"initials",initials); + uCentral::RESTAPI_utils::field_from_json( Obj,"visual",visual); + uCentral::RESTAPI_utils::field_from_json( Obj,"mobiles",mobiles); + uCentral::RESTAPI_utils::field_from_json( Obj,"phones",phones); + uCentral::RESTAPI_utils::field_from_json( Obj,"location",location); + uCentral::RESTAPI_utils::field_from_json( Obj,"primaryEmail",primaryEmail); + uCentral::RESTAPI_utils::field_from_json( Obj,"secondaryEmail",secondaryEmail); + uCentral::RESTAPI_utils::field_from_json( Obj,"accessPIN",accessPIN); + return true; + } catch (...) { + + } + return false; + } + + void ServiceConfiguration::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + managementPolicy.to_json(Obj); + } + + bool ServiceConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + managementPolicy.from_json(Obj); + return true; + } catch(...) { + + } + return false; + } + + void InventoryTag::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json(Obj, "serialNumber", serialNumber); + uCentral::RESTAPI_utils::field_to_json(Obj, "venue", venue); + uCentral::RESTAPI_utils::field_to_json(Obj, "entity", entity); + uCentral::RESTAPI_utils::field_to_json(Obj, "subEntity", subEntity); + uCentral::RESTAPI_utils::field_to_json(Obj, "subVenue", subVenue); + uCentral::RESTAPI_utils::field_to_json(Obj, "subscriber", subscriber); + } + + bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + uCentral::RESTAPI_utils::field_from_json( Obj,"serialNumber",serialNumber); + uCentral::RESTAPI_utils::field_from_json( Obj,"venue",venue); + uCentral::RESTAPI_utils::field_from_json( Obj,"entity",entity); + uCentral::RESTAPI_utils::field_from_json( Obj,"subEntity",subEntity); + uCentral::RESTAPI_utils::field_from_json( Obj,"subVenue",subVenue); + uCentral::RESTAPI_utils::field_from_json( Obj,"subscriber",subscriber); + return true; + } catch(...) { + + } + return false; + } + + void DeviceConfiguration::to_json(Poco::JSON::Object &Obj) const { + info.to_json(Obj); + managementPolicy.to_json(Obj); + uCentral::RESTAPI_utils::field_to_json( Obj,"deviceTypes",deviceTypes); + uCentral::RESTAPI_utils::field_to_json( Obj,"configuration",configuration); + } + + bool DeviceConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) { + try { + info.from_json(Obj); + managementPolicy.from_json(Obj); + uCentral::RESTAPI_utils::field_from_json( Obj,"deviceTypes",deviceTypes); + uCentral::RESTAPI_utils::field_from_json( Obj,"configuration",configuration); + return true; + } catch(...) { + + } + return false; + } + + void Report::to_json(Poco::JSON::Object &Obj) const { + uCentral::RESTAPI_utils::field_to_json(Obj, "snapshot", snapShot); + uCentral::RESTAPI_utils::field_to_json(Obj, "devices", tenants); + }; + + void Report::reset() { + tenants.clear(); + } + +}; diff --git a/src/RESTAPI_ProvObjects.h b/src/RESTAPI_ProvObjects.h new file mode 100644 index 0000000..6e9f2e6 --- /dev/null +++ b/src/RESTAPI_ProvObjects.h @@ -0,0 +1,250 @@ +// +// Created by stephane bourque on 2021-08-04. +// + +#ifndef OWPROV_RESTAPI_PROVOBJECTS_H +#define OWPROV_RESTAPI_PROVOBJECTS_H + +#include +#include "RESTAPI_SecurityObjects.h" + +namespace OpenWifi::ProvObjects { + + struct ObjectInfo { + uCentral::Types::UUID_t id; + std::string name; + std::string description; + uCentral::SecurityObjects::NoteInfoVec notes; + uint64_t created; + uint64_t modified; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct ManagementPolicyEntry { + uCentral::Types::UUIDvec_t users; + uCentral::Types::UUIDvec_t resources; + uCentral::Types::StringVec access; + std::string policy; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct ManagementPolicy { + ObjectInfo info; + std::vector entries; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct Entity { + ObjectInfo info; + uCentral::Types::UUID_t parent; + uCentral::Types::UUIDvec_t children; + uCentral::Types::UUIDvec_t venues; + uCentral::Types::UUIDvec_t managers; + uCentral::Types::UUIDvec_t contacts; + uCentral::Types::UUIDvec_t locations; + uCentral::Types::UUID_t managementPolicy; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct DiGraphEntry { + uCentral::Types::UUID_t parent; + uCentral::Types::UUID_t child; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + typedef std::vector DiGraph; + + struct Venue { + ObjectInfo info; + uCentral::Types::UUID_t owner; + uCentral::Types::UUID_t parent; + uCentral::Types::UUIDvec_t children; + uCentral::Types::UUIDvec_t managers; + uCentral::Types::UUID_t managementPolicy; + uCentral::Types::UUIDvec_t devices; + DiGraph topology; + std::string design; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct ManagementGroup { + ObjectInfo info; + ManagementPolicy managementPolicy; + uCentral::Types::UUIDvec_t managers; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + enum LocationType { + LT_SERVICE, LT_EQUIPMENT, LT_AUTO, LT_MANUAL, + LT_SPECIAL, LT_UNKNOWN, LT_CORPORATE + }; + + inline std::string to_string(LocationType L) { + switch(L) { + case LT_SERVICE: return "SERVICE"; + case LT_EQUIPMENT: return "EQUIPMENT"; + case LT_AUTO: return "AUTO"; + case LT_MANUAL: return "MANUAL"; + case LT_SPECIAL: return "SPECIAL"; + case LT_UNKNOWN: return "UNKNOWN"; + case LT_CORPORATE: return "CORPORATE"; + default: return "UNKNOWN"; + } + } + + inline LocationType location_from_string(const std::string &S) { + if(!Poco::icompare(S,"SERVICE")) + return LT_SERVICE; + else if(!Poco::icompare(S,"EQUIPMENT")) + return LT_EQUIPMENT; + else if(!Poco::icompare(S,"AUTO")) + return LT_AUTO; + else if(!Poco::icompare(S,"MANUAL")) + return LT_MANUAL; + else if(!Poco::icompare(S,"SPECIAL")) + return LT_SPECIAL; + else if(!Poco::icompare(S,"UNKNOWN")) + return LT_UNKNOWN; + else if(!Poco::icompare(S,"CORPORATE")) + return LT_CORPORATE; + return LT_UNKNOWN; + } + + struct LocationTypeS { + LocationType type; + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct Location { + ObjectInfo info; + LocationType type; + std::string buildingName; + uCentral::Types::StringVec addressLines; + std::string city; + std::string state; + std::string postal; + std::string country; + uCentral::Types::StringVec telephones; + uCentral::Types::UUID_t contact; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + enum ContactType { + CT_SUBSCRIBER, CT_USER, CT_INSTALLER, CT_CSR, CT_MANAGER, + CT_BUSINESSOWNER, CT_TECHNICIAN, CT_CORPORATE, CT_UNKNOWN + }; + + inline std::string to_string(ContactType L) { + switch(L) { + case CT_SUBSCRIBER: return "SUBSCRIBER"; + case CT_USER: return "USER"; + case CT_INSTALLER: return "INSTALLER"; + case CT_CSR: return "CSR"; + case CT_MANAGER: return "MANAGER"; + case CT_BUSINESSOWNER: return "BUSINESSOWNER"; + case CT_TECHNICIAN: return "TECHNICIAN"; + case CT_CORPORATE: return "CORPORATE"; + case CT_UNKNOWN: return "UNKNOWN"; + default: return "UNKNOWN"; + } + } + + inline ContactType contact_from_string(const std::string &S) { + if(!Poco::icompare(S,"SUBSCRIBER")) + return CT_SUBSCRIBER; + else if(!Poco::icompare(S,"USER")) + return CT_USER; + else if(!Poco::icompare(S,"INSTALLER")) + return CT_INSTALLER; + else if(!Poco::icompare(S,"CSR")) + return CT_CSR; + else if(!Poco::icompare(S,"BUSINESSOWNER")) + return CT_BUSINESSOWNER; + else if(!Poco::icompare(S,"TECHNICIAN")) + return CT_TECHNICIAN; + else if(!Poco::icompare(S,"CORPORATE")) + return CT_CORPORATE; + else if(!Poco::icompare(S,"UNKNOWN")) + return CT_UNKNOWN; + return CT_UNKNOWN; + } + + struct Contact { + ObjectInfo info; + ContactType type; + std::string title; + std::string salutation; + std::string firstname; + std::string lastname; + std::string initials; + std::string visual; + uCentral::Types::StringVec mobiles; + uCentral::Types::StringVec phones; + uCentral::Types::UUID_t location; + std::string primaryEmail; + std::string secondaryEmail; + std::string accessPIN; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct ServiceConfiguration { + ObjectInfo info; + ManagementPolicy managementPolicy; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct DeviceConfiguration { + ObjectInfo info; + ManagementPolicy managementPolicy; + uCentral::Types::StringVec deviceTypes; + std::string configuration; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct InventoryTag { + ObjectInfo info; + std::string serialNumber; + std::string venue; + std::string entity; + std::string subEntity; + std::string subVenue; + std::string subscriber; + + void to_json(Poco::JSON::Object &Obj) const; + bool from_json(const Poco::JSON::Object::Ptr &Obj); + }; + + struct Report { + uint64_t snapShot; + uCentral::Types::CountedMap tenants; + + void reset(); + void to_json(Poco::JSON::Object &Obj) const; + }; +}; + + +#endif //OWPROV_RESTAPI_PROVOBJECTS_H diff --git a/src/RESTAPI_TopoObjects.cpp b/src/RESTAPI_TopoObjects.cpp deleted file mode 100644 index ae3c098..0000000 --- a/src/RESTAPI_TopoObjects.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// Created by stephane bourque on 2021-07-25. -// - -#include "RESTAPI_TopoObjects.h" - -namespace uCentral::TopoObjects { - void Report::reset() { - } -} \ No newline at end of file diff --git a/src/RESTAPI_TopoObjects.h b/src/RESTAPI_TopoObjects.h deleted file mode 100644 index 029dff1..0000000 --- a/src/RESTAPI_TopoObjects.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// Created by stephane bourque on 2021-07-25. -// - -#ifndef UCENTRAL_TOPO_RESTAPI_TOPOOBJECTS_H -#define UCENTRAL_TOPO_RESTAPI_TOPOOBJECTS_H - -#include "Poco/JSON/Object.h" - -namespace uCentral::TopoObjects { - struct Report { - - void to_json(Poco::JSON::Object &Obj) const; - void reset(); - bool from_json(const Poco::JSON::Object::Ptr &Obj); - }; -} - -#endif //UCENTRAL_TOPO_RESTAPI_TOPOOBJECTS_H diff --git a/src/RESTAPI_entity_handler.cpp b/src/RESTAPI_entity_handler.cpp new file mode 100644 index 0000000..3c362e3 --- /dev/null +++ b/src/RESTAPI_entity_handler.cpp @@ -0,0 +1,41 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#include "RESTAPI_entity_handler.h" + + +namespace OpenWifi{ + void RESTAPI_entity_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response) { + if (!ContinueProcessing(Request, Response)) + return; + + if (!IsAuthorized(Request, Response)) + return; + + ParseParameters(Request); + if(Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) + DoGet(Request, Response); + else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) + DoPost(Request, Response); + else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) + DoDelete(Request, Response); + else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_PUT) + DoPut(Request, Response); + else + BadRequest(Request, Response, "Unknown HTTP Method"); + } + + void RESTAPI_entity_handler::DoGet(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response) {} + + void RESTAPI_entity_handler::DoDelete(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response) {} + + void RESTAPI_entity_handler::DoPost(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response) {} + + void RESTAPI_entity_handler::DoPut(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response) {} +} \ No newline at end of file diff --git a/src/RESTAPI_entity_handler.h b/src/RESTAPI_entity_handler.h new file mode 100644 index 0000000..3727fc6 --- /dev/null +++ b/src/RESTAPI_entity_handler.h @@ -0,0 +1,38 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#ifndef OWPROV_RESTAPI_ENTITY_HANDLER_H +#define OWPROV_RESTAPI_ENTITY_HANDLER_H + +#include "RESTAPI_handler.h" + +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" + +namespace OpenWifi { + class RESTAPI_entity_handler : public uCentral::RESTAPIHandler { + public: + RESTAPI_entity_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal) + : RESTAPIHandler(bindings, L, + std::vector{ + Poco::Net::HTTPRequest::HTTP_GET, Poco::Net::HTTPRequest::HTTP_POST, + Poco::Net::HTTPRequest::HTTP_PUT, Poco::Net::HTTPRequest::HTTP_DELETE, + Poco::Net::HTTPRequest::HTTP_OPTIONS}, + Internal) {} + void handleRequest(Poco::Net::HTTPServerRequest &request, + Poco::Net::HTTPServerResponse &response) override final; + static const std::list PathName() { return std::list{"/api/v1/entity/{uuid}"}; }; + + void DoGet(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response); + void DoPost(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response); + void DoPut(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response); + void DoDelete(Poco::Net::HTTPServerRequest &Request, + Poco::Net::HTTPServerResponse &Response); + }; +} + +#endif //OWPROV_RESTAPI_ENTITY_HANDLER_H diff --git a/src/RESTAPI_handler.cpp b/src/RESTAPI_handler.cpp index 5b36c0c..6aeb5e6 100644 --- a/src/RESTAPI_handler.cpp +++ b/src/RESTAPI_handler.cpp @@ -364,11 +364,11 @@ namespace uCentral { Poco::JSON::Stringifier::stringify(Object, Answer); } - void RESTAPIHandler::InitQueryBlock() { + bool RESTAPIHandler::InitQueryBlock() { QB_.SerialNumber = GetParameter(uCentral::RESTAPI::Protocol::SERIALNUMBER, ""); QB_.StartDate = GetParameter(uCentral::RESTAPI::Protocol::STARTDATE, 0); QB_.EndDate = GetParameter(uCentral::RESTAPI::Protocol::ENDDATE, 0); - QB_.Offset = GetParameter(uCentral::RESTAPI::Protocol::OFFSET, 0); + QB_.Offset = GetParameter(uCentral::RESTAPI::Protocol::OFFSET, 1); QB_.Limit = GetParameter(uCentral::RESTAPI::Protocol::LIMIT, 100); QB_.Filter = GetParameter(uCentral::RESTAPI::Protocol::FILTER, ""); QB_.Select = GetParameter(uCentral::RESTAPI::Protocol::SELECT, ""); @@ -376,6 +376,9 @@ namespace uCentral { QB_.LogType = GetParameter(uCentral::RESTAPI::Protocol::LOGTYPE,0); QB_.LastOnly = GetBoolParameter(uCentral::RESTAPI::Protocol::LASTONLY,false); QB_.Newest = GetBoolParameter(uCentral::RESTAPI::Protocol::NEWEST,false); + + if(QB_.Offset<1) return false; + return true; } [[nodiscard]] uint64_t RESTAPIHandler::Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default){ diff --git a/src/RESTAPI_handler.h b/src/RESTAPI_handler.h index 3f5d8af..8106efe 100644 --- a/src/RESTAPI_handler.h +++ b/src/RESTAPI_handler.h @@ -140,7 +140,7 @@ namespace uCentral { void SendFile(Poco::File & File, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); const std::string &GetBinding(const std::string &Name, const std::string &Default); - void InitQueryBlock(); + bool InitQueryBlock(); [[nodiscard]] static uint64_t Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default=0); [[nodiscard]] static std::string GetS(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, const std::string & Default=""); @@ -166,7 +166,7 @@ namespace uCentral { Poco::Net::HTTPServerResponse &Response) override { if (!IsAuthorized(Request, Response)) return; - BadRequest(Request, Response); + BadRequest(Request, Response, "Unknown API endpoint"); } }; diff --git a/src/RESTAPI_server.cpp b/src/RESTAPI_server.cpp index 0723d09..87e4bea 100644 --- a/src/RESTAPI_server.cpp +++ b/src/RESTAPI_server.cpp @@ -9,13 +9,14 @@ #include "RESTAPI_handler.h" #include "RESTAPI_system_command.h" +#include "RESTAPI_entity_handler.h" namespace uCentral { class RESTAPI_server *RESTAPI_server::instance_ = nullptr; RESTAPI_server::RESTAPI_server() noexcept: - SubSystemServer("RESTAPIServer", "RESTAPIServer", "ucentralfws.restapi") + SubSystemServer("RESTAPIServer", "RESTAPIServer", "owprov.restapi") { } @@ -60,7 +61,8 @@ namespace uCentral { // std::cout << "Path: " << Request.getURI() << std::endl; return RESTAPI_Router< - RESTAPI_system_command + RESTAPI_system_command, + OpenWifi::RESTAPI_entity_handler >(Path,Bindings,Logger_); } diff --git a/src/RESTAPI_system_command.cpp b/src/RESTAPI_system_command.cpp index 23b8467..2134f7c 100644 --- a/src/RESTAPI_system_command.cpp +++ b/src/RESTAPI_system_command.cpp @@ -27,8 +27,8 @@ namespace uCentral { DoPost(Request, Response); else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET) DoGet(Request, Response); - - BadRequest(Request, Response); + else + BadRequest(Request, Response, "Unsupported method."); } void RESTAPI_system_command::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { @@ -94,7 +94,7 @@ namespace uCentral { } catch(const Poco::Exception &E) { Logger_.log(E); } - BadRequest(Request, Response); + BadRequest(Request, Response, "Unsupported or missing parameters."); } void RESTAPI_system_command::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { @@ -126,7 +126,7 @@ namespace uCentral { } catch (const Poco::Exception &E) { Logger_.log(E); } - BadRequest(Request, Response); + BadRequest(Request, Response, "Unsupported or missing parameters."); } } \ No newline at end of file diff --git a/src/StorageService.cpp b/src/StorageService.cpp index cc00992..60bd3f9 100644 --- a/src/StorageService.cpp +++ b/src/StorageService.cpp @@ -6,9 +6,10 @@ // Arilia Wireless Inc. // +#include "Poco/Util/Application.h" + #include "StorageService.h" #include "Daemon.h" -#include "Poco/Util/Application.h" #include "Utils.h" namespace uCentral { @@ -20,28 +21,6 @@ namespace uCentral { { } - std::string Storage::ConvertParams(const std::string & S) const { - std::string R; - - R.reserve(S.size()*2+1); - - if(dbType_==pgsql) { - auto Idx=1; - for(auto const & i:S) - { - if(i=='?') { - R += '$'; - R.append(std::to_string(Idx++)); - } else { - R += i; - } - } - } else { - R = S; - } - return R; - } - int Storage::Start() { SubMutexGuard Guard(Mutex_); @@ -50,14 +29,32 @@ namespace uCentral { std::string DBType = Daemon()->ConfigGetString("storage.type"); if (DBType == "sqlite") { + DBType_ = ORM::DBType::sqlite; Setup_SQLite(); } else if (DBType == "postgresql") { + DBType_ = ORM::DBType::postgresql; Setup_PostgreSQL(); } else if (DBType == "mysql") { + DBType_ = ORM::DBType::mysql; Setup_MySQL(); } - Create_Tables(); + EntityDB_ = std::make_unique(DBType_,*Pool_, Logger_); + PolicyDB_ = std::make_unique(DBType_, *Pool_, Logger_); + VenueDB_ = std::make_unique(DBType_, *Pool_, Logger_); + LocationDB_ = std::make_unique(DBType_, *Pool_, Logger_); + ContactDB_ = std::make_unique(DBType_, *Pool_, Logger_); + InventoryDB_ = std::make_unique(DBType_, *Pool_, Logger_); + + EntityDB_->Create(); + PolicyDB_->Create(); + VenueDB_->Create(); + LocationDB_->Create(); + ContactDB_->Create(); + InventoryDB_->Create(); + + OpenWifi::ProvObjects::Entity R; + EntityDB_->GetRecord("id","xxx",R); return 0; } @@ -65,5 +62,7 @@ namespace uCentral { void Storage::Stop() { Logger_.notice("Stopping."); } + } + // namespace \ No newline at end of file diff --git a/src/StorageService.h b/src/StorageService.h index bff7579..0150fcc 100644 --- a/src/StorageService.h +++ b/src/StorageService.h @@ -13,31 +13,23 @@ #include "Poco/Data/SessionPool.h" #include "Poco/Data/SQLite/Connector.h" -#ifndef SMALL_BUILD #include "Poco/Data/PostgreSQL/Connector.h" #include "Poco/Data/MySQL/Connector.h" -#endif - -#include "RESTAPI_TopoObjects.h" #include "SubSystemServer.h" +#include "orm.h" + +#include "storage_entity.h" +#include "storage_policies.h" +#include "storage_venue.h" +#include "storage_location.h" +#include "storage_contact.h" +#include "storage_inventory.h" + namespace uCentral { class Storage : public SubSystemServer { - public: - enum StorageType { - sqlite, - pgsql, - mysql - }; - - enum CommandExecutionType { - COMMAND_PENDING, - COMMAND_EXECUTED, - COMMAND_COMPLETED - }; - static Storage *instance() { if (instance_ == nullptr) { instance_ = new Storage; @@ -45,28 +37,37 @@ namespace uCentral { return instance_; } - - int Create_Tables(); - int Start() override; void Stop() override; - int Setup_SQLite(); + [[nodiscard]] std::string ConvertParams(const std::string &S) const; -#ifndef SMALL_BUILD + int Setup_SQLite(); int Setup_MySQL(); int Setup_PostgreSQL(); -#endif + + OpenWifi::EntityDB & EntityDB() { return *EntityDB_; }; + OpenWifi::PolicyDB & PolicyDB() { return *PolicyDB_; }; + OpenWifi::VenueDB & VenueDB() { return *VenueDB_; }; + OpenWifi::LocationDB & LocationDB() { return *LocationDB_; }; + OpenWifi::ContactDB & ContactDB() { return *ContactDB_;}; + OpenWifi::InventoryDB & InventoryDB() { return *InventoryDB_; }; + private: static Storage *instance_; std::unique_ptr Pool_= nullptr; - StorageType dbType_ = sqlite; std::unique_ptr SQLiteConn_= nullptr; -#ifndef SMALL_BUILD std::unique_ptr PostgresConn_= nullptr; std::unique_ptr MySQLConn_= nullptr; -#endif + + ORM::DBType DBType_ = ORM::DBType::sqlite; + std::unique_ptr EntityDB_; + std::unique_ptr PolicyDB_; + std::unique_ptr VenueDB_; + std::unique_ptr LocationDB_; + std::unique_ptr ContactDB_; + std::unique_ptr InventoryDB_; Storage() noexcept; }; diff --git a/src/orm.h b/src/orm.h new file mode 100644 index 0000000..6d87e01 --- /dev/null +++ b/src/orm.h @@ -0,0 +1,514 @@ + +#ifndef __OPENWIFI_ORM_H__ +#define __OPENWIFI_ORM_H__ +#include +#include +#include +#include +#include +#include +#include + +#include "Poco/Tuple.h" +#include "Poco/Data/SessionPool.h" +#include "Poco/Data/Statement.h" +#include "Poco/Data/RecordSet.h" +#include "Poco/Data/SQLite/Connector.h" +#include "Poco/Logger.h" + +namespace ORM { + enum DBType { + sqlite, + postgresql, + mysql + }; + + enum FieldType { + FT_INT, + FT_BIGINT, + FT_TEXT, + FT_VARCHAR, + FT_BLOB + }; + + enum Indextype { + ASC, + DESC + }; + + struct Field { + std::string Name; + FieldType Type; + int Size=0; + bool Index=false; + + + Field(std::string & N) { + Name = N; + Type = FT_TEXT; + } + + Field(std::string N, int S) { + Name = N; + Type = FT_TEXT; + Size = S; + } + + Field(std::string N, int S, bool I) { + Name = N; + Type = FT_TEXT; + Size = S; + Index = I; + } + }; + typedef std::vector FieldVec; + + struct IndexEntry { + std::string FieldName; + Indextype Type; + }; + typedef std::vector IndexEntryVec; + + struct Index { + std::string Name; + IndexEntryVec Entries; + }; + typedef std::vector IndexVec; + + inline std::string FieldTypeToChar(DBType Type, FieldType T, int Size=0) { + switch(T) { + case FT_INT: return "INT"; + case FT_BIGINT: return "BIGINT"; + case FT_TEXT: return "TEXT"; + case FT_VARCHAR: + if(Size) + return std::string("VARCHAR(") + std::to_string(Size) + std::string(")"); + else + return "TEXT"; + case FT_BLOB: + if(Type==DBType::mysql) + return "LONGBLOB"; + else if(Type==DBType::postgresql) + return "BYTEA"; + else if(Type==DBType::sqlite) + return "BLOB"; + default: + assert(false); + return ""; + } + assert(false); + return ""; + } + + enum CompareOperations { + EQUAL, + LESS, + LESS_OR_EQUAL, + GREATER, + GREATER_OR_EQUAL, + NOT_EQUAL + }; + + inline std::string to_string(ORM::CompareOperations O) { + switch(O) { + case EQUAL: return "="; + case LESS: return "<"; + case LESS_OR_EQUAL: return "<="; + case GREATER: return ">"; + case GREATER_OR_EQUAL: return ">="; + case NOT_EQUAL: return "!="; + } + } + + inline std::string to_string(uint64_t V) { + return std::to_string(V); + } + + inline std::string to_string(int V) { + return std::to_string(V); + } + + inline std::string to_string(bool V) { + return std::to_string(V); + } + + inline std::string to_string(const std::string &S) { + return S; + } + + inline std::string to_string(const char * S) { + return S; + } + + template struct Comparison { + std::string Name; + ValueType Value; + ORM::CompareOperations Operation; + Comparison(const std::string & N, ORM::CompareOperations Op, ValueType & V) : + Name(N), Operation(Op), Value(V) {} + + std::string OP() { + return Name + " " + to_string(Operation) + " " + to_string(Value); + } + }; + + template class DB { + public: + DB( DBType dbtype, + const char *TableName, + const FieldVec & Fields, + const IndexVec & Indexes, + Poco::Data::SessionPool & Pool, + Poco::Logger &L): + Type(dbtype), + DBName(TableName), + Pool_(Pool), + Logger_(L) + { + bool first = true; + int Place=0; + + assert( RecordTuple::length == Fields.size()); + + for(const auto &i:Fields) { + + FieldNames_[i.Name] = Place; + if(!first) { + CreateFields_ += ", "; + SelectFields_ += ", "; + UpdateFields_ += ", "; + SelectList_ += ", "; + } else { + SelectList_ += "("; + } + + CreateFields_ += i.Name + " " + FieldTypeToChar(Type, i.Type,i.Size) + (i.Index ? " unique primary key" : ""); + SelectFields_ += i.Name ; + UpdateFields_ += i.Name + "=?"; + SelectList_ += "?"; + first = false; + Place++; + } + SelectList_ += ")"; + + if(!Indexes.empty()) { + if(Type==sqlite || Type==postgresql) { + for(const auto &j:Indexes) { + std::string IndexLine; + + IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + DBName + " ("; + bool first_entry=true; + for(const auto &k:j.Entries) { + assert(FieldNames_.find(k.FieldName) != FieldNames_.end()); + if(!first_entry) { + IndexLine += " , "; + } + first_entry = false; + IndexLine += k.FieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ; + } + IndexLine += " );"; + IndexCreation += IndexLine; + } + } else if(Type==mysql) { + bool firstIndex = true; + std::string IndexLine; + for(const auto &j:Indexes) { + if(!firstIndex) + IndexLine += ", "; + firstIndex = false; + IndexLine += " INDEX " + j.Name + " ( " ; + bool first_entry=true; + for(const auto &k:j.Entries) { + assert(FieldNames_.find(k.FieldName) != FieldNames_.end()); + if(!first_entry) { + IndexLine += " ,"; + } + first_entry = false; + IndexLine += k.FieldName + std::string(k.Type == Indextype::ASC ? " ASC" : " DESC"); + } + IndexLine += " ) "; + } + IndexCreation = IndexLine; + } + } + } + + [[nodiscard]] const std::string & CreateFields() const { return CreateFields_; }; + [[nodiscard]] const std::string & SelectFields() const { return SelectFields_; }; + [[nodiscard]] const std::string & SelectList() const { return SelectList_; }; + [[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; }; + + static std::string Escape(const std::string &S) { + std::string R; + + for(const auto &i:S) + if(i=='\'') + R += "''"; + else + R += i; + return R; + } + + inline bool Create() { + std::string S; + + if(Type==mysql) { + if(IndexCreation.empty()) + S = "create table if not exists " + DBName +" ( " + CreateFields_ + " )" ; + else + S = "create table if not exists " + DBName +" ( " + CreateFields_ + " ), " + IndexCreation + " )"; + } else if (Type==postgresql || Type==sqlite) { + S = "create table if not exists " + DBName + " ( " + CreateFields_ + " ); " + IndexCreation ; + } + + // std::cout << "CREATE-DB: " << S << std::endl; + + try { + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement CreateStatement(Session); + + CreateStatement << S; + CreateStatement.execute(); + return true; + } catch (const Poco::Exception &E) { + std::cout << "Exception while creating DB: " << E.name() << std::endl; + } + return false; + } + + std::string ConvertParams(const std::string & S) const { + std::string R; + + R.reserve(S.size()*2+1); + + if(Type==postgresql) { + auto Idx=1; + for(auto const & i:S) + { + if(i=='?') { + R += '$'; + R.append(std::to_string(Idx++)); + } else { + R += i; + } + } + } else { + R = S; + } + return R; + } + + virtual void Convert( RecordTuple &in , RecordType &out); + virtual void Convert( RecordType &in , RecordTuple &out); + + bool CreateRecord( RecordType & R) { + try { + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement Insert(Session); + + RecordTuple RT; + ConvertParams(R, RT); + + std::string St = "insert into " + DBName + " ( " + SelectFields_ + " ) values " + SelectList_; + Insert << ConvertParams(St) , + Poco::Data::Keywords::use(RT), + Insert.execute(); + return true; + } catch (const Poco::Exception &E) { + // Logger_.log(E); + } + return false; + } + + template bool GetRecord( const std::string &FieldName, T Value, RecordType & R) { + try { + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement Select(Session); + RecordTuple RT; + + std::string St = "select " + SelectFields_ + " from " + DBName + " where " + FieldName + "=?" ; + Select << ConvertParams(St) , + Poco::Data::Keywords::into(RT), + Poco::Data::Keywords::use(Value); + Select.execute(); + + Convert(RT,R); + return true; + } catch (const Poco::Exception &E) { + // Logger_.log(E); + } + return false; + } + + typedef std::vector StringVec; + + template < typename T, + typename T0, typename T1> bool GR(const StringVec &FieldName, T & R,T0 &V0, T1 &V1) { + try { + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement Select(Session); + RecordTuple RT; + + std::string St = "select " + SelectFields_ + " from " + DBName + + " where " + FieldName[0] + "=? and " + FieldName[1] + "=?" ; + Select << ConvertParams(St) , + Poco::Data::Keywords::into(RT), + Poco::Data::Keywords::use(V0), + Poco::Data::Keywords::use(V1); + Select.execute(); + + Convert(RT,R); + return true; + } catch (const Poco::Exception &E) { + // Logger_.log(E); + } + return false; + } + + typedef std::vector RecordList; + + bool GetRecords( uint64_t Offset, uint64_t HowMany, std::vector & Records, std::string Where = "") { + try { + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement Select(Session); + RecordList RL; + std::string St = "select " + SelectFields_ + " from " + DBName + ComputeRange(Offset, HowMany) ; + + Select << ConvertParams(St) , + Poco::Data::Keywords::into(RL); + Select.execute(); + + for(const auto &i:RL) { + RecordType R; + Convert(i, R); + Records.template emplace_back(R); + } + return true; + } catch (const Poco::Exception &E) { + // Logger_.log(E); + } + return false; + } + + template bool UpdateRecord( const std::string &FieldName, T & Value, RecordType & R) { + try { + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement Update(Session); + + RecordTuple RT; + + Convert(R, RT); + + std::string St = "update " + DBName + " set " + UpdateFields_ + " where " + FieldName + "=?" ; + Update << ConvertParams(St) , + Poco::Data::Keywords::use(RT), + Poco::Data::Keywords::use(Value); + Update.execute(); + return true; + } catch (const Poco::Exception &E) { + // Logger_.log(E); + } + return false; + } + + template bool DeleteRecord( const std::string &FieldName, T Value) { + try { + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement Delete(Session); + + std::string St = "delete from " + DBName + " where " + FieldName + "=?" ; + Delete << ConvertParams(St) , + Poco::Data::Keywords::use(Value); + Delete.execute(); + return true; + } catch (const Poco::Exception &E) { + // Logger_.log(E); + } + return false; + } + + bool DeleteRecords( const std::string & WhereClause ) { + try { + assert( !WhereClause.empty()); + Poco::Data::Session Session = Pool_.get(); + Poco::Data::Statement Delete(Session); + + std::string St = "delete from " + DBName + " " + WhereClause; + Delete << ConvertParams(St); + Delete.execute(); + return true; + } catch (const Poco::Exception &E) { + // Logger_.log(E); + } + return false; + } + + [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { + if(From<1) From=1; + if(Type==ORM::sqlite) { + return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " "; + } else if(Type==ORM::postgresql) { + return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; + } else if(Type==ORM::mysql) { + return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; + } + return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; + } + + private: + DBType Type; + std::string DBName; + std::string CreateFields_; + std::string SelectFields_; + std::string SelectList_; + std::string UpdateFields_; + std::string IndexCreation; + std::map FieldNames_; + Poco::Data::SessionPool &Pool_; + Poco::Logger &Logger_; + }; +} + +/* +int main(int, char**) +{ + auto SQLiteConn_ = std::make_unique(); + SQLiteConn_->registerConnector(); + auto Pool_ = std::make_unique(SQLiteConn_->name(), "test.db", 4, 64, 60); + + ORM::FieldVec DB1Fields{ ORM::Field{"id",40, true}, + ORM::Field{"name", ORM::FT_INT} }; + ORM::IndexVec Indexes{ + { std::string("name_index"), ORM::IndexEntryVec{ {std::string("name"), ORM::Indextype::ASC} } } }; + + ORM::DB DB1(ORM::sqlite , + "tab1", + ORM::FieldVec{ + ORM::Field{"id",40, true}, + ORM::Field{"name", ORM::FT_INT} }, + ORM::IndexVec{{ std::string("name_index"), ORM::IndexEntryVec{ {std::string("name"), ORM::Indextype::ASC} } }}, + *Pool_); + + std::cout << DB1.CreateFields() << std::endl; + std::cout << DB1.SelectFields() << std::endl; + std::cout << DB1.SelectList() << std::endl; + std::cout << DB1.UpdateFields() << std::endl; + + std::cout << DB1.Create() << std::endl; + + User U1{ 25, "steph"}; + + auto SS = &User::Name; + + std::cout << (typeid( User::Name ) == typeid( std::string )) << std::endl; + std::cout << "Name: " << U1.*SS << std::endl; + + auto RR = ORM::Escape("I'm a \"cool\" dude"); + std::cout << "RR: " << RR << std::endl; + + return 0; +} + + */ + +#endif \ No newline at end of file diff --git a/src/storage_contact.cpp b/src/storage_contact.cpp new file mode 100644 index 0000000..279602f --- /dev/null +++ b/src/storage_contact.cpp @@ -0,0 +1,89 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#include "storage_contact.h" +#include "Utils.h" +#include "uCentralTypes.h" +#include "RESTAPI_utils.h" +#include "RESTAPI_SecurityObjects.h" + +namespace OpenWifi { + + static ORM::FieldVec ContactDB_Fields{ + // object info + ORM::Field{"id",64, true}, + ORM::Field{"name",ORM::FieldType::FT_TEXT}, + ORM::Field{"description",ORM::FieldType::FT_TEXT}, + ORM::Field{"notes",ORM::FieldType::FT_TEXT}, + ORM::Field{"created",ORM::FieldType::FT_BIGINT}, + ORM::Field{"modified",ORM::FieldType::FT_BIGINT}, + ORM::Field{"type",ORM::FieldType::FT_TEXT}, + ORM::Field{"title",ORM::FieldType::FT_TEXT}, + ORM::Field{"salutation",ORM::FieldType::FT_TEXT}, + ORM::Field{"firstname",ORM::FieldType::FT_TEXT}, + ORM::Field{"lastname",ORM::FieldType::FT_TEXT}, + ORM::Field{"initials",ORM::FieldType::FT_TEXT}, + ORM::Field{"visual",ORM::FieldType::FT_TEXT}, + ORM::Field{"mobiles",ORM::FieldType::FT_TEXT}, + ORM::Field{"phones",ORM::FieldType::FT_TEXT}, + ORM::Field{"location",ORM::FieldType::FT_TEXT}, + ORM::Field{"primaryEmail",ORM::FieldType::FT_TEXT}, + ORM::Field{"secondaryEmail",ORM::FieldType::FT_TEXT}, + ORM::Field{"accessPIN",ORM::FieldType::FT_TEXT} + }; + + static ORM::IndexVec ContactDB_Indexes{ + { std::string("contact_name_index"), + ORM::IndexEntryVec{ + {std::string("name"), + ORM::Indextype::ASC} } } + }; + + ContactDB::ContactDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : + DB(T, "contacts", ContactDB_Fields, ContactDB_Indexes, P, L) {} + +} + +template<> void ORM::DB< OpenWifi::ContactDBRecordType, OpenWifi::ProvObjects::Contact>::Convert(OpenWifi::ContactDBRecordType &In, OpenWifi::ProvObjects::Contact &Out) { + Out.info.id = In.get<0>(); + Out.info.name = In.get<1>(); + Out.info.description = In.get<2>(); + Out.info.notes = uCentral::RESTAPI_utils::to_object_array(In.get<3>()); + Out.info.created = In.get<4>(); + Out.info.modified = In.get<5>(); + + Out.type = OpenWifi::ProvObjects::contact_from_string(In.get<6>()); + Out.title = In.get<7>(); + Out.salutation = In.get<8>(); + Out.firstname = In.get<9>(); + Out.lastname = In.get<10>(); + Out.initials = In.get<11>(); + Out.visual = In.get<12>(); + uCentral::Types::from_string(In.get<13>(), Out.mobiles); + uCentral::Types::from_string(In.get<14>(), Out.phones); + Out.primaryEmail = In.get<15>(); + Out.secondaryEmail = In.get<16>(); + Out.accessPIN = In.get<17>(); +} + +template<> void ORM::DB< OpenWifi::ContactDBRecordType, OpenWifi::ProvObjects::Contact>::Convert(OpenWifi::ProvObjects::Contact &In, OpenWifi::ContactDBRecordType &Out) { + Out.set<0>(In.info.id); + Out.set<1>(In.info.name); + Out.set<2>(In.info.description); + Out.set<3>(uCentral::RESTAPI_utils::to_string(In.info.notes)); + Out.set<4>(In.info.created); + Out.set<5>(In.info.modified); + Out.set<6>(to_string(In.type)); + Out.set<7>(In.title); + Out.set<8>(In.salutation); + Out.set<9>(In.firstname); + Out.set<10>(In.lastname); + Out.set<11>(In.initials); + Out.set<12>(In.visual); + Out.set<13>(uCentral::Types::to_string(In.mobiles)); + Out.set<14>(uCentral::Types::to_string(In.phones)); + Out.set<15>(In.primaryEmail); + Out.set<16>(In.secondaryEmail); + Out.set<17>(In.accessPIN); +} diff --git a/src/storage_contact.h b/src/storage_contact.h new file mode 100644 index 0000000..6614938 --- /dev/null +++ b/src/storage_contact.h @@ -0,0 +1,42 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#ifndef OWPROV_STORAGE_CONTACT_H +#define OWPROV_STORAGE_CONTACT_H + +#include "orm.h" +#include "RESTAPI_ProvObjects.h" + +namespace OpenWifi { + typedef Poco::Tuple< + std::string, + std::string, + std::string, + std::string, + uint64_t, + uint64_t, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string + > ContactDBRecordType; + + class ContactDB : public ORM::DB { + public: + ContactDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + private: + }; +} + + +#endif //OWPROV_STORAGE_CONTACT_H diff --git a/src/storage_entity.cpp b/src/storage_entity.cpp new file mode 100644 index 0000000..9382bf5 --- /dev/null +++ b/src/storage_entity.cpp @@ -0,0 +1,69 @@ +// +// Created by stephane bourque on 2021-08-15. +// + +#include "storage_entity.h" +#include "Utils.h" +#include "uCentralTypes.h" +#include "RESTAPI_utils.h" +#include "RESTAPI_SecurityObjects.h" + +namespace OpenWifi { + + static ORM::FieldVec EntityDB_Fields{ + // object info + ORM::Field{"id",64, true}, + ORM::Field{"name",ORM::FieldType::FT_TEXT}, + ORM::Field{"description",ORM::FieldType::FT_TEXT}, + ORM::Field{"notes",ORM::FieldType::FT_TEXT}, + ORM::Field{"created",ORM::FieldType::FT_BIGINT}, + ORM::Field{"modified",ORM::FieldType::FT_BIGINT}, + ORM::Field{"parent",ORM::FieldType::FT_TEXT}, + ORM::Field{"children",ORM::FieldType::FT_TEXT}, + ORM::Field{"managers",ORM::FieldType::FT_TEXT}, + ORM::Field{"contacts",ORM::FieldType::FT_TEXT}, + ORM::Field{"locations",ORM::FieldType::FT_TEXT}, + ORM::Field{"managementPolicy",ORM::FieldType::FT_TEXT} + }; + + static ORM::IndexVec EntityDB_Indexes{ + { std::string("entity_name_index"), + ORM::IndexEntryVec{ + {std::string("name"), + ORM::Indextype::ASC} } } + }; + + EntityDB::EntityDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : + DB(T, "entities", EntityDB_Fields, EntityDB_Indexes, P, L) {} + +} + +template<> void ORM::DB< OpenWifi::EntityDBRecordType, OpenWifi::ProvObjects::Entity>::Convert(OpenWifi::EntityDBRecordType &In, OpenWifi::ProvObjects::Entity &Out) { + Out.info.id = In.get<0>(); + Out.info.name = In.get<1>(); + Out.info.description = In.get<2>(); + Out.info.notes = uCentral::RESTAPI_utils::to_object_array(In.get<3>()); + Out.info.created = In.get<4>(); + Out.info.modified = In.get<5>(); + Out.parent = In.get<6>(); + uCentral::Types::from_string(In.get<7>(), Out.children); + uCentral::Types::from_string(In.get<8>(), Out.managers); + uCentral::Types::from_string(In.get<9>(), Out.contacts); + uCentral::Types::from_string(In.get<10>(), Out.locations); + Out.managementPolicy = In.get<11>(); +} + +template<> void ORM::DB< OpenWifi::EntityDBRecordType, OpenWifi::ProvObjects::Entity>::Convert(OpenWifi::ProvObjects::Entity &In, OpenWifi::EntityDBRecordType &Out) { + Out.set<0>(In.info.id); + Out.set<1>(In.info.name); + Out.set<2>(In.info.description); + Out.set<3>(uCentral::RESTAPI_utils::to_string(In.info.notes)); + Out.set<4>(In.info.created); + Out.set<5>(In.info.modified); + Out.set<6>(In.parent); + Out.set<7>(uCentral::Types::to_string(In.children)); + Out.set<8>(uCentral::Types::to_string(In.managers)); + Out.set<9>(uCentral::Types::to_string(In.contacts)); + Out.set<10>(uCentral::Types::to_string(In.locations)); + Out.set<11>(In.managementPolicy); +} diff --git a/src/storage_entity.h b/src/storage_entity.h new file mode 100644 index 0000000..4cc049f --- /dev/null +++ b/src/storage_entity.h @@ -0,0 +1,50 @@ +// +// Created by stephane bourque on 2021-08-15. +// + +#ifndef OWPROV_STORAGE_ENTITY_H +#define OWPROV_STORAGE_ENTITY_H + +#include "orm.h" +#include "RESTAPI_ProvObjects.h" + +namespace OpenWifi { + + /* + ORM::Field{"id",64, true}, + ORM::Field{"name",ORM::FieldType::FT_TEXT}, + ORM::Field{"description",ORM::FieldType::FT_TEXT}, + ORM::Field{"notes",ORM::FieldType::FT_TEXT}, + ORM::Field{"created",ORM::FieldType::FT_BIGINT}, + ORM::Field{"modified",ORM::FieldType::FT_BIGINT}, + ORM::Field{"parent",ORM::FieldType::FT_TEXT}, + ORM::Field{"children",ORM::FieldType::FT_TEXT}, + ORM::Field{"managers",ORM::FieldType::FT_TEXT}, + ORM::Field{"contacts",ORM::FieldType::FT_TEXT}, + ORM::Field{"locations",ORM::FieldType::FT_TEXT}, + ORM::Field{"managementPolicy",ORM::FieldType::FT_TEXT} + */ + typedef Poco::Tuple< + std::string, + std::string, + std::string, + std::string, + uint64_t, + uint64_t, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string + > EntityDBRecordType; + + class EntityDB : public ORM::DB { + public: + EntityDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + private: + }; +} + + +#endif //OWPROV_STORAGE_ENTITY_H diff --git a/src/storage_inventory.cpp b/src/storage_inventory.cpp new file mode 100644 index 0000000..543214b --- /dev/null +++ b/src/storage_inventory.cpp @@ -0,0 +1,70 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#include "storage_inventory.h" +#include "Utils.h" +#include "uCentralTypes.h" +#include "RESTAPI_utils.h" +#include "RESTAPI_SecurityObjects.h" + +namespace OpenWifi { + + static ORM::FieldVec InventoryDB_Fields{ + // object info + ORM::Field{"id",64, true}, + ORM::Field{"name",ORM::FieldType::FT_TEXT}, + ORM::Field{"description",ORM::FieldType::FT_TEXT}, + ORM::Field{"notes",ORM::FieldType::FT_TEXT}, + ORM::Field{"created",ORM::FieldType::FT_BIGINT}, + ORM::Field{"modified",ORM::FieldType::FT_BIGINT}, + 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} + }; + + static ORM::IndexVec InventoryDB_Indexes{ + { std::string("inventory_name_index"), + ORM::IndexEntryVec{ + {std::string("name"), + ORM::Indextype::ASC} } }, + { std::string("serial_index"), + ORM::IndexEntryVec{ + {std::string("serialNumber"), + ORM::Indextype::ASC} } } + }; + + InventoryDB::InventoryDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : + DB(T, "inventory", InventoryDB_Fields, InventoryDB_Indexes, P, L) {} + +} + +template<> void ORM::DB< OpenWifi::InventoryDBRecordType, OpenWifi::ProvObjects::InventoryTag>::Convert(OpenWifi::InventoryDBRecordType &In, OpenWifi::ProvObjects::InventoryTag &Out) { + Out.info.id = In.get<0>(); + Out.info.name = In.get<1>(); + Out.info.description = In.get<2>(); + Out.info.notes = uCentral::RESTAPI_utils::to_object_array(In.get<3>()); + Out.info.created = In.get<4>(); + Out.info.modified = In.get<5>(); + 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>(); +} + +template<> void ORM::DB< OpenWifi::InventoryDBRecordType, OpenWifi::ProvObjects::InventoryTag>::Convert(OpenWifi::ProvObjects::InventoryTag &In, OpenWifi::InventoryDBRecordType &Out) { + Out.set<0>(In.info.id); + Out.set<1>(In.info.name); + Out.set<2>(In.info.description); + Out.set<3>(uCentral::RESTAPI_utils::to_string(In.info.notes)); + Out.set<4>(In.info.created); + Out.set<5>(In.info.modified); + 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); +} diff --git a/src/storage_inventory.h b/src/storage_inventory.h new file mode 100644 index 0000000..0a5363c --- /dev/null +++ b/src/storage_inventory.h @@ -0,0 +1,33 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#ifndef OWPROV_STORAGE_INVENTORY_H +#define OWPROV_STORAGE_INVENTORY_H + +#include "orm.h" +#include "RESTAPI_ProvObjects.h" + +namespace OpenWifi { + typedef Poco::Tuple< + std::string, + std::string, + std::string, + std::string, + uint64_t, + uint64_t, + std::string, + std::string, + std::string, + std::string, + std::string + > InventoryDBRecordType; + + class InventoryDB : public ORM::DB { + public: + InventoryDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + private: + }; +} + +#endif //OWPROV_STORAGE_INVENTORY_H diff --git a/src/storage_location.cpp b/src/storage_location.cpp new file mode 100644 index 0000000..2271c06 --- /dev/null +++ b/src/storage_location.cpp @@ -0,0 +1,78 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#include "storage_location.h" +#include "Utils.h" +#include "uCentralTypes.h" +#include "RESTAPI_utils.h" +#include "RESTAPI_SecurityObjects.h" + +namespace OpenWifi { + + static ORM::FieldVec LocationDB_Fields{ + // object info + ORM::Field{"id",64, true}, + ORM::Field{"name",ORM::FieldType::FT_TEXT}, + ORM::Field{"description",ORM::FieldType::FT_TEXT}, + ORM::Field{"notes",ORM::FieldType::FT_TEXT}, + ORM::Field{"created",ORM::FieldType::FT_BIGINT}, + ORM::Field{"modified",ORM::FieldType::FT_BIGINT}, + ORM::Field{"type",ORM::FieldType::FT_TEXT}, + ORM::Field{"buildingName",ORM::FieldType::FT_TEXT}, + ORM::Field{"addressLines",ORM::FieldType::FT_TEXT}, + ORM::Field{"city",ORM::FieldType::FT_TEXT}, + ORM::Field{"state",ORM::FieldType::FT_TEXT}, + ORM::Field{"postal",ORM::FieldType::FT_TEXT}, + ORM::Field{"country",ORM::FieldType::FT_TEXT}, + ORM::Field{"telephones",ORM::FieldType::FT_TEXT}, + ORM::Field{"contact",ORM::FieldType::FT_TEXT} + }; + + static ORM::IndexVec LocationDB_Indexes{ + { std::string("location_name_index"), + ORM::IndexEntryVec{ + {std::string("name"), + ORM::Indextype::ASC} } } + }; + + LocationDB::LocationDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : + DB(T, "locations", LocationDB_Fields, LocationDB_Indexes, P, L) {} + +} + +template<> void ORM::DB< OpenWifi::LocationDBRecordType, OpenWifi::ProvObjects::Location>::Convert(OpenWifi::LocationDBRecordType &In, OpenWifi::ProvObjects::Location &Out) { + Out.info.id = In.get<0>(); + Out.info.name = In.get<1>(); + Out.info.description = In.get<2>(); + Out.info.notes = uCentral::RESTAPI_utils::to_object_array(In.get<3>()); + Out.info.created = In.get<4>(); + Out.info.modified = In.get<5>(); + Out.type = OpenWifi::ProvObjects::location_from_string(In.get<6>()); + Out.buildingName = In.get<7>(); + uCentral::Types::from_string(In.get<8>(), Out.addressLines); + Out.city = In.get<9>(); + Out.state = In.get<10>(); + Out.postal = In.get<11>(); + Out.country = In.get<12>(); + uCentral::Types::from_string(In.get<13>(), Out.telephones); + Out.contact = In.get<14>(); +} + +template<> void ORM::DB< OpenWifi::LocationDBRecordType, OpenWifi::ProvObjects::Location>::Convert(OpenWifi::ProvObjects::Location &In, OpenWifi::LocationDBRecordType &Out) { + Out.set<0>(In.info.id); + Out.set<1>(In.info.name); + Out.set<2>(In.info.description); + Out.set<3>(uCentral::RESTAPI_utils::to_string(In.info.notes)); + Out.set<4>(In.info.created); + Out.set<5>(In.info.modified); + Out.set<6>(OpenWifi::ProvObjects::to_string(In.type)); + Out.set<7>(In.buildingName); + Out.set<8>(uCentral::Types::to_string(In.addressLines)); + Out.set<9>(In.city); + Out.set<10>(In.state); + Out.set<11>(In.postal); + Out.set<12>(In.country); + Out.set<13>(uCentral::Types::to_string(In.telephones)); + Out.set<14>(In.contact); +} diff --git a/src/storage_location.h b/src/storage_location.h new file mode 100644 index 0000000..e94429e --- /dev/null +++ b/src/storage_location.h @@ -0,0 +1,38 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#ifndef OWPROV_STORAGE_LOCATION_H +#define OWPROV_STORAGE_LOCATION_H + +#include "orm.h" +#include "RESTAPI_ProvObjects.h" + +namespace OpenWifi { + typedef Poco::Tuple< + std::string, + std::string, + std::string, + std::string, + uint64_t, + uint64_t, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string + > LocationDBRecordType; + + class LocationDB : public ORM::DB { + public: + LocationDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + private: + }; +} + + +#endif //OWPROV_STORAGE_LOCATION_H diff --git a/src/storage_mysql.cpp b/src/storage_mysql.cpp index ca7ecfb..bd07927 100644 --- a/src/storage_mysql.cpp +++ b/src/storage_mysql.cpp @@ -17,8 +17,6 @@ namespace uCentral { int Storage::Setup_MySQL() { - dbType_ = mysql ; - Logger_.notice("MySQL Storage enabled."); auto NumSessions = Daemon()->ConfigGetInt("storage.type.mysql.maxsessions", 64); auto IdleTime = Daemon()->ConfigGetInt("storage.type.mysql.idletime", 60); diff --git a/src/storage_pgql.cpp b/src/storage_pgql.cpp index d7b2f44..8a813f7 100644 --- a/src/storage_pgql.cpp +++ b/src/storage_pgql.cpp @@ -17,8 +17,6 @@ namespace uCentral { int Storage::Setup_PostgreSQL() { Logger_.notice("PostgreSQL Storage enabled."); - dbType_ = pgsql ; - 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"); diff --git a/src/storage_policies.cpp b/src/storage_policies.cpp new file mode 100644 index 0000000..0a7182d --- /dev/null +++ b/src/storage_policies.cpp @@ -0,0 +1,54 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#include "storage_policies.h" +#include "Utils.h" +#include "uCentralTypes.h" +#include "RESTAPI_utils.h" +#include "RESTAPI_SecurityObjects.h" + +namespace OpenWifi { + + static ORM::FieldVec PolicyDB_Fields{ + // object info + ORM::Field{"id",64, true}, + ORM::Field{"name",ORM::FieldType::FT_TEXT}, + ORM::Field{"description",ORM::FieldType::FT_TEXT}, + 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} + }; + + static ORM::IndexVec PolicyDB_Indexes{ + { std::string("policy_name_index"), + ORM::IndexEntryVec{ + {std::string("name"), + ORM::Indextype::ASC} } } + }; + + PolicyDB::PolicyDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : + DB(T, "policies", PolicyDB_Fields, PolicyDB_Indexes, P, L) {} + +} + +template<> void ORM::DB< OpenWifi::PolicyDBRecordType, OpenWifi::ProvObjects::ManagementPolicy>::Convert(OpenWifi::PolicyDBRecordType &In, OpenWifi::ProvObjects::ManagementPolicy &Out) { + Out.info.id = In.get<0>(); + Out.info.name = In.get<1>(); + Out.info.description = In.get<2>(); + Out.info.notes = uCentral::RESTAPI_utils::to_object_array(In.get<3>()); + Out.info.created = In.get<4>(); + Out.info.modified = In.get<5>(); + Out.entries = uCentral::RESTAPI_utils::to_object_array(In.get<6>()); +} + +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); + Out.set<2>(In.info.description); + Out.set<3>(uCentral::RESTAPI_utils::to_string(In.info.notes)); + Out.set<4>(In.info.created); + Out.set<5>(In.info.modified); + Out.set<6>(uCentral::RESTAPI_utils::to_string(In.entries)); +} diff --git a/src/storage_policies.h b/src/storage_policies.h new file mode 100644 index 0000000..7945bbe --- /dev/null +++ b/src/storage_policies.h @@ -0,0 +1,30 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#ifndef OWPROV_STORAGE_POLICIES_H +#define OWPROV_STORAGE_POLICIES_H + +#include "orm.h" +#include "RESTAPI_ProvObjects.h" + +namespace OpenWifi { + typedef Poco::Tuple< + std::string, + std::string, + std::string, + std::string, + uint64_t, + uint64_t, + std::string + > PolicyDBRecordType; + + class PolicyDB : public ORM::DB { + public: + PolicyDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + private: + }; +} + + +#endif //OWPROV_STORAGE_POLICIES_H diff --git a/src/storage_tables.cpp b/src/storage_tables.cpp deleted file mode 100644 index 580c616..0000000 --- a/src/storage_tables.cpp +++ /dev/null @@ -1,17 +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 "StorageService.h" - -namespace uCentral { - - int Storage::Create_Tables() { - return 0; - } - -} \ No newline at end of file diff --git a/src/storage_venue.cpp b/src/storage_venue.cpp new file mode 100644 index 0000000..c4cc48b --- /dev/null +++ b/src/storage_venue.cpp @@ -0,0 +1,73 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#include "storage_venue.h" +#include "Utils.h" +#include "uCentralTypes.h" +#include "RESTAPI_utils.h" +#include "RESTAPI_SecurityObjects.h" + +namespace OpenWifi { + + static ORM::FieldVec VenueDB_Fields{ + // object info + ORM::Field{"id",64, true}, + ORM::Field{"name",ORM::FieldType::FT_TEXT}, + ORM::Field{"description",ORM::FieldType::FT_TEXT}, + ORM::Field{"notes",ORM::FieldType::FT_TEXT}, + ORM::Field{"created",ORM::FieldType::FT_BIGINT}, + ORM::Field{"modified",ORM::FieldType::FT_BIGINT}, + ORM::Field{"owner",ORM::FieldType::FT_TEXT}, + ORM::Field{"parent",ORM::FieldType::FT_TEXT}, + ORM::Field{"children",ORM::FieldType::FT_TEXT}, + ORM::Field{"managers",ORM::FieldType::FT_TEXT}, + ORM::Field{"managementPolicy",ORM::FieldType::FT_TEXT}, + ORM::Field{"devices",ORM::FieldType::FT_TEXT}, + ORM::Field{"topology",ORM::FieldType::FT_TEXT}, + ORM::Field{"design",ORM::FieldType::FT_TEXT} + }; + + static ORM::IndexVec VenueDB_Indexes{ + { std::string("venue_name_index"), + ORM::IndexEntryVec{ + {std::string("name"), + ORM::Indextype::ASC} } } + }; + + VenueDB::VenueDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : + DB(T, "venues", VenueDB_Fields, VenueDB_Indexes, P, L) {} + +} + +template<> void ORM::DB< OpenWifi::VenueDBRecordType, OpenWifi::ProvObjects::Venue>::Convert(OpenWifi::VenueDBRecordType &In, OpenWifi::ProvObjects::Venue &Out) { + Out.info.id = In.get<0>(); + Out.info.name = In.get<1>(); + Out.info.description = In.get<2>(); + Out.info.notes = uCentral::RESTAPI_utils::to_object_array(In.get<3>()); + Out.info.created = In.get<4>(); + Out.info.modified = In.get<5>(); + Out.owner = In.get<6>(); + Out.parent = In.get<7>(); + uCentral::Types::from_string(In.get<8>(), Out.children); + uCentral::Types::from_string(In.get<9>(), Out.managers); + uCentral::Types::from_string(In.get<10>(), Out.devices); + Out.topology = uCentral::RESTAPI_utils::to_object_array(In.get<11>()); + Out.design = In.get<12>(); +} + +template<> void ORM::DB< OpenWifi::VenueDBRecordType, OpenWifi::ProvObjects::Venue>::Convert(OpenWifi::ProvObjects::Venue &In, OpenWifi::VenueDBRecordType &Out) { + Out.set<0>(In.info.id); + Out.set<1>(In.info.name); + Out.set<2>(In.info.description); + Out.set<3>(uCentral::RESTAPI_utils::to_string(In.info.notes)); + Out.set<4>(In.info.created); + Out.set<5>(In.info.modified); + Out.set<6>(In.owner); + Out.set<7>(In.parent); + Out.set<8>(uCentral::Types::to_string(In.children)); + Out.set<9>(uCentral::Types::to_string(In.managers)); + Out.set<10>(uCentral::Types::to_string(In.devices)); + Out.set<11>(uCentral::RESTAPI_utils::to_string(In.topology)); + Out.set<12>(In.design); +} diff --git a/src/storage_venue.h b/src/storage_venue.h new file mode 100644 index 0000000..9620a05 --- /dev/null +++ b/src/storage_venue.h @@ -0,0 +1,38 @@ +// +// Created by stephane bourque on 2021-08-16. +// + +#ifndef OWPROV_STORAGE_VENUE_H +#define OWPROV_STORAGE_VENUE_H + +#include "orm.h" +#include "RESTAPI_ProvObjects.h" + +namespace OpenWifi { + typedef Poco::Tuple< + std::string, + std::string, + std::string, + std::string, + uint64_t, + uint64_t, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string, + std::string + > VenueDBRecordType; + + class VenueDB : public ORM::DB { + public: + VenueDB( ORM::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + private: + }; +} + + + +#endif //OWPROV_STORAGE_VENUE_H diff --git a/src/uCentralTypes.h b/src/uCentralTypes.h index 75b392a..2cb3ca6 100644 --- a/src/uCentralTypes.h +++ b/src/uCentralTypes.h @@ -15,6 +15,8 @@ #include #include +#include "Poco/StringTokenizer.h" + namespace uCentral::Types { typedef std::pair StringPair; typedef std::vector StringPairVec; @@ -28,6 +30,9 @@ namespace uCentral::Types { typedef std::map NotifyTable; typedef std::map CountedMap; + typedef std::string UUID_t; + typedef std::vector UUIDvec_t; + inline void UpdateCountedMap(CountedMap &M, const std::string &S ) { auto it = M.find(S); if(it==M.end()) @@ -35,6 +40,29 @@ namespace uCentral::Types { else it->second += 1; } + + inline std::string to_string( const StringVec &V) { + std::string Result; + + bool first=true; + for(const auto &i:V) { + if(first) { + Result += i; + first = false; + } else { + Result += ","; + Result += i; + } + } + return Result; + } + + inline void from_string(const std::string &S, StringVec &V) { + Poco::StringTokenizer Tokens(S,",",Poco::StringTokenizer::TOK_TRIM | Poco::StringTokenizer::TOK_IGNORE_EMPTY); + + for(auto const &i:Tokens) + V.emplace_back(i); + } }; #endif // UCENTRALGW_UCENTRALTYPES_H diff --git a/ucentralgw.service b/ucentralgw.service new file mode 100644 index 0000000..a8a91e0 --- /dev/null +++ b/ucentralgw.service @@ -0,0 +1,22 @@ +[Unit] +Description=OpenWiFi Provisioning Service +After=network-online.target docker.service +Wants=network-online.target + +[Service] +Type=simple +Environment="$OWPROV_ROOT=/home/admin/dev/ow-prov" +ExecStart=/home/admin/dev/ow-prov/cmake-build/owprov +WorkingDirectory=/home/admin/dev/ow-prov +# ExecReload=/bin/kill -s HUP $MAINPID +User=admin +# TimeoutSec=0 +RestartSec=2 +Restart=always +StartLimitBurst=3 +# KillMode=process +LimitNOFILE=500000 +LimitNPROC=500000 + +[Install] +WantedBy=multi-user.target