mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
				synced 2025-11-03 20:27:45 +00:00 
			
		
		
		
	Compare commits
	
		
			46 Commits
		
	
	
		
			v2.6.0-RC1
			...
			release/v2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					830750f857 | ||
| 
						 | 
					f8d3079f44 | ||
| 
						 | 
					81cec762f7 | ||
| 
						 | 
					a430ad7e71 | ||
| 
						 | 
					d1c13ad2dd | ||
| 
						 | 
					b837e41569 | ||
| 
						 | 
					5e39987e36 | ||
| 
						 | 
					890eb7311a | ||
| 
						 | 
					fc509adf01 | ||
| 
						 | 
					f43198f874 | ||
| 
						 | 
					767331f575 | ||
| 
						 | 
					d26ef6eeba | ||
| 
						 | 
					8c672f058f | ||
| 
						 | 
					3134947b57 | ||
| 
						 | 
					448563ab06 | ||
| 
						 | 
					2a22a35e58 | ||
| 
						 | 
					8e8656a6ae | ||
| 
						 | 
					e745d4efe7 | ||
| 
						 | 
					701e0b50ff | ||
| 
						 | 
					df082a969e | ||
| 
						 | 
					8863d2ecc9 | ||
| 
						 | 
					5e1937ec4f | ||
| 
						 | 
					e679dc7458 | ||
| 
						 | 
					7e1a962b57 | ||
| 
						 | 
					8ad2e12f12 | ||
| 
						 | 
					23d16e619a | ||
| 
						 | 
					760cad9a14 | ||
| 
						 | 
					94997a1f9f | ||
| 
						 | 
					9060fef03d | ||
| 
						 | 
					2f8eb90c5a | ||
| 
						 | 
					c0d0435efa | ||
| 
						 | 
					6942de0475 | ||
| 
						 | 
					cce2528ec4 | ||
| 
						 | 
					3be0fd45d9 | ||
| 
						 | 
					8b1a80ce09 | ||
| 
						 | 
					5e12f00558 | ||
| 
						 | 
					1d534cb974 | ||
| 
						 | 
					a7e9c96f8d | ||
| 
						 | 
					cb3f7a0872 | ||
| 
						 | 
					6ad434c02f | ||
| 
						 | 
					62e3ada15c | ||
| 
						 | 
					2beef2daba | ||
| 
						 | 
					4b131465fb | ||
| 
						 | 
					cafc243e55 | ||
| 
						 | 
					5c44134f9d | ||
| 
						 | 
					8ed86d3582 | 
							
								
								
									
										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/owsec/$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/owsec/$PR_BRANCH_TAG"
 | 
			
		||||
          else
 | 
			
		||||
            echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image"
 | 
			
		||||
          fi
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@ if [ "$SELFSIGNED_CERTS" = 'true' ]; then
 | 
			
		||||
    update-ca-certificates
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWSEC_CONFIG"/owsec.properties ]]; then
 | 
			
		||||
if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
 | 
			
		||||
  RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWSEC_ROOT/certs/restapi-ca.pem"} \
 | 
			
		||||
  RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16001"} \
 | 
			
		||||
  RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWSEC_ROOT/certs/restapi-cert.pem"} \
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@ fullnameOverride: ""
 | 
			
		||||
images:
 | 
			
		||||
  owsec:
 | 
			
		||||
    repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec
 | 
			
		||||
    tag: v2.6.0-RC1
 | 
			
		||||
    tag: v2.6.0
 | 
			
		||||
    pullPolicy: Always
 | 
			
		||||
#    regcred:
 | 
			
		||||
#      registry: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ namespace OpenWifi {
 | 
			
		||||
 | 
			
		||||
    void ActionLinkManager::run() {
 | 
			
		||||
        Running_ = true ;
 | 
			
		||||
        Utils::SetThreadName("action-mgr");
 | 
			
		||||
 | 
			
		||||
        while(Running_) {
 | 
			
		||||
            Poco::Thread::trySleep(2000);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
//	Arilia Wireless Inc.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "Poco/Util/Application.h"
 | 
			
		||||
#include "Poco/Util/Option.h"
 | 
			
		||||
#include "Poco/Environment.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,10 @@ namespace OpenWifi {
 | 
			
		||||
    void OpenWifi::RESTAPI_sms_handler::DoPost() {
 | 
			
		||||
        const auto &Obj = ParsedBody_;
 | 
			
		||||
 | 
			
		||||
        if(!SMSSender()->Enabled()) {
 | 
			
		||||
            return BadRequest(RESTAPI::Errors::SMSMFANotEnabled);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string Arg;
 | 
			
		||||
        if(HasParameter("validateNumber",Arg) && Arg=="true" && Obj->has("to")) {
 | 
			
		||||
            auto Number = Obj->get("to").toString();
 | 
			
		||||
 
 | 
			
		||||
@@ -76,12 +76,21 @@ namespace OpenWifi {
 | 
			
		||||
                        return BadRequest(RESTAPI::Errors::SMSMissingPhoneNumber);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if(!SMSSender()->Enabled()) {
 | 
			
		||||
                        return BadRequest(RESTAPI::Errors::SMSMFANotEnabled);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (SMSSender()->StartValidation(MFC.sms, UserInfo_.userinfo.email)) {
 | 
			
		||||
                        return OK();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return InternalError(RESTAPI::Errors::SMSTryLater);
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (GetBoolParameter("completeValidation", false)) {
 | 
			
		||||
 | 
			
		||||
                    if(!SMSSender()->Enabled()) {
 | 
			
		||||
                        return BadRequest(RESTAPI::Errors::SMSMFANotEnabled);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    auto ChallengeCode = GetParameter("challengeCode", "");
 | 
			
		||||
                    if (ChallengeCode.empty()) {
 | 
			
		||||
                        return BadRequest(RESTAPI::Errors::SMSMissingChallenge);
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ namespace OpenWifi {
 | 
			
		||||
 | 
			
		||||
        auto Reset = GetBoolParameter("reset",false);
 | 
			
		||||
        std::string QRCode;
 | 
			
		||||
 | 
			
		||||
        if(TotpCache()->StartValidation(UserInfo_.userinfo,false,QRCode,Reset)) {
 | 
			
		||||
            return SendFileContent(QRCode, "image/svg+xml","qrcode.svg");
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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_;
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,8 @@ namespace OpenWifi {
 | 
			
		||||
 | 
			
		||||
    bool SMSSender::StartValidation(const std::string &Number, const std::string &UserName) {
 | 
			
		||||
        std::lock_guard     G(Mutex_);
 | 
			
		||||
        if(!Enabled_)
 | 
			
		||||
            return false;
 | 
			
		||||
        CleanCache();
 | 
			
		||||
        uint64_t Now=OpenWifi::Now();
 | 
			
		||||
        auto Challenge = MFAServer::MakeChallenge();
 | 
			
		||||
@@ -56,6 +58,9 @@ namespace OpenWifi {
 | 
			
		||||
    bool SMSSender::IsNumberValid(const std::string &Number, const std::string &UserName) {
 | 
			
		||||
        std::lock_guard     G(Mutex_);
 | 
			
		||||
 | 
			
		||||
        if(!Enabled_)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        for(const auto &i:Cache_) {
 | 
			
		||||
            if(i.Number==Number && i.UserName==UserName)
 | 
			
		||||
                return i.Validated;
 | 
			
		||||
@@ -66,6 +71,9 @@ namespace OpenWifi {
 | 
			
		||||
    bool SMSSender::CompleteValidation(const std::string &Number, const std::string &Code, const std::string &UserName) {
 | 
			
		||||
        std::lock_guard     G(Mutex_);
 | 
			
		||||
 | 
			
		||||
        if(!Enabled_)
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        for(auto &i:Cache_) {
 | 
			
		||||
            if(i.Code==Code && i.Number==Number && i.UserName==UserName) {
 | 
			
		||||
                i.Validated=true;
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ namespace OpenWifi {
 | 
			
		||||
 | 
			
		||||
    void SMTPMailerService::run() {
 | 
			
		||||
        Running_ = true;
 | 
			
		||||
 | 
			
		||||
        Utils::SetThreadName("smtp-mailer");
 | 
			
		||||
        while(Running_) {
 | 
			
		||||
 | 
			
		||||
            Poco::Thread::trySleep(10000);
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,7 @@ namespace OpenWifi {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void Archiver::onTimer([[maybe_unused]] Poco::Timer &timer) {
 | 
			
		||||
        Utils::SetThreadName("archiver");
 | 
			
		||||
        Poco::Logger &logger = Poco::Logger::get("STORAGE-ARCHIVER");
 | 
			
		||||
        logger.information("Squiggy the DB: removing old tokens.");
 | 
			
		||||
        StorageService()->SubTokenDB().CleanExpiredTokens();
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,6 @@ namespace OpenWifi {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        std::string GenerateQRCode(const std::string &Secret, const std::string &email) {
 | 
			
		||||
 | 
			
		||||
            std::string uri{
 | 
			
		||||
                "otpauth://totp/" + Issuer_ + ":" +
 | 
			
		||||
                email + "?secret=" + Secret + "&issuer=" + Issuer_
 | 
			
		||||
@@ -55,10 +54,10 @@ namespace OpenWifi {
 | 
			
		||||
        static bool ValidateCode( const std::string &Secret, const std::string &Code, std::string & Expecting) {
 | 
			
		||||
            uint64_t Now = OpenWifi::Now();
 | 
			
		||||
            uint32_t p = CppTotp::totp(CppTotp::Bytes::ByteString{ (const u_char *)Secret.c_str()}, Now, 0, 30, 6);
 | 
			
		||||
            char buffer[16];
 | 
			
		||||
            char buffer[16]{0};
 | 
			
		||||
            sprintf(buffer,"%06u",p);
 | 
			
		||||
            Expecting = buffer;
 | 
			
		||||
            return Code == buffer;
 | 
			
		||||
            Expecting = std::string(buffer);
 | 
			
		||||
            return Code == Expecting;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int Start() override {
 | 
			
		||||
@@ -92,26 +91,13 @@ namespace OpenWifi {
 | 
			
		||||
            auto Secret = GenerateSecret(20, Base32Secret);
 | 
			
		||||
            QRCode = GenerateQRCode(Base32Secret, User.email);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
        struct Entry {
 | 
			
		||||
            bool        Subscriber=false;
 | 
			
		||||
            uint64_t    Start = 0;
 | 
			
		||||
            uint64_t    Done = 0 ;
 | 
			
		||||
            uint64_t    Verifications = 0 ;
 | 
			
		||||
            std::string Secret;
 | 
			
		||||
            std::string QRCode;
 | 
			
		||||
            std::string LastCode;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
            Entry E{ .Subscriber = Subscriber,
 | 
			
		||||
                     .Start = OpenWifi::Now(),
 | 
			
		||||
                     .Done = 0,
 | 
			
		||||
                     .Verifications = 0,
 | 
			
		||||
                     .Secret = Secret,
 | 
			
		||||
                     .QRCode = QRCode,
 | 
			
		||||
                     .LastCode = 0
 | 
			
		||||
                     .LastCode = ""
 | 
			
		||||
                     };
 | 
			
		||||
            Cache_[User.id] = E;
 | 
			
		||||
            return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +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",
 | 
			
		||||
@@ -518,7 +519,7 @@ namespace OpenWifi {
 | 
			
		||||
					"maximum": 4050
 | 
			
		||||
				},
 | 
			
		||||
				"proto": {
 | 
			
		||||
					"decription": "The L2 vlan tag that shall be added (1q,1ad) ",
 | 
			
		||||
					"decription": "The L2 vlan tag that shall be added (1q,1ad ) ",
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"enum": [
 | 
			
		||||
						"802.1ad",
 | 
			
		||||
@@ -669,6 +670,47 @@ namespace OpenWifi {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"interface.ipv4.port-forward": {
 | 
			
		||||
			"type": "object",
 | 
			
		||||
			"properties": {
 | 
			
		||||
				"protocol": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"enum": [
 | 
			
		||||
						"tcp",
 | 
			
		||||
						"udp",
 | 
			
		||||
						"any"
 | 
			
		||||
					],
 | 
			
		||||
					"default": "any"
 | 
			
		||||
				},
 | 
			
		||||
				"external-port": {
 | 
			
		||||
					"type": [
 | 
			
		||||
						"integer",
 | 
			
		||||
						"string"
 | 
			
		||||
					],
 | 
			
		||||
					"minimum": 0,
 | 
			
		||||
					"maximum": 65535,
 | 
			
		||||
					"format": "uc-portrange"
 | 
			
		||||
				},
 | 
			
		||||
				"internal-address": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"format": "ipv4",
 | 
			
		||||
					"example": "0.0.0.120"
 | 
			
		||||
				},
 | 
			
		||||
				"internal-port": {
 | 
			
		||||
					"type": [
 | 
			
		||||
						"integer",
 | 
			
		||||
						"string"
 | 
			
		||||
					],
 | 
			
		||||
					"minimum": 0,
 | 
			
		||||
					"maximum": 65535,
 | 
			
		||||
					"format": "uc-portrange"
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			"required": [
 | 
			
		||||
				"external-port",
 | 
			
		||||
				"internal-address"
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"interface.ipv4": {
 | 
			
		||||
			"type": "object",
 | 
			
		||||
			"properties": {
 | 
			
		||||
@@ -722,6 +764,12 @@ namespace OpenWifi {
 | 
			
		||||
					"items": {
 | 
			
		||||
						"$ref": "#/$defs/interface.ipv4.dhcp-lease"
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"port-forward": {
 | 
			
		||||
					"type": "array",
 | 
			
		||||
					"items": {
 | 
			
		||||
						"$ref": "#/$defs/interface.ipv4.port-forward"
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
@@ -751,6 +799,96 @@ namespace OpenWifi {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
		"interface.ipv6.port-forward": {
 | 
			
		||||
			"type": "object",
 | 
			
		||||
			"properties": {
 | 
			
		||||
				"protocol": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"enum": [
 | 
			
		||||
						"tcp",
 | 
			
		||||
						"udp",
 | 
			
		||||
						"any"
 | 
			
		||||
					],
 | 
			
		||||
					"default": "any"
 | 
			
		||||
				},
 | 
			
		||||
				"external-port": {
 | 
			
		||||
					"type": [
 | 
			
		||||
						"integer",
 | 
			
		||||
						"string"
 | 
			
		||||
					],
 | 
			
		||||
					"minimum": 0,
 | 
			
		||||
					"maximum": 65535,
 | 
			
		||||
					"format": "uc-portrange"
 | 
			
		||||
				},
 | 
			
		||||
				"internal-address": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"format": "ipv6",
 | 
			
		||||
					"example": "::1234:abcd"
 | 
			
		||||
				},
 | 
			
		||||
				"internal-port": {
 | 
			
		||||
					"type": [
 | 
			
		||||
						"integer",
 | 
			
		||||
						"string"
 | 
			
		||||
					],
 | 
			
		||||
					"minimum": 0,
 | 
			
		||||
					"maximum": 65535,
 | 
			
		||||
					"format": "uc-portrange"
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			"required": [
 | 
			
		||||
				"external-port",
 | 
			
		||||
				"internal-address"
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"interface.ipv6.traffic-allow": {
 | 
			
		||||
			"type": "object",
 | 
			
		||||
			"properties": {
 | 
			
		||||
				"protocol": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"default": "any"
 | 
			
		||||
				},
 | 
			
		||||
				"source-address": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"format": "uc-cidr6",
 | 
			
		||||
					"example": "2001:db8:1234:abcd::/64",
 | 
			
		||||
					"default": "::/0"
 | 
			
		||||
				},
 | 
			
		||||
				"source-ports": {
 | 
			
		||||
					"type": "array",
 | 
			
		||||
					"minItems": 1,
 | 
			
		||||
					"items": {
 | 
			
		||||
						"type": [
 | 
			
		||||
							"integer",
 | 
			
		||||
							"string"
 | 
			
		||||
						],
 | 
			
		||||
						"minimum": 0,
 | 
			
		||||
						"maximum": 65535,
 | 
			
		||||
						"format": "uc-portrange"
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"destination-address": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"format": "ipv6",
 | 
			
		||||
					"example": "::1000"
 | 
			
		||||
				},
 | 
			
		||||
				"destination-ports": {
 | 
			
		||||
					"type": "array",
 | 
			
		||||
					"minItems": 1,
 | 
			
		||||
					"items": {
 | 
			
		||||
						"type": [
 | 
			
		||||
							"integer",
 | 
			
		||||
							"string"
 | 
			
		||||
						],
 | 
			
		||||
						"minimum": 0,
 | 
			
		||||
						"maximum": 65535,
 | 
			
		||||
						"format": "uc-portrange"
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			},
 | 
			
		||||
			"required": [
 | 
			
		||||
				"destination-address"
 | 
			
		||||
			]
 | 
			
		||||
		},
 | 
			
		||||
		"interface.ipv6": {
 | 
			
		||||
			"type": "object",
 | 
			
		||||
			"properties": {
 | 
			
		||||
@@ -782,6 +920,18 @@ namespace OpenWifi {
 | 
			
		||||
				},
 | 
			
		||||
				"dhcpv6": {
 | 
			
		||||
					"$ref": "#/$defs/interface.ipv6.dhcpv6"
 | 
			
		||||
				},
 | 
			
		||||
				"port-forward": {
 | 
			
		||||
					"type": "array",
 | 
			
		||||
					"items": {
 | 
			
		||||
						"$ref": "#/$defs/interface.ipv6.port-forward"
 | 
			
		||||
					}
 | 
			
		||||
				},
 | 
			
		||||
				"traffic-allow": {
 | 
			
		||||
					"type": "array",
 | 
			
		||||
					"items": {
 | 
			
		||||
						"$ref": "#/$defs/interface.ipv6.traffic-allow"
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
@@ -866,7 +1016,7 @@ namespace OpenWifi {
 | 
			
		||||
				},
 | 
			
		||||
				"gateway-fqdn": {
 | 
			
		||||
					"type": "string",
 | 
			
		||||
					"format": "fqdn",
 | 
			
		||||
					"format": "uc-fqdn",
 | 
			
		||||
					"default": "ucentral.splash"
 | 
			
		||||
				},
 | 
			
		||||
				"max-clients": {
 | 
			
		||||
@@ -901,6 +1051,7 @@ namespace OpenWifi {
 | 
			
		||||
						"psk",
 | 
			
		||||
						"psk2",
 | 
			
		||||
						"psk-mixed",
 | 
			
		||||
						"psk2-radius",
 | 
			
		||||
						"wpa",
 | 
			
		||||
						"wpa2",
 | 
			
		||||
						"wpa-mixed",
 | 
			
		||||
@@ -961,6 +1112,10 @@ namespace OpenWifi {
 | 
			
		||||
					"type": "boolean",
 | 
			
		||||
					"default": false
 | 
			
		||||
				},
 | 
			
		||||
				"reduced-neighbor-reporting": {
 | 
			
		||||
					"type": "boolean",
 | 
			
		||||
					"default": false
 | 
			
		||||
				},
 | 
			
		||||
				"lci": {
 | 
			
		||||
					"type": "string"
 | 
			
		||||
				},
 | 
			
		||||
@@ -1527,6 +1682,11 @@ namespace OpenWifi {
 | 
			
		||||
					"decription": "This option allows embedding custom vendor specific IEs inside the beacons of a BSS in AP mode.",
 | 
			
		||||
					"type": "string"
 | 
			
		||||
				},
 | 
			
		||||
				"fils-discovery-interval": {
 | 
			
		||||
					"type": "integer",
 | 
			
		||||
					"default": 20,
 | 
			
		||||
					"maximum": 10000
 | 
			
		||||
				},
 | 
			
		||||
				"encryption": {
 | 
			
		||||
					"$ref": "#/$defs/interface.ssid.encryption"
 | 
			
		||||
				},
 | 
			
		||||
@@ -2087,6 +2247,10 @@ namespace OpenWifi {
 | 
			
		||||
				"auto-channel": {
 | 
			
		||||
					"type": "boolean",
 | 
			
		||||
					"default": false
 | 
			
		||||
				},
 | 
			
		||||
				"ipv6": {
 | 
			
		||||
					"type": "boolean",
 | 
			
		||||
					"default": false
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		},
 | 
			
		||||
@@ -2193,7 +2357,7 @@ namespace OpenWifi {
 | 
			
		||||
									"properties": {
 | 
			
		||||
										"fqdn": {
 | 
			
		||||
											"type": "string",
 | 
			
		||||
											"format": "fqdn"
 | 
			
		||||
											"format": "uc-fqdn"
 | 
			
		||||
										},
 | 
			
		||||
										"suffix-matching": {
 | 
			
		||||
											"type": "boolean",
 | 
			
		||||
@@ -2444,8 +2608,7 @@ namespace OpenWifi {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    )"_json;
 | 
			
		||||
)"_json;
 | 
			
		||||
 | 
			
		||||
    class custom_error_handler : public nlohmann::json_schema::basic_error_handler
 | 
			
		||||
    {
 | 
			
		||||
@@ -2460,9 +2623,18 @@ 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.");
 | 
			
		||||
			Initialized_ = Working_ = true;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
 | 
			
		||||
			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.");
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -2528,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}$"};
 | 
			
		||||
@@ -2578,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;
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,11 @@ namespace OpenWifi {
 | 
			
		||||
    inline uint64_t Now() { return std::time(nullptr); };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace OpenWifi::Utils {
 | 
			
		||||
    std::vector<unsigned char> base64decode(const std::string& input);
 | 
			
		||||
    std::string base64encode(const unsigned char *input, uint32_t size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using namespace std::chrono_literals;
 | 
			
		||||
 | 
			
		||||
#include "Poco/Util/Application.h"
 | 
			
		||||
@@ -238,6 +243,11 @@ namespace OpenWifi::RESTAPI_utils {
 | 
			
		||||
        Obj.set(Field,Value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Poco::Data::BLOB &Value) {
 | 
			
		||||
        auto Result = Utils::base64encode((const unsigned char *)Value.rawContent(),Value.size());
 | 
			
		||||
        Obj.set(Field,Result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::StringPairVec & S) {
 | 
			
		||||
        Poco::JSON::Array   Array;
 | 
			
		||||
        for(const auto &i:S) {
 | 
			
		||||
@@ -334,12 +344,12 @@ namespace OpenWifi::RESTAPI_utils {
 | 
			
		||||
 | 
			
		||||
    inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, double & Value) {
 | 
			
		||||
        if(Obj->has(Field) && !Obj->isNull(Field))
 | 
			
		||||
            Value = (double) Obj->get(Field);
 | 
			
		||||
            Value = (double)Obj->get(Field);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, float & Value) {
 | 
			
		||||
        if(Obj->has(Field) && !Obj->isNull(Field))
 | 
			
		||||
            Value = (float) Obj->get(Field);
 | 
			
		||||
            Value = (float)Obj->get(Field);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, bool &Value) {
 | 
			
		||||
@@ -374,7 +384,14 @@ namespace OpenWifi::RESTAPI_utils {
 | 
			
		||||
 | 
			
		||||
    inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, uint64_t &Value) {
 | 
			
		||||
        if(Obj->has(Field) && !Obj->isNull(Field))
 | 
			
		||||
            Value = (uint64_t ) Obj->get(Field);
 | 
			
		||||
            Value = (uint64_t)Obj->get(Field);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Poco::Data::BLOB &Value) {
 | 
			
		||||
        if(Obj->has(Field) && !Obj->isNull(Field)) {
 | 
			
		||||
            auto Result = Utils::base64decode(Obj->get(Field).toString());
 | 
			
		||||
            Value.assignRaw((const unsigned char *)&Result[0],Result.size());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char *Field, Types::StringPairVec &Vec) {
 | 
			
		||||
@@ -643,6 +660,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 +1205,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 +1354,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 +1885,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 +1935,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_)
 | 
			
		||||
@@ -2045,6 +2081,17 @@ namespace OpenWifi {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        static inline bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, Poco::Data::BLOB &Value) {
 | 
			
		||||
            if(O->has(Field)) {
 | 
			
		||||
                std::string Content = O->get(Field).toString();
 | 
			
		||||
                auto DecodedBlob = Utils::base64decode(Content);
 | 
			
		||||
                Value.assignRaw((const unsigned char *)&DecodedBlob[0],DecodedBlob.size());
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        template <typename T> bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, const T &value, T & assignee) {
 | 
			
		||||
            if(O->has(Field)) {
 | 
			
		||||
                assignee = value;
 | 
			
		||||
@@ -2582,7 +2629,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 +2655,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 +2712,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 +2738,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 +2933,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 +3002,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 +3034,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 +3058,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 +3167,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 +3576,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 +3973,7 @@ namespace OpenWifi {
 | 
			
		||||
 | 
			
		||||
    inline int MicroService::main([[maybe_unused]] const ArgVec &args) {
 | 
			
		||||
 | 
			
		||||
		// Utils::SetThreadName("main");
 | 
			
		||||
	    MyErrorHandler	ErrorHandler(*this);
 | 
			
		||||
	    Poco::ErrorHandler::set(&ErrorHandler);
 | 
			
		||||
 | 
			
		||||
@@ -4037,6 +4089,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 +4175,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 +4215,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 +4457,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 +4515,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 +4594,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 +4670,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 +4875,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 +4972,7 @@ namespace OpenWifi {
 | 
			
		||||
 | 
			
		||||
    inline void WebSocketClientServer::run() {
 | 
			
		||||
        Running_ = true ;
 | 
			
		||||
		Utils::SetThreadName("ws:clnt-svr");
 | 
			
		||||
        while(Running_) {
 | 
			
		||||
            Poco::Thread::trySleep(2000);
 | 
			
		||||
 | 
			
		||||
@@ -4962,8 +5020,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 +5047,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;
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
null
 | 
			
		||||
		Reference in New Issue
	
	Block a user