mirror of
				https://github.com/Telecominfraproject/wlan-cloud-owprov.git
				synced 2025-10-29 09:42:38 +00:00 
			
		
		
		
	Compare commits
	
		
			60 Commits
		
	
	
		
			v2.6.0-RC1
			...
			v2.6.0-RC4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 944500dea9 | ||
|   | a5e0dcb210 | ||
|   | 096da35ff4 | ||
|   | bd7f3af11c | ||
|   | 2a06021c4a | ||
|   | bf18bb25ba | ||
|   | 656562c691 | ||
|   | e93f899b76 | ||
|   | eda73038f6 | ||
|   | 953ca155a4 | ||
|   | 898806f232 | ||
|   | 7d97b19b85 | ||
|   | d6c587fde6 | ||
|   | 58c9a7805b | ||
|   | 94dd4c84e9 | ||
|   | 2636715f6f | ||
|   | f9f4624add | ||
|   | cf441de197 | ||
|   | 2ea7e3dcc5 | ||
|   | 158455a528 | ||
|   | 4d2ccec1a8 | ||
|   | 7dad5a9bdb | ||
|   | cd2ac84c5b | ||
|   | 205343619b | ||
|   | 9735f709e9 | ||
|   | ae5fd31818 | ||
|   | aa1136e55b | ||
|   | 2b46ad4a66 | ||
|   | 439aa1d07a | ||
|   | a9293a7717 | ||
|   | 43d7078cb7 | ||
|   | 18f5d42f00 | ||
|   | 70622b2bb8 | ||
|   | 5b24aea47c | ||
|   | e97617a0db | ||
|   | ba63a7033f | ||
|   | e9db2e1a0d | ||
|   | d85fef7725 | ||
|   | 543c46bf68 | ||
|   | 73eec53fe4 | ||
|   | 8ad2d67c2c | ||
|   | 80d5ae340f | ||
|   | 265ae7483b | ||
|   | 43c4ad2211 | ||
|   | 442f810688 | ||
|   | 2dca5204ea | ||
|   | 5cccd0b797 | ||
|   | b8bcece4bf | ||
|   | dc2abe2154 | ||
|   | 8c14bb5b3a | ||
|   | 6ec4bc7115 | ||
|   | 9883a40ec6 | ||
|   | cc647b8108 | ||
|   | 3b0f2a0977 | ||
|   | dfefe39188 | ||
|   | 7d65e19d29 | ||
|   | 1e16c59743 | ||
|   | 4582cbd133 | ||
|   | 18e4b68c1f | ||
|   | 46a11ebda2 | 
							
								
								
									
										8
									
								
								.github/workflows/cleanup.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/cleanup.yml
									
									
									
									
										vendored
									
									
								
							| @@ -17,4 +17,10 @@ jobs: | ||||
|     steps: | ||||
|       - run: | | ||||
|           export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-') | ||||
|           curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owprov/$PR_BRANCH_TAG" | ||||
|  | ||||
|           if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then | ||||
|             echo "PR branch is $PR_BRANCH_TAG, deleting Docker image" | ||||
|             curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owprov/$PR_BRANCH_TAG" | ||||
|           else | ||||
|             echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image" | ||||
|           fi | ||||
|   | ||||
| @@ -125,7 +125,6 @@ add_executable(owprov | ||||
|         src/RESTAPI/RESTAPI_db_helpers.h | ||||
|         src/JobController.cpp src/JobController.h | ||||
|         src/JobRegistrations.cpp | ||||
|         src/storage/storage_jobs.cpp src/storage/storage_jobs.h | ||||
|         src/storage/storage_maps.cpp src/storage/storage_maps.h | ||||
|         src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h | ||||
|         src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h | ||||
|   | ||||
| @@ -5,7 +5,7 @@ if [ "$SELFSIGNED_CERTS" = 'true' ]; then | ||||
|     update-ca-certificates | ||||
| fi | ||||
|  | ||||
| if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWPROV_CONFIG"/owprov.properties ]]; then | ||||
| if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then | ||||
|   RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWPROV_ROOT/certs/restapi-ca.pem"} \ | ||||
|   RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16005"} \ | ||||
|   RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWPROV_ROOT/certs/restapi-cert.pem"} \ | ||||
|   | ||||
| @@ -9,7 +9,7 @@ fullnameOverride: "" | ||||
| images: | ||||
|   owprov: | ||||
|     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov | ||||
|     tag: v2.6.0-RC1 | ||||
|     tag: v2.6.0-RC4 | ||||
|     pullPolicy: Always | ||||
| #    regcred: | ||||
| #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | ||||
|   | ||||
							
								
								
									
										268
									
								
								openapi/ow_or_ameriband.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								openapi/ow_or_ameriband.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,268 @@ | ||||
| openapi: 3.0.1 | ||||
| info: | ||||
|   title: OpenWiFi Open roaming Ameriband Provisioning Model | ||||
|   description: Registration of an OpenRoaming profile with Ameriband for TIP OpenWifi. | ||||
|   version: 1.0.0 | ||||
|   license: | ||||
|     name: BSD3 | ||||
|     url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE | ||||
|  | ||||
| servers: | ||||
|   - url: 'https://tip.regiatration.ameriband.com:8001/api/v1' | ||||
|  | ||||
| security: | ||||
|   - bearerAuth: [] | ||||
|  | ||||
| components: | ||||
|   securitySchemes: | ||||
|     bearerAuth: | ||||
|       type: http | ||||
|       scheme: bearer | ||||
|  | ||||
|   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 | ||||
|                 enum: | ||||
|                   - 0     # Success | ||||
|                   - 8     # INVALID_TOKEN | ||||
|                   - 9     # EXPIRED_TOKEN | ||||
|               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 | ||||
|  | ||||
|     BadRequest: | ||||
|       description: The requested operation failed. | ||||
|       content: | ||||
|         application/json: | ||||
|           schema: | ||||
|             properties: | ||||
|               ErrorCode: | ||||
|                 type: integer | ||||
|               ErrorDetails: | ||||
|                 type: string | ||||
|               ErrorDescription: | ||||
|                 type: integer | ||||
|  | ||||
|   schemas: | ||||
|     RegistrationRequest: | ||||
|       type: object | ||||
|       properties: | ||||
|         orgRequestId: | ||||
|           type: string | ||||
|           format: uuid | ||||
|           minLength: 36 | ||||
|           maxLength: 36 | ||||
|           example: | ||||
|             Client will generate a UUID that must be returned in the response. | ||||
|         orgAcceptedTermsAndConditions: | ||||
|           type: boolean | ||||
|           default: false | ||||
|         orgLegalName: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|         orgWebSite: | ||||
|           type: string | ||||
|           format: url | ||||
|           minLength: 1 | ||||
|         orgContact: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|           example: | ||||
|             John Smith | ||||
|         orgEmail: | ||||
|           type: string | ||||
|           format: email | ||||
|           minLength: 1 | ||||
|         orgPhone: | ||||
|           type: string | ||||
|           example: | ||||
|             (607)555-1234 or +1(223)555-1222 | ||||
|         orgLocation: | ||||
|           type: string | ||||
|           example: | ||||
|             Boston, NH - LA, CA | ||||
|         orgCertificate: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|           example: | ||||
|             This must be the entire PEM file content of the certificate, encoded using base64 | ||||
|  | ||||
|     RegistrationResponse: | ||||
|       type: object | ||||
|       properties: | ||||
|         orgRequestId: | ||||
|           type: string | ||||
|           format: uuid | ||||
|           minLength: 36 | ||||
|           maxLength: 36 | ||||
|           example: | ||||
|             This should be the same orgRequestId passed during registration. | ||||
|         orgNASID: | ||||
|           type: string | ||||
|           minLength: 10 | ||||
|           description: | ||||
|             This is the NASID generated by Ameriband. It will be used by the operator as NASID when contacting Ameriband. | ||||
|         ameribandCertificate: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|           example: | ||||
|             This must be the entire PEM file content of the certificate, encoded using base64 | ||||
|  | ||||
|     RegistrationInformationRequest: | ||||
|       type: object | ||||
|       properties: | ||||
|         link: | ||||
|           description: This should be the link where a potential registrant can read the terms and conditions of registering with Ameriband. | ||||
|           type: string | ||||
|           format: url | ||||
|           minLength: 1 | ||||
|           example: | ||||
|             https://ameriband.com/romain-registration.html | ||||
|  | ||||
| paths: | ||||
|   /termsAndConditions: | ||||
|     get: | ||||
|       summary: The registrant must be given a chance to view the terms and conditions of the relationship they are entering into | ||||
|       operationId: getTermsAndConditions | ||||
|       responses: | ||||
|         200: | ||||
|           description: Sucessfully retrieved Terms and Conditions | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/RegistrationInformationRequest' | ||||
|         404: | ||||
|           $ref: '#/components/responses/Unauthorized' | ||||
|  | ||||
|   /registration: | ||||
|     get: | ||||
|       tags: | ||||
|         - Registration | ||||
|       operationId: getRegistrationInformation | ||||
|       summary: This should return the information from a registration based on the NASID | ||||
|       parameters: | ||||
|         - in: query | ||||
|           name: orgNASID | ||||
|           schema: | ||||
|             type: string | ||||
|           required: true | ||||
|           example: | ||||
|             This is the orgNASID returned during registration. | ||||
|       responses: | ||||
|         200: | ||||
|           $ref: '#/components/schemas/RegistrationResponse' | ||||
|         403: | ||||
|           $ref: '#/components/responses/Unauthorized' | ||||
|         404: | ||||
|           $ref: '#/components/responses/NotFound' | ||||
|  | ||||
|     post: | ||||
|       summary: Called when the registrant ahs read the T&Cs and iw willing to submit their information to enter in a partnership | ||||
|       tags: | ||||
|         - Registration | ||||
|       operationId: createRegistration | ||||
|       requestBody: | ||||
|         required: true | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/RegistrationRequest' | ||||
|       responses: | ||||
|         200: | ||||
|           description: Succesfully registered | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/RegistrationResponse' | ||||
|         400: | ||||
|           description: Registration failed due to  missing or incomplete information | ||||
|           $ref: '#/components/responses/BadRequest' | ||||
|         403: | ||||
|           $ref: '#/components/responses/Unauthorized' | ||||
|  | ||||
|     put: | ||||
|       summary: Called when the registrant needs to update its information with Ameriband. The does not generate a new NASID. | ||||
|       tags: | ||||
|         - Registration | ||||
|       operationId: updateRegistration | ||||
|       parameters: | ||||
|         - in: query | ||||
|           name: orgNASID | ||||
|           schema: | ||||
|             type: string | ||||
|           required: true | ||||
|           example: | ||||
|             This is the orgNASID returned during registration. | ||||
|       requestBody: | ||||
|         required: true | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/RegistrationRequest' | ||||
|       responses: | ||||
|         200: | ||||
|           description: Succesfully found the information based on the orgNASID | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/RegistrationResponse' | ||||
|         400: | ||||
|           $ref: '#/components/responses/BadRequest' | ||||
|         403: | ||||
|           $ref: '#/components/responses/Unauthorized' | ||||
|         404: | ||||
|           $ref: '#/components/responses/NotFound' | ||||
|  | ||||
|     delete: | ||||
|       tags: | ||||
|         - Registration | ||||
|       summary: When a registrant wants to terminate a relationship with Ameriband. Ameriband should also delete all information from the registrant | ||||
|       operationId: deleteRegistration | ||||
|       parameters: | ||||
|         - in: query | ||||
|           name: orgNASID | ||||
|           schema: | ||||
|             type: string | ||||
|           required: true | ||||
|           example: | ||||
|             This is the orgNASID returned during registration. | ||||
|       responses: | ||||
|         204: | ||||
|           $ref: '#/components/responses/Success' | ||||
|         403: | ||||
|           $ref: '#/components/responses/Unauthorized' | ||||
|         404: | ||||
|           $ref: '#/components/responses/NotFound' | ||||
| @@ -27,71 +27,13 @@ components: | ||||
|  | ||||
|   responses: | ||||
|     NotFound: | ||||
|       description: The specified resource was not found. | ||||
|       content: | ||||
|         application/json: | ||||
|           schema: | ||||
|             properties: | ||||
|               ErrorCode: | ||||
|                 type: integer | ||||
|               ErrorDetails: | ||||
|                 type: string | ||||
|               ErrorDescription: | ||||
|                 type: string | ||||
|  | ||||
|       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound' | ||||
|     Unauthorized: | ||||
|       description: The requested does not have sufficient rights to perform the operation. | ||||
|       content: | ||||
|         application/json: | ||||
|           schema: | ||||
|             properties: | ||||
|               ErrorCode: | ||||
|                 type: integer | ||||
|                 enum: | ||||
|                   - 0     # Success | ||||
|                   - 1     # PASSWORD_CHANGE_REQUIRED, | ||||
|                   - 2     # INVALID_CREDENTIALS, | ||||
|                   - 3     # PASSWORD_ALREADY_USED, | ||||
|                   - 4     # USERNAME_PENDING_VERIFICATION, | ||||
|                   - 5     # PASSWORD_INVALID, | ||||
|                   - 6     # INTERNAL_ERROR, | ||||
|                   - 7     # ACCESS_DENIED, | ||||
|                   - 8     # INVALID_TOKEN | ||||
|                   - 9     # EXPIRED_TOKEN | ||||
|                   - 10    # RATE_LIMIT_EXCEEDED | ||||
|                   - 11    # BAD_MFA_TRANSACTION | ||||
|                   - 12    # MFA_FAILURE | ||||
|                   - 13    # SECURITY_SERVICE_UNREACHABLE | ||||
|               ErrorDetails: | ||||
|                 type: string | ||||
|               ErrorDescription: | ||||
|                 type: string | ||||
|  | ||||
|       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized' | ||||
|     Success: | ||||
|       description: The requested operation was performed. | ||||
|       content: | ||||
|         application/json: | ||||
|           schema: | ||||
|             properties: | ||||
|               Operation: | ||||
|                 type: string | ||||
|               Details: | ||||
|                 type: string | ||||
|               Code: | ||||
|                 type: integer | ||||
|  | ||||
|       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success' | ||||
|     BadRequest: | ||||
|       description: The requested operation failed. | ||||
|       content: | ||||
|         application/json: | ||||
|           schema: | ||||
|             properties: | ||||
|               ErrorCode: | ||||
|                 type: integer | ||||
|               ErrorDetails: | ||||
|                 type: string | ||||
|               ErrorDescription: | ||||
|                 type: integer | ||||
|       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest' | ||||
|  | ||||
|   schemas: | ||||
|  | ||||
|   | ||||
| @@ -153,60 +153,62 @@ namespace OpenWifi { | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         std::set<std::string>   Sections; | ||||
|         for(const auto &i:Config_) { | ||||
|             Poco::JSON::Parser  P; | ||||
|             auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>(); | ||||
|             auto Names = O->getNames(); | ||||
|             for(const auto &SectionName:Names) { | ||||
|                 auto InsertInfo = Sections.insert(SectionName); | ||||
|                 if (InsertInfo.second) { | ||||
|                     if (O->isArray(SectionName)) { | ||||
|                         auto OriginalArray = O->getArray(SectionName); | ||||
|                         if (Explain_) { | ||||
|                             Poco::JSON::Object ExObj; | ||||
|                             ExObj.set("from-uuid", i.info.id); | ||||
|                             ExObj.set("from-name", i.info.name); | ||||
|                             ExObj.set("action", "added"); | ||||
|                             ExObj.set("element", OriginalArray); | ||||
|                             Explanation_.add(ExObj); | ||||
|         try { | ||||
|             std::set<std::string> Sections; | ||||
|             for (const auto &i: Config_) { | ||||
|                 Poco::JSON::Parser P; | ||||
|                 auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>(); | ||||
|                 auto Names = O->getNames(); | ||||
|                 for (const auto &SectionName: Names) { | ||||
|                     auto InsertInfo = Sections.insert(SectionName); | ||||
|                     if (InsertInfo.second) { | ||||
|                         if (O->isArray(SectionName)) { | ||||
|                             auto OriginalArray = O->getArray(SectionName); | ||||
|                             if (Explain_) { | ||||
|                                 Poco::JSON::Object ExObj; | ||||
|                                 ExObj.set("from-uuid", i.info.id); | ||||
|                                 ExObj.set("from-name", i.info.name); | ||||
|                                 ExObj.set("action", "added"); | ||||
|                                 ExObj.set("element", OriginalArray); | ||||
|                                 Explanation_.add(ExObj); | ||||
|                             } | ||||
|                             auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>(); | ||||
|                             ReplaceVariablesInArray(OriginalArray, ExpandedArray); | ||||
|                             Configuration->set(SectionName, ExpandedArray); | ||||
|                         } else if (O->isObject(SectionName)) { | ||||
|                             auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>(); | ||||
|                             if (Explain_) { | ||||
|                                 Poco::JSON::Object ExObj; | ||||
|                                 ExObj.set("from-uuid", i.info.id); | ||||
|                                 ExObj.set("from-name", i.info.name); | ||||
|                                 ExObj.set("action", "added"); | ||||
|                                 ExObj.set("element", OriginalSection); | ||||
|                                 Explanation_.add(ExObj); | ||||
|                             } | ||||
|                             auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>(); | ||||
|                             ReplaceVariablesInObject(OriginalSection, ExpandedSection); | ||||
|                             Configuration->set(SectionName, ExpandedSection); | ||||
|                         } else { | ||||
|                             std::cout << " --- unknown element type --- " << O->get(SectionName).toString() | ||||
|                                       << std::endl; | ||||
|                         } | ||||
|                         auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>(); | ||||
|                         ReplaceVariablesInArray(OriginalArray, ExpandedArray); | ||||
|                         Configuration->set(SectionName, ExpandedArray); | ||||
|                     } else if (O->isObject(SectionName)) { | ||||
|                         auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>(); | ||||
|                         if (Explain_) { | ||||
|                             Poco::JSON::Object ExObj; | ||||
|                             ExObj.set("from-uuid", i.info.id); | ||||
|                             ExObj.set("from-name", i.info.name); | ||||
|                             ExObj.set("action", "added"); | ||||
|                             ExObj.set("element", OriginalSection); | ||||
|                             Explanation_.add(ExObj); | ||||
|                         } | ||||
|                         auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>(); | ||||
|                         ReplaceVariablesInObject(OriginalSection, ExpandedSection); | ||||
|                         Configuration->set(SectionName, ExpandedSection); | ||||
|                     } else { | ||||
|                         std::cout << " --- unknown element type --- " << O->get(SectionName).toString() << std::endl; | ||||
|                     } | ||||
|                 } else { | ||||
|                     if (Explain_) { | ||||
|                         Poco::JSON::Object ExObj; | ||||
|                         ExObj.set("from-uuid", i.info.id); | ||||
|                         ExObj.set("from-name", i.info.name); | ||||
|                         ExObj.set("action", "ignored"); | ||||
|                         ExObj.set("reason", "weight insufficient"); | ||||
|                         ExObj.set("element", O->get(SectionName)); | ||||
|                         Explanation_.add(ExObj); | ||||
|                         if (Explain_) { | ||||
|                             Poco::JSON::Object ExObj; | ||||
|                             ExObj.set("from-uuid", i.info.id); | ||||
|                             ExObj.set("from-name", i.info.name); | ||||
|                             ExObj.set("action", "ignored"); | ||||
|                             ExObj.set("reason", "weight insufficient"); | ||||
|                             ExObj.set("element", O->get(SectionName)); | ||||
|                             Explanation_.add(ExObj); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         if(Config_.empty()) | ||||
|             return false; | ||||
|         } catch (...) { | ||||
|  | ||||
|         return true; | ||||
|         } | ||||
|         return !Config_.empty(); | ||||
|     } | ||||
|  | ||||
|     static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) { | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace OpenWifi { | ||||
|  | ||||
|     void AutoDiscovery::run() { | ||||
|         Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); | ||||
|         Utils::SetThreadName("auto-discovery"); | ||||
|         while(Note && Running_) { | ||||
|             auto Msg = dynamic_cast<DiscoveryMessage *>(Note.get()); | ||||
|             if(Msg!= nullptr) { | ||||
|   | ||||
| @@ -26,6 +26,8 @@ namespace OpenWifi { | ||||
|                 {"https://ucentral.io/ucentral.schema.pretty.json", "ucentral.schema.pretty.json" } | ||||
|             }; | ||||
|  | ||||
|         Utils::SetThreadName("file-dmnldr"); | ||||
|  | ||||
|         for(const auto &[url,filename]:Files) { | ||||
|             try { | ||||
|                 std::string FileContent; | ||||
|   | ||||
| @@ -27,11 +27,32 @@ namespace OpenWifi { | ||||
|  | ||||
|     void JobController::run() { | ||||
|         Running_ = true ; | ||||
|  | ||||
|         Utils::SetThreadName("job-controller"); | ||||
|         while(Running_) { | ||||
|             Poco::Thread::trySleep(2000); | ||||
|  | ||||
|             std::lock_guard G(Mutex_); | ||||
|  | ||||
|             for(auto &job:jobs_) { | ||||
|                 if(job!=nullptr) { | ||||
|                     if(job->Started()==0 && Pool_.used()<Pool_.available()) { | ||||
|                         job->Logger().information(fmt::format("Starting {}: {}",job->JobId(),job->Name())); | ||||
|                         job->Start(); | ||||
|                         Pool_.start(*job); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for(auto it = jobs_.begin(); it!=jobs_.end();) { | ||||
|                 if(*it!=nullptr && (*it)->Completed()!=0) { | ||||
|                     auto tmp = it; | ||||
|                     (*it)->Logger().information(fmt::format("Completed {}: {}",(*it)->JobId(),(*it)->Name())); | ||||
|                     it = jobs_.erase(it); | ||||
|                     delete *tmp; | ||||
|                 } else { | ||||
|                     ++it; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -7,99 +7,45 @@ | ||||
| #include <vector> | ||||
| #include <utility> | ||||
| #include <functional> | ||||
| #include <list> | ||||
| #include "framework/MicroService.h" | ||||
|  | ||||
| namespace OpenWifi { | ||||
|  | ||||
|     class Job { | ||||
|         public: | ||||
|             struct Parameter { | ||||
|                 std::string name; | ||||
|                 std::string value; | ||||
|                 inline void to_json(Poco::JSON::Object &Obj) const { | ||||
|                     RESTAPI_utils::field_to_json(Obj,"name",name); | ||||
|                     RESTAPI_utils::field_to_json(Obj,"value",value); | ||||
|                 } | ||||
|     class Job : public Poco::Runnable { | ||||
|     public: | ||||
|         Job(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||
|             jobId_(JobID), | ||||
|             name_(name), | ||||
|             parameters_(parameters), | ||||
|             when_(when), | ||||
|             userinfo_(UI), | ||||
|             Logger_(L) | ||||
|         {}; | ||||
|  | ||||
|                 inline bool from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|                     try { | ||||
|                         RESTAPI_utils::field_from_json(Obj,"name",name); | ||||
|                         RESTAPI_utils::field_from_json(Obj,"value",value); | ||||
|                         return true; | ||||
|                     } catch (...) { | ||||
|         virtual void run() = 0; | ||||
|         [[nodiscard]] std::string Name() const { return name_; } | ||||
|         const SecurityObjects::UserInfo & UserInfo() const { return userinfo_; } | ||||
|         Poco::Logger & Logger() { return Logger_; } | ||||
|         const std::string & JobId() const { return jobId_; } | ||||
|         const std::string & Parameter(int x) const { return parameters_[x];} | ||||
|         uint64_t When() const { return when_; } | ||||
|         void Start() { started_ = OpenWifi::Now(); } | ||||
|         uint64_t Started() const { return started_; } | ||||
|         uint64_t Completed() const { return completed_;} | ||||
|         void Complete() { completed_ = OpenWifi::Now(); } | ||||
|  | ||||
|                     } | ||||
|                     return false; | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             struct Status { | ||||
|                 Types::UUID_t   UUID; | ||||
|                 uint64_t        Start = 0 ; | ||||
|                 uint64_t        Progress = 0 ; | ||||
|                 uint64_t        Completed = 0 ; | ||||
|                 std::string     CurrentDisplay; | ||||
|             }; | ||||
|  | ||||
|             struct Result { | ||||
|                 int         Error=0; | ||||
|                 std::string Reason; | ||||
|             }; | ||||
|  | ||||
|             typedef std::vector<Parameter>       Parameters; | ||||
|             typedef std::vector<Parameters>      ParametersVec; | ||||
|             typedef std::function<bool(const Parameters &Parameters, Result &Result, bool &Retry)>  WorkerFunction; | ||||
|             typedef std::vector<Status>          Statuses; | ||||
|  | ||||
|             Job(std::string Title, | ||||
|                          std::string Description, | ||||
|                          std::string RegisteredName, | ||||
|                          ParametersVec Parameters, | ||||
|                          [[maybe_unused]] bool Parallel=true) : | ||||
|                     Title_(std::move(Title)), | ||||
|                     Description_(std::move(Description)), | ||||
|                     RegisteredName_(std::move(RegisteredName)), | ||||
|                     Parameters_(std::move(Parameters)) | ||||
|                 { | ||||
|                     UUID_ = MicroService::instance().CreateUUID(); | ||||
|                 } | ||||
|  | ||||
|             [[nodiscard]] inline const Types::UUID_t & ID() const { return UUID_; } | ||||
|  | ||||
|         private: | ||||
|             Types::UUID_t       UUID_; | ||||
|             std::string         Title_; | ||||
|             std::string         Description_; | ||||
|             std::string         RegisteredName_; | ||||
|             ParametersVec       Parameters_; | ||||
|     private: | ||||
|         std::string                 jobId_; | ||||
|         std::string                 name_; | ||||
|         std::vector<std::string>    parameters_; | ||||
|         uint64_t                    when_=0; | ||||
|         SecurityObjects::UserInfo   userinfo_; | ||||
|         Poco::Logger                & Logger_; | ||||
|         uint64_t                    started_=0; | ||||
|         uint64_t                    completed_=0; | ||||
|     }; | ||||
|  | ||||
|     class JobRegistry { | ||||
|         public: | ||||
|             static auto instance() { | ||||
|                 static auto instance_ = new JobRegistry; | ||||
|                 return instance_; | ||||
|             } | ||||
|  | ||||
|             inline void RegisterJobType( const std::string & JobType, Job::WorkerFunction Function) { | ||||
|                     JobTypes_[JobType] = std::move(Function); | ||||
|             } | ||||
|  | ||||
|             inline bool Execute(const std::string &JobType, const Job::Parameters & Params, Job::Result &Result, bool & Retry) { | ||||
|                 auto Hint = JobTypes_.find(JobType); | ||||
|                 if(Hint != end(JobTypes_)) { | ||||
|                     Hint->second(Params, Result, Retry); | ||||
|                     return true; | ||||
|                 } | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|         private: | ||||
|             std::map<std::string,Job::WorkerFunction>  JobTypes_; | ||||
|     }; | ||||
|  | ||||
|     inline auto JobRegistry() { return JobRegistry::instance(); } | ||||
|  | ||||
|     class JobController : public SubSystemServer, Poco::Runnable { | ||||
|         public: | ||||
|             static auto instance() { | ||||
| @@ -112,11 +58,16 @@ namespace OpenWifi { | ||||
|             void run() override; | ||||
|             inline void wakeup() { Thr_.wakeUp(); } | ||||
|  | ||||
|             bool JobList(Job::Statuses & Statuses); | ||||
|             void AddJob( Job* newJob ) { | ||||
|                 std::lock_guard G(Mutex_); | ||||
|                 jobs_.push_back(newJob); | ||||
|             } | ||||
|  | ||||
|         private: | ||||
|             Poco::Thread            Thr_; | ||||
|             std::atomic_bool        Running_=false; | ||||
|             Poco::Thread                        Thr_; | ||||
|             std::atomic_bool                    Running_=false; | ||||
|             std::list<Job *>                    jobs_; | ||||
|             Poco::ThreadPool                    Pool_; | ||||
|  | ||||
|         JobController() noexcept: | ||||
|             SubSystemServer("JobController", "JOB-SVR", "job") | ||||
|   | ||||
| @@ -27,6 +27,7 @@ namespace OpenWifi{ | ||||
|             for (const auto &i: V.children) { | ||||
|                 ProvObjects::Venue V2; | ||||
|                 if (StorageService()->VenueDB().GetRecord("id", i, V2)) { | ||||
|                     std::copy(V2.devices.begin(),V2.devices.end(),std::back_inserter(R)); | ||||
|                     auto LowerDevs = GetDevices(V2, GetChildren); | ||||
|                     std::copy(LowerDevs.begin(), LowerDevs.end(), std::back_inserter(R)); | ||||
|                 } | ||||
| @@ -227,10 +228,10 @@ namespace OpenWifi{ | ||||
|  | ||||
|             Poco::JSON::Object  Answer; | ||||
|             SNL.serialNumbers = Existing.devices; | ||||
|  | ||||
|             auto Task = new VenueConfigUpdater(UUID,UserInfo_.userinfo,0,Logger()); | ||||
|             auto JobId = Task->Start(); | ||||
|  | ||||
|             auto JobId = MicroService::instance().CreateUUID(); | ||||
|             Types::StringVec Parameters{UUID};; | ||||
|             auto NewJob = new VenueConfigUpdater(JobId,"VenueConfigurationUpdater", Parameters, 0, UserInfo_.userinfo, Logger()); | ||||
|             JobController()->AddJob(dynamic_cast<Job*>(NewJob)); | ||||
|             SNL.to_json(Answer); | ||||
|             Answer.set("jobId",JobId); | ||||
|             return ReturnObject(Answer); | ||||
| @@ -241,10 +242,10 @@ namespace OpenWifi{ | ||||
|  | ||||
|             Poco::JSON::Object  Answer; | ||||
|             SNL.serialNumbers = Existing.devices; | ||||
|  | ||||
|             auto Task = new VenueUpgrade(UUID,UserInfo_.userinfo,0,Logger()); | ||||
|             auto JobId = Task->Start(); | ||||
|  | ||||
|             auto JobId = MicroService::instance().CreateUUID(); | ||||
|             Types::StringVec Parameters{UUID};; | ||||
|             auto NewJob = new VenueUpgrade(JobId,"VenueFirmwareUpgrade", Parameters, 0, UserInfo_.userinfo, Logger()); | ||||
|             JobController()->AddJob(dynamic_cast<Job*>(NewJob)); | ||||
|             SNL.to_json(Answer); | ||||
|             Answer.set("jobId",JobId); | ||||
|             return ReturnObject(Answer); | ||||
| @@ -255,10 +256,10 @@ namespace OpenWifi{ | ||||
|  | ||||
|             Poco::JSON::Object  Answer; | ||||
|             SNL.serialNumbers = Existing.devices; | ||||
|  | ||||
|             auto Task = new VenueRebooter(UUID,UserInfo_.userinfo,0,Logger()); | ||||
|             auto JobId = Task->Start(); | ||||
|  | ||||
|             auto JobId = MicroService::instance().CreateUUID(); | ||||
|             Types::StringVec Parameters{UUID};; | ||||
|             auto NewJob = new VenueRebooter(JobId,"VenueRebooter", Parameters, 0, UserInfo_.userinfo, Logger()); | ||||
|             JobController()->AddJob(dynamic_cast<Job*>(NewJob)); | ||||
|             SNL.to_json(Answer); | ||||
|             Answer.set("jobId",JobId); | ||||
|             return ReturnObject(Answer); | ||||
|   | ||||
| @@ -538,8 +538,8 @@ namespace OpenWifi::AnalyticsObjects { | ||||
|  | ||||
|     void WifiClientHistory::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"timestamp",timestamp); | ||||
|         field_to_json(Obj,"stationId",stationId); | ||||
|         field_to_json(Obj,"bssId",bssId); | ||||
|         field_to_json(Obj,"station_id",station_id); | ||||
|         field_to_json(Obj,"bssid",bssid); | ||||
|         field_to_json(Obj,"ssid",ssid); | ||||
|         field_to_json(Obj,"rssi",rssi); | ||||
|         field_to_json(Obj,"rx_bitrate",rx_bitrate); | ||||
| @@ -573,13 +573,14 @@ namespace OpenWifi::AnalyticsObjects { | ||||
|         field_to_json(Obj,"connected",connected); | ||||
|         field_to_json(Obj,"inactive",inactive); | ||||
|         field_to_json(Obj,"tx_retries",tx_retries); | ||||
|         field_to_json(Obj,"venue_id",venue_id); | ||||
|     } | ||||
|  | ||||
|     bool WifiClientHistory::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj,"timestamp",timestamp); | ||||
|             field_from_json(Obj,"stationId",stationId); | ||||
|             field_from_json(Obj,"bssId",bssId); | ||||
|             field_from_json(Obj,"station_id",station_id); | ||||
|             field_from_json(Obj,"bssid",bssid); | ||||
|             field_from_json(Obj,"ssid",ssid); | ||||
|             field_from_json(Obj,"rssi",rssi); | ||||
|             field_from_json(Obj,"rx_bitrate",rx_bitrate); | ||||
| @@ -613,6 +614,7 @@ namespace OpenWifi::AnalyticsObjects { | ||||
|             field_from_json(Obj,"connected",connected); | ||||
|             field_from_json(Obj,"inactive",inactive); | ||||
|             field_from_json(Obj,"tx_retries",tx_retries); | ||||
|             field_from_json(Obj,"venue_id",venue_id); | ||||
|             return true; | ||||
|         } catch(...) { | ||||
|  | ||||
|   | ||||
| @@ -376,8 +376,8 @@ namespace OpenWifi { | ||||
|  | ||||
|         struct WifiClientHistory { | ||||
|             uint64_t        timestamp=OpenWifi::Now(); | ||||
|             std::string     stationId; | ||||
|             std::string     bssId; | ||||
|             std::string     station_id; | ||||
|             std::string     bssid; | ||||
|             std::string     ssid; | ||||
|             int64_t         rssi=0; | ||||
|             uint32_t        rx_bitrate=0; | ||||
| @@ -411,6 +411,7 @@ namespace OpenWifi { | ||||
|             uint64_t        connected=0; | ||||
|             uint64_t        inactive=0; | ||||
|             uint64_t        tx_retries=0; | ||||
|             std::string     venue_id; | ||||
|  | ||||
|             void to_json(Poco::JSON::Object &Obj) const; | ||||
|             bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|   | ||||
| @@ -3,176 +3,206 @@ | ||||
| // | ||||
|  | ||||
| #include "RESTAPI_CertObjects.h" | ||||
| #include "framework/MicroService.h" | ||||
|  | ||||
| using OpenWifi::RESTAPI_utils::field_to_json; | ||||
| using OpenWifi::RESTAPI_utils::field_from_json; | ||||
|  | ||||
| namespace OpenWifi { | ||||
|     namespace  CertObjects { | ||||
|         void CertificateEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|             field_to_json(Obj,"id", id); | ||||
|             field_to_json(Obj,"entity", entity); | ||||
|             field_to_json(Obj,"creator", creator); | ||||
|             field_to_json(Obj,"type", type); | ||||
|             field_to_json(Obj,"status", status); | ||||
|             field_to_json(Obj,"certificate", certificate); | ||||
|             field_to_json(Obj,"key", key); | ||||
|             field_to_json(Obj,"devid", devid); | ||||
|             field_to_json(Obj,"cas", cas); | ||||
|             field_to_json(Obj,"manufacturer", manufacturer); | ||||
|             field_to_json(Obj,"model", model); | ||||
|             field_to_json(Obj,"redirector", redirector); | ||||
|             field_to_json(Obj,"commonName", commonName); | ||||
|             field_to_json(Obj,"certificateId", certificateId); | ||||
|             field_to_json(Obj,"batch", batch); | ||||
|             field_to_json(Obj,"created", created); | ||||
|             field_to_json(Obj,"modified", modified); | ||||
|             field_to_json(Obj,"revoked", revoked); | ||||
|             field_to_json(Obj,"revokeCount", revokeCount); | ||||
|         } | ||||
| namespace OpenWifi::CertObjects { | ||||
|     void CertificateEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"id", id); | ||||
|         field_to_json(Obj,"entity", entity); | ||||
|         field_to_json(Obj,"creator", creator); | ||||
|         field_to_json(Obj,"type", type); | ||||
|         field_to_json(Obj,"status", status); | ||||
|         field_to_json(Obj,"certificate", certificate); | ||||
|         field_to_json(Obj,"key", key); | ||||
|         field_to_json(Obj,"devid", devid); | ||||
|         field_to_json(Obj,"cas", cas); | ||||
|         field_to_json(Obj,"manufacturer", manufacturer); | ||||
|         field_to_json(Obj,"model", model); | ||||
|         field_to_json(Obj,"redirector", redirector); | ||||
|         field_to_json(Obj,"commonName", commonName); | ||||
|         field_to_json(Obj,"certificateId", certificateId); | ||||
|         field_to_json(Obj,"batch", batch); | ||||
|         field_to_json(Obj,"created", created); | ||||
|         field_to_json(Obj,"modified", modified); | ||||
|         field_to_json(Obj,"revoked", revoked); | ||||
|         field_to_json(Obj,"revokeCount", revokeCount); | ||||
|         field_to_json(Obj,"synched", synched); | ||||
|     } | ||||
|  | ||||
|         bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|             try { | ||||
|                 field_from_json(Obj,"id", id); | ||||
|                 field_from_json(Obj,"entity", entity); | ||||
|                 field_from_json(Obj,"creator", creator); | ||||
|                 field_from_json(Obj,"type", type); | ||||
|                 field_from_json(Obj,"status", status); | ||||
|                 field_from_json(Obj,"certificate", certificate); | ||||
|                 field_from_json(Obj,"key", key); | ||||
|                 field_from_json(Obj,"devid", devid); | ||||
|                 field_from_json(Obj,"cas", cas); | ||||
|                 field_from_json(Obj,"manufacturer", manufacturer); | ||||
|                 field_from_json(Obj,"model", model); | ||||
|                 field_from_json(Obj,"redirector", redirector); | ||||
|                 field_from_json(Obj,"commonName", commonName); | ||||
|                 field_from_json(Obj,"certificateId", certificateId); | ||||
|                 field_from_json(Obj,"batch", batch); | ||||
|                 field_from_json(Obj,"created", created); | ||||
|                 field_from_json(Obj,"modified", modified); | ||||
|                 field_from_json(Obj,"revoked", revoked); | ||||
|                 field_from_json(Obj,"revokeCount", revokeCount); | ||||
|                 return true; | ||||
|             } catch (...) { | ||||
|             } | ||||
|             return false; | ||||
|     bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj,"id", id); | ||||
|             field_from_json(Obj,"entity", entity); | ||||
|             field_from_json(Obj,"creator", creator); | ||||
|             field_from_json(Obj,"type", type); | ||||
|             field_from_json(Obj,"status", status); | ||||
|             field_from_json(Obj,"certificate", certificate); | ||||
|             field_from_json(Obj,"key", key); | ||||
|             field_from_json(Obj,"devid", devid); | ||||
|             field_from_json(Obj,"cas", cas); | ||||
|             field_from_json(Obj,"manufacturer", manufacturer); | ||||
|             field_from_json(Obj,"model", model); | ||||
|             field_from_json(Obj,"redirector", redirector); | ||||
|             field_from_json(Obj,"commonName", commonName); | ||||
|             field_from_json(Obj,"certificateId", certificateId); | ||||
|             field_from_json(Obj,"batch", batch); | ||||
|             field_from_json(Obj,"created", created); | ||||
|             field_from_json(Obj,"modified", modified); | ||||
|             field_from_json(Obj,"revoked", revoked); | ||||
|             field_from_json(Obj,"revokeCount", revokeCount); | ||||
|             field_from_json(Obj,"synched", synched); | ||||
|             return true; | ||||
|         } catch (...) { | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|         void EntityEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|             field_to_json(Obj,"id", id); | ||||
|             field_to_json(Obj,"creator", creator); | ||||
|             field_to_json(Obj,"name", name); | ||||
|             field_to_json(Obj,"description", description); | ||||
|             field_to_json(Obj,"defaultRedirector", defaultRedirector); | ||||
|             field_to_json(Obj,"apiKey", apiKey); | ||||
|             field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile); | ||||
|             field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile); | ||||
|             field_to_json(Obj,"organization", organization); | ||||
|             field_to_json(Obj,"created", created); | ||||
|             field_to_json(Obj,"modified", modified); | ||||
|             field_to_json(Obj,"suspended", suspended); | ||||
|             field_to_json(Obj,"deleted", deleted); | ||||
|             field_to_json(Obj,"notes", notes); | ||||
|         } | ||||
|     void EntityEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"id", id); | ||||
|         field_to_json(Obj,"creator", creator); | ||||
|         field_to_json(Obj,"name", name); | ||||
|         field_to_json(Obj,"description", description); | ||||
|         field_to_json(Obj,"defaultRedirector", defaultRedirector); | ||||
|         field_to_json(Obj,"apiKey", apiKey); | ||||
|         field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile); | ||||
|         field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile); | ||||
|         field_to_json(Obj,"organization", organization); | ||||
|         field_to_json(Obj,"created", created); | ||||
|         field_to_json(Obj,"modified", modified); | ||||
|         field_to_json(Obj,"suspended", suspended); | ||||
|         field_to_json(Obj,"deleted", deleted); | ||||
|         field_to_json(Obj,"notes", notes); | ||||
|     } | ||||
|  | ||||
|         bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|             try { | ||||
|                 field_from_json(Obj,"id", id); | ||||
|                 field_from_json(Obj,"creator", creator); | ||||
|                 field_from_json(Obj,"name", name); | ||||
|                 field_from_json(Obj,"description", description); | ||||
|                 field_from_json(Obj,"defaultRedirector", defaultRedirector); | ||||
|                 field_from_json(Obj,"apiKey", apiKey); | ||||
|                 field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile); | ||||
|                 field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile); | ||||
|                 field_from_json(Obj,"organization", organization); | ||||
|                 field_from_json(Obj,"created", created); | ||||
|                 field_from_json(Obj,"modified", modified); | ||||
|                 field_from_json(Obj,"suspended", suspended); | ||||
|                 field_from_json(Obj,"deleted", deleted); | ||||
|                 field_from_json(Obj,"notes", notes); | ||||
|                 return true; | ||||
|             } catch (...) { | ||||
|             } | ||||
|             return false; | ||||
|     bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj,"id", id); | ||||
|             field_from_json(Obj,"creator", creator); | ||||
|             field_from_json(Obj,"name", name); | ||||
|             field_from_json(Obj,"description", description); | ||||
|             field_from_json(Obj,"defaultRedirector", defaultRedirector); | ||||
|             field_from_json(Obj,"apiKey", apiKey); | ||||
|             field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile); | ||||
|             field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile); | ||||
|             field_from_json(Obj,"organization", organization); | ||||
|             field_from_json(Obj,"created", created); | ||||
|             field_from_json(Obj,"modified", modified); | ||||
|             field_from_json(Obj,"suspended", suspended); | ||||
|             field_from_json(Obj,"deleted", deleted); | ||||
|             field_from_json(Obj,"notes", notes); | ||||
|             return true; | ||||
|         } catch (...) { | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|         void BatchEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|             field_to_json(Obj,"id", id); | ||||
|             field_to_json(Obj,"entity", entity); | ||||
|             field_to_json(Obj,"creator", creator); | ||||
|             field_to_json(Obj,"name", name); | ||||
|             field_to_json(Obj,"description", description); | ||||
|             field_to_json(Obj,"manufacturer", manufacturer); | ||||
|             field_to_json(Obj,"model", model); | ||||
|             field_to_json(Obj,"redirector", redirector); | ||||
|             field_to_json(Obj,"commonNames", commonNames); | ||||
|             field_to_json(Obj,"jobHistory", jobHistory); | ||||
|             field_to_json(Obj,"notes", notes); | ||||
|             field_to_json(Obj,"submitted", submitted); | ||||
|             field_to_json(Obj,"started", started); | ||||
|             field_to_json(Obj,"completed", completed); | ||||
|             field_to_json(Obj,"modified", modified); | ||||
|         } | ||||
|     void BatchEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"id", id); | ||||
|         field_to_json(Obj,"entity", entity); | ||||
|         field_to_json(Obj,"creator", creator); | ||||
|         field_to_json(Obj,"name", name); | ||||
|         field_to_json(Obj,"description", description); | ||||
|         field_to_json(Obj,"manufacturer", manufacturer); | ||||
|         field_to_json(Obj,"model", model); | ||||
|         field_to_json(Obj,"redirector", redirector); | ||||
|         field_to_json(Obj,"commonNames", commonNames); | ||||
|         field_to_json(Obj,"jobHistory", jobHistory); | ||||
|         field_to_json(Obj,"notes", notes); | ||||
|         field_to_json(Obj,"submitted", submitted); | ||||
|         field_to_json(Obj,"started", started); | ||||
|         field_to_json(Obj,"completed", completed); | ||||
|         field_to_json(Obj,"modified", modified); | ||||
|     } | ||||
|  | ||||
|         bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|             try { | ||||
|                 field_from_json(Obj,"id", id); | ||||
|                 field_from_json(Obj,"entity", entity); | ||||
|                 field_from_json(Obj,"creator", creator); | ||||
|                 field_from_json(Obj,"name", name); | ||||
|                 field_from_json(Obj,"description", description); | ||||
|                 field_from_json(Obj,"manufacturer", manufacturer); | ||||
|                 field_from_json(Obj,"model", model); | ||||
|                 field_from_json(Obj,"redirector", redirector); | ||||
|                 field_from_json(Obj,"commonNames", commonNames); | ||||
|                 field_from_json(Obj,"jobHistory", jobHistory); | ||||
|                 field_from_json(Obj,"notes", notes); | ||||
|                 field_from_json(Obj,"submitted", submitted); | ||||
|                 field_from_json(Obj,"started", started); | ||||
|                 field_from_json(Obj,"completed", completed); | ||||
|                 field_from_json(Obj,"modified", modified); | ||||
|                 return true; | ||||
|             } catch (...) { | ||||
|             } | ||||
|             return false; | ||||
|     bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj,"id", id); | ||||
|             field_from_json(Obj,"entity", entity); | ||||
|             field_from_json(Obj,"creator", creator); | ||||
|             field_from_json(Obj,"name", name); | ||||
|             field_from_json(Obj,"description", description); | ||||
|             field_from_json(Obj,"manufacturer", manufacturer); | ||||
|             field_from_json(Obj,"model", model); | ||||
|             field_from_json(Obj,"redirector", redirector); | ||||
|             field_from_json(Obj,"commonNames", commonNames); | ||||
|             field_from_json(Obj,"jobHistory", jobHistory); | ||||
|             field_from_json(Obj,"notes", notes); | ||||
|             field_from_json(Obj,"submitted", submitted); | ||||
|             field_from_json(Obj,"started", started); | ||||
|             field_from_json(Obj,"completed", completed); | ||||
|             field_from_json(Obj,"modified", modified); | ||||
|             return true; | ||||
|         } catch (...) { | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|         void JobEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|             field_to_json(Obj,"id", id); | ||||
|             field_to_json(Obj,"entity", entity); | ||||
|             field_to_json(Obj,"creator", creator); | ||||
|             field_to_json(Obj,"batch", batch); | ||||
|             field_to_json(Obj,"commonNames", commonNames); | ||||
|             field_to_json(Obj,"completedNames", completedNames); | ||||
|             field_to_json(Obj,"errorNames", errorNames); | ||||
|             field_to_json(Obj,"status", status); | ||||
|             field_to_json(Obj,"command", command); | ||||
|             field_to_json(Obj,"parameters", parameters); | ||||
|             field_to_json(Obj,"submitted", submitted); | ||||
|             field_to_json(Obj,"started", started); | ||||
|             field_to_json(Obj,"completed", completed); | ||||
|         } | ||||
|     void JobEntry::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"id", id); | ||||
|         field_to_json(Obj,"entity", entity); | ||||
|         field_to_json(Obj,"creator", creator); | ||||
|         field_to_json(Obj,"batch", batch); | ||||
|         field_to_json(Obj,"commonNames", commonNames); | ||||
|         field_to_json(Obj,"completedNames", completedNames); | ||||
|         field_to_json(Obj,"errorNames", errorNames); | ||||
|         field_to_json(Obj,"status", status); | ||||
|         field_to_json(Obj,"command", command); | ||||
|         field_to_json(Obj,"parameters", parameters); | ||||
|         field_to_json(Obj,"submitted", submitted); | ||||
|         field_to_json(Obj,"started", started); | ||||
|         field_to_json(Obj,"completed", completed); | ||||
|     } | ||||
|  | ||||
|         bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|             try { | ||||
|                 field_from_json(Obj,"id", id); | ||||
|                 field_from_json(Obj,"entity", entity); | ||||
|                 field_from_json(Obj,"creator", creator); | ||||
|                 field_from_json(Obj,"batch", batch); | ||||
|                 field_from_json(Obj,"commonNames", commonNames); | ||||
|                 field_from_json(Obj,"completedNames", completedNames); | ||||
|                 field_from_json(Obj,"errorNames", errorNames); | ||||
|                 field_from_json(Obj,"status", status); | ||||
|                 field_from_json(Obj,"command", command); | ||||
|                 field_from_json(Obj,"parameters", parameters); | ||||
|                 field_from_json(Obj,"submitted", submitted); | ||||
|                 field_from_json(Obj,"started", started); | ||||
|                 field_from_json(Obj,"completed", completed); | ||||
|                 return true; | ||||
|             } catch (...) { | ||||
|             } | ||||
|             return false; | ||||
|     bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj,"id", id); | ||||
|             field_from_json(Obj,"entity", entity); | ||||
|             field_from_json(Obj,"creator", creator); | ||||
|             field_from_json(Obj,"batch", batch); | ||||
|             field_from_json(Obj,"commonNames", commonNames); | ||||
|             field_from_json(Obj,"completedNames", completedNames); | ||||
|             field_from_json(Obj,"errorNames", errorNames); | ||||
|             field_from_json(Obj,"status", status); | ||||
|             field_from_json(Obj,"command", command); | ||||
|             field_from_json(Obj,"parameters", parameters); | ||||
|             field_from_json(Obj,"submitted", submitted); | ||||
|             field_from_json(Obj,"started", started); | ||||
|             field_from_json(Obj,"completed", completed); | ||||
|             return true; | ||||
|         } catch (...) { | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     void DashBoardYearlyStats::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj, "year", year); | ||||
|         field_to_json(Obj, "activeCerts", activeCerts); | ||||
|         field_to_json(Obj, "revokedCerts", revokedCerts); | ||||
|     } | ||||
|  | ||||
|     void Dashboard::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"snapshot", snapshot); | ||||
|         field_to_json(Obj,"numberOfIssuedCerts", numberOfIssuedCerts); | ||||
|         field_to_json(Obj,"numberOfRevokedCerts", numberOfRevokedCerts); | ||||
|         field_to_json(Obj,"activeCertsPerOrganization", activeCertsPerOrganization); | ||||
|         field_to_json(Obj,"revokedCertsPerOrganization", revokedCertsPerOrganization); | ||||
|         field_to_json(Obj,"numberOfRedirectors", numberOfRedirectors); | ||||
|         field_to_json(Obj,"deviceTypes", deviceTypes); | ||||
|         field_to_json(Obj,"monthlyNumberOfCerts", monthlyNumberOfCerts); | ||||
|         field_to_json(Obj,"monthlyNumberOfCertsPerOrgPerYear", monthlyNumberOfCertsPerOrgPerYear); | ||||
|     } | ||||
|  | ||||
|     void Dashboard::reset() { | ||||
|         snapshot=0; | ||||
|         numberOfRevokedCerts = numberOfIssuedCerts = 0; | ||||
|         activeCertsPerOrganization.clear(); | ||||
|         revokedCertsPerOrganization.clear(); | ||||
|         numberOfRedirectors.clear(); | ||||
|         deviceTypes.clear(); | ||||
|         monthlyNumberOfCerts.clear(); | ||||
|         monthlyNumberOfCertsPerOrgPerYear.clear(); | ||||
|     } | ||||
| } | ||||
| @@ -5,97 +5,118 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <string> | ||||
| #include "framework/MicroService.h" | ||||
| #include "framework/OpenWifiTypes.h" | ||||
| #include "RESTObjects/RESTAPI_SecurityObjects.h" | ||||
|  | ||||
| namespace OpenWifi { | ||||
| namespace OpenWifi::CertObjects { | ||||
|  | ||||
|     namespace CertObjects { | ||||
|     struct CertificateEntry { | ||||
|         OpenWifi::Types::UUID_t         id; | ||||
|         OpenWifi::Types::UUID_t         entity; | ||||
|         OpenWifi::Types::UUID_t         creator; | ||||
|         std::string                     type; | ||||
|         std::string                     status; | ||||
|         std::string                     certificate; | ||||
|         std::string                     key; | ||||
|         std::string                     devid; | ||||
|         std::string                     cas; | ||||
|         std::string                     manufacturer; | ||||
|         std::string                     model; | ||||
|         std::string                     redirector; | ||||
|         std::string                     commonName; | ||||
|         std::string                     certificateId; | ||||
|         OpenWifi::Types::UUID_t         batch; | ||||
|         uint64_t                        created = 0; | ||||
|         uint64_t                        modified = 0; | ||||
|         uint64_t                        revoked = 0; | ||||
|         uint64_t                        revokeCount = 0; | ||||
|         uint64_t                        synched = 0; | ||||
|  | ||||
|         struct CertificateEntry { | ||||
|             OpenWifi::Types::UUID_t         id; | ||||
|             OpenWifi::Types::UUID_t         entity; | ||||
|             OpenWifi::Types::UUID_t         creator; | ||||
|             std::string                     type; | ||||
|             std::string                     status; | ||||
|             std::string                     certificate; | ||||
|             std::string                     key; | ||||
|             std::string                     devid; | ||||
|             std::string                     cas; | ||||
|             std::string                     manufacturer; | ||||
|             std::string                     model; | ||||
|             std::string                     redirector; | ||||
|             std::string                     commonName; | ||||
|             std::string                     certificateId; | ||||
|             OpenWifi::Types::UUID_t         batch; | ||||
|             uint64_t                        created = 0; | ||||
|             uint64_t                        modified = 0; | ||||
|             uint64_t                        revoked = 0; | ||||
|             uint64_t                        revokeCount = 0; | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|             void to_json(Poco::JSON::Object &Obj) const; | ||||
|             bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|         }; | ||||
|     struct EntityEntry { | ||||
|         OpenWifi::Types::UUID_t         id; | ||||
|         OpenWifi::Types::UUID_t         creator; | ||||
|         std::string                     name; | ||||
|         std::string                     description; | ||||
|         std::string                     defaultRedirector; | ||||
|         std::string                     apiKey; | ||||
|         std::string                     serverEnrollmentProfile; | ||||
|         std::string                     clientEnrollmentProfile; | ||||
|         std::string                     organization; | ||||
|         SecurityObjects::NoteInfoVec    notes; | ||||
|         bool                            suspended=false; | ||||
|         bool                            deleted=false; | ||||
|         uint64_t                        created = 0 ; | ||||
|         uint64_t                        modified = 0 ; | ||||
|  | ||||
|         struct EntityEntry { | ||||
|             OpenWifi::Types::UUID_t         id; | ||||
|             OpenWifi::Types::UUID_t         creator; | ||||
|             std::string                     name; | ||||
|             std::string                     description; | ||||
|             std::string                     defaultRedirector; | ||||
|             std::string                     apiKey; | ||||
|             std::string                     serverEnrollmentProfile; | ||||
|             std::string                     clientEnrollmentProfile; | ||||
|             std::string                     organization; | ||||
|             SecurityObjects::NoteInfoVec    notes; | ||||
|             bool                            suspended=false; | ||||
|             bool                            deleted=false; | ||||
|             uint64_t                        created = 0 ; | ||||
|             uint64_t                        modified = 0 ; | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|             void to_json(Poco::JSON::Object &Obj) const; | ||||
|             bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|         }; | ||||
|     struct BatchEntry { | ||||
|         OpenWifi::Types::UUID_t         id; | ||||
|         OpenWifi::Types::UUID_t         entity; | ||||
|         OpenWifi::Types::UUID_t         creator; | ||||
|         std::string                     name; | ||||
|         std::string                     description; | ||||
|         std::string                     manufacturer; | ||||
|         std::string                     model; | ||||
|         std::string                     redirector; | ||||
|         std::vector<std::string>        commonNames; | ||||
|         std::vector<std::string>        jobHistory; | ||||
|         SecurityObjects::NoteInfoVec    notes; | ||||
|         uint64_t                        submitted = 0 ; | ||||
|         uint64_t                        started = 0 ; | ||||
|         uint64_t                        completed = 0 ; | ||||
|         uint64_t                        modified = 0 ; | ||||
|  | ||||
|         struct BatchEntry { | ||||
|             OpenWifi::Types::UUID_t         id; | ||||
|             OpenWifi::Types::UUID_t         entity; | ||||
|             OpenWifi::Types::UUID_t         creator; | ||||
|             std::string                     name; | ||||
|             std::string                     description; | ||||
|             std::string                     manufacturer; | ||||
|             std::string                     model; | ||||
|             std::string                     redirector; | ||||
|             std::vector<std::string>        commonNames; | ||||
|             std::vector<std::string>        jobHistory; | ||||
|             SecurityObjects::NoteInfoVec    notes; | ||||
|             uint64_t                        submitted = 0 ; | ||||
|             uint64_t                        started = 0 ; | ||||
|             uint64_t                        completed = 0 ; | ||||
|             uint64_t                        modified = 0 ; | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|             void to_json(Poco::JSON::Object &Obj) const; | ||||
|             bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|         }; | ||||
|     struct JobEntry { | ||||
|         OpenWifi::Types::UUID_t         id; | ||||
|         OpenWifi::Types::UUID_t         entity; | ||||
|         OpenWifi::Types::UUID_t         creator; | ||||
|         OpenWifi::Types::UUID_t         batch; | ||||
|         std::string                     command; | ||||
|         OpenWifi::Types::StringVec      commonNames; | ||||
|         OpenWifi::Types::StringVec      completedNames; | ||||
|         OpenWifi::Types::StringVec      errorNames; | ||||
|         Types::StringPairVec            parameters; | ||||
|         std::string                     status; | ||||
|         uint64_t                        submitted=0; | ||||
|         uint64_t                        started=0; | ||||
|         uint64_t                        completed=0; | ||||
|  | ||||
|         struct JobEntry { | ||||
|             OpenWifi::Types::UUID_t         id; | ||||
|             OpenWifi::Types::UUID_t         entity; | ||||
|             OpenWifi::Types::UUID_t         creator; | ||||
|             OpenWifi::Types::UUID_t         batch; | ||||
|             std::string                     command; | ||||
|             OpenWifi::Types::StringVec      commonNames; | ||||
|             OpenWifi::Types::StringVec      completedNames; | ||||
|             OpenWifi::Types::StringVec      errorNames; | ||||
|             Types::StringPairVec            parameters; | ||||
|             std::string                     status; | ||||
|             uint64_t                        submitted=0; | ||||
|             uint64_t                        started=0; | ||||
|             uint64_t                        completed=0; | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|     struct DashBoardYearlyStats { | ||||
|         uint64_t                            year=0; | ||||
|         OpenWifi::Types::Counted3DMapSII    activeCerts; | ||||
|         OpenWifi::Types::Counted3DMapSII    revokedCerts; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|     }; | ||||
|  | ||||
|     struct Dashboard { | ||||
|         uint64_t                            snapshot=0; | ||||
|         uint64_t                            numberOfIssuedCerts=0; | ||||
|         uint64_t                            numberOfRevokedCerts=0; | ||||
|         OpenWifi::Types::CountedMap         activeCertsPerOrganization; | ||||
|         OpenWifi::Types::CountedMap         revokedCertsPerOrganization; | ||||
|         OpenWifi::Types::CountedMap         numberOfRedirectors; | ||||
|         OpenWifi::Types::CountedMap         deviceTypes; | ||||
|         OpenWifi::Types::CountedMap         monthlyNumberOfCerts; | ||||
|         std::vector<DashBoardYearlyStats>   monthlyNumberOfCertsPerOrgPerYear; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         void reset(); | ||||
|     }; | ||||
|  | ||||
|             void to_json(Poco::JSON::Object &Obj) const; | ||||
|             bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|         }; | ||||
|     } | ||||
| } | ||||
| @@ -233,7 +233,7 @@ namespace OpenWifi::FMSObjects { | ||||
|         UnknownFirmwares_.clear(); | ||||
|         totalSecondsOld_.clear(); | ||||
|         numberOfDevices = 0 ; | ||||
|         snapshot = std::time(nullptr); | ||||
|         snapshot = OpenWifi::Now(); | ||||
|     } | ||||
|  | ||||
|     bool DeviceReport::from_json([[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) { | ||||
| @@ -273,4 +273,37 @@ namespace OpenWifi::FMSObjects { | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     void DeviceCurrentInfo::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj, "serialNumber",serialNumber); | ||||
|         field_to_json(Obj, "revision", revision); | ||||
|         field_to_json(Obj, "upgraded", upgraded); | ||||
|     } | ||||
|  | ||||
|     bool DeviceCurrentInfo::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj, "serialNumber",serialNumber); | ||||
|             field_from_json(Obj, "revision", revision); | ||||
|             field_from_json(Obj, "upgraded", upgraded); | ||||
|             return true; | ||||
|         } catch(...) { | ||||
|  | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     void DeviceCurrentInfoList::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj, "devices",devices); | ||||
|     } | ||||
|  | ||||
|     bool DeviceCurrentInfoList::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj, "devices",devices); | ||||
|             return true; | ||||
|         } catch(...) { | ||||
|  | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -4,9 +4,7 @@ | ||||
|  | ||||
| #include <string> | ||||
|  | ||||
| #ifndef UCENTRALFMS_RESTAPI_FMSOBJECTS_H | ||||
| #define UCENTRALFMS_RESTAPI_FMSOBJECTS_H | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "RESTAPI_SecurityObjects.h" | ||||
| #include "framework/OpenWifiTypes.h" | ||||
| @@ -29,7 +27,7 @@ namespace OpenWifi::FMSObjects { | ||||
|         std::string     location; | ||||
|         std::string     uploader; | ||||
|         std::string     digest; | ||||
|         bool            latest=0; | ||||
|         bool            latest=false; | ||||
|         SecurityObjects::NoteInfoVec    notes; | ||||
|         uint64_t        created=0; | ||||
|  | ||||
| @@ -141,7 +139,21 @@ namespace OpenWifi::FMSObjects { | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|     struct DeviceCurrentInfo { | ||||
|         std::string                 serialNumber; | ||||
|         std::string                 revision; | ||||
|         uint64_t                    upgraded=0; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|     struct DeviceCurrentInfoList { | ||||
|         std::vector<DeviceCurrentInfo>  devices; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif //UCENTRALFMS_RESTAPI_FMSOBJECTS_H | ||||
|   | ||||
							
								
								
									
										110
									
								
								src/RESTObjects/RESTAPI_OWLSobjects.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/RESTObjects/RESTAPI_OWLSobjects.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| // | ||||
| // Created by stephane bourque on 2021-08-31. | ||||
| // | ||||
|  | ||||
| #include "framework/MicroService.h" | ||||
|  | ||||
| using OpenWifi::RESTAPI_utils::field_to_json; | ||||
| using OpenWifi::RESTAPI_utils::field_from_json; | ||||
| using OpenWifi::RESTAPI_utils::EmbedDocument; | ||||
|  | ||||
| #include "RESTAPI_OWLSobjects.h" | ||||
|  | ||||
| // SIM -> 0x53/0x073, 0x49/0x69, 0x4d/0x6d | ||||
|  | ||||
| namespace OpenWifi::OWLSObjects { | ||||
|  | ||||
|     void SimulationDetails::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"id", id); | ||||
|         field_to_json(Obj,"name", name); | ||||
|         field_to_json(Obj,"gateway", gateway); | ||||
|         field_to_json(Obj,"certificate", certificate); | ||||
|         field_to_json(Obj,"key", key); | ||||
|         field_to_json(Obj,"macPrefix", macPrefix); | ||||
|         field_to_json(Obj,"deviceType", deviceType); | ||||
|         field_to_json(Obj,"devices", devices); | ||||
|         field_to_json(Obj,"healthCheckInterval", healthCheckInterval); | ||||
|         field_to_json(Obj,"stateInterval", stateInterval); | ||||
|         field_to_json(Obj,"minAssociations", minAssociations); | ||||
|         field_to_json(Obj,"maxAssociations", maxAssociations); | ||||
|         field_to_json(Obj,"minClients", minClients); | ||||
|         field_to_json(Obj,"maxClients", maxClients); | ||||
|         field_to_json(Obj,"simulationLength", simulationLength); | ||||
|         field_to_json(Obj,"threads", threads); | ||||
|         field_to_json(Obj,"clientInterval", clientInterval); | ||||
|         field_to_json(Obj,"keepAlive", keepAlive); | ||||
|         field_to_json(Obj,"reconnectInterval", reconnectInterval); | ||||
|         field_to_json(Obj,"concurrentDevices", concurrentDevices); | ||||
|     } | ||||
|  | ||||
|     bool SimulationDetails::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj,"id", id); | ||||
|             field_from_json(Obj,"name", name); | ||||
|             field_from_json(Obj,"gateway", gateway); | ||||
|             field_from_json(Obj,"certificate", certificate); | ||||
|             field_from_json(Obj,"key", key); | ||||
|             field_from_json(Obj,"macPrefix", macPrefix); | ||||
|             field_from_json(Obj,"deviceType", deviceType); | ||||
|             field_from_json(Obj,"devices", devices); | ||||
|             field_from_json(Obj,"healthCheckInterval", healthCheckInterval); | ||||
|             field_from_json(Obj,"stateInterval", stateInterval); | ||||
|             field_from_json(Obj,"minAssociations", minAssociations); | ||||
|             field_from_json(Obj,"maxAssociations", maxAssociations); | ||||
|             field_from_json(Obj,"minClients", minClients); | ||||
|             field_from_json(Obj,"maxClients", maxClients); | ||||
|             field_from_json(Obj,"simulationLength", simulationLength); | ||||
|             field_from_json(Obj,"threads", threads); | ||||
|             field_from_json(Obj,"clientInterval", clientInterval); | ||||
|             field_from_json(Obj,"keepAlive", keepAlive); | ||||
|             field_from_json(Obj,"reconnectInterval", reconnectInterval); | ||||
|             field_from_json(Obj,"concurrentDevices", concurrentDevices); | ||||
|             return true; | ||||
|         } catch(...) { | ||||
|  | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     void SimulationDetailsList::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"list", list); | ||||
|     } | ||||
|  | ||||
|     bool SimulationDetailsList::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
|         try { | ||||
|             field_from_json(Obj,"list", list); | ||||
|             return true; | ||||
|         } catch(...) { | ||||
|  | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     void SimulationStatus::to_json(Poco::JSON::Object &Obj) const { | ||||
|         field_to_json(Obj,"id", id); | ||||
|         field_to_json(Obj,"simulationId", simulationId); | ||||
|         field_to_json(Obj,"state", state); | ||||
|         field_to_json(Obj,"tx", tx); | ||||
|         field_to_json(Obj,"rx", rx); | ||||
|         field_to_json(Obj,"msgsTx", msgsTx); | ||||
|         field_to_json(Obj,"msgsRx", msgsRx); | ||||
|         field_to_json(Obj,"liveDevices", liveDevices); | ||||
|         field_to_json(Obj,"timeToFullDevices", timeToFullDevices); | ||||
|         field_to_json(Obj,"startTime", startTime); | ||||
|         field_to_json(Obj,"endTime", endTime); | ||||
|         field_to_json(Obj,"errorDevices", errorDevices); | ||||
|         field_to_json(Obj,"owner", owner); | ||||
|     } | ||||
|  | ||||
|     void Dashboard::to_json([[maybe_unused]] Poco::JSON::Object &Obj) const { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     bool Dashboard::from_json([[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     void Dashboard::reset() { | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/RESTObjects/RESTAPI_OWLSobjects.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/RESTObjects/RESTAPI_OWLSobjects.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| // | ||||
| // Created by stephane bourque on 2021-08-31. | ||||
| // | ||||
|  | ||||
| #ifndef UCENTRALSIM_RESTAPI_OWLSOBJECTS_H | ||||
| #define UCENTRALSIM_RESTAPI_OWLSOBJECTS_H | ||||
|  | ||||
| #include <vector> | ||||
| #include "Poco/JSON/Object.h" | ||||
|  | ||||
| namespace OpenWifi::OWLSObjects { | ||||
|  | ||||
|     struct SimulationDetails { | ||||
|         std::string     id; | ||||
|         std::string     name; | ||||
|         std::string     gateway; | ||||
|         std::string     certificate; | ||||
|         std::string     key; | ||||
|         std::string     macPrefix; | ||||
|         std::string     deviceType; | ||||
|         uint64_t        devices = 5; | ||||
|         uint64_t        healthCheckInterval = 60; | ||||
|         uint64_t        stateInterval = 60 ; | ||||
|         uint64_t        minAssociations = 1; | ||||
|         uint64_t        maxAssociations = 3; | ||||
|         uint64_t        minClients = 1 ; | ||||
|         uint64_t        maxClients = 3; | ||||
|         uint64_t        simulationLength = 60 * 60; | ||||
|         uint64_t        threads = 16; | ||||
|         uint64_t        clientInterval = 1; | ||||
|         uint64_t        keepAlive = 300; | ||||
|         uint64_t        reconnectInterval = 30 ; | ||||
|         uint64_t        concurrentDevices = 5; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|     struct SimulationDetailsList { | ||||
|         std::vector<SimulationDetails>  list; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|     }; | ||||
|  | ||||
|     struct SimulationStatus { | ||||
|         std::string     id; | ||||
|         std::string     simulationId; | ||||
|         std::string     state; | ||||
|         uint64_t        tx; | ||||
|         uint64_t        rx; | ||||
|         uint64_t        msgsTx; | ||||
|         uint64_t        msgsRx; | ||||
|         uint64_t        liveDevices; | ||||
|         uint64_t        timeToFullDevices; | ||||
|         uint64_t        startTime; | ||||
|         uint64_t        endTime; | ||||
|         uint64_t        errorDevices; | ||||
|         std::string     owner; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|     }; | ||||
|  | ||||
|  | ||||
|     struct Dashboard { | ||||
|         int O; | ||||
|  | ||||
|         void to_json(Poco::JSON::Object &Obj) const; | ||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|         void reset(); | ||||
|  | ||||
|     }; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif //UCENTRALSIM_RESTAPI_OWLSOBJECTS_H | ||||
| @@ -9,6 +9,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <string> | ||||
| #include <type_traits> | ||||
| #include "framework/OpenWifiTypes.h" | ||||
| #include "Poco/JSON/Object.h" | ||||
| #include "Poco/Data/LOB.h" | ||||
| @@ -27,8 +28,13 @@ namespace OpenWifi { | ||||
|             bool Delete_ = true; | ||||
|             bool PortalLogin_ = true; | ||||
|  | ||||
|             AclTemplate()  noexcept = default; | ||||
|  | ||||
|             void to_json(Poco::JSON::Object &Obj) const; | ||||
|             bool from_json(const Poco::JSON::Object::Ptr &Obj);	}; | ||||
|             bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
|         }; | ||||
|  | ||||
|         static_assert( std::is_nothrow_move_constructible_v<AclTemplate> ); | ||||
|  | ||||
|         struct WebToken { | ||||
|             std::string access_token_; | ||||
|   | ||||
| @@ -42,6 +42,7 @@ namespace OpenWifi { | ||||
|  | ||||
|     void Signup::run() { | ||||
|         Running_ = true; | ||||
|         Utils::SetThreadName("signup-mgr"); | ||||
|         while(Running_) { | ||||
|             Poco::Thread::trySleep(5000); | ||||
|  | ||||
|   | ||||
| @@ -105,6 +105,7 @@ namespace OpenWifi { | ||||
|     } | ||||
|  | ||||
|     void Storage::onTimer([[maybe_unused]] Poco::Timer &timer) { | ||||
|         Utils::SetThreadName("strg-janitor"); | ||||
|     } | ||||
|  | ||||
|     void Storage::Stop() { | ||||
| @@ -213,31 +214,109 @@ namespace OpenWifi { | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
|         auto FixEntityDevices = [&](const ProvObjects::Entity &E) -> bool { | ||||
|         auto FixEntity = [&](const ProvObjects::Entity &E) -> bool { | ||||
|             Types::UUIDvec_t NewDevices; | ||||
|             bool Modified=false; | ||||
|             for(const auto &device:E.devices) { | ||||
|                 ProvObjects::InventoryTag T; | ||||
|                 if(InventoryDB().GetRecord("id", device, T)) { | ||||
|                     NewDevices.emplace_back(device); | ||||
|                 } else { | ||||
|  | ||||
|                     Modified=true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if(NewDevices!=E.devices) { | ||||
|             Types::UUIDvec_t NewContacts; | ||||
|             for(const auto &contact:E.contacts) { | ||||
|                 ProvObjects::Contact C; | ||||
|                 if(ContactDB().GetRecord("id", contact, C)) { | ||||
|                     NewContacts.emplace_back(contact); | ||||
|                 } else { | ||||
|                     Modified=true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             Types::UUIDvec_t NewLocations; | ||||
|             for(const auto &location:E.locations) { | ||||
|                 ProvObjects::Location L; | ||||
|                 if(LocationDB().GetRecord("id", location, L)) { | ||||
|                     NewLocations.emplace_back(location); | ||||
|                 } else { | ||||
|                     Modified=true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             Types::UUIDvec_t NewVenues; | ||||
|             for(const auto &venue:E.venues) { | ||||
|                 ProvObjects::Venue V; | ||||
|                 if(VenueDB().GetRecord("id", venue, V)) { | ||||
|                     NewVenues.emplace_back(venue); | ||||
|                 } else { | ||||
|                     Modified=true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             Types::UUIDvec_t NewVariables; | ||||
|             for(const auto &variable:E.variables) { | ||||
|                 ProvObjects::VariableBlock V; | ||||
|                 if(VariablesDB().GetRecord("id", variable, V)) { | ||||
|                     NewVariables.emplace_back(variable); | ||||
|                 } else { | ||||
|                     Modified=true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if(Modified) | ||||
|             { | ||||
|                 Logger().warning(fmt::format("  fixing entity: {}",E.info.name)); | ||||
|                 ProvObjects::Entity NewEntity = E; | ||||
|                 NewEntity.devices = NewDevices; | ||||
|                 NewEntity.contacts = NewContacts; | ||||
|                 NewEntity.locations = NewLocations; | ||||
|                 NewEntity.venues = NewVenues; | ||||
|                 NewEntity.variables = NewVariables; | ||||
|                 EntityDB().UpdateRecord("id", E.info.id, NewEntity); | ||||
|             } | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
|         auto FixInventory = [&](const ProvObjects::InventoryTag &T) -> bool { | ||||
|             // check the venue/entity for this device. | ||||
|             ProvObjects::InventoryTag   NewTag{T}; | ||||
|             bool modified=false; | ||||
|             if(!T.venue.empty() && !VenueDB().Exists("id",T.venue)) { | ||||
|                 NewTag.venue.clear(); | ||||
|                 modified=true; | ||||
|             } | ||||
|  | ||||
|             if(!T.entity.empty() && !EntityDB().Exists("id",T.entity)) { | ||||
|                 NewTag.entity.clear(); | ||||
|                 modified=true; | ||||
|             } | ||||
|  | ||||
|             if(!T.location.empty() && !LocationDB().Exists("id",T.location)) { | ||||
|                 NewTag.location.clear(); | ||||
|                 modified=true; | ||||
|             } | ||||
|  | ||||
|             if(!T.contact.empty() && !ContactDB().Exists("id",T.contact)) { | ||||
|                 NewTag.contact.clear(); | ||||
|                 modified=true; | ||||
|             } | ||||
|  | ||||
|             if(modified) { | ||||
|                 Logger().warning(fmt::format("  fixing entity: {}",T.info.name)); | ||||
|                 InventoryDB().UpdateRecord("id", T.info.id, NewTag); | ||||
|             } | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
|         Logger().information("Checking DB consistency: venues"); | ||||
|         VenueDB().Iterate(FixVenueDevices); | ||||
|         Logger().information("Checking DB consistency: entities"); | ||||
|         EntityDB().Iterate(FixEntityDevices); | ||||
|  | ||||
|         EntityDB().Iterate(FixEntity); | ||||
|         Logger().information("Checking DB consistency: inventory"); | ||||
|         InventoryDB().Iterate(FixInventory); | ||||
|     } | ||||
|  | ||||
|     void Storage::InitializeSystemDBs() { | ||||
|   | ||||
| @@ -21,7 +21,7 @@ namespace OpenWifi { | ||||
|     } | ||||
|  | ||||
|     void TagServer::run() { | ||||
|  | ||||
|         Utils::SetThreadName("tag-server"); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -9,6 +9,7 @@ | ||||
| #include "APConfig.h" | ||||
| #include "sdks/SDK_gw.h" | ||||
| #include "framework/WebSocketClientNotifications.h" | ||||
| #include "JobController.h" | ||||
|  | ||||
| namespace OpenWifi { | ||||
|  | ||||
| @@ -37,35 +38,42 @@ namespace OpenWifi { | ||||
|         void run() final { | ||||
|             ProvObjects::InventoryTag   Device; | ||||
|             started_=true; | ||||
|             Utils::SetThreadName("venue-cfg"); | ||||
|             if(StorageService()->InventoryDB().GetRecord("id",uuid_,Device)) { | ||||
|                 SerialNumber = Device.serialNumber; | ||||
|                 // std::cout << "Starting push for " << Device.serialNumber << std::endl; | ||||
|                 Logger().debug(fmt::format("{}: Computing configuration.",Device.serialNumber)); | ||||
|                 auto DeviceConfig = std::make_shared<APConfig>(Device.serialNumber, Device.deviceType, Logger(), false); | ||||
|                 auto Configuration = Poco::makeShared<Poco::JSON::Object>(); | ||||
|                 if (DeviceConfig->Get(Configuration)) { | ||||
|                     std::ostringstream OS; | ||||
|                     Configuration->stringify(OS); | ||||
|                     auto Response=Poco::makeShared<Poco::JSON::Object>(); | ||||
|                     Logger().debug(fmt::format("{}: Pushing configuration.",Device.serialNumber)); | ||||
|                     if (SDK::GW::Device::Configure(nullptr, Device.serialNumber, Configuration, Response)) { | ||||
|                         Logger().debug(fmt::format("{}: Configuration pushed.",Device.serialNumber)); | ||||
|                         Logger().information(fmt::format("{}: Updated.", Device.serialNumber)); | ||||
|                         // std::cout << Device.serialNumber << ": Updated" << std::endl; | ||||
|                         updated_++; | ||||
|                 try { | ||||
|                     if (DeviceConfig->Get(Configuration)) { | ||||
|                         std::ostringstream OS; | ||||
|                         Configuration->stringify(OS); | ||||
|                         auto Response = Poco::makeShared<Poco::JSON::Object>(); | ||||
|                         Logger().debug(fmt::format("{}: Pushing configuration.", Device.serialNumber)); | ||||
|                         if (SDK::GW::Device::Configure(nullptr, Device.serialNumber, Configuration, Response)) { | ||||
|                             Logger().debug(fmt::format("{}: Configuration pushed.", Device.serialNumber)); | ||||
|                             Logger().information(fmt::format("{}: Updated.", Device.serialNumber)); | ||||
|                             // std::cout << Device.serialNumber << ": Updated" << std::endl; | ||||
|                             updated_++; | ||||
|                         } else { | ||||
|                             Logger().information(fmt::format("{}: Not updated.", Device.serialNumber)); | ||||
|                             // std::cout << Device.serialNumber << ": Failed" << std::endl; | ||||
|                             failed_++; | ||||
|                         } | ||||
|                     } else { | ||||
|                         Logger().information(fmt::format("{}: Not updated.", Device.serialNumber)); | ||||
|                         // std::cout << Device.serialNumber << ": Failed" << std::endl; | ||||
|                         failed_++; | ||||
|                         Logger().debug(fmt::format("{}: Configuration is bad.", Device.serialNumber)); | ||||
|                         bad_config_++; | ||||
|                         // std::cout << Device.serialNumber << ": Bad config" << std::endl; | ||||
|                     } | ||||
|                 } else { | ||||
|                     Logger().debug(fmt::format("{}: Configuration is bad.",Device.serialNumber)); | ||||
|                 } catch (...) { | ||||
|                     Logger().debug(fmt::format("{}: Configuration is bad (caused an exception).", Device.serialNumber)); | ||||
|                     bad_config_++; | ||||
|                     // std::cout << Device.serialNumber << ": Bad config" << std::endl; | ||||
|                 } | ||||
|             } | ||||
|             done_ = true; | ||||
|             // std::cout << "Done push for " << Device.serialNumber << std::endl; | ||||
|             Utils::SetThreadName("free"); | ||||
|         } | ||||
|  | ||||
|         uint64_t        updated_=0, failed_=0, bad_config_=0; | ||||
| @@ -80,43 +88,21 @@ namespace OpenWifi { | ||||
|         inline Poco::Logger & Logger() { return Logger_; } | ||||
|     }; | ||||
|  | ||||
|     class VenueConfigUpdater: public Poco::Runnable { | ||||
|     class VenueConfigUpdater: public Job { | ||||
|     public: | ||||
|         explicit VenueConfigUpdater(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : | ||||
|             VenueUUID_(VenueUUID), | ||||
|             UI_(UI), | ||||
|             When_(When), | ||||
|             Logger_(L) | ||||
|         { | ||||
|         VenueConfigUpdater(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||
|                 Job(JobID, name, parameters, when, UI, L) { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         inline std::string Start() { | ||||
|             JobId_ = MicroService::CreateUUID(); | ||||
|             Worker_.start(*this); | ||||
|             return JobId_; | ||||
|         } | ||||
|         inline virtual void run() { | ||||
|             std::string                 VenueUUID_; | ||||
|  | ||||
|     private: | ||||
|         std::string                 VenueUUID_; | ||||
|         SecurityObjects::UserInfo   UI_; | ||||
|         uint64_t                    When_; | ||||
|         Poco::Logger                &Logger_; | ||||
|         Poco::Thread                Worker_; | ||||
|         std::string                 JobId_; | ||||
|         Poco::ThreadPool            Pool_{2,16,300}; | ||||
|  | ||||
|         inline Poco::Logger & Logger() { return Logger_; } | ||||
|  | ||||
|         inline void run() final { | ||||
|  | ||||
|             if(When_ && When_>OpenWifi::Now()) | ||||
|                 Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 ); | ||||
|             Utils::SetThreadName("venue-update"); | ||||
|             VenueUUID_ = Parameter(0); | ||||
|  | ||||
|             WebSocketNotification<WebSocketNotificationJobContent> N; | ||||
|  | ||||
|             Logger().information(fmt::format("Job {} Starting.", JobId_)); | ||||
|  | ||||
|             ProvObjects::Venue  Venue; | ||||
|             uint64_t Updated = 0, Failed = 0 , BadConfigs = 0 ; | ||||
|             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { | ||||
| @@ -127,7 +113,7 @@ namespace OpenWifi { | ||||
|                 }; | ||||
|  | ||||
|                 N.content.title = fmt::format("Updating {} configurations", Venue.info.name); | ||||
|                 N.content.jobId = JobId_; | ||||
|                 N.content.jobId = JobId(); | ||||
|  | ||||
|                 std::array<tState,MaxThreads> Tasks; | ||||
|  | ||||
| @@ -196,17 +182,18 @@ namespace OpenWifi { | ||||
|                 } | ||||
|  | ||||
|                 N.content.details = fmt::format("Job {} Completed: {} updated, {} failed to update, {} bad configurations. ", | ||||
|                                                 JobId_, Updated ,Failed, BadConfigs); | ||||
|                                                 JobId(), Updated ,Failed, BadConfigs); | ||||
|  | ||||
|             } else { | ||||
|                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); | ||||
|                 Logger().warning(N.content.details); | ||||
|             } | ||||
|  | ||||
|             WebSocketClientNotificationVenueUpdateJobCompletionToUser(UI_.email, N); | ||||
|             WebSocketClientNotificationVenueUpdateJobCompletionToUser(UserInfo().email, N); | ||||
|             Logger().information(fmt::format("Job {} Completed: {} updated, {} failed to update , {} bad configurations.", | ||||
|                                              JobId_, Updated ,Failed, BadConfigs)); | ||||
|             delete this; | ||||
|                                              JobId(), Updated ,Failed, BadConfigs)); | ||||
|             Utils::SetThreadName("free"); | ||||
|             Complete(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "StorageService.h" | ||||
| #include "APConfig.h" | ||||
| #include "sdks/SDK_gw.h" | ||||
| #include "JobController.h" | ||||
|  | ||||
| namespace OpenWifi { | ||||
|  | ||||
| @@ -48,42 +49,19 @@ namespace OpenWifi { | ||||
|         inline Poco::Logger & Logger() { return Logger_; } | ||||
|     }; | ||||
|  | ||||
|     class VenueRebooter: public Poco::Runnable { | ||||
|     class VenueRebooter: public Job { | ||||
|     public: | ||||
|         explicit VenueRebooter(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : | ||||
|                 VenueUUID_(VenueUUID), | ||||
|                 UI_(UI), | ||||
|                 When_(When), | ||||
|                 Logger_(L) | ||||
|         { | ||||
|         VenueRebooter(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||
|                 Job(JobID, name, parameters, when, UI, L) { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         inline std::string Start() { | ||||
|             JobId_ = MicroService::CreateUUID(); | ||||
|             Worker_.start(*this); | ||||
|             return JobId_; | ||||
|         } | ||||
|         inline virtual void run() final { | ||||
|  | ||||
|     private: | ||||
|         std::string                 VenueUUID_; | ||||
|         SecurityObjects::UserInfo   UI_; | ||||
|         uint64_t                    When_; | ||||
|         Poco::Logger                &Logger_; | ||||
|         Poco::Thread                Worker_; | ||||
|         std::string                 JobId_; | ||||
|         Poco::ThreadPool            Pool_{2,16,300}; | ||||
|  | ||||
|         inline Poco::Logger & Logger() { return Logger_; } | ||||
|  | ||||
|         inline void run() final { | ||||
|  | ||||
|             if(When_ && When_>OpenWifi::Now()) | ||||
|                 Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 ); | ||||
|             Utils::SetThreadName("venue-reboot"); | ||||
|  | ||||
|             WebSocketClientNotificationVenueRebootList_t        N; | ||||
|  | ||||
|             Logger().information(fmt::format("Job {} Starting.", JobId_)); | ||||
|             auto VenueUUID_ = Parameter(0); | ||||
|  | ||||
|             ProvObjects::Venue  Venue; | ||||
|             uint64_t rebooted_ = 0, failed_ = 0; | ||||
| @@ -95,7 +73,7 @@ namespace OpenWifi { | ||||
|                 }; | ||||
|  | ||||
|                 N.content.title = fmt::format("Rebooting {} devices.", Venue.info.name); | ||||
|                 N.content.jobId = JobId_; | ||||
|                 N.content.jobId = JobId(); | ||||
|  | ||||
|                 std::array<tState,MaxThreads> Tasks; | ||||
|  | ||||
| @@ -160,17 +138,18 @@ namespace OpenWifi { | ||||
|                 } | ||||
|  | ||||
|                 N.content.details = fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", | ||||
|                                                 JobId_, rebooted_ ,failed_); | ||||
|                                                 JobId(), rebooted_ ,failed_); | ||||
|  | ||||
|             } else { | ||||
|                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); | ||||
|                 Logger().warning(N.content.details); | ||||
|             } | ||||
|  | ||||
|             WebSocketClientNotificationVenueRebootCompletionToUser(UI_.email,N); | ||||
|             WebSocketClientNotificationVenueRebootCompletionToUser(UserInfo().email,N); | ||||
|             Logger().information(fmt::format("Job {} Completed: {} rebooted, {} failed to reboot.", | ||||
|                                              JobId_, rebooted_ ,failed_)); | ||||
|             delete this; | ||||
|                                              JobId(), rebooted_ ,failed_)); | ||||
|             Utils::SetThreadName("free"); | ||||
|             Complete(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "APConfig.h" | ||||
| #include "sdks/SDK_gw.h" | ||||
| #include "sdks/SDK_fms.h" | ||||
| #include "JobController.h" | ||||
|  | ||||
| namespace OpenWifi { | ||||
|     class VenueDeviceUpgrade : public Poco::Runnable { | ||||
| @@ -69,43 +70,20 @@ namespace OpenWifi { | ||||
|         inline Poco::Logger & Logger() { return Logger_; } | ||||
|     }; | ||||
|  | ||||
|     class VenueUpgrade: public Poco::Runnable { | ||||
|     class VenueUpgrade: public Job { | ||||
|     public: | ||||
|         explicit VenueUpgrade(const std::string & VenueUUID, const SecurityObjects::UserInfo &UI, uint64_t When, Poco::Logger &L) : | ||||
|                 VenueUUID_(VenueUUID), | ||||
|                 UI_(UI), | ||||
|                 When_(When), | ||||
|                 Logger_(L) | ||||
|         { | ||||
|         VenueUpgrade(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||
|                 Job(JobID, name, parameters, when, UI, L) { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         inline std::string Start() { | ||||
|             JobId_ = MicroService::CreateUUID(); | ||||
|             Worker_.start(*this); | ||||
|             return JobId_; | ||||
|         } | ||||
|         inline virtual void run() final { | ||||
|  | ||||
|     private: | ||||
|         std::string                 VenueUUID_; | ||||
|         SecurityObjects::UserInfo   UI_; | ||||
|         uint64_t                    When_; | ||||
|         Poco::Logger                &Logger_; | ||||
|         Poco::Thread                Worker_; | ||||
|         std::string                 JobId_; | ||||
|         Poco::ThreadPool            Pool_{2,16,300}; | ||||
|  | ||||
|         inline Poco::Logger & Logger() { return Logger_; } | ||||
|  | ||||
|         inline void run() final { | ||||
|  | ||||
|             if(When_ && When_>OpenWifi::Now()) | ||||
|                 Poco::Thread::trySleep( (long) (When_ - OpenWifi::Now()) * 1000 ); | ||||
|             Utils::SetThreadName("venue-upgr"); | ||||
|             auto VenueUUID_ = Parameter(0); | ||||
|  | ||||
|             WebSocketClientNotificationVenueRebootList_t        N; | ||||
|  | ||||
|             Logger().information(fmt::format("Job {} Starting.", JobId_)); | ||||
|  | ||||
|             ProvObjects::Venue  Venue; | ||||
|             uint64_t upgraded_ = 0, failed_ = 0; | ||||
|             if(StorageService()->VenueDB().GetRecord("id",VenueUUID_,Venue)) { | ||||
| @@ -116,7 +94,7 @@ namespace OpenWifi { | ||||
|                 }; | ||||
|  | ||||
|                 N.content.title = fmt::format("Upgrading {} devices.", Venue.info.name); | ||||
|                 N.content.jobId = JobId_; | ||||
|                 N.content.jobId = JobId(); | ||||
|  | ||||
|                 std::array<tState,MaxThreads> Tasks; | ||||
|                 ProvObjects::DeviceRules    Rules; | ||||
| @@ -184,17 +162,19 @@ namespace OpenWifi { | ||||
|                 } | ||||
|  | ||||
|                 N.content.details = fmt::format("Job {} Completed: {} upgraded, {} failed to upgrade.", | ||||
|                                                 JobId_, upgraded_ ,failed_); | ||||
|                                                 JobId(), upgraded_ ,failed_); | ||||
|  | ||||
|             } else { | ||||
|                 N.content.details = fmt::format("Venue {} no longer exists.",VenueUUID_); | ||||
|                 Logger().warning(N.content.details); | ||||
|             } | ||||
|  | ||||
|             WebSocketClientNotificationVenueRebootCompletionToUser(UI_.email,N); | ||||
|             WebSocketClientNotificationVenueRebootCompletionToUser(UserInfo().email,N); | ||||
|             Logger().information(fmt::format("Job {} Completed: {} upgraded, {} failed to upgrade.", | ||||
|                                              JobId_, upgraded_ ,failed_)); | ||||
|             delete this; | ||||
|                                              JobId(), upgraded_ ,failed_)); | ||||
|             Utils::SetThreadName("free"); | ||||
|  | ||||
|             Complete(); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| @@ -13,10 +13,10 @@ | ||||
|  | ||||
| namespace OpenWifi { | ||||
|  | ||||
|     static const std::string GitUCentralJSONSchemaFile{ | ||||
|             "https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"}; | ||||
| static const std::string GitUCentralJSONSchemaFile{ | ||||
| 		"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"}; | ||||
|  | ||||
|     static json DefaultUCentralSchema = R"( | ||||
| static json DefaultUCentralSchema = R"( | ||||
|  | ||||
| { | ||||
| 	"$id": "https://openwrt.org/ucentral.schema.json", | ||||
| @@ -2623,16 +2623,17 @@ namespace OpenWifi { | ||||
|     void ConfigurationValidator::Init() { | ||||
|         if(Initialized_) | ||||
|             return; | ||||
|         std::string GitSchema; | ||||
|  | ||||
|         if(MicroService::instance().ConfigGetBool("ucentral.datamodel.internal",true)) { | ||||
|             RootSchema_ = DefaultUCentralSchema; | ||||
|             Logger().information("Using uCentral validation from built-in default."); | ||||
|             return; | ||||
|         } | ||||
|         std::string GitSchema; | ||||
| 		if(MicroService::instance().ConfigGetBool("ucentral.datamodel.internal",true)) { | ||||
| 			RootSchema_ = DefaultUCentralSchema; | ||||
| 			Logger().information("Using uCentral validation from built-in default."); | ||||
| 			Initialized_ = Working_ = true; | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
|         try { | ||||
|             auto GitURI = MicroService::instance().ConfigGetString("ucentral.datamodel.uri",GitUCentralJSONSchemaFile); | ||||
| 			auto GitURI = MicroService::instance().ConfigGetString("ucentral.datamodel.uri",GitUCentralJSONSchemaFile); | ||||
|             if(Utils::wgets(GitURI, GitSchema)) { | ||||
|                 RootSchema_ = json::parse(GitSchema); | ||||
|                 Logger().information("Using uCentral validation schema from GIT."); | ||||
| @@ -2699,6 +2700,17 @@ namespace OpenWifi { | ||||
|         return IsCIDRv4(value) || IsCIDRv6(value); | ||||
|     } | ||||
|  | ||||
|     static inline bool IsPortRangeIsValid(const std::string &r) { | ||||
|         const auto ports = Poco::StringTokenizer("-",r,Poco::StringTokenizer::TOK_TRIM); | ||||
|  | ||||
|         for(const auto &port:ports) { | ||||
|             uint32_t port_num = std::stoul(port); | ||||
|             if(port_num==0 || port_num>65535) | ||||
|                 return false; | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     void ConfigurationValidator::my_format_checker(const std::string &format, const std::string &value) | ||||
|     { | ||||
|         static const std::regex host_regex{"^(?=.{1,254}$)((?=[a-z0-9-]{1,63}\\.)(xn--+)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}$"}; | ||||
| @@ -2749,6 +2761,14 @@ namespace OpenWifi { | ||||
|             } catch (...) { | ||||
|             } | ||||
|             throw std::invalid_argument(value + " is not a valid URI: should be something like https://hello.world.com."); | ||||
|         } else if(format == "uc-portrange") { | ||||
|             try { | ||||
|                 if(IsPortRangeIsValid(value)) | ||||
|                     return; | ||||
|                 throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port."); | ||||
|             } catch (...) { | ||||
|             } | ||||
|             throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port."); | ||||
|         } else if(format == "ip") { | ||||
|             if (IsIP(value)) | ||||
|                 return; | ||||
|   | ||||
| @@ -643,6 +643,27 @@ namespace OpenWifi::RESTAPI_utils { | ||||
|  | ||||
| namespace OpenWifi::Utils { | ||||
|  | ||||
| 	inline void SetThreadName(const char *name) { | ||||
| #ifdef __linux__ | ||||
| 		Poco::Thread::current()->setName(name); | ||||
| 		pthread_setname_np(pthread_self(), name); | ||||
| #endif | ||||
| #ifdef __APPLE__ | ||||
| 	Poco::Thread::current()->setName(name); | ||||
| 	pthread_setname_np(name); | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| 	inline void SetThreadName(Poco::Thread &thr, const char *name) { | ||||
| #ifdef __linux__ | ||||
| 		thr.setName(name); | ||||
| 		pthread_setname_np(thr.tid(), name); | ||||
| #endif | ||||
| #ifdef __APPLE__ | ||||
| 		thr.setName(name); | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
|     enum MediaTypeEncodings { | ||||
|         PLAIN, | ||||
|         BINARY, | ||||
| @@ -1167,6 +1188,7 @@ namespace OpenWifi { | ||||
|     static const std::string uSERVICE_SUBCRIBER{ "owsub"}; | ||||
|     static const std::string uSERVICE_INSTALLER{ "owinst"}; | ||||
|     static const std::string uSERVICE_ANALYTICS{ "owanalytics"}; | ||||
| 	static const std::string uSERVICE_OWRRM{ "owrrm"}; | ||||
|  | ||||
| 	class ConfigurationEntry { | ||||
| 	  public: | ||||
| @@ -1315,7 +1337,7 @@ namespace OpenWifi { | ||||
| 		inline void Start(); | ||||
| 		inline void Stop(); | ||||
| 	  private: | ||||
| 		std::atomic_bool 	Running_ = false; | ||||
| 		mutable std::atomic_bool 	Running_ = false; | ||||
| 		Poco::Thread		Thread_; | ||||
| 	}; | ||||
|  | ||||
| @@ -1846,7 +1868,8 @@ namespace OpenWifi { | ||||
| 	            Request = &RequestIn; | ||||
| 	            Response = &ResponseIn; | ||||
|  | ||||
| 				Poco::Thread::current()->setName("WebServerThread_" + std::to_string(TransactionId_)); | ||||
| 				std::string th_name = "restsvr_" + std::to_string(TransactionId_); | ||||
| 				Utils::SetThreadName(th_name.c_str()); | ||||
|  | ||||
|                 if(Request->getContentLength()>0) { | ||||
|                     if(Request->getContentType().find("application/json")!=std::string::npos) { | ||||
| @@ -1895,36 +1918,32 @@ namespace OpenWifi { | ||||
| 	    [[nodiscard]] inline bool NeedAdditionalInfo() const { return QB_.AdditionalInfo; } | ||||
| 	    [[nodiscard]] inline const std::vector<std::string> & SelectedRecords() const { return QB_.Select; } | ||||
|  | ||||
| /*	    [[nodiscard]] inline const Poco::JSON::Object::Ptr ParseStream() { | ||||
| 	        return IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>(); | ||||
| 	    } | ||||
| */ | ||||
| 		inline static bool ParseBindings(const std::string & Request, const std::list<std::string> & EndPoints, BindingMap &bindings) { | ||||
| 			bindings.clear(); | ||||
| 			auto PathItems = Poco::StringTokenizer(Request, "/"); | ||||
|  | ||||
| 	    inline static bool ParseBindings(const std::string & Request, const std::list<std::string> & EndPoints, BindingMap &bindings) { | ||||
| 	        bindings.clear(); | ||||
| 	        std::vector<std::string> PathItems = Utils::Split(Request, '/'); | ||||
| 			for(const auto &EndPoint:EndPoints) { | ||||
| 				auto ParamItems = Poco::StringTokenizer(EndPoint, "/"); | ||||
| 				if (PathItems.count() != ParamItems.count()) | ||||
| 					continue; | ||||
|  | ||||
| 	        for(const auto &EndPoint:EndPoints) { | ||||
| 	            std::vector<std::string> ParamItems = Utils::Split(EndPoint, '/'); | ||||
| 	            if (PathItems.size() != ParamItems.size()) | ||||
| 	                continue; | ||||
|  | ||||
| 	            bool Matched = true; | ||||
| 	            for (size_t i = 0; i != PathItems.size() && Matched; i++) { | ||||
| 	                if (PathItems[i] != ParamItems[i]) { | ||||
| 	                    if (ParamItems[i][0] == '{') { | ||||
| 	                        auto ParamName = ParamItems[i].substr(1, ParamItems[i].size() - 2); | ||||
| 	                        bindings[Poco::toLower(ParamName)] = PathItems[i]; | ||||
| 	                    } else { | ||||
| 	                        Matched = false; | ||||
| 	                    } | ||||
| 	                } | ||||
| 	            } | ||||
| 	            if(Matched) | ||||
| 	                return true; | ||||
| 	        } | ||||
| 	        return false; | ||||
| 	    } | ||||
| 				bool Matched = true; | ||||
| 				for (size_t i = 0; i < PathItems.count(); i++) { | ||||
| 					if (PathItems[i] != ParamItems[i]) { | ||||
| 						if (ParamItems[i][0] == '{') { | ||||
| 							auto ParamName = ParamItems[i].substr(1, ParamItems[i].size() - 2); | ||||
| 							bindings[Poco::toLower(ParamName)] = PathItems[i]; | ||||
| 						} else { | ||||
| 							Matched = false; | ||||
| 							break; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 				if(Matched) | ||||
| 					return true; | ||||
| 			} | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 	    inline void PrintBindings() { | ||||
| 	        for (const auto &[key, value] : Bindings_) | ||||
| @@ -2582,7 +2601,7 @@ namespace OpenWifi { | ||||
|     private: | ||||
|         std::recursive_mutex  	Mutex_; | ||||
|         Poco::Thread        	Worker_; | ||||
|         std::atomic_bool    	Running_=false; | ||||
|         mutable std::atomic_bool    	Running_=false; | ||||
| 		Poco::NotificationQueue	Queue_; | ||||
|     }; | ||||
|  | ||||
| @@ -2608,7 +2627,7 @@ namespace OpenWifi { | ||||
| 	  private: | ||||
| 		std::recursive_mutex  	Mutex_; | ||||
|         Poco::Thread        	Worker_; | ||||
|         std::atomic_bool    	Running_=false; | ||||
|         mutable std::atomic_bool    	Running_=false; | ||||
|     }; | ||||
|  | ||||
| 	class KafkaDispatcher : public Poco::Runnable { | ||||
| @@ -2665,6 +2684,7 @@ namespace OpenWifi { | ||||
|  | ||||
| 		inline void run() override { | ||||
| 			Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); | ||||
| 			Utils::SetThreadName("kafka-dispatch"); | ||||
| 			while(Note && Running_) { | ||||
| 				auto Msg = dynamic_cast<KafkaMessage*>(Note.get()); | ||||
| 				if(Msg!= nullptr) { | ||||
| @@ -2690,7 +2710,7 @@ namespace OpenWifi { | ||||
| 		std::recursive_mutex  	Mutex_; | ||||
| 		Types::NotifyTable      Notifiers_; | ||||
| 		Poco::Thread        	Worker_; | ||||
| 		std::atomic_bool    	Running_=false; | ||||
| 		mutable std::atomic_bool    	Running_=false; | ||||
| 		uint64_t          		FunctionId_=1; | ||||
| 		Poco::NotificationQueue	Queue_; | ||||
| 	}; | ||||
| @@ -2885,6 +2905,7 @@ namespace OpenWifi { | ||||
|  | ||||
| 	            void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override | ||||
| 	            { | ||||
| 					Utils::SetThreadName("alb-request"); | ||||
| 					try { | ||||
| 						if((id_ % 100) == 0) { | ||||
| 							Logger_.debug(fmt::format("ALB-REQUEST({}): ALB Request {}.", | ||||
| @@ -2953,7 +2974,7 @@ namespace OpenWifi { | ||||
| 	    std::unique_ptr<Poco::Net::HTTPServer>   	Server_; | ||||
| 	    std::unique_ptr<Poco::Net::ServerSocket> 	Socket_; | ||||
| 	    int                                     	Port_ = 0; | ||||
| 	    std::atomic_bool                            Running_=false; | ||||
| 	    mutable std::atomic_bool                            Running_=false; | ||||
| 	}; | ||||
|  | ||||
| 	inline auto ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } | ||||
| @@ -2985,7 +3006,7 @@ namespace OpenWifi { | ||||
|  | ||||
| 	    inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) { | ||||
| 	        RESTAPIHandler::BindingMap Bindings; | ||||
| 			Poco::Thread::current()->setName(fmt::format("RESTAPI_ExtServer_{}",Id)); | ||||
| 			Utils::SetThreadName(fmt::format("rest_ext_{}",Id).c_str()); | ||||
| 	        return RESTAPI_ExtRouter(Path, Bindings, Logger(), Server_, Id); | ||||
| 	    } | ||||
|  | ||||
| @@ -3009,7 +3030,7 @@ namespace OpenWifi { | ||||
| 	    inline Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &Request) override { | ||||
| 			try { | ||||
| 				Poco::URI uri(Request.getURI()); | ||||
| 				Poco::Thread::current()->setName(fmt::format("ExtWebServer_{}",TransactionId_)); | ||||
| 				Utils::SetThreadName(fmt::format("rest_ext_{}",TransactionId_).c_str()); | ||||
| 				return RESTAPI_ExtServer()->CallServer(uri.getPath(), TransactionId_++); | ||||
| 			} catch (...) { | ||||
|  | ||||
| @@ -3118,7 +3139,7 @@ namespace OpenWifi { | ||||
|  | ||||
| 	    inline Poco::Net::HTTPRequestHandler *CallServer(const std::string &Path, uint64_t Id) { | ||||
| 	        RESTAPIHandler::BindingMap Bindings; | ||||
| 			Poco::Thread::current()->setName(fmt::format("RESTAPI_IntServer_{}",Id)); | ||||
| 			Utils::SetThreadName(fmt::format("rest_int_{}",Id).c_str()); | ||||
| 	        return RESTAPI_IntRouter(Path, Bindings, Logger(), Server_, Id); | ||||
| 	    } | ||||
| 	private: | ||||
| @@ -3527,7 +3548,9 @@ namespace OpenWifi { | ||||
|     void DaemonPostInitialization(Poco::Util::Application &self); | ||||
|  | ||||
| 	inline void MicroService::initialize(Poco::Util::Application &self) { | ||||
| 	    // add the default services | ||||
| 		// Utils::SetThreadName("microservice"); | ||||
|  | ||||
| 		// add the default services | ||||
|         LoadConfigurationFile(); | ||||
|         InitializeLoggingSystem(); | ||||
|  | ||||
| @@ -3922,6 +3945,7 @@ namespace OpenWifi { | ||||
|  | ||||
|     inline int MicroService::main([[maybe_unused]] const ArgVec &args) { | ||||
|  | ||||
| 		// Utils::SetThreadName("main"); | ||||
| 	    MyErrorHandler	ErrorHandler(*this); | ||||
| 	    Poco::ErrorHandler::set(&ErrorHandler); | ||||
|  | ||||
| @@ -4037,6 +4061,7 @@ namespace OpenWifi { | ||||
|  | ||||
|     inline void BusEventManager::run() { | ||||
|         Running_ = true; | ||||
| 		Utils::SetThreadName("BusEventManager"); | ||||
|         auto Msg = MicroService::instance().MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_JOIN); | ||||
|         KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,MicroService::instance().PrivateEndPoint(),Msg, false); | ||||
|         while(Running_) { | ||||
| @@ -4122,6 +4147,8 @@ namespace OpenWifi { | ||||
| 	} | ||||
|  | ||||
| 	inline void KafkaProducer::run() { | ||||
|  | ||||
| 		Utils::SetThreadName("KafkaProducer"); | ||||
| 	    cppkafka::Configuration Config({ | ||||
|             { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||
|             { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") } | ||||
| @@ -4160,6 +4187,8 @@ namespace OpenWifi { | ||||
| 	} | ||||
|  | ||||
| 	inline void KafkaConsumer::run() { | ||||
| 		Utils::SetThreadName("KafkaConsumer"); | ||||
|  | ||||
| 	    cppkafka::Configuration Config({ | ||||
| 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||
| 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }, | ||||
| @@ -4400,7 +4429,7 @@ namespace OpenWifi { | ||||
|                                                Path, | ||||
|                                                Poco::Net::HTTPMessage::HTTP_1_1); | ||||
|  | ||||
|                 Poco::Logger::get("REST-CALLER-GET").debug(fmt::format(" {}", URI.toString())); | ||||
|                 poco_debug(Poco::Logger::get("REST-CALLER-GET"),fmt::format(" {}", URI.toString())); | ||||
|  | ||||
|                 if(BearerToken.empty()) { | ||||
|                     Request.add("X-API-KEY", Svc.AccessKey); | ||||
| @@ -4458,7 +4487,7 @@ namespace OpenWifi { | ||||
|                 for (const auto &qp : QueryData_) | ||||
|                     URI.addQueryParameter(qp.first, qp.second); | ||||
|  | ||||
|                 Poco::Logger::get("REST-CALLER-PUT").debug(fmt::format("{}", URI.toString())); | ||||
|                 poco_debug(Poco::Logger::get("REST-CALLER-PUT"),fmt::format("{}", URI.toString())); | ||||
|  | ||||
|                 std::string Path(URI.getPathAndQuery()); | ||||
|  | ||||
| @@ -4537,7 +4566,7 @@ namespace OpenWifi { | ||||
|                 for (const auto &qp : QueryData_) | ||||
|                     URI.addQueryParameter(qp.first, qp.second); | ||||
|  | ||||
|                 Poco::Logger::get("REST-CALLER-POST").debug(fmt::format(" {}", URI.toString())); | ||||
|                 poco_debug(Poco::Logger::get("REST-CALLER-POST"),fmt::format(" {}", URI.toString())); | ||||
|  | ||||
|                 std::string Path(URI.getPathAndQuery()); | ||||
|  | ||||
| @@ -4613,7 +4642,7 @@ namespace OpenWifi { | ||||
|                 for (const auto &qp : QueryData_) | ||||
|                     URI.addQueryParameter(qp.first, qp.second); | ||||
|  | ||||
|                 Poco::Logger::get("REST-CALLER-DELETE").debug(fmt::format(" {}", URI.toString())); | ||||
|                 poco_debug(Poco::Logger::get("REST-CALLER-DELETE"),fmt::format(" {}", URI.toString())); | ||||
|  | ||||
|                 std::string Path(URI.getPathAndQuery()); | ||||
|  | ||||
| @@ -4818,7 +4847,7 @@ namespace OpenWifi { | ||||
| 		[[nodiscard]] bool SendToUser(const std::string &userName, const std::string &Payload); | ||||
| 		void SendToAll(const std::string &Payload); | ||||
|     private: | ||||
|         std::atomic_bool Running_ = false; | ||||
|         mutable std::atomic_bool Running_ = false; | ||||
|         Poco::Thread Thr_; | ||||
|         // std::unique_ptr<MyParallelSocketReactor> ReactorPool_; | ||||
| 		Poco::Net::SocketReactor					Reactor_; | ||||
| @@ -4915,6 +4944,7 @@ namespace OpenWifi { | ||||
|  | ||||
|     inline void WebSocketClientServer::run() { | ||||
|         Running_ = true ; | ||||
| 		Utils::SetThreadName("ws:clnt-svr"); | ||||
|         while(Running_) { | ||||
|             Poco::Thread::trySleep(2000); | ||||
|  | ||||
| @@ -4962,8 +4992,12 @@ namespace OpenWifi { | ||||
|  | ||||
|         for(const auto &client:Clients_) { | ||||
|             if(client.second.second == UserName) { | ||||
|                 if(client.second.first->Send(Payload)) | ||||
|                     Sent++; | ||||
| 				try { | ||||
| 					if (client.second.first->Send(Payload)) | ||||
| 						Sent++; | ||||
| 				} catch (...) { | ||||
| 					return false; | ||||
| 				} | ||||
|             } | ||||
|         } | ||||
|         return Sent>0; | ||||
| @@ -4985,70 +5019,70 @@ namespace OpenWifi { | ||||
|         int flags; | ||||
|         int n; | ||||
|         bool Done=false; | ||||
|         Poco::Buffer<char>			IncomingFrame(0); | ||||
|         n = WS_->receiveFrame(IncomingFrame, flags); | ||||
|         auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; | ||||
| 		try { | ||||
| 			Poco::Buffer<char> IncomingFrame(0); | ||||
| 			n = WS_->receiveFrame(IncomingFrame, flags); | ||||
| 			auto Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK; | ||||
|  | ||||
|         if(n==0) { | ||||
|             return delete this; | ||||
|         } | ||||
| 			if (n == 0) { | ||||
| 				return delete this; | ||||
| 			} | ||||
|  | ||||
|         switch(Op) { | ||||
|             case Poco::Net::WebSocket::FRAME_OP_PING: { | ||||
|                 WS_->sendFrame("", 0, | ||||
|                                (int)Poco::Net::WebSocket::FRAME_OP_PONG | | ||||
|                                (int)Poco::Net::WebSocket::FRAME_FLAG_FIN); | ||||
|             } | ||||
|                 break; | ||||
|             case Poco::Net::WebSocket::FRAME_OP_PONG: { | ||||
|             } | ||||
|                 break; | ||||
|             case Poco::Net::WebSocket::FRAME_OP_CLOSE: { | ||||
|                 Logger().warning(Poco::format("CLOSE(%s): Client is closing its connection.",Id_)); | ||||
|                 Done=true; | ||||
|             } | ||||
|                 break; | ||||
|             case Poco::Net::WebSocket::FRAME_OP_TEXT: { | ||||
|                 IncomingFrame.append(0); | ||||
|                 if(!Authenticated_) { | ||||
|                     std::string Frame{IncomingFrame.begin()}; | ||||
|                     auto Tokens = Utils::Split(Frame,':'); | ||||
|                     bool Expired = false, Contacted = false; | ||||
|                     if(Tokens.size()==2 && AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired, Contacted)) { | ||||
|                         Authenticated_=true; | ||||
|                         std::string S{"Welcome! Bienvenue! Bienvenidos!"}; | ||||
|                         WS_->sendFrame(S.c_str(),S.size()); | ||||
|                         WebSocketClientServer()->SetUser(Id_,UserInfo_.userinfo.email); | ||||
|                     } else { | ||||
|                         std::string S{"Invalid token. Closing connection."}; | ||||
|                         WS_->sendFrame(S.c_str(),S.size()); | ||||
|                         Done=true; | ||||
|                     } | ||||
| 			switch (Op) { | ||||
| 			case Poco::Net::WebSocket::FRAME_OP_PING: { | ||||
| 				WS_->sendFrame("", 0, | ||||
| 							   (int)Poco::Net::WebSocket::FRAME_OP_PONG | | ||||
| 								   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN); | ||||
| 			} break; | ||||
| 			case Poco::Net::WebSocket::FRAME_OP_PONG: { | ||||
| 			} break; | ||||
| 			case Poco::Net::WebSocket::FRAME_OP_CLOSE: { | ||||
| 				Logger().warning(Poco::format("CLOSE(%s): Client is closing its connection.", Id_)); | ||||
| 				Done = true; | ||||
| 			} break; | ||||
| 			case Poco::Net::WebSocket::FRAME_OP_TEXT: { | ||||
| 				IncomingFrame.append(0); | ||||
| 				if (!Authenticated_) { | ||||
| 					std::string Frame{IncomingFrame.begin()}; | ||||
| 					auto Tokens = Utils::Split(Frame, ':'); | ||||
| 					bool Expired = false, Contacted = false; | ||||
| 					if (Tokens.size() == 2 && | ||||
| 						AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired, Contacted)) { | ||||
| 						Authenticated_ = true; | ||||
| 						std::string S{"Welcome! Bienvenue! Bienvenidos!"}; | ||||
| 						WS_->sendFrame(S.c_str(), S.size()); | ||||
| 						WebSocketClientServer()->SetUser(Id_, UserInfo_.userinfo.email); | ||||
| 					} else { | ||||
| 						std::string S{"Invalid token. Closing connection."}; | ||||
| 						WS_->sendFrame(S.c_str(), S.size()); | ||||
| 						Done = true; | ||||
| 					} | ||||
|  | ||||
|                 } else { | ||||
|                     try { | ||||
|                         Poco::JSON::Parser P; | ||||
|                         auto Obj = P.parse(IncomingFrame.begin()) | ||||
|                                 .extract<Poco::JSON::Object::Ptr>(); | ||||
|                         std::string Answer; | ||||
|                         if(Processor_!= nullptr) | ||||
|                             Processor_->Processor(Obj, Answer, Done); | ||||
|                         if (!Answer.empty()) | ||||
|                             WS_->sendFrame(Answer.c_str(), (int) Answer.size()); | ||||
|                         else { | ||||
|                             WS_->sendFrame("{}", 2); | ||||
|                         } | ||||
|                     } catch (const Poco::JSON::JSONException & E) { | ||||
|                         Logger().log(E); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|                 break; | ||||
|             default: | ||||
|             { | ||||
|  | ||||
|             } | ||||
|         } | ||||
| 				} else { | ||||
| 					try { | ||||
| 						Poco::JSON::Parser P; | ||||
| 						auto Obj = | ||||
| 							P.parse(IncomingFrame.begin()).extract<Poco::JSON::Object::Ptr>(); | ||||
| 						std::string Answer; | ||||
| 						if (Processor_ != nullptr) | ||||
| 							Processor_->Processor(Obj, Answer, Done); | ||||
| 						if (!Answer.empty()) | ||||
| 							WS_->sendFrame(Answer.c_str(), (int)Answer.size()); | ||||
| 						else { | ||||
| 							WS_->sendFrame("{}", 2); | ||||
| 						} | ||||
| 					} catch (const Poco::JSON::JSONException &E) { | ||||
| 						Logger().log(E); | ||||
| 						Done=true; | ||||
| 					} | ||||
| 				} | ||||
| 			} break; | ||||
| 			default: { | ||||
| 			} | ||||
| 			} | ||||
| 		} catch (...) { | ||||
| 			Done=true; | ||||
| 		} | ||||
|  | ||||
|         if(Done) { | ||||
|             delete this; | ||||
|   | ||||
| @@ -133,6 +133,37 @@ namespace ORM { | ||||
|         return R; | ||||
|     } | ||||
|  | ||||
|     inline std::string WHERE_AND_(std::string Result) { | ||||
|         return Result; | ||||
|     } | ||||
|  | ||||
|     template <typename T, typename... Args> std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value, Args... args) { | ||||
|         if constexpr(std::is_same_v<T,std::string>) | ||||
|         { | ||||
|             if(!Value.empty()) { | ||||
|                 if(!Result.empty()) | ||||
|                     Result += " and "; | ||||
|                 Result += fieldName; | ||||
|                 Result += '='; | ||||
|                 Result += "'"; | ||||
|                 Result += Escape(Value); | ||||
|                 Result += "'"; | ||||
|             } | ||||
|         } else { | ||||
|             if(!Result.empty()) | ||||
|                 Result += " and "; | ||||
|             Result += fieldName ; | ||||
|             Result += '='; | ||||
|             Result += std::to_string(Value); | ||||
|         } | ||||
|         return WHERE_AND_(Result,args...); | ||||
|     } | ||||
|  | ||||
|     template <typename... Args> std::string WHERE_AND(Args... args) { | ||||
|         std::string Result; | ||||
|         return WHERE_AND_(Result, args...); | ||||
|     } | ||||
|  | ||||
|     enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE }; | ||||
|     enum SqlBinaryOp { AND = 0 , OR }; | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <string> | ||||
| #include <cstring> | ||||
| #include "Poco/String.h" | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| @@ -428,6 +429,7 @@ namespace OpenWifi::uCentralProtocol { | ||||
| 	static const char *RADIUSACCT = "acct"; | ||||
| 	static const char *RADIUSAUTH = "auth"; | ||||
| 	static const char *RADIUSDST = "dst"; | ||||
| 	static const char *IES = "ies"; | ||||
| 	} | ||||
|  | ||||
| namespace OpenWifi::uCentralProtocol::Events { | ||||
| @@ -457,25 +459,28 @@ namespace OpenWifi::uCentralProtocol::Events { | ||||
| 		ET_TELEMETRY | ||||
| 	}; | ||||
|  | ||||
| 	inline static EVENT_MSG EventFromString(const std::string & Method) { | ||||
|         static std::vector<std::pair<const char *,EVENT_MSG>>   Values{ | ||||
|                 { CFGPENDING , ET_CFGPENDING }, | ||||
|                 { CONNECT, ET_CONNECT }, | ||||
|                 { CRASHLOG, ET_CRASHLOG }, | ||||
|                 { DEVICEUPDATE, ET_DEVICEUPDATE }, | ||||
|                 { HEALTHCHECK, ET_HEALTHCHECK }, | ||||
|                 { LOG, ET_LOG }, | ||||
|                 { PING, ET_PING }, | ||||
|                 { RECOVERY, ET_RECOVERY }, | ||||
|                 { STATE, ET_STATE }, | ||||
|                 { TELEMETRY, ET_TELEMETRY } | ||||
|         }; | ||||
|  | ||||
|         std::string L = Poco::toLower(Method); | ||||
|         auto hint = std::find_if(cbegin(Values),cend(Values),[&](const std::pair<const char *,EVENT_MSG> &v) ->bool { return strcmp(v.first,L.c_str())==0; }); | ||||
|         if(hint == cend(Values)) | ||||
|             return ET_UNKNOWN; | ||||
|         return hint->second; | ||||
| 	inline EVENT_MSG EventFromString(const std::string & Method) { | ||||
| 		if(strcmp(STATE,Method.c_str())==0) | ||||
| 			return ET_STATE; | ||||
| 		else if(strcmp(HEALTHCHECK,Method.c_str())==0) | ||||
| 			return ET_HEALTHCHECK; | ||||
| 		else if(strcmp(CONNECT,Method.c_str())==0) | ||||
| 			return ET_CONNECT; | ||||
| 		else if(strcmp(CFGPENDING,Method.c_str())==0) | ||||
| 			return ET_CFGPENDING; | ||||
| 		else if(strcmp(CRASHLOG,Method.c_str())==0) | ||||
| 			return ET_CRASHLOG; | ||||
| 		else if(strcmp(DEVICEUPDATE,Method.c_str())==0) | ||||
| 			return ET_DEVICEUPDATE; | ||||
| 		else if(strcmp(LOG,Method.c_str())==0) | ||||
| 			return ET_LOG; | ||||
| 		else if(strcmp(PING,Method.c_str())==0) | ||||
| 			return ET_PING; | ||||
| 		else if(strcmp(RECOVERY,Method.c_str())==0) | ||||
| 			return ET_RECOVERY; | ||||
| 		else if(strcmp(TELEMETRY,Method.c_str())==0) | ||||
| 			return ET_TELEMETRY; | ||||
| 		return ET_UNKNOWN; | ||||
| 	}; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										13
									
								
								src/ow_version.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/ow_version.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| // | ||||
| // Created by stephane bourque on 2021-12-06. | ||||
| // | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <string> | ||||
|  | ||||
| namespace OW_VERSION { | ||||
|     inline static const std::string VERSION{"2.6.0"}; | ||||
|     inline static const std::string BUILD{"128"}; | ||||
|     inline static const std::string HASH{"3b0f2a0"}; | ||||
| } | ||||
| @@ -96,40 +96,42 @@ namespace OpenWifi { | ||||
|     void EntityDB::AddVenues(Poco::JSON::Object &Tree, const std::string & Node) { | ||||
|         ProvObjects::Venue E; | ||||
|         // std::cout << "Adding venue:" << Node << std::endl; | ||||
|         StorageService()->VenueDB().GetRecord("id",Node,E); | ||||
|         Poco::JSON::Array   Venues; | ||||
|         for(const auto &i:E.children) { | ||||
|             Poco::JSON::Object Venue; | ||||
|             AddVenues(Venue, i); | ||||
|             Venues.add(Venue); | ||||
|         if(StorageService()->VenueDB().GetRecord("id",Node,E)) { | ||||
|             Poco::JSON::Array Venues; | ||||
|             for (const auto &i: E.children) { | ||||
|                 Poco::JSON::Object Venue; | ||||
|                 AddVenues(Venue, i); | ||||
|                 Venues.add(Venue); | ||||
|             } | ||||
|             Tree.set("type", "venue"); | ||||
|             Tree.set("name", E.info.name); | ||||
|             Tree.set("uuid", E.info.id); | ||||
|             Tree.set("children", Venues); | ||||
|         } | ||||
|         Tree.set("type","venue"); | ||||
|         Tree.set("name",E.info.name); | ||||
|         Tree.set("uuid",E.info.id); | ||||
|         Tree.set("children",Venues); | ||||
|     } | ||||
|  | ||||
|     void EntityDB::BuildTree(Poco::JSON::Object &Tree, const std::string & Node) { | ||||
|         ProvObjects::Entity E; | ||||
|         // std::cout << "Adding node:" << Node << std::endl; | ||||
|         StorageService()->EntityDB().GetRecord("id",Node,E); | ||||
|         Poco::JSON::Array   Children; | ||||
|         for(const auto &i:E.children) { | ||||
|             Poco::JSON::Object  Child; | ||||
|             BuildTree(Child,i); | ||||
|             Children.add(Child); | ||||
|         if(StorageService()->EntityDB().GetRecord("id",Node,E)) { | ||||
|             Poco::JSON::Array Children; | ||||
|             for (const auto &i: E.children) { | ||||
|                 Poco::JSON::Object Child; | ||||
|                 BuildTree(Child, i); | ||||
|                 Children.add(Child); | ||||
|             } | ||||
|             Poco::JSON::Array Venues; | ||||
|             for (const auto &i: E.venues) { | ||||
|                 Poco::JSON::Object Venue; | ||||
|                 AddVenues(Venue, i); | ||||
|                 Venues.add(Venue); | ||||
|             } | ||||
|             Tree.set("type", "entity"); | ||||
|             Tree.set("name", E.info.name); | ||||
|             Tree.set("uuid", E.info.id); | ||||
|             Tree.set("children", Children); | ||||
|             Tree.set("venues", Venues); | ||||
|         } | ||||
|         Poco::JSON::Array   Venues; | ||||
|         for(const auto &i:E.venues) { | ||||
|             Poco::JSON::Object Venue; | ||||
|             AddVenues(Venue, i); | ||||
|             Venues.add(Venue); | ||||
|         } | ||||
|         Tree.set("type","entity"); | ||||
|         Tree.set("name",E.info.name); | ||||
|         Tree.set("uuid",E.info.id); | ||||
|         Tree.set("children",Children); | ||||
|         Tree.set("venues", Venues); | ||||
|     } | ||||
|  | ||||
|     void EntityDB::ImportVenues(const Poco::JSON::Object::Ptr &O, const std::string &Parent) { | ||||
|   | ||||
| @@ -1,51 +0,0 @@ | ||||
| // | ||||
| // Created by stephane bourque on 2021-10-28. | ||||
| // | ||||
|  | ||||
| #include "storage_jobs.h" | ||||
| #include "framework/OpenWifiTypes.h" | ||||
| #include "framework/MicroService.h" | ||||
|  | ||||
| namespace OpenWifi { | ||||
|  | ||||
|     static  ORM::FieldVec    JobDB_Fields{ | ||||
|         // object info | ||||
|         ORM::Field{"id",64, true}, | ||||
|         ORM::Field{"name",ORM::FieldType::FT_TEXT}, | ||||
|         ORM::Field{"description",ORM::FieldType::FT_TEXT}, | ||||
|         ORM::Field{"type",ORM::FieldType::FT_TEXT}, | ||||
|         ORM::Field{"progress",ORM::FieldType::FT_BIGINT}, | ||||
|         ORM::Field{"total",ORM::FieldType::FT_BIGINT}, | ||||
|         ORM::Field{"parameters",ORM::FieldType::FT_TEXT} | ||||
|     }; | ||||
|  | ||||
|     static  ORM::IndexVec    JobDB_Indexes{ | ||||
|         { std::string("job_name_index"), | ||||
|           ORM::IndexEntryVec{ | ||||
|             {std::string("name"), | ||||
|              ORM::Indextype::ASC} } } | ||||
|     }; | ||||
|  | ||||
|     JobDB::JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : | ||||
|     DB(T, "jobs", JobDB_Fields, JobDB_Indexes, P, L, "job") {} | ||||
| } | ||||
|  | ||||
| template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(const OpenWifi::JobDBRecordType &In, OpenWifi::JobRecord &Out) { | ||||
|     Out.id = In.get<0>(); | ||||
|     Out.name = In.get<1>(); | ||||
|     Out.description = In.get<2>(); | ||||
|     Out.type = In.get<3>(); | ||||
|     Out.progress = In.get<4>(); | ||||
|     Out.total = In.get<5>(); | ||||
|     Out.parameters = OpenWifi::RESTAPI_utils::to_array_of_array_of_object<OpenWifi::Job::Parameter>(In.get<3>()); | ||||
| } | ||||
|  | ||||
| template<> void ORM::DB<OpenWifi::JobDBRecordType, OpenWifi::JobRecord>::Convert(const OpenWifi::JobRecord &In, OpenWifi::JobDBRecordType &Out) { | ||||
|     Out.set<0>(In.id); | ||||
|     Out.set<1>(In.name); | ||||
|     Out.set<2>(In.description); | ||||
|     Out.set<3>(In.type); | ||||
|     Out.set<4>(In.progress); | ||||
|     Out.set<5>(In.total); | ||||
|     Out.set<6>(OpenWifi::RESTAPI_utils::to_string(In.parameters)); | ||||
| } | ||||
| @@ -1,40 +0,0 @@ | ||||
| // | ||||
| // Created by stephane bourque on 2021-10-28. | ||||
| // | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "framework/orm.h" | ||||
| #include "JobController.h" | ||||
|  | ||||
| namespace OpenWifi { | ||||
|     typedef Poco::Tuple< | ||||
|         std::string, | ||||
|         std::string, | ||||
|         std::string, | ||||
|         std::string, | ||||
|         uint64_t, | ||||
|         uint64_t, | ||||
|         std::string | ||||
|     > JobDBRecordType; | ||||
|  | ||||
|     struct JobRecord { | ||||
|         Types::UUID_t       id; | ||||
|         std::string         name; | ||||
|         std::string         description; | ||||
|         std::string         type; | ||||
|         uint64_t            progress; | ||||
|         uint64_t            total; | ||||
|         Job::ParametersVec  parameters; | ||||
|  | ||||
|         // void from_string(const std::string &S); | ||||
|         // std::string to_string() const; | ||||
|     }; | ||||
|  | ||||
|     class JobDB : public ORM::DB<JobDBRecordType, JobRecord> { | ||||
|     public: | ||||
|         JobDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); | ||||
|         virtual ~JobDB() {}; | ||||
|     private: | ||||
|     }; | ||||
| } | ||||
| @@ -499,6 +499,14 @@ listvenues() { | ||||
|     jq < ${result_file} | ||||
| } | ||||
|  | ||||
| getvenuedevices() { | ||||
|     curl    ${FLAGS} -X GET "https://${OWPROV}/api/v1/venue/$1?getDevices=true&getChildren=true" \ | ||||
|         -H "Content-Type: application/json" \ | ||||
|         -H "Authorization: Bearer ${token}" \ | ||||
|         -H "Accept: application/json" > ${result_file} | ||||
|     jq < ${result_file} | ||||
| } | ||||
|  | ||||
| shopt -s nocasematch | ||||
| case "$1" in | ||||
|     "login") login; echo "You are logged in..."  ; logout ;; | ||||
| @@ -546,6 +554,7 @@ case "$1" in | ||||
|     "getsignup") login; getsignup $2; logout;; | ||||
|     "getsubdevs") login; getsubdevs $2; logout;; | ||||
|     "listvenues") login; listvenues $2; logout;; | ||||
|     "getvenuedevices") login; getvenuedevices $2; logout;; | ||||
|     *) help ;; | ||||
| esac | ||||
|  | ||||
|   | ||||
							
								
								
									
										24
									
								
								test_scripts/update_objects.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								test_scripts/update_objects.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| dst=~/Desktop/Dropbox/clion/last_obj_update | ||||
| src=~/Desktop/Dropbox/clion | ||||
| rm -rf ${dst} | ||||
| mkdir ${dst} | ||||
|  | ||||
| cp ${src}/wlan-cloud-ucentralgw/src/RESTObjects/RESTAPI_GWobjects.* ${dst}/. | ||||
| cp ${src}/wlan-cloud-ucentralsec/src/RESTObjects/RESTAPI_SecurityObjects.* ${dst}/. | ||||
| cp ${src}/wlan-cloud-ucentralfms/src/RESTObjects/RESTAPI_FMSObjects.* ${dst}/. | ||||
| cp ${src}/wlan-cloud-prov/src/RESTObjects/RESTAPI_ProvObjects.* ${dst}/. | ||||
| cp ${src}/wlan-cloud-analytics/src/RESTObjects/RESTAPI_AnalyticsObjects.* ${dst}/. | ||||
| cp ${src}/wlan-cloud-certportal/src/RESTObjects/RESTAPI_CertObjects.* ${dst}/. | ||||
| cp ${src}/wlan-cloud-userportal/src/RESTObjects/RESTAPI_SubObjects.* ${dst}/. | ||||
| cp ${src}/ucentralsim/src/RESTObjects/RESTAPI_OWLSobjects.* ${dst}/. | ||||
|  | ||||
| cp ${dst}/*.* ${src}/wlan-cloud-ucentralgw/src/RESTObjects/. | ||||
| cp ${dst}/*.* ${src}/wlan-cloud-ucentralsec/src/RESTObjects/. | ||||
| cp ${dst}/*.* ${src}/wlan-cloud-ucentralfms/src/RESTObjects/. | ||||
| cp ${dst}/*.* ${src}/wlan-cloud-prov/src/RESTObjects/. | ||||
| cp ${dst}/*.* ${src}/wlan-cloud-analytics/src/RESTObjects/. | ||||
| cp ${dst}/*.* ${src}/wlan-cloud-certportal/src/RESTObjects/. | ||||
| cp ${dst}/*.* ${src}/wlan-cloud-userportal/src/RESTObjects/. | ||||
| cp ${dst}/*.* ${src}/ucentralsim/src/RESTObjects/. | ||||
		Reference in New Issue
	
	Block a user