mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
				synced 2025-10-30 18:28:03 +00:00 
			
		
		
		
	Merge branch 'master' into feature/wifi-5420--add-sysctl-context
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
This commit is contained in:
		| @@ -1,5 +1,5 @@ | |||||||
| cmake_minimum_required(VERSION 3.13) | cmake_minimum_required(VERSION 3.13) | ||||||
| project(owgw VERSION 2.4.0) | project(owgw VERSION 2.5.0) | ||||||
|  |  | ||||||
| set(CMAKE_CXX_STANDARD 17) | set(CMAKE_CXX_STANDARD 17) | ||||||
|  |  | ||||||
| @@ -104,7 +104,7 @@ add_executable( owgw | |||||||
|         src/TelemetryStream.cpp src/TelemetryStream.h |         src/TelemetryStream.cpp src/TelemetryStream.h | ||||||
|         src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.h |         src/framework/ConfigurationValidator.cpp src/framework/ConfigurationValidator.h | ||||||
|         src/ConfigurationCache.cpp src/ConfigurationCache.h |         src/ConfigurationCache.cpp src/ConfigurationCache.h | ||||||
|         ) |         src/CapabilitiesCache.h) | ||||||
|  |  | ||||||
| if(NOT SMALL_BUILD) | if(NOT SMALL_BUILD) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,9 +26,9 @@ Poco may take several minutes depending on the platform you are building on. | |||||||
| ### Ubuntu | ### Ubuntu | ||||||
| These instructions have proven to work on Ubuntu 20.4. | These instructions have proven to work on Ubuntu 20.4. | ||||||
| ``` | ``` | ||||||
| sudo apt install git cmake g++ libssl-dev libmariadb-dev unixodbc-dev  | sudo apt install git cmake g++ libssl-dev libmariadb-dev  | ||||||
| sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev | sudo apt install libpq-dev libaprutil1-dev apache2-dev libboost-all-dev | ||||||
| sudo apt install librdkafka-dev liblua5.3-dev libmysqlclient-dev | sudo apt install librdkafka-dev libmysqlclient-dev default-libmysqlclient-dev | ||||||
|  |  | ||||||
| git clone https://github.com/stephb9959/poco | git clone https://github.com/stephb9959/poco | ||||||
| cd poco | cd poco | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ spec: | |||||||
|       annotations: |       annotations: | ||||||
|         checksum/config: {{ include "owgw.config" . | sha256sum }} |         checksum/config: {{ include "owgw.config" . | sha256sum }} | ||||||
|         {{- if .Values.podSecurityPolicy.enabled }} |         {{- if .Values.podSecurityPolicy.enabled }} | ||||||
|         kubernetes.io/psp: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-unsafe-sysctl |         kubernetes.io/psp: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl | ||||||
|         {{- end }} |         {{- end }} | ||||||
|         {{- with .Values.podAnnotations }} |         {{- with .Values.podAnnotations }} | ||||||
|         {{- toYaml . | nindent 8 }} |         {{- toYaml . | nindent 8 }} | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| apiVersion: policy/v1beta1 | apiVersion: policy/v1beta1 | ||||||
| kind: PodSecurityPolicy | kind: PodSecurityPolicy | ||||||
| metadata: | metadata: | ||||||
|   name: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-unsafe-sysctl |   name: {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl | ||||||
|   labels: |   labels: | ||||||
|     app.kubernetes.io/name: {{ include "owgw.name" . }} |     app.kubernetes.io/name: {{ include "owgw.name" . }} | ||||||
|     helm.sh/chart: {{ include "owgw.chart" . }} |     helm.sh/chart: {{ include "owgw.chart" . }} | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								helm/templates/role.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								helm/templates/role.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | {{- if .Values.podSecurityPolicy.enabled }} | ||||||
|  | --- | ||||||
|  | kind: Role | ||||||
|  | apiVersion: rbac.authorization.k8s.io/v1 | ||||||
|  | metadata: | ||||||
|  |   name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl | ||||||
|  | rules: | ||||||
|  | - apiGroups: | ||||||
|  |   - policy | ||||||
|  |   resources: | ||||||
|  |   - podsecuritypolicies | ||||||
|  |   verbs: | ||||||
|  |   - use | ||||||
|  |   resourceNames: | ||||||
|  |   - {{ include "owgw.fullname" . }}-{{ .Release.Namespace }}-owgw-unsafe-sysctl | ||||||
|  | {{- end }} | ||||||
							
								
								
									
										15
									
								
								helm/templates/rolebinding.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								helm/templates/rolebinding.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | {{- if .Values.podSecurityPolicy.enabled }} | ||||||
|  | --- | ||||||
|  | apiVersion: rbac.authorization.k8s.io/v1 | ||||||
|  | kind: RoleBinding | ||||||
|  | metadata: | ||||||
|  |   name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl-to-default | ||||||
|  | roleRef: | ||||||
|  |   apiGroup: rbac.authorization.k8s.io | ||||||
|  |   kind: Role | ||||||
|  |   name: {{ include "owgw.fullname" . }}-owgw-use-unsafe-sysctl | ||||||
|  | subjects: | ||||||
|  | - kind: ServiceAccount | ||||||
|  |   name: default | ||||||
|  |   namespace: {{ .Release.Namespace }} | ||||||
|  | {{- end }} | ||||||
| @@ -2,7 +2,7 @@ openapi: 3.0.1 | |||||||
| info: | info: | ||||||
|   title: uCentral gateway API |   title: uCentral gateway API | ||||||
|   description: A process to manage configuration for devices. |   description: A process to manage configuration for devices. | ||||||
|   version: 2.0.0 |   version: 2.5.0 | ||||||
|   license: |   license: | ||||||
|     name: BSD3 |     name: BSD3 | ||||||
|     url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE |     url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE | ||||||
| @@ -51,6 +51,16 @@ components: | |||||||
|             properties: |             properties: | ||||||
|               ErrorCode: |               ErrorCode: | ||||||
|                 type: integer |                 type: integer | ||||||
|  |                 enum: | ||||||
|  |                   - 0     # Success | ||||||
|  |                   - 1     # PASSWORD_CHANGE_REQUIRED, | ||||||
|  |                   - 2     # INVALID_CREDENTIALS, | ||||||
|  |                   - 3     # PASSWORD_ALREADY_USED, | ||||||
|  |                   - 4     # USERNAME_PENDING_VERIFICATION, | ||||||
|  |                   - 5     # PASSWORD_INVALID, | ||||||
|  |                   - 6     # INTERNAL_ERROR, | ||||||
|  |                   - 7     # ACCESS_DENIED, | ||||||
|  |                   - 8     # INVALID_TOKEN | ||||||
|               ErrorDetails: |               ErrorDetails: | ||||||
|                 type: string |                 type: string | ||||||
|               ErrorDescription: |               ErrorDescription: | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								src/CapabilitiesCache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/CapabilitiesCache.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2021-11-17. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "nlohmann/json.hpp" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  | 	static const std::string CapabilitiesCacheFileName{"/capabilities_cache.json"}; | ||||||
|  |  | ||||||
|  | 	class CapabilitiesCache { | ||||||
|  | 	  public: | ||||||
|  |  | ||||||
|  | 		static CapabilitiesCache * instance() { | ||||||
|  | 			static CapabilitiesCache * instance = new CapabilitiesCache; | ||||||
|  | 			return instance; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline void Add(const std::string & DeviceType, const std::string & Platform) { | ||||||
|  | 			std::lock_guard	G(Mutex_); | ||||||
|  | 			if(!Loaded_) | ||||||
|  | 				LoadIt(); | ||||||
|  | 			auto P = Poco::toUpper(Platform); | ||||||
|  | 			auto Hint = Caps_.find(DeviceType); | ||||||
|  | 			if(Hint==Caps_.end()) { | ||||||
|  | 				Caps_.insert(std::make_pair(DeviceType,P)); | ||||||
|  | 				SaveIt(); | ||||||
|  | 			} | ||||||
|  | 			if(Hint->second != P) { | ||||||
|  | 				Hint->second = P; | ||||||
|  | 				SaveIt(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline std::string Get(const std::string & DeviceType) { | ||||||
|  | 			std::lock_guard	G(Mutex_); | ||||||
|  |  | ||||||
|  | 			if(!Loaded_) { | ||||||
|  | 				LoadIt(); | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			auto Hint = Caps_.find(DeviceType); | ||||||
|  | 			if(Hint==Caps_.end()) | ||||||
|  | 				return "AP"; | ||||||
|  | 			return Hint->second; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	  private: | ||||||
|  | 		std::mutex			Mutex_; | ||||||
|  | 		std::atomic_bool 	Loaded_=false; | ||||||
|  | 		std::map<std::string,std::string>	Caps_; | ||||||
|  |  | ||||||
|  | 		inline void LoadIt() { | ||||||
|  | 			try { | ||||||
|  | 				std::ifstream i(MicroService::instance().DataDir()+CapabilitiesCacheFileName); | ||||||
|  | 				nlohmann::json cache; | ||||||
|  | 				i >> cache; | ||||||
|  |  | ||||||
|  | 				for(const auto &[Type,Platform]:cache.items()) { | ||||||
|  | 					std::cout << "Type:" << Type << std::endl; | ||||||
|  | 					Caps_[Type] = Platform; | ||||||
|  | 				} | ||||||
|  | 			} catch(...) { | ||||||
|  |  | ||||||
|  | 			} | ||||||
|  | 			Loaded_ = true; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline void SaveIt() { | ||||||
|  | 			std::ofstream i(MicroService::instance().DataDir()+CapabilitiesCacheFileName); | ||||||
|  | 			nlohmann::json cache(Caps_); | ||||||
|  | 			i << cache; | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  | } | ||||||
| @@ -68,8 +68,8 @@ namespace OpenWifi { | |||||||
| 			bool GetCommand(uint64_t Id, const std::string & SerialNumber, CommandTag &T); | 			bool GetCommand(uint64_t Id, const std::string & SerialNumber, CommandTag &T); | ||||||
|  |  | ||||||
| 			static CommandManager *instance() { | 			static CommandManager *instance() { | ||||||
| 				static CommandManager instance; | 			    static CommandManager *instance_ = new CommandManager; | ||||||
| 				return &instance; | 				return instance_; | ||||||
| 			} | 			} | ||||||
| 			inline bool Running() const { return Running_; } | 			inline bool Running() const { return Running_; } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,11 +26,8 @@ | |||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
| 	class Daemon *Daemon::instance_ = nullptr; |  | ||||||
|  |  | ||||||
| 	class Daemon *Daemon::instance() { | 	class Daemon *Daemon::instance() { | ||||||
| 		if (instance_ == nullptr) { | 	    static Daemon instance(vDAEMON_PROPERTIES_FILENAME, | ||||||
| 			instance_ = new Daemon(vDAEMON_PROPERTIES_FILENAME, |  | ||||||
| 								   vDAEMON_ROOT_ENV_VAR, | 								   vDAEMON_ROOT_ENV_VAR, | ||||||
| 								   vDAEMON_CONFIG_ENV_VAR, | 								   vDAEMON_CONFIG_ENV_VAR, | ||||||
| 								   vDAEMON_APP_NAME, | 								   vDAEMON_APP_NAME, | ||||||
| @@ -47,35 +44,46 @@ namespace OpenWifi { | |||||||
| 									   StorageArchiver(), | 									   StorageArchiver(), | ||||||
| 									   TelemetryStream() | 									   TelemetryStream() | ||||||
| 								   }); | 								   }); | ||||||
| 		} |         return &instance; | ||||||
| 		return instance_; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	static const std::vector<std::pair<std::string,std::string>>		DefaultDeviceTypes{ | ||||||
|  | 		{"cig_wf160d","AP"}, | ||||||
|  | 		{"cig_wf188","AP"}, | ||||||
|  | 		{"cig_wf188n","AP"}, | ||||||
|  | 		{"cig_wf194c","AP"}, | ||||||
|  | 		{"cig_wf194c4","AP"}, | ||||||
|  | 		{"edgecore_eap101","AP"}, | ||||||
|  | 		{"edgecore_eap102","AP"}, | ||||||
|  | 		{"edgecore_ecs4100-12ph","AP"}, | ||||||
|  | 		{"edgecore_ecw5211","AP"}, | ||||||
|  | 		{"edgecore_ecw5410","AP"}, | ||||||
|  | 		{"edgecore_oap100","AP"}, | ||||||
|  | 		{"edgecore_spw2ac1200","SWITCH"}, | ||||||
|  | 		{"edgecore_spw2ac1200-lan-poe","SWITCH"}, | ||||||
|  | 		{"edgecore_ssw2ac2600","SWITCH"}, | ||||||
|  | 		{"hfcl_ion4","AP"}, | ||||||
|  | 		{"indio_um-305ac","AP"}, | ||||||
|  | 		{"linksys_e8450-ubi","AP"}, | ||||||
|  | 		{"linksys_ea6350","AP"}, | ||||||
|  | 		{"linksys_ea6350-v4","AP"}, | ||||||
|  | 		{"linksys_ea8300","AP"}, | ||||||
|  | 		{"mikrotik_nand","AP"}, | ||||||
|  | 		{"tp-link_ec420-g1","AP"}, | ||||||
|  | 		{"tplink_cpe210_v3","AP"}, | ||||||
|  | 		{"tplink_cpe510_v3","AP"}, | ||||||
|  | 		{"tplink_eap225_outdoor_v1","AP"}, | ||||||
|  | 		{"tplink_ec420","AP"}, | ||||||
|  | 		{"tplink_ex227","AP"}, | ||||||
|  | 		{"tplink_ex228","AP"}, | ||||||
|  | 		{"tplink_ex447","AP"}, | ||||||
|  | 		{"wallys_dr40x9","AP"} | ||||||
|  | 	}; | ||||||
|  | 	 | ||||||
| 	void Daemon::initialize() { | 	void Daemon::initialize() { | ||||||
| 		Config::Config::Init(); | 		Config::Config::Init(); | ||||||
|         AutoProvisioning_ = config().getBool("openwifi.autoprovisioning",false); |         AutoProvisioning_ = config().getBool("openwifi.autoprovisioning",false); | ||||||
|  |         DeviceTypes_ = DefaultDeviceTypes; | ||||||
|         // DeviceTypeIdentifications_ |  | ||||||
|         Types::StringVec   Keys; |  | ||||||
|         config().keys("openwifi.devicetypes",Keys); |  | ||||||
|         for(const auto & i:Keys) |  | ||||||
|         { |  | ||||||
|         	std::string Line = config().getString("openwifi.devicetypes."+i); |  | ||||||
|             auto P1 = Line.find_first_of(':'); |  | ||||||
|             auto Type = Line.substr(0, P1); |  | ||||||
|             auto List = Line.substr(P1+1); |  | ||||||
|  |  | ||||||
|             Types::StringVec  Tokens = Utils::Split(List); |  | ||||||
|  |  | ||||||
|             auto Entry = DeviceTypeIdentifications_.find(Type); |  | ||||||
| 			if(DeviceTypeIdentifications_.end() == Entry) { |  | ||||||
| 				std::set<std::string>	S; |  | ||||||
| 				S.insert(Tokens.begin(),Tokens.end()); |  | ||||||
| 				DeviceTypeIdentifications_[Type] = S; |  | ||||||
| 			} else { |  | ||||||
| 				Entry->second.insert(Tokens.begin(),Tokens.end()); |  | ||||||
| 			} |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void MicroServicePostInitialization() { |     void MicroServicePostInitialization() { | ||||||
| @@ -83,22 +91,20 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     [[nodiscard]] std::string Daemon::IdentifyDevice(const std::string & Id ) const { |     [[nodiscard]] std::string Daemon::IdentifyDevice(const std::string & Id ) const { | ||||||
|         for(const auto &[Type,List]:DeviceTypeIdentifications_) | 	    for(const auto &[DeviceType,Type]:DeviceTypes_) | ||||||
|         { |         { | ||||||
| 			if(List.find(Id)!=List.end()) |         	if(Id == DeviceType) | ||||||
| 				return Type; |         		return Type; | ||||||
|         } |         } | ||||||
|         return "AP"; |         return "AP"; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||||
| 	try { | 	try { | ||||||
|  |  | ||||||
| 		auto App = OpenWifi::Daemon::instance(); | 		auto App = OpenWifi::Daemon::instance(); | ||||||
| 		auto ExitCode =  App->run(argc, argv); | 		auto ExitCode =  App->run(argc, argv); | ||||||
| 		delete App; |  | ||||||
|  |  | ||||||
| 		return ExitCode; | 		return ExitCode; | ||||||
|  |  | ||||||
| 	} catch (Poco::Exception &exc) { | 	} catch (Poco::Exception &exc) { | ||||||
|   | |||||||
| @@ -54,9 +54,8 @@ namespace OpenWifi { | |||||||
| 			inline DeviceDashboard	& GetDashboard() { return DB_; } | 			inline DeviceDashboard	& GetDashboard() { return DB_; } | ||||||
| 			Poco::Logger & Log() { return Poco::Logger::get(AppName()); } | 			Poco::Logger & Log() { return Poco::Logger::get(AppName()); } | ||||||
| 	  	private: | 	  	private: | ||||||
| 			static Daemon 				*instance_; |  | ||||||
| 			bool                        AutoProvisioning_ = false; | 			bool                        AutoProvisioning_ = false; | ||||||
| 			Types::StringMapStringSet   DeviceTypeIdentifications_; | 			std::vector<std::pair<std::string,std::string>> DeviceTypes_; | ||||||
| 			DeviceDashboard				DB_; | 			DeviceDashboard				DB_; | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -16,10 +16,6 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| 	DeviceRegistry::DeviceRegistry() noexcept: |  | ||||||
| 		SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") { |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	int DeviceRegistry::Start() { | 	int DeviceRegistry::Start() { | ||||||
| 		std::lock_guard		Guard(Mutex_); | 		std::lock_guard		Guard(Mutex_); | ||||||
|         Logger_.notice("Starting "); |         Logger_.notice("Starting "); | ||||||
| @@ -96,13 +92,13 @@ namespace OpenWifi { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	GWObjects::ConnectionState * DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr) | 	std::shared_ptr<DeviceRegistry::ConnectionEntry> DeviceRegistry::Register(const std::string & SerialNumber, WSConnection *Ptr) | ||||||
|     { |     { | ||||||
| 		std::lock_guard		Guard(Mutex_); | 		std::lock_guard		Guard(Mutex_); | ||||||
|  |  | ||||||
|         auto Device = Devices_.find(SerialNumber); |         auto Device = Devices_.find(SerialNumber); | ||||||
|         if( Device == Devices_.end()) { |         if( Device == Devices_.end()) { | ||||||
|             auto E = std::make_unique<ConnectionEntry>(); |         	auto E = Devices_[SerialNumber] = std::make_shared<ConnectionEntry>(); | ||||||
|  |  | ||||||
|             E->WSConn_ = Ptr; |             E->WSConn_ = Ptr; | ||||||
|             E->Conn_.SerialNumber = SerialNumber; |             E->Conn_.SerialNumber = SerialNumber; | ||||||
| @@ -114,9 +110,7 @@ namespace OpenWifi { | |||||||
|             E->Conn_.TX = 0 ; |             E->Conn_.TX = 0 ; | ||||||
|             E->Conn_.RX = 0; |             E->Conn_.RX = 0; | ||||||
| 			E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE; | 			E->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE; | ||||||
| 			auto R=&E->Conn_; |             return E; | ||||||
|             Devices_[SerialNumber] = std::move(E); |  | ||||||
|             return R; |  | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
| @@ -124,7 +118,7 @@ namespace OpenWifi { | |||||||
|             Device->second->Conn_.Connected = true; |             Device->second->Conn_.Connected = true; | ||||||
|             Device->second->Conn_.LastContact = std::time(nullptr); |             Device->second->Conn_.LastContact = std::time(nullptr); | ||||||
| 			Device->second->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE; | 			Device->second->Conn_.VerifiedCertificate = GWObjects::CertificateValidation::NO_CERTIFICATE; | ||||||
|             return &Device->second->Conn_; |             return Device->second; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -141,15 +135,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     void DeviceRegistry::UnRegister(const std::string & SerialNumber, WSConnection *Ptr) { |     void DeviceRegistry::UnRegister(const std::string & SerialNumber, WSConnection *Ptr) { | ||||||
| 		std::lock_guard		Guard(Mutex_); | 		std::lock_guard		Guard(Mutex_); | ||||||
|  | 		Devices_.erase(SerialNumber); | ||||||
|         auto Device = Devices_.find(SerialNumber); |  | ||||||
|  |  | ||||||
|         if( Device != Devices_.end() && Device->second->WSConn_==Ptr) { |  | ||||||
|             Device->second->Conn_.Address = ""; |  | ||||||
|             Device->second->WSConn_ = nullptr; |  | ||||||
|             Device->second->Conn_.Connected = false; |  | ||||||
| 			Device->second->Conn_.VerifiedCertificate = GWObjects::NO_CERTIFICATE; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| 	bool DeviceRegistry::SendFrame(const std::string & SerialNumber, const std::string & Payload) { | 	bool DeviceRegistry::SendFrame(const std::string & SerialNumber, const std::string & Payload) { | ||||||
| @@ -238,12 +224,12 @@ namespace OpenWifi { | |||||||
| 		std::lock_guard		Guard(Mutex_); | 		std::lock_guard		Guard(Mutex_); | ||||||
|  |  | ||||||
| 		for(auto const &[SerialNumber,Connection]:Devices_) { | 		for(auto const &[SerialNumber,Connection]:Devices_) { | ||||||
| 			Types::UpdateCountedMap(D.status, Connection->Conn_.Connected ? "connected" : "not connected"); | 			UpdateCountedMap(D.status, Connection->Conn_.Connected ? "connected" : "not connected"); | ||||||
| 			Types::UpdateCountedMap(D.vendors, OUIServer()->GetManufacturer(SerialNumber)); | 			UpdateCountedMap(D.vendors, OUIServer()->GetManufacturer(SerialNumber)); | ||||||
| 			Types::UpdateCountedMap(D.certificates, ComputeCertificateTag(Connection->Conn_.VerifiedCertificate)); | 			UpdateCountedMap(D.certificates, ComputeCertificateTag(Connection->Conn_.VerifiedCertificate)); | ||||||
| 			Types::UpdateCountedMap(D.lastContact, ComputeUpLastContactTag(Connection->Conn_.LastContact)); | 			UpdateCountedMap(D.lastContact, ComputeUpLastContactTag(Connection->Conn_.LastContact)); | ||||||
| 			Types::UpdateCountedMap(D.healths, ComputeSanityTag(Connection->LastHealthcheck.Sanity)); | 			UpdateCountedMap(D.healths, ComputeSanityTag(Connection->LastHealthcheck.Sanity)); | ||||||
| 			Types::UpdateCountedMap(D.deviceType, Connection->Conn_.Compatible); | 			UpdateCountedMap(D.deviceType, Connection->Conn_.Compatible); | ||||||
| 			if(!Connection->LastStats.empty()) { | 			if(!Connection->LastStats.empty()) { | ||||||
| 				Poco::JSON::Parser	P; | 				Poco::JSON::Parser	P; | ||||||
|  |  | ||||||
| @@ -252,21 +238,21 @@ namespace OpenWifi { | |||||||
| 				if(RawObject->has("unit")) { | 				if(RawObject->has("unit")) { | ||||||
| 					auto Unit = RawObject->getObject("unit"); | 					auto Unit = RawObject->getObject("unit"); | ||||||
| 					if (Unit->has("uptime")) { | 					if (Unit->has("uptime")) { | ||||||
| 						Types::UpdateCountedMap(D.upTimes, ComputeUpTimeTag(Unit->get("uptime"))); | 						UpdateCountedMap(D.upTimes, ComputeUpTimeTag(Unit->get("uptime"))); | ||||||
| 					} | 					} | ||||||
| 					if (Unit->has("memory")) { | 					if (Unit->has("memory")) { | ||||||
| 						auto Memory = Unit->getObject("memory"); | 						auto Memory = Unit->getObject("memory"); | ||||||
| 						uint64_t Free = Memory->get("free"); | 						uint64_t Free = Memory->get("free"); | ||||||
| 						uint64_t Total = Memory->get("total"); | 						uint64_t Total = Memory->get("total"); | ||||||
| 						Types::UpdateCountedMap(D.memoryUsed, ComputeFreeMemoryTag(Free, Total)); | 						UpdateCountedMap(D.memoryUsed, ComputeFreeMemoryTag(Free, Total)); | ||||||
| 					} | 					} | ||||||
| 					if (Unit->has("load")) { | 					if (Unit->has("load")) { | ||||||
| 						auto Load = Unit->getArray("load"); | 						auto Load = Unit->getArray("load"); | ||||||
| 						Types::UpdateCountedMap(D.load1, | 						UpdateCountedMap(D.load1, | ||||||
| 												ComputeLoadTag(Load->getElement<uint64_t>(0))); | 												ComputeLoadTag(Load->getElement<uint64_t>(0))); | ||||||
| 						Types::UpdateCountedMap(D.load5, | 						UpdateCountedMap(D.load5, | ||||||
| 												ComputeLoadTag(Load->getElement<uint64_t>(1))); | 												ComputeLoadTag(Load->getElement<uint64_t>(1))); | ||||||
| 						Types::UpdateCountedMap(D.load15, | 						UpdateCountedMap(D.load15, | ||||||
| 												ComputeLoadTag(Load->getElement<uint64_t>(2))); | 												ComputeLoadTag(Load->getElement<uint64_t>(2))); | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
|   | |||||||
| @@ -29,8 +29,8 @@ namespace OpenWifi { | |||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|         static DeviceRegistry *instance() { |         static DeviceRegistry *instance() { | ||||||
| 			static DeviceRegistry instance; |             static DeviceRegistry *instance_ = new DeviceRegistry; | ||||||
|             return &instance; |             return instance_; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| 		int Start() override; | 		int Start() override; | ||||||
| @@ -41,7 +41,7 @@ namespace OpenWifi { | |||||||
| 		void SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State); | 		void SetState(const std::string & SerialNumber, GWObjects::ConnectionState & State); | ||||||
| 		bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData); | 		bool GetHealthcheck(const std::string &SerialNumber, GWObjects::HealthCheck & CheckData); | ||||||
| 		void SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck &H); | 		void SetHealthcheck(const std::string &SerialNumber, const GWObjects::HealthCheck &H); | ||||||
| 		GWObjects::ConnectionState * Register(const std::string & SerialNumber, WSConnection *); | 		std::shared_ptr<ConnectionEntry> Register(const std::string & SerialNumber, WSConnection *); | ||||||
| 		void UnRegister(const std::string & SerialNumber, WSConnection *); | 		void UnRegister(const std::string & SerialNumber, WSConnection *); | ||||||
| 		bool SendCommand(GWObjects::CommandDetails & Command); | 		bool SendCommand(GWObjects::CommandDetails & Command); | ||||||
| 		bool Connected(const std::string & SerialNumber); | 		bool Connected(const std::string & SerialNumber); | ||||||
| @@ -51,9 +51,11 @@ namespace OpenWifi { | |||||||
| 		bool AnalyzeRegistry(GWObjects::Dashboard &D); | 		bool AnalyzeRegistry(GWObjects::Dashboard &D); | ||||||
|  |  | ||||||
| 	  private: | 	  private: | ||||||
| 		std::map<std::string,std::unique_ptr<ConnectionEntry>>   Devices_; | 		std::map<std::string,std::shared_ptr<ConnectionEntry>>   Devices_; | ||||||
|  |  | ||||||
| 		DeviceRegistry() noexcept; | 		DeviceRegistry() noexcept: | ||||||
|  |     		SubSystemServer("DeviceRegistry", "DevStatus", "devicestatus") { | ||||||
|  | 		} | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline DeviceRegistry * DeviceRegistry() { return DeviceRegistry::instance(); } | 	inline DeviceRegistry * DeviceRegistry() { return DeviceRegistry::instance(); } | ||||||
|   | |||||||
| @@ -30,8 +30,8 @@ namespace OpenWifi { | |||||||
| 		const std::string & Path() { return Path_; }; | 		const std::string & Path() { return Path_; }; | ||||||
|  |  | ||||||
|         static FileUploader *instance() { |         static FileUploader *instance() { | ||||||
| 			static FileUploader instance; |             static FileUploader * instance_ = new FileUploader; | ||||||
| 			return &instance; | 			return instance_; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| 		[[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; } | 		[[nodiscard]] inline uint64_t MaxSize() const { return MaxSize_; } | ||||||
|   | |||||||
| @@ -15,8 +15,8 @@ namespace OpenWifi { | |||||||
| 		typedef std::map<uint64_t,std::string>	OUIMap; | 		typedef std::map<uint64_t,std::string>	OUIMap; | ||||||
|  |  | ||||||
| 		static OUIServer *instance() { | 		static OUIServer *instance() { | ||||||
| 			static OUIServer instance; | 		    static OUIServer *instance_ = new OUIServer; | ||||||
| 			return &instance; | 			return instance_; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		int Start() override; | 		int Start() override; | ||||||
|   | |||||||
| @@ -15,7 +15,10 @@ namespace OpenWifi { | |||||||
| 		Poco::JSON::Array	Arr; | 		Poco::JSON::Array	Arr; | ||||||
| 		Poco::JSON::Object	Answer; | 		Poco::JSON::Object	Answer; | ||||||
|  |  | ||||||
| 		if(StorageService()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) { | 		if(QB_.CountOnly) { | ||||||
|  | 			auto Count = StorageService()->GetBlackListDeviceCount(); | ||||||
|  | 			return ReturnCountOnly(Count); | ||||||
|  | 		} else if(StorageService()->GetBlackListDevices(QB_.Offset, QB_.Limit, Devices)) { | ||||||
| 			for(const auto &i:Devices) { | 			for(const auto &i:Devices) { | ||||||
| 				Poco::JSON::Object O; | 				Poco::JSON::Object O; | ||||||
| 				i.to_json(O); | 				i.to_json(O); | ||||||
|   | |||||||
| @@ -15,6 +15,12 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
| 	void RESTAPI_default_configurations::DoGet() { | 	void RESTAPI_default_configurations::DoGet() { | ||||||
|  |  | ||||||
|  | 		if(QB_.CountOnly) { | ||||||
|  | 			auto Count = StorageService()->GetDefaultConfigurationsCount(); | ||||||
|  | 			return ReturnCountOnly(Count); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		std::vector<GWObjects::DefaultConfiguration> DefConfigs; | 		std::vector<GWObjects::DefaultConfiguration> DefConfigs; | ||||||
| 		StorageService()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs); | 		StorageService()->GetDefaultConfigurations(QB_.Offset, QB_.Limit, DefConfigs); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -204,7 +204,7 @@ void RESTAPI_device_commandHandler::Configure() { | |||||||
| 			GWObjects::CommandDetails Cmd; | 			GWObjects::CommandDetails Cmd; | ||||||
|  |  | ||||||
| 			Cmd.SerialNumber = SerialNumber_; | 			Cmd.SerialNumber = SerialNumber_; | ||||||
| 			Cmd.UUID = MicroService::instance().CreateUUID(); | 			Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 			Cmd.SubmittedBy = UserInfo_.webtoken.username_; | 			Cmd.SubmittedBy = UserInfo_.webtoken.username_; | ||||||
| 			Cmd.Command = uCentralProtocol::CONFIGURE; | 			Cmd.Command = uCentralProtocol::CONFIGURE; | ||||||
| 			Cmd.RunAt = When; | 			Cmd.RunAt = When; | ||||||
| @@ -246,7 +246,7 @@ void RESTAPI_device_commandHandler::Upgrade() { | |||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
|  |  | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| 		Cmd.UUID = MicroService::instance().CreateUUID(); | 		Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | ||||||
| 		Cmd.Command = uCentralProtocol::UPGRADE; | 		Cmd.Command = uCentralProtocol::UPGRADE; | ||||||
| 		Cmd.RunAt = When; | 		Cmd.RunAt = When; | ||||||
| @@ -357,7 +357,7 @@ void RESTAPI_device_commandHandler::ExecuteCommand() { | |||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
|  |  | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| 		Cmd.UUID = MicroService::instance().CreateUUID(); | 		Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | ||||||
| 		Cmd.Command = Command; | 		Cmd.Command = Command; | ||||||
| 		Cmd.Custom = 1; | 		Cmd.Custom = 1; | ||||||
| @@ -397,7 +397,7 @@ void RESTAPI_device_commandHandler::Reboot() { | |||||||
| 		uint64_t When = GetWhen(Obj); | 		uint64_t When = GetWhen(Obj); | ||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| 		Cmd.UUID = MicroService::instance().CreateUUID(); | 		Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | ||||||
| 		Cmd.Command = uCentralProtocol::REBOOT; | 		Cmd.Command = uCentralProtocol::REBOOT; | ||||||
| 		Cmd.RunAt = When; | 		Cmd.RunAt = When; | ||||||
| @@ -434,7 +434,7 @@ void RESTAPI_device_commandHandler::Factory() { | |||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
|  |  | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| 		Cmd.UUID = MicroService::instance().CreateUUID(); | 		Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | ||||||
| 		Cmd.Command = uCentralProtocol::FACTORY; | 		Cmd.Command = uCentralProtocol::FACTORY; | ||||||
| 		Cmd.RunAt = When; | 		Cmd.RunAt = When; | ||||||
| @@ -480,7 +480,7 @@ void RESTAPI_device_commandHandler::LEDs() { | |||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
|  |  | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| 		Cmd.UUID = MicroService::instance().CreateUUID(); | 		Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | ||||||
| 		Cmd.Command = uCentralProtocol::LEDS; | 		Cmd.Command = uCentralProtocol::LEDS; | ||||||
| 		Cmd.RunAt = When; | 		Cmd.RunAt = When; | ||||||
| @@ -519,7 +519,7 @@ void RESTAPI_device_commandHandler::Trace() { | |||||||
|  |  | ||||||
| 		auto Network = GetS(RESTAPI::Protocol::NETWORK, Obj); | 		auto Network = GetS(RESTAPI::Protocol::NETWORK, Obj); | ||||||
| 		auto Interface = GetS(RESTAPI::Protocol::INTERFACE, Obj); | 		auto Interface = GetS(RESTAPI::Protocol::INTERFACE, Obj); | ||||||
| 		auto UUID = MicroService::instance().CreateUUID(); | 		auto UUID = MicroService::CreateUUID(); | ||||||
| 		auto URI = FileUploader()->FullName() + UUID; | 		auto URI = FileUploader()->FullName() + UUID; | ||||||
|  |  | ||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
| @@ -567,7 +567,7 @@ void RESTAPI_device_commandHandler::WifiScan() { | |||||||
| 		 (!Obj->has(RESTAPI::Protocol::BANDS) && | 		 (!Obj->has(RESTAPI::Protocol::BANDS) && | ||||||
| 		  !Obj->has(RESTAPI::Protocol::CHANNELS)))) { | 		  !Obj->has(RESTAPI::Protocol::CHANNELS)))) { | ||||||
| 		bool Verbose = GetB(RESTAPI::Protocol::VERBOSE, Obj); | 		bool Verbose = GetB(RESTAPI::Protocol::VERBOSE, Obj); | ||||||
| 		auto UUID = MicroService::instance().CreateUUID(); | 		auto UUID = MicroService::CreateUUID(); | ||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
|  |  | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| @@ -618,7 +618,7 @@ void RESTAPI_device_commandHandler::EventQueue() { | |||||||
|  |  | ||||||
| 		auto Types = Obj->getArray(RESTAPI::Protocol::TYPES); | 		auto Types = Obj->getArray(RESTAPI::Protocol::TYPES); | ||||||
|  |  | ||||||
| 		auto UUID = MicroService::instance().CreateUUID(); | 		auto UUID = MicroService::CreateUUID(); | ||||||
| 		GWObjects::CommandDetails Cmd; | 		GWObjects::CommandDetails Cmd; | ||||||
|  |  | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| @@ -664,7 +664,7 @@ void RESTAPI_device_commandHandler::MakeRequest() { | |||||||
|  |  | ||||||
| 		Cmd.SerialNumber = SerialNumber_; | 		Cmd.SerialNumber = SerialNumber_; | ||||||
| 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | 		Cmd.SubmittedBy = UserInfo_.webtoken.username_; | ||||||
| 		Cmd.UUID = MicroService::instance().CreateUUID(); | 		Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 		Cmd.Command = uCentralProtocol::REQUEST; | 		Cmd.Command = uCentralProtocol::REQUEST; | ||||||
| 		Cmd.RunAt = When; | 		Cmd.RunAt = When; | ||||||
|  |  | ||||||
| @@ -689,7 +689,7 @@ void RESTAPI_device_commandHandler::MakeRequest() { | |||||||
| 		if (MicroService::instance().ConfigGetString("rtty.enabled", "false") == "true") { | 		if (MicroService::instance().ConfigGetString("rtty.enabled", "false") == "true") { | ||||||
| 			GWObjects::Device	Device; | 			GWObjects::Device	Device; | ||||||
| 			if (StorageService()->GetDevice(SerialNumber_, Device)) { | 			if (StorageService()->GetDevice(SerialNumber_, Device)) { | ||||||
| 				auto CommandUUID = MicroService::instance().CreateUUID(); | 				auto CommandUUID = MicroService::CreateUUID(); | ||||||
|  |  | ||||||
| 				GWObjects::RttySessionDetails Rtty{ | 				GWObjects::RttySessionDetails Rtty{ | ||||||
| 					.SerialNumber = SerialNumber_, | 					.SerialNumber = SerialNumber_, | ||||||
|   | |||||||
| @@ -46,7 +46,8 @@ namespace OpenWifi { | |||||||
| 								if(!Authenticated) { | 								if(!Authenticated) { | ||||||
| 									std::string Frame{IncomingFrame.begin()}; | 									std::string Frame{IncomingFrame.begin()}; | ||||||
| 									auto Tokens = Utils::Split(Frame,':'); | 									auto Tokens = Utils::Split(Frame,':'); | ||||||
| 									if(Tokens.size()==2 && AuthClient()->IsTokenAuthorized(Tokens[1], UserInfo_)) { | 									bool Expired=false; | ||||||
|  | 									if(Tokens.size()==2 && AuthClient()->IsAuthorized(Tokens[1], UserInfo_, Expired)) { | ||||||
| 										Authenticated=true; | 										Authenticated=true; | ||||||
| 										std::string S{"Welcome! Bienvenue! Bienvenidos!"}; | 										std::string S{"Welcome! Bienvenue! Bienvenidos!"}; | ||||||
| 										WS.sendFrame(S.c_str(),S.size()); | 										WS.sendFrame(S.c_str(),S.size()); | ||||||
|   | |||||||
| @@ -12,6 +12,7 @@ | |||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #ifdef	TIP_GATEWAY_SERVICE | #ifdef	TIP_GATEWAY_SERVICE | ||||||
| #include "DeviceRegistry.h" | #include "DeviceRegistry.h" | ||||||
|  | #include "CapabilitiesCache.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #include "RESTAPI_GWobjects.h" | #include "RESTAPI_GWobjects.h" | ||||||
| @@ -26,7 +27,7 @@ namespace OpenWifi::GWObjects { | |||||||
| 	void Device::to_json(Poco::JSON::Object &Obj) const { | 	void Device::to_json(Poco::JSON::Object &Obj) const { | ||||||
| 		field_to_json(Obj,"serialNumber", SerialNumber); | 		field_to_json(Obj,"serialNumber", SerialNumber); | ||||||
| #ifdef TIP_GATEWAY_SERVICE | #ifdef TIP_GATEWAY_SERVICE | ||||||
| 		field_to_json(Obj,"deviceType", Daemon::instance()->IdentifyDevice(Compatible)); | 		field_to_json(Obj,"deviceType", CapabilitiesCache::instance()->Get(Compatible)); | ||||||
| #endif | #endif | ||||||
| 		field_to_json(Obj,"macAddress", MACAddress); | 		field_to_json(Obj,"macAddress", MACAddress); | ||||||
| 		field_to_json(Obj,"manufacturer", Manufacturer); | 		field_to_json(Obj,"manufacturer", Manufacturer); | ||||||
|   | |||||||
| @@ -10,27 +10,30 @@ | |||||||
| #include "RESTAPI_ProvObjects.h" | #include "RESTAPI_ProvObjects.h" | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  |  | ||||||
|  | using OpenWifi::RESTAPI_utils::field_to_json; | ||||||
|  | using OpenWifi::RESTAPI_utils::field_from_json; | ||||||
|  |  | ||||||
| namespace OpenWifi::ProvObjects { | namespace OpenWifi::ProvObjects { | ||||||
|  |  | ||||||
|     void ObjectInfo::to_json(Poco::JSON::Object &Obj) const { |     void ObjectInfo::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json(Obj,"id",id); |         field_to_json(Obj,"id",id); | ||||||
|         RESTAPI_utils::field_to_json(Obj,"name",name); |         field_to_json(Obj,"name",name); | ||||||
|         RESTAPI_utils::field_to_json(Obj,"description",description); |         field_to_json(Obj,"description",description); | ||||||
|         RESTAPI_utils::field_to_json(Obj,"created",created); |         field_to_json(Obj,"created",created); | ||||||
|         RESTAPI_utils::field_to_json(Obj,"modified",modified); |         field_to_json(Obj,"modified",modified); | ||||||
|         RESTAPI_utils::field_to_json(Obj,"notes",notes); |         field_to_json(Obj,"notes",notes); | ||||||
|         RESTAPI_utils::field_to_json(Obj,"tags",tags); |         field_to_json(Obj,"tags",tags); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool ObjectInfo::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool ObjectInfo::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json(Obj,"id",id); |             field_from_json(Obj,"id",id); | ||||||
|             RESTAPI_utils::field_from_json(Obj,"name",name); |             field_from_json(Obj,"name",name); | ||||||
|             RESTAPI_utils::field_from_json(Obj,"description",description); |             field_from_json(Obj,"description",description); | ||||||
|             RESTAPI_utils::field_from_json(Obj,"created",created); |             field_from_json(Obj,"created",created); | ||||||
|             RESTAPI_utils::field_from_json(Obj,"modified",modified); |             field_from_json(Obj,"modified",modified); | ||||||
|             RESTAPI_utils::field_from_json(Obj,"notes",notes); |             field_from_json(Obj,"notes",notes); | ||||||
|             RESTAPI_utils::field_from_json(Obj,"tags",tags); |             field_from_json(Obj,"tags",tags); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -39,18 +42,18 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void ManagementPolicyEntry::to_json(Poco::JSON::Object &Obj) const { |     void ManagementPolicyEntry::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json( Obj,"users",users); |         field_to_json( Obj,"users",users); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"resources",resources); |         field_to_json( Obj,"resources",resources); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"access",access); |         field_to_json( Obj,"access",access); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"policy",policy); |         field_to_json( Obj,"policy",policy); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool ManagementPolicyEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool ManagementPolicyEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json( Obj,"users",users); |             field_from_json( Obj,"users",users); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"resources",resources); |             field_from_json( Obj,"resources",resources); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"access",access); |             field_from_json( Obj,"access",access); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"policy",policy); |             field_from_json( Obj,"policy",policy); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -60,17 +63,17 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void ManagementPolicy::to_json(Poco::JSON::Object &Obj) const { |     void ManagementPolicy::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "entries", entries); |         field_to_json(Obj, "entries", entries); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "inUse", inUse); |         field_to_json(Obj, "inUse", inUse); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "entity", entity); |         field_to_json(Obj, "entity", entity); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool ManagementPolicy::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool ManagementPolicy::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             RESTAPI_utils::field_from_json(Obj, "entries", entries); |             field_from_json(Obj, "entries", entries); | ||||||
|             RESTAPI_utils::field_from_json(Obj, "inUse", inUse); |             field_from_json(Obj, "inUse", inUse); | ||||||
|             RESTAPI_utils::field_from_json(Obj, "entity", entity); |             field_from_json(Obj, "entity", entity); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -80,31 +83,31 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void Entity::to_json(Poco::JSON::Object &Obj) const { |     void Entity::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"parent",parent); |         field_to_json( Obj,"parent",parent); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"venues",venues); |         field_to_json( Obj,"venues",venues); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"children",children); |         field_to_json( Obj,"children",children); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"contacts",contacts); |         field_to_json( Obj,"contacts",contacts); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"locations",locations); |         field_to_json( Obj,"locations",locations); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); |         field_to_json( Obj,"managementPolicy",managementPolicy); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"deviceConfiguration",deviceConfiguration); |         field_to_json( Obj,"deviceConfiguration",deviceConfiguration); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"devices",devices); |         field_to_json( Obj,"devices",devices); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"rrm",rrm); |         field_to_json( Obj,"rrm",rrm); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"sourceIP",sourceIP); |         field_to_json( Obj,"sourceIP",sourceIP); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Entity::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool Entity::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"parent",parent); |             field_from_json( Obj,"parent",parent); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"venues",venues); |             field_from_json( Obj,"venues",venues); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"children",children); |             field_from_json( Obj,"children",children); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"contacts",contacts); |             field_from_json( Obj,"contacts",contacts); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"locations",locations); |             field_from_json( Obj,"locations",locations); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); |             field_from_json( Obj,"managementPolicy",managementPolicy); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"deviceConfiguration",deviceConfiguration); |             field_from_json( Obj,"deviceConfiguration",deviceConfiguration); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"devices",devices); |             field_from_json( Obj,"devices",devices); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"rrm",rrm); |             field_from_json( Obj,"rrm",rrm); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"sourceIP",sourceIP); |             field_from_json( Obj,"sourceIP",sourceIP); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -113,14 +116,14 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void DiGraphEntry::to_json(Poco::JSON::Object &Obj) const { |     void DiGraphEntry::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json( Obj,"parent",parent); |         field_to_json( Obj,"parent",parent); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"child",child); |         field_to_json( Obj,"child",child); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool DiGraphEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool DiGraphEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json( Obj,"parent",parent); |             field_from_json( Obj,"parent",parent); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"child",child); |             field_from_json( Obj,"child",child); | ||||||
|             return true; |             return true; | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
|  |  | ||||||
| @@ -130,37 +133,37 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void Venue::to_json(Poco::JSON::Object &Obj) const { |     void Venue::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"parent",parent); |         field_to_json( Obj,"parent",parent); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"entity",entity); |         field_to_json( Obj,"entity",entity); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"children",children); |         field_to_json( Obj,"children",children); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"devices",devices); |         field_to_json( Obj,"devices",devices); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"topology",topology); |         field_to_json( Obj,"topology",topology); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"parent",parent); |         field_to_json( Obj,"parent",parent); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"design",design); |         field_to_json( Obj,"design",design); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); |         field_to_json( Obj,"managementPolicy",managementPolicy); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"deviceConfiguration",deviceConfiguration); |         field_to_json( Obj,"deviceConfiguration",deviceConfiguration); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"contact",contact); |         field_to_json( Obj,"contact",contact); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"location",location); |         field_to_json( Obj,"location",location); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"rrm",rrm); |         field_to_json( Obj,"rrm",rrm); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"sourceIP",sourceIP); |         field_to_json( Obj,"sourceIP",sourceIP); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Venue::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool Venue::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"parent",parent); |             field_from_json( Obj,"parent",parent); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entity",entity); |             field_from_json( Obj,"entity",entity); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"children",children); |             field_from_json( Obj,"children",children); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"devices",devices); |             field_from_json( Obj,"devices",devices); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"topology",topology); |             field_from_json( Obj,"topology",topology); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"parent",parent); |             field_from_json( Obj,"parent",parent); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"design",design); |             field_from_json( Obj,"design",design); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); |             field_from_json( Obj,"managementPolicy",managementPolicy); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"deviceConfiguration",deviceConfiguration); |             field_from_json( Obj,"deviceConfiguration",deviceConfiguration); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"contact",contact); |             field_from_json( Obj,"contact",contact); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"location",location); |             field_from_json( Obj,"location",location); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"rrm",rrm); |             field_from_json( Obj,"rrm",rrm); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"sourceIP",sourceIP); |             field_from_json( Obj,"sourceIP",sourceIP); | ||||||
|             return true; |             return true; | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
|  |  | ||||||
| @@ -169,16 +172,16 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void UserInfoDigest::to_json(Poco::JSON::Object &Obj) const { |     void UserInfoDigest::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json( Obj,"id",id); |         field_to_json( Obj,"id",id); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"entity",loginId); |         field_to_json( Obj,"entity",loginId); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"children",userType); |         field_to_json( Obj,"children",userType); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool UserInfoDigest::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool UserInfoDigest::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json( Obj,"id",id); |             field_from_json( Obj,"id",id); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entity",loginId); |             field_from_json( Obj,"entity",loginId); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"children",userType); |             field_from_json( Obj,"children",userType); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|         } |         } | ||||||
| @@ -187,17 +190,17 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void ManagementRole::to_json(Poco::JSON::Object &Obj) const { |     void ManagementRole::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); |         field_to_json( Obj,"managementPolicy",managementPolicy); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"users",users); |         field_to_json( Obj,"users",users); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"entity",entity); |         field_to_json( Obj,"entity",entity); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool ManagementRole::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool ManagementRole::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); |             field_from_json( Obj,"managementPolicy",managementPolicy); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"users",users); |             field_from_json( Obj,"users",users); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entity",entity); |             field_from_json( Obj,"entity",entity); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|         } |         } | ||||||
| @@ -206,39 +209,39 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void Location::to_json(Poco::JSON::Object &Obj) const { |     void Location::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"type",OpenWifi::ProvObjects::to_string(type)); |         field_to_json( Obj,"type",OpenWifi::ProvObjects::to_string(type)); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"buildingName",buildingName); |         field_to_json( Obj,"buildingName",buildingName); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"addressLines",addressLines); |         field_to_json( Obj,"addressLines",addressLines); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"city",city); |         field_to_json( Obj,"city",city); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"state",state); |         field_to_json( Obj,"state",state); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"postal",postal); |         field_to_json( Obj,"postal",postal); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"country",country); |         field_to_json( Obj,"country",country); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"phones",phones); |         field_to_json( Obj,"phones",phones); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"mobiles",mobiles); |         field_to_json( Obj,"mobiles",mobiles); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"geoCode",geoCode); |         field_to_json( Obj,"geoCode",geoCode); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"inUse",inUse); |         field_to_json( Obj,"inUse",inUse); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"entity",entity); |         field_to_json( Obj,"entity",entity); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); |         field_to_json( Obj,"managementPolicy",managementPolicy); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             std::string tmp_type; |             std::string tmp_type; | ||||||
|             RESTAPI_utils::field_from_json( Obj,"type", tmp_type); |             field_from_json( Obj,"type", tmp_type); | ||||||
|             type = location_from_string(tmp_type); |             type = location_from_string(tmp_type); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"buildingName",buildingName); |             field_from_json( Obj,"buildingName",buildingName); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"addressLines",addressLines); |             field_from_json( Obj,"addressLines",addressLines); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"city",city); |             field_from_json( Obj,"city",city); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"state",state); |             field_from_json( Obj,"state",state); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"postal",postal); |             field_from_json( Obj,"postal",postal); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"country",country); |             field_from_json( Obj,"country",country); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"phones",phones); |             field_from_json( Obj,"phones",phones); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"mobiles",mobiles); |             field_from_json( Obj,"mobiles",mobiles); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"geoCode",geoCode); |             field_from_json( Obj,"geoCode",geoCode); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"inUse",inUse); |             field_from_json( Obj,"inUse",inUse); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entity",entity); |             field_from_json( Obj,"entity",entity); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); |             field_from_json( Obj,"managementPolicy",managementPolicy); | ||||||
|             return true; |             return true; | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
|  |  | ||||||
| @@ -248,43 +251,43 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void Contact::to_json(Poco::JSON::Object &Obj) const { |     void Contact::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"type", to_string(type)); |         field_to_json( Obj,"type", to_string(type)); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"title",title); |         field_to_json( Obj,"title",title); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"salutation",salutation); |         field_to_json( Obj,"salutation",salutation); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"firstname",firstname); |         field_to_json( Obj,"firstname",firstname); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"lastname",lastname); |         field_to_json( Obj,"lastname",lastname); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"initials",initials); |         field_to_json( Obj,"initials",initials); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"visual",visual); |         field_to_json( Obj,"visual",visual); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"mobiles",mobiles); |         field_to_json( Obj,"mobiles",mobiles); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"phones",phones); |         field_to_json( Obj,"phones",phones); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"primaryEmail",primaryEmail); |         field_to_json( Obj,"primaryEmail",primaryEmail); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"secondaryEmail",secondaryEmail); |         field_to_json( Obj,"secondaryEmail",secondaryEmail); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"accessPIN",accessPIN); |         field_to_json( Obj,"accessPIN",accessPIN); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"inUse",inUse); |         field_to_json( Obj,"inUse",inUse); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"entity",entity); |         field_to_json( Obj,"entity",entity); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); |         field_to_json( Obj,"managementPolicy",managementPolicy); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Contact::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool Contact::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             std::string tmp_type; |             std::string tmp_type; | ||||||
|             RESTAPI_utils::field_from_json( Obj,"type", tmp_type); |             field_from_json( Obj,"type", tmp_type); | ||||||
|             type = contact_from_string(tmp_type); |             type = contact_from_string(tmp_type); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"title",title); |             field_from_json( Obj,"title",title); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"salutation",salutation); |             field_from_json( Obj,"salutation",salutation); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"firstname",firstname); |             field_from_json( Obj,"firstname",firstname); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"lastname",lastname); |             field_from_json( Obj,"lastname",lastname); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"initials",initials); |             field_from_json( Obj,"initials",initials); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"visual",visual); |             field_from_json( Obj,"visual",visual); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"mobiles",mobiles); |             field_from_json( Obj,"mobiles",mobiles); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"phones",phones); |             field_from_json( Obj,"phones",phones); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"primaryEmail",primaryEmail); |             field_from_json( Obj,"primaryEmail",primaryEmail); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"secondaryEmail",secondaryEmail); |             field_from_json( Obj,"secondaryEmail",secondaryEmail); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"accessPIN",accessPIN); |             field_from_json( Obj,"accessPIN",accessPIN); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"inUse",inUse); |             field_from_json( Obj,"inUse",inUse); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entity",entity); |             field_from_json( Obj,"entity",entity); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); |             field_from_json( Obj,"managementPolicy",managementPolicy); | ||||||
|             return true; |             return true; | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
|  |  | ||||||
| @@ -294,35 +297,35 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void InventoryTag::to_json(Poco::JSON::Object &Obj) const { |     void InventoryTag::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "serialNumber", serialNumber); |         field_to_json(Obj, "serialNumber", serialNumber); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "venue", venue); |         field_to_json(Obj, "venue", venue); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "entity", entity); |         field_to_json(Obj, "entity", entity); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "subscriber", subscriber); |         field_to_json(Obj, "subscriber", subscriber); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "deviceType", deviceType); |         field_to_json(Obj, "deviceType", deviceType); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "qrCode", qrCode); |         field_to_json(Obj, "qrCode", qrCode); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "geoCode", geoCode); |         field_to_json(Obj, "geoCode", geoCode); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "location", location); |         field_to_json(Obj, "location", location); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "contact", contact); |         field_to_json(Obj, "contact", contact); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"deviceConfiguration",deviceConfiguration); |         field_to_json( Obj,"deviceConfiguration",deviceConfiguration); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"rrm",rrm); |         field_to_json( Obj,"rrm",rrm); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); |         field_to_json( Obj,"managementPolicy",managementPolicy); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"serialNumber",serialNumber); |             field_from_json( Obj,"serialNumber",serialNumber); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"venue",venue); |             field_from_json( Obj,"venue",venue); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entity",entity); |             field_from_json( Obj,"entity",entity); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"subscriber",subscriber); |             field_from_json( Obj,"subscriber",subscriber); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"deviceType",deviceType); |             field_from_json( Obj,"deviceType",deviceType); | ||||||
|             RESTAPI_utils::field_from_json(Obj, "qrCode", qrCode); |             field_from_json(Obj, "qrCode", qrCode); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"geoCode",geoCode); |             field_from_json( Obj,"geoCode",geoCode); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"location",location); |             field_from_json( Obj,"location",location); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"contact",contact); |             field_from_json( Obj,"contact",contact); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"deviceConfiguration",deviceConfiguration); |             field_from_json( Obj,"deviceConfiguration",deviceConfiguration); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"rrm",rrm); |             field_from_json( Obj,"rrm",rrm); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); |             field_from_json( Obj,"managementPolicy",managementPolicy); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -331,18 +334,18 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const { |     void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json( Obj,"name", name); |         field_to_json( Obj,"name", name); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"description", description); |         field_to_json( Obj,"description", description); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"weight", weight); |         field_to_json( Obj,"weight", weight); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"configuration", configuration); |         field_to_json( Obj,"configuration", configuration); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool DeviceConfigurationElement::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool DeviceConfigurationElement::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json( Obj,"name",name); |             field_from_json( Obj,"name",name); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"description",description); |             field_from_json( Obj,"description",description); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"weight",weight); |             field_from_json( Obj,"weight",weight); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"configuration",configuration); |             field_from_json( Obj,"configuration",configuration); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -352,27 +355,27 @@ namespace OpenWifi::ProvObjects { | |||||||
|  |  | ||||||
|     void DeviceConfiguration::to_json(Poco::JSON::Object &Obj) const { |     void DeviceConfiguration::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         info.to_json(Obj); |         info.to_json(Obj); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"managementPolicy",managementPolicy); |         field_to_json( Obj,"managementPolicy",managementPolicy); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"deviceTypes",deviceTypes); |         field_to_json( Obj,"deviceTypes",deviceTypes); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"configuration",configuration); |         field_to_json( Obj,"configuration",configuration); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"inUse",inUse); |         field_to_json( Obj,"inUse",inUse); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"variables",variables); |         field_to_json( Obj,"variables",variables); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"rrm",rrm); |         field_to_json( Obj,"rrm",rrm); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"firmwareUpgrade",firmwareUpgrade); |         field_to_json( Obj,"firmwareUpgrade",firmwareUpgrade); | ||||||
|         RESTAPI_utils::field_to_json( Obj,"firmwareRCOnly",firmwareRCOnly); |         field_to_json( Obj,"firmwareRCOnly",firmwareRCOnly); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool DeviceConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool DeviceConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             info.from_json(Obj); |             info.from_json(Obj); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"managementPolicy",managementPolicy); |             field_from_json( Obj,"managementPolicy",managementPolicy); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"deviceTypes",deviceTypes); |             field_from_json( Obj,"deviceTypes",deviceTypes); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"configuration",configuration); |             field_from_json( Obj,"configuration",configuration); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"inUse",inUse); |             field_from_json( Obj,"inUse",inUse); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"variables",variables); |             field_from_json( Obj,"variables",variables); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"rrm",rrm); |             field_from_json( Obj,"rrm",rrm); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"firmwareUpgrade",firmwareUpgrade); |             field_from_json( Obj,"firmwareUpgrade",firmwareUpgrade); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"firmwareRCOnly",firmwareRCOnly); |             field_from_json( Obj,"firmwareRCOnly",firmwareRCOnly); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -381,8 +384,8 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Report::to_json(Poco::JSON::Object &Obj) const { |     void Report::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json(Obj, "snapshot", snapShot); |         field_to_json(Obj, "snapshot", snapShot); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "devices", tenants); |         field_to_json(Obj, "devices", tenants); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     void Report::reset() { |     void Report::reset() { | ||||||
| @@ -390,16 +393,16 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void ExpandedUseEntry::to_json(Poco::JSON::Object &Obj) const { |     void ExpandedUseEntry::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json(Obj, "uuid", uuid); |         field_to_json(Obj, "uuid", uuid); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "name", name); |         field_to_json(Obj, "name", name); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "description", description); |         field_to_json(Obj, "description", description); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool ExpandedUseEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool ExpandedUseEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json( Obj,"uuid",uuid); |             field_from_json( Obj,"uuid",uuid); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"name",name); |             field_from_json( Obj,"name",name); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"description",description); |             field_from_json( Obj,"description",description); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -408,14 +411,14 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void ExpandedUseEntryList::to_json(Poco::JSON::Object &Obj) const { |     void ExpandedUseEntryList::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json(Obj, "type", type); |         field_to_json(Obj, "type", type); | ||||||
|         RESTAPI_utils::field_to_json(Obj, "entries", entries); |         field_to_json(Obj, "entries", entries); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool ExpandedUseEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool ExpandedUseEntryList::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json( Obj,"type",type); |             field_from_json( Obj,"type",type); | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entries",entries); |             field_from_json( Obj,"entries",entries); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -424,12 +427,157 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void ExpandedUseEntryMapList::to_json(Poco::JSON::Object &Obj) const { |     void ExpandedUseEntryMapList::to_json(Poco::JSON::Object &Obj) const { | ||||||
|         RESTAPI_utils::field_to_json(Obj, "entries", entries); |         field_to_json(Obj, "entries", entries); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool ExpandedUseEntryMapList::from_json(const Poco::JSON::Object::Ptr &Obj) { |     bool ExpandedUseEntryMapList::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         try { |         try { | ||||||
|             RESTAPI_utils::field_from_json( Obj,"entries",entries); |             field_from_json( Obj,"entries",entries); | ||||||
|  |             return true; | ||||||
|  |         } catch(...) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void UuidList::to_json(Poco::JSON::Object &Obj) const { | ||||||
|  |         field_to_json(Obj, "list", list); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool UuidList::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|  |         try { | ||||||
|  |             field_from_json(Obj, "list", list); | ||||||
|  |             return true; | ||||||
|  |         } catch(...) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void field_to_json(Poco::JSON::Object &Obj, const char * FieldName, ACLACCESS A) { | ||||||
|  |         switch(A) { | ||||||
|  |             case READ: Obj.set(FieldName,"read"); break; | ||||||
|  |             case MODIFY: Obj.set(FieldName,"modify"); break; | ||||||
|  |             case CREATE: Obj.set(FieldName,"create"); break; | ||||||
|  |             case DELETE: Obj.set(FieldName,"delete"); break; | ||||||
|  |             case NONE: | ||||||
|  |                 default: | ||||||
|  |                     Obj.set(FieldName,"none"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char * FieldName, ACLACCESS &A) { | ||||||
|  |         if(Obj->has(FieldName)) { | ||||||
|  |             auto V = Obj->getValue<std::string>(FieldName); | ||||||
|  |             if(V=="read") | ||||||
|  |                 A = READ; | ||||||
|  |             else if(V=="modify") | ||||||
|  |                 A = MODIFY; | ||||||
|  |             else if(V=="create") | ||||||
|  |                 A = CREATE; | ||||||
|  |             else if(V=="delete") | ||||||
|  |                 A = DELETE; | ||||||
|  |             else if(V=="none") | ||||||
|  |                 A = NONE; | ||||||
|  |             else | ||||||
|  |                 throw Poco::Exception("invalid JSON"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ObjectACL::to_json(Poco::JSON::Object &Obj) const { | ||||||
|  |         RESTAPI_utils::field_to_json(Obj, "users", users); | ||||||
|  |         RESTAPI_utils::field_to_json(Obj, "roles", roles); | ||||||
|  |         field_to_json(Obj, "access", access); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool ObjectACL::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|  |         try { | ||||||
|  |             RESTAPI_utils::field_from_json(Obj, "users", users); | ||||||
|  |             RESTAPI_utils::field_from_json(Obj, "roles", roles); | ||||||
|  |             field_from_json(Obj, "access", access); | ||||||
|  |             return true; | ||||||
|  |         } catch(...) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     void ObjectACLList::to_json(Poco::JSON::Object &Obj) const { | ||||||
|  |         RESTAPI_utils::field_to_json(Obj, "list", list); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool ObjectACLList::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|  |         try { | ||||||
|  |             RESTAPI_utils::field_from_json(Obj, "list", list); | ||||||
|  |             return true; | ||||||
|  |         } catch(...) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::string to_string(VISIBILITY A) { | ||||||
|  |         switch(A) { | ||||||
|  |             case PUBLIC: return "public"; | ||||||
|  |             case SELECT: return "select"; | ||||||
|  |             case PRIVATE: | ||||||
|  |             default: | ||||||
|  |                 return "private"; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void field_to_json(Poco::JSON::Object &Obj, const char * FieldName, VISIBILITY A) { | ||||||
|  |         Obj.set(FieldName,to_string(A)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     VISIBILITY visibility_from_string(const std::string &V) { | ||||||
|  |         if(V=="public") | ||||||
|  |             return PUBLIC; | ||||||
|  |         else if(V=="select") | ||||||
|  |             return SELECT; | ||||||
|  |         else if(V=="private") | ||||||
|  |             return PRIVATE; | ||||||
|  |         throw Poco::Exception("invalid json"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char * FieldName, VISIBILITY &A) { | ||||||
|  |         if(Obj->has(FieldName)) { | ||||||
|  |             auto V = Obj->getValue<std::string>(FieldName); | ||||||
|  |             A = visibility_from_string(V); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void Map::to_json(Poco::JSON::Object &Obj) const { | ||||||
|  |         info.to_json(Obj); | ||||||
|  |         RESTAPI_utils::field_to_json( Obj,"data",data); | ||||||
|  |         RESTAPI_utils::field_to_json( Obj,"entity",entity); | ||||||
|  |         RESTAPI_utils::field_to_json( Obj,"creator",creator); | ||||||
|  |         field_to_json( Obj,"visibility",visibility); | ||||||
|  |         RESTAPI_utils::field_to_json( Obj,"access",access); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool Map::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|  |         try { | ||||||
|  |             info.from_json(Obj); | ||||||
|  |             RESTAPI_utils::field_from_json( Obj,"data",data); | ||||||
|  |             RESTAPI_utils::field_from_json( Obj,"entity",entity); | ||||||
|  |             RESTAPI_utils::field_from_json( Obj,"creator",creator); | ||||||
|  |             field_from_json( Obj,"visibility",visibility); | ||||||
|  |             RESTAPI_utils::field_from_json( Obj,"access",access); | ||||||
|  |             return true; | ||||||
|  |         } catch(...) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void MapList::to_json(Poco::JSON::Object &Obj) const { | ||||||
|  |         RESTAPI_utils::field_to_json( Obj,"list",list); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool MapList::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||||
|  |         try { | ||||||
|  |             RESTAPI_utils::field_from_json( Obj,"list",list); | ||||||
|             return true; |             return true; | ||||||
|         } catch(...) { |         } catch(...) { | ||||||
|  |  | ||||||
| @@ -438,13 +586,48 @@ namespace OpenWifi::ProvObjects { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) { |     bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) { | ||||||
|  |         uint64_t Now = std::time(nullptr); | ||||||
|         if(O->has("name")) |         if(O->has("name")) | ||||||
|             I.name = O->get("name").toString(); |             I.name = O->get("name").toString(); | ||||||
|  |  | ||||||
|  |         if(I.name.empty()) | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|         if(O->has("description")) |         if(O->has("description")) | ||||||
|             I.description = O->get("description").toString(); |             I.description = O->get("description").toString(); | ||||||
|         SecurityObjects::MergeNotes(O,U,I.notes); |         SecurityObjects::MergeNotes(O,U,I.notes); | ||||||
|         I.modified = std::time(nullptr); |         SecurityObjects::NoteInfoVec N; | ||||||
|  |         for(auto &i:I.notes) { | ||||||
|  |             if(i.note.empty()) | ||||||
|  |                 continue; | ||||||
|  |             N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note}); | ||||||
|  |         } | ||||||
|  |         I.modified = Now; | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| }; |     bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I) { | ||||||
|  |         uint64_t Now = std::time(nullptr); | ||||||
|  |         if(O->has("name")) | ||||||
|  |             I.name = O->get("name").toString(); | ||||||
|  |  | ||||||
|  |         if(I.name.empty()) | ||||||
|  |             return false; | ||||||
|  |  | ||||||
|  |         if(O->has("description")) | ||||||
|  |             I.description = O->get("description").toString(); | ||||||
|  |  | ||||||
|  |         SecurityObjects::NoteInfoVec N; | ||||||
|  |         for(auto &i:I.notes) { | ||||||
|  |             if(i.note.empty()) | ||||||
|  |                 continue; | ||||||
|  |             N.push_back(SecurityObjects::NoteInfo{.created=Now,.createdBy=U.email,.note=i.note}); | ||||||
|  |         } | ||||||
|  |         I.notes = N; | ||||||
|  |         I.modified = I.created = Now; | ||||||
|  |         I.id = MicroService::CreateUUID(); | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,6 +15,13 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi::ProvObjects { | namespace OpenWifi::ProvObjects { | ||||||
|  |  | ||||||
|  |     enum FIRMWARE_UPGRADE_RULES { | ||||||
|  |         dont_upgrade, | ||||||
|  |         upgrade_inherit, | ||||||
|  |         upgrade_release_only, | ||||||
|  |         upgrade_latest | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     struct ObjectInfo { |     struct ObjectInfo { | ||||||
|         Types::UUID_t   id; |         Types::UUID_t   id; | ||||||
|         std::string     name; |         std::string     name; | ||||||
| @@ -317,7 +324,61 @@ namespace OpenWifi::ProvObjects { | |||||||
|         bool from_json(const Poco::JSON::Object::Ptr &Obj); |         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     struct UuidList { | ||||||
|  |         std::vector<std::string>    list; | ||||||
|  |  | ||||||
|  |         void to_json(Poco::JSON::Object &Obj) const; | ||||||
|  |         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     enum ACLACCESS { | ||||||
|  |         NONE, READ, MODIFY, CREATE, DELETE | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     struct ObjectACL { | ||||||
|  |         UuidList        users; | ||||||
|  |         UuidList        roles; | ||||||
|  |         ACLACCESS       access = NONE; | ||||||
|  |  | ||||||
|  |         void to_json(Poco::JSON::Object &Obj) const; | ||||||
|  |         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     struct ObjectACLList { | ||||||
|  |         std::vector<ObjectACL>  list; | ||||||
|  |  | ||||||
|  |         void to_json(Poco::JSON::Object &Obj) const; | ||||||
|  |         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     enum VISIBILITY { | ||||||
|  |         PUBLIC, PRIVATE, SELECT | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     std::string to_string(VISIBILITY A); | ||||||
|  |     VISIBILITY visibility_from_string(const std::string &V); | ||||||
|  |  | ||||||
|  |     struct Map { | ||||||
|  |         ObjectInfo          info; | ||||||
|  |         std::string         data; | ||||||
|  |         std::string         entity; | ||||||
|  |         std::string         creator; | ||||||
|  |         VISIBILITY          visibility = PRIVATE; | ||||||
|  |         ObjectACLList       access; | ||||||
|  |  | ||||||
|  |         void to_json(Poco::JSON::Object &Obj) const; | ||||||
|  |         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     struct MapList { | ||||||
|  |         std::vector<Map>    list; | ||||||
|  |  | ||||||
|  |         void to_json(Poco::JSON::Object &Obj) const; | ||||||
|  |         bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||||
|  |     }; | ||||||
|  |  | ||||||
|     bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I); |     bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I); | ||||||
|  |     bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -491,7 +491,6 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 	    field_to_json(Obj,"expires",expires); | 	    field_to_json(Obj,"expires",expires); | ||||||
| 	    field_to_json(Obj,"completed",completed); | 	    field_to_json(Obj,"completed",completed); | ||||||
| 	    field_to_json(Obj,"canceled",canceled); | 	    field_to_json(Obj,"canceled",canceled); | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) { |     bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) { | ||||||
| @@ -511,6 +510,24 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 	        return true; | 	        return true; | ||||||
| 	    } catch(...) { | 	    } catch(...) { | ||||||
|  |  | ||||||
|  | 	    } | ||||||
|  | 	    return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |     void Preferences::to_json(Poco::JSON::Object &Obj) const { | ||||||
|  | 	    field_to_json(Obj,"id",id); | ||||||
|  | 	    field_to_json(Obj,"modified",modified); | ||||||
|  | 	    field_to_json(Obj,"data",data); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  |     bool Preferences::from_json(Poco::JSON::Object::Ptr &Obj) { | ||||||
|  | 	    try { | ||||||
|  | 	        field_from_json(Obj,"id",id); | ||||||
|  | 	        field_from_json(Obj,"modified",modified); | ||||||
|  | 	        field_from_json(Obj,"data",data); | ||||||
|  | 	        return true; | ||||||
|  | 	    } catch(...) { | ||||||
|  |  | ||||||
| 	    } | 	    } | ||||||
| 	    return false; | 	    return false; | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -9,8 +9,8 @@ | |||||||
| #ifndef UCENTRAL_RESTAPI_SECURITYOBJECTS_H | #ifndef UCENTRAL_RESTAPI_SECURITYOBJECTS_H | ||||||
| #define UCENTRAL_RESTAPI_SECURITYOBJECTS_H | #define UCENTRAL_RESTAPI_SECURITYOBJECTS_H | ||||||
|  |  | ||||||
| #include "Poco/JSON/Object.h" |  | ||||||
| #include "framework/OpenWifiTypes.h" | #include "framework/OpenWifiTypes.h" | ||||||
|  | #include "Poco/JSON/Object.h" | ||||||
|  |  | ||||||
| namespace OpenWifi::SecurityObjects { | namespace OpenWifi::SecurityObjects { | ||||||
|  |  | ||||||
| @@ -59,15 +59,15 @@ namespace OpenWifi::SecurityObjects { | |||||||
|  |  | ||||||
| 	struct MobilePhoneNumber { | 	struct MobilePhoneNumber { | ||||||
| 	    std::string number; | 	    std::string number; | ||||||
| 	    bool verified; | 	    bool verified = false; | ||||||
| 	    bool primary; | 	    bool primary = false; | ||||||
|  |  | ||||||
| 	    void to_json(Poco::JSON::Object &Obj) const; | 	    void to_json(Poco::JSON::Object &Obj) const; | ||||||
| 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	struct MfaAuthInfo { | 	struct MfaAuthInfo { | ||||||
| 	    bool enabled; | 	    bool enabled = false; | ||||||
| 	    std::string method; | 	    std::string method; | ||||||
|  |  | ||||||
| 	    void to_json(Poco::JSON::Object &Obj) const; | 	    void to_json(Poco::JSON::Object &Obj) const; | ||||||
| @@ -86,7 +86,7 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 	    std::string uuid; | 	    std::string uuid; | ||||||
| 	    std::string question; | 	    std::string question; | ||||||
| 	    std::string method; | 	    std::string method; | ||||||
| 	    uint64_t    created; | 	    uint64_t    created = std::time(nullptr); | ||||||
|  |  | ||||||
| 	    void to_json(Poco::JSON::Object &Obj) const; | 	    void to_json(Poco::JSON::Object &Obj) const; | ||||||
| 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | ||||||
| @@ -244,6 +244,14 @@ namespace OpenWifi::SecurityObjects { | |||||||
|         void to_json(Poco::JSON::Object &Obj) const; |         void to_json(Poco::JSON::Object &Obj) const; | ||||||
| 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  | 	struct Preferences { | ||||||
|  | 	    std::string                         id; | ||||||
|  | 	    uint64_t                            modified; | ||||||
|  | 	    Types::StringPairVec                data; | ||||||
|  | 	    void to_json(Poco::JSON::Object &Obj) const; | ||||||
|  | 	    bool from_json(Poco::JSON::Object::Ptr &Obj); | ||||||
|  | 	}; | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif //UCENTRAL_RESTAPI_SECURITYOBJECTS_H | #endif //UCENTRAL_RESTAPI_SECURITYOBJECTS_H | ||||||
| @@ -11,9 +11,9 @@ namespace OpenWifi { | |||||||
| 	class SerialNumberCache : public SubSystemServer { | 	class SerialNumberCache : public SubSystemServer { | ||||||
| 		public: | 		public: | ||||||
|  |  | ||||||
| 		static SerialNumberCache *instance() { | 		static SerialNumberCache * instance() { | ||||||
| 			static SerialNumberCache instance; | 		    static SerialNumberCache * instance_ = new SerialNumberCache; | ||||||
| 			return &instance; | 			return instance_; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		int Start() override; | 		int Start() override; | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ namespace OpenWifi { | |||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if(Conn_) | 				if(Conn_) | ||||||
| 					GetAssociations(O,Conn_->Associations_2G,Conn_->Associations_5G); | 					GetAssociations(O,Conn_->Conn_.Associations_2G,Conn_->Conn_.Associations_5G); | ||||||
|  |  | ||||||
| 				if(UpdatesSinceLastWrite_>10) | 				if(UpdatesSinceLastWrite_>10) | ||||||
| 					Save(); | 					Save(); | ||||||
|   | |||||||
| @@ -9,11 +9,12 @@ | |||||||
| #include "Poco/JSON/Object.h" | #include "Poco/JSON/Object.h" | ||||||
| #include "Poco/Logger.h" | #include "Poco/Logger.h" | ||||||
| #include "RESTObjects//RESTAPI_GWobjects.h" | #include "RESTObjects//RESTAPI_GWobjects.h" | ||||||
|  | #include "DeviceRegistry.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
| 	class StateProcessor { | 	class StateProcessor { | ||||||
| 	  public: | 	  public: | ||||||
| 		explicit StateProcessor(GWObjects::ConnectionState * Conn, Poco::Logger & L): | 		explicit StateProcessor(std::shared_ptr<DeviceRegistry::ConnectionEntry> Conn, Poco::Logger & L): | ||||||
|  			Conn_(Conn), Logger_(L) {} |  			Conn_(Conn), Logger_(L) {} | ||||||
|  |  | ||||||
| 		~StateProcessor() { | 		~StateProcessor() { | ||||||
| @@ -37,7 +38,7 @@ namespace OpenWifi { | |||||||
| 		// interface name is the key, each entry is a map with the stats name as key and then the value | 		// interface name is the key, each entry is a map with the stats name as key and then the value | ||||||
| 		std::map<std::string,std::map<std::string,uint64_t>>	Stats_; | 		std::map<std::string,std::map<std::string,uint64_t>>	Stats_; | ||||||
| 		uint64_t 						UpdatesSinceLastWrite_ = 0 ; | 		uint64_t 						UpdatesSinceLastWrite_ = 0 ; | ||||||
| 		GWObjects::ConnectionState	* 	Conn_ = nullptr; | 		std::shared_ptr<DeviceRegistry::ConnectionEntry> 	Conn_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,90 +10,66 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| 	void StorageArchiver::run() { | 	void Archiver::onTimer(Poco::Timer &timer){ | ||||||
| 		Running_ = true ; | 		auto Now = std::time(nullptr); | ||||||
| 		GetLastRun(); | 		for(const auto &i:DBs_) { | ||||||
| 		while(Running_) { | 			if (!Poco::icompare(i.DBName, "healthchecks")) { | ||||||
| 			Poco::Thread::trySleep(2000); | 				Logger_.information("Archiving HealthChecks..."); | ||||||
| 			Poco::DateTime	Now; | 				StorageService()->RemoveHealthChecksRecordsOlderThan( | ||||||
|  | 					Now - (i.HowManyDays * 24 * 60 * 60)); | ||||||
| 			if(!Running_) | 			} else if (!Poco::icompare(i.DBName, "statistics")) { | ||||||
| 				break; | 				Logger_.information("Archiving Statistics..."); | ||||||
|  | 				StorageService()->RemoveStatisticsRecordsOlderThan( | ||||||
| 			if(LastRun_!=Now.day()) { | 					Now - (i.HowManyDays * 24 * 60 * 60)); | ||||||
| 				if(Now.hour()>=RunAtHour_ && Now.minute()>=RunAtMin_) { | 			} else if (!Poco::icompare(i.DBName, "devicelogs")) { | ||||||
| 					std::lock_guard G(Mutex_); | 				Logger_.information("Archiving Device Logs..."); | ||||||
| 					for(const auto &i:DBs_) { | 				StorageService()->RemoveDeviceLogsRecordsOlderThan( | ||||||
| 						if (!Poco::icompare(i.DBName, "healthchecks")) { | 					Now - (i.HowManyDays * 24 * 60 * 60)); | ||||||
| 							Logger_.information("Archiving HealthChecks..."); | 			} else if (!Poco::icompare(i.DBName, "commandlist")) { | ||||||
| 							StorageService()->RemoveHealthChecksRecordsOlderThan( | 				Logger_.information("Archiving Command History..."); | ||||||
| 								std::time(nullptr) - (i.HowManyDays * 24 * 60 * 60)); | 				StorageService()->RemoveCommandListRecordsOlderThan( | ||||||
| 						} else if (!Poco::icompare(i.DBName, "statistics")) { | 					Now - (i.HowManyDays * 24 * 60 * 60)); | ||||||
| 							Logger_.information("Archiving Statistics..."); | 			} else { | ||||||
| 							StorageService()->RemoveStatisticsRecordsOlderThan( | 				Logger_.information(Poco::format("Cannot archive DB '%s'", i.DBName)); | ||||||
| 								std::time(nullptr) - (i.HowManyDays * 24 * 60 * 60)); |  | ||||||
| 						} else if (!Poco::icompare(i.DBName, "devicelogs")) { |  | ||||||
| 							Logger_.information("Archiving Device Logs..."); |  | ||||||
| 							StorageService()->RemoveDeviceLogsRecordsOlderThan( |  | ||||||
| 								std::time(nullptr) - (i.HowManyDays * 24 * 60 * 60)); |  | ||||||
| 						} else if (!Poco::icompare(i.DBName, "commandlist")) { |  | ||||||
| 							Logger_.information("Archiving Command History..."); |  | ||||||
| 							StorageService()->RemoveCommandListRecordsOlderThan( |  | ||||||
| 								std::time(nullptr) - (i.HowManyDays * 24 * 60 * 60)); |  | ||||||
| 						} else { |  | ||||||
| 						} |  | ||||||
| 					} |  | ||||||
| 					LastRun_ = Now.day(); |  | ||||||
| 					SetLastRun(); |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		AppServiceRegistry().Set("lastStorageArchiverRun", (uint64_t) Now); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void StorageArchiver::GetLastRun() { | 	static auto CalculateDelta(int H, int M) { | ||||||
| 		try { | 		Poco::LocalDateTime dt; | ||||||
| 			Poco::File	LR(LastRunFileName_); | 		Poco::LocalDateTime scheduled(dt.year(), dt.month(), dt.day(), H, M, 0); | ||||||
| 			try { |  | ||||||
| 				if (LR.exists()) { |  | ||||||
| 					std::ifstream I; |  | ||||||
| 					I.open(LR.path()); |  | ||||||
| 					I >> LastRun_; |  | ||||||
| 					I.close(); |  | ||||||
| 				} else { |  | ||||||
| 					LastRun_ = 0; |  | ||||||
| 				} |  | ||||||
| 			} catch(...) { |  | ||||||
| 				LastRun_=0; |  | ||||||
| 			} |  | ||||||
| 		} catch(...) { |  | ||||||
| 			LastRun_=0; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void StorageArchiver::SetLastRun() { | 		size_t delta = 0; | ||||||
| 		try { | 		if ((dt.hour() < H) || (dt.hour()==H && dt.minute()<M)) { | ||||||
| 			std::ofstream O; | 			delta = scheduled.timestamp().epochTime() - dt.timestamp().epochTime(); | ||||||
| 			O.open(LastRunFileName_,std::ios::binary | std::ios::trunc); | 		} else { | ||||||
| 			O << LastRun_; | 			delta = (24*60*60) - (dt.timestamp().epochTime() - scheduled.timestamp().epochTime()); | ||||||
| 			O.close(); |  | ||||||
| 		} catch(const Poco::Exception &E) { |  | ||||||
| 			Logger_.log(E); |  | ||||||
| 		} | 		} | ||||||
|  | 		return delta; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	int StorageArchiver::Start() { | 	int StorageArchiver::Start() { | ||||||
|  |  | ||||||
| 		Enabled_ = MicroService::instance().ConfigGetBool("archiver.enabled",false); | 		Enabled_ = MicroService::instance().ConfigGetBool("archiver.enabled",false); | ||||||
|  |  | ||||||
| 		if(!Enabled_) { | 		if(!Enabled_) { | ||||||
| 			Logger_.information("Archiver is disabled."); | 			Logger_.information("Archiver is disabled."); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		ArchiverCallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(Archiver_,&Archiver::onTimer); | ||||||
|  |  | ||||||
| 		auto Schedule = MicroService::instance().ConfigGetString("archiver.schedule","03:00"); | 		auto Schedule = MicroService::instance().ConfigGetString("archiver.schedule","03:00"); | ||||||
| 		Types::StringVec S = Utils::Split(Schedule,':'); | 		auto S = Poco::StringTokenizer(Schedule,":"); | ||||||
| 		RunAtHour_ = std::atoi(S[0].c_str()); |  | ||||||
| 		RunAtMin_ = std::atoi(S[1].c_str()); | 		int RunAtHour_, RunAtMin_; | ||||||
|  | 		if(S.count()!=2) { | ||||||
|  | 			RunAtHour_ = 3 ; | ||||||
|  | 			RunAtMin_ = 0; | ||||||
|  | 		} else { | ||||||
|  | 			RunAtHour_ = std::atoi(S[0].c_str()); | ||||||
|  | 			RunAtMin_ = std::atoi(S[1].c_str()); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		for(int i=0;i<20;i++) { | 		for(int i=0;i<20;i++) { | ||||||
| 			std::string key = "archiver.db." + std::to_string(i) + ".name"; | 			std::string key = "archiver.db." + std::to_string(i) + ".name"; | ||||||
| @@ -103,7 +79,7 @@ namespace OpenWifi { | |||||||
| 					if(Poco::icompare(DBName,DB)==0) { | 					if(Poco::icompare(DBName,DB)==0) { | ||||||
| 						std::string Key = "archiver.db." + std::to_string(i) + ".keep"; | 						std::string Key = "archiver.db." + std::to_string(i) + ".keep"; | ||||||
| 						auto Keep = MicroService::instance().ConfigGetInt(Key,7); | 						auto Keep = MicroService::instance().ConfigGetInt(Key,7); | ||||||
| 						DBs_.push_back(ArchiverDBEntry{ | 						Archiver_.AddDb(Archiver::ArchiverDBEntry{ | ||||||
| 							.DBName = DB, | 							.DBName = DB, | ||||||
| 							.HowManyDays = Keep | 							.HowManyDays = Keep | ||||||
| 						}); | 						}); | ||||||
| @@ -111,17 +87,21 @@ namespace OpenWifi { | |||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		LastRunFileName_ = MicroService::instance().DataDir() + "/archiver_lastrun.txt"; |  | ||||||
| 		Janitor_.start(*this); | 		int NextRun = CalculateDelta(RunAtHour_,RunAtMin_); | ||||||
|  |  | ||||||
|  | 		Logger_.information(Poco::format("Next run in %d seconds.",NextRun)); | ||||||
|  |  | ||||||
|  | 		Timer_.setStartInterval( NextRun * 1000); | ||||||
|  | 		Timer_.setPeriodicInterval(24 * 60 * 60 * 1000); // 1 hours | ||||||
|  | 		Timer_.start(*ArchiverCallback_); | ||||||
|  |  | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void StorageArchiver::Stop() { | 	void StorageArchiver::Stop() { | ||||||
|  | 		if(Enabled_) { | ||||||
| 		if(Running_) { | 			Timer_.stop(); | ||||||
| 			Running_=false; |  | ||||||
| 			Janitor_.wakeUp(); |  | ||||||
| 			Janitor_.join(); |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -8,51 +8,58 @@ | |||||||
| #include <functional> | #include <functional> | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "Poco/Timer.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| struct ArchiverDBEntry { |     static const std::list<std::string>		AllInternalDBNames{"healthchecks", "statistics", "devicelogs" , "commandlist" }; | ||||||
| 	std::string 					DBName; |  | ||||||
| 	uint64_t 						HowManyDays=7; |  | ||||||
| }; |  | ||||||
| typedef std::vector<ArchiverDBEntry>	ArchiverDBEntryVec; |  | ||||||
|  |  | ||||||
| static const std::list<std::string>		AllInternalDBNames{"healthchecks", "statistics", "devicelogs" , "commandlist" }; |     class Archiver { | ||||||
|  |       public: | ||||||
|  |     	struct ArchiverDBEntry { | ||||||
|  |     		std::string 					DBName; | ||||||
|  |     		uint64_t 						HowManyDays=7; | ||||||
|  |     	}; | ||||||
|  |     	typedef std::vector<ArchiverDBEntry>	ArchiverDBEntryVec; | ||||||
|  |  | ||||||
| class StorageArchiver : public SubSystemServer, Poco::Runnable { | 		explicit Archiver(Poco::Logger &Logger): | ||||||
|  | 			Logger_(Logger) { | ||||||
|   	public: |  | ||||||
| 		static StorageArchiver *instance() { |  | ||||||
| 			static StorageArchiver instance; |  | ||||||
| 			return &instance; |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		void 	run() override; |     	void onTimer(Poco::Timer & timer); | ||||||
| 		int 	Start() override; |     	inline void AddDb(const ArchiverDBEntry &E ) { | ||||||
| 		void 	Stop() override; | 			DBs_.push_back(E); | ||||||
| 		void 	GetLastRun(); |  | ||||||
| 		void 	SetLastRun(); |  | ||||||
|  |  | ||||||
| 		inline bool Enabled() const { return Enabled_; } |  | ||||||
|  |  | ||||||
| 	private: |  | ||||||
| 		std::atomic_bool 			Running_ = false; |  | ||||||
| 		std::atomic_bool 			Enabled_ = false; |  | ||||||
| 		Poco::Thread				Janitor_; |  | ||||||
| 		ArchiverDBEntryVec			DBs_; |  | ||||||
| 		uint64_t 					RunAtHour_=0; |  | ||||||
| 		uint64_t 					RunAtMin_=0; |  | ||||||
| 		uint64_t 					LastRun_=0; |  | ||||||
| 		std::string 				LastRunFileName_; |  | ||||||
|  |  | ||||||
| 		StorageArchiver() noexcept: |  | ||||||
| 			SubSystemServer("StorageArchiver", "STORAGE-ARCHIVE", "archiver") |  | ||||||
| 		{ |  | ||||||
| 		} | 		} | ||||||
|  |       private: | ||||||
|  | 		Poco::Logger		&Logger_; | ||||||
|  |     	ArchiverDBEntryVec	DBs_; | ||||||
|  |     }; | ||||||
|  |  | ||||||
| }; |     class StorageArchiver : public SubSystemServer { | ||||||
|  |  | ||||||
| inline StorageArchiver * StorageArchiver() { return StorageArchiver::instance(); } |         public: | ||||||
|  |             static StorageArchiver *instance() { | ||||||
|  |                 static StorageArchiver * instance_ = new StorageArchiver; | ||||||
|  |                 return instance_; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int 	Start() override; | ||||||
|  |             void 	Stop() override; | ||||||
|  |             inline bool Enabled() const { return Enabled_; } | ||||||
|  |  | ||||||
|  |         private: | ||||||
|  |             std::atomic_bool 				Enabled_ = false; | ||||||
|  |             Poco::Timer                     Timer_; | ||||||
|  |             Archiver                        Archiver_{Logger_}; | ||||||
|  |             std::unique_ptr<Poco::TimerCallback<Archiver>>   ArchiverCallback_; | ||||||
|  |  | ||||||
|  |             StorageArchiver() noexcept: | ||||||
|  |                 SubSystemServer("StorageArchiver", "STORAGE-ARCHIVE", "archiver") | ||||||
|  |             { | ||||||
|  |             } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     inline StorageArchiver * StorageArchiver() { return StorageArchiver::instance(); } | ||||||
|  |  | ||||||
| }  // namespace | }  // namespace | ||||||
|  |  | ||||||
|   | |||||||
| @@ -28,8 +28,8 @@ namespace OpenWifi { | |||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|         static Storage *instance() { |         static Storage *instance() { | ||||||
| 			static Storage instance; | 			static Storage * instance_ = new Storage; | ||||||
| 			return &instance; | 			return instance_; | ||||||
|         } |         } | ||||||
|  |  | ||||||
| 		typedef std::map<std::string,std::string>	DeviceCapabilitiesCache; | 		typedef std::map<std::string,std::string>	DeviceCapabilitiesCache; | ||||||
| @@ -89,6 +89,7 @@ namespace OpenWifi { | |||||||
| 		bool GetDefaultConfiguration(std::string &name, GWObjects::DefaultConfiguration & DefConfig); | 		bool GetDefaultConfiguration(std::string &name, GWObjects::DefaultConfiguration & DefConfig); | ||||||
| 		bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany, std::vector<GWObjects::DefaultConfiguration> &Devices); | 		bool GetDefaultConfigurations(uint64_t From, uint64_t HowMany, std::vector<GWObjects::DefaultConfiguration> &Devices); | ||||||
| 		bool FindDefaultConfigurationForModel(const std::string & Model, GWObjects::DefaultConfiguration & DefConfig ); | 		bool FindDefaultConfigurationForModel(const std::string & Model, GWObjects::DefaultConfiguration & DefConfig ); | ||||||
|  | 		uint64_t GetDefaultConfigurationsCount(); | ||||||
|  |  | ||||||
| 		bool AddCommand(std::string & SerialNumber, GWObjects::CommandDetails & Command,CommandExecutionType Type); | 		bool AddCommand(std::string & SerialNumber, GWObjects::CommandDetails & Command,CommandExecutionType Type); | ||||||
| 		bool GetCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands); | 		bool GetCommands(std::string &SerialNumber, uint64_t FromDate, uint64_t ToDate, uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::CommandDetails> & Commands); | ||||||
| @@ -115,6 +116,8 @@ namespace OpenWifi { | |||||||
| 		bool IsBlackListed(std::string & SerialNumber); | 		bool IsBlackListed(std::string & SerialNumber); | ||||||
| 		bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::BlackListedDevice> & Devices ); | 		bool GetBlackListDevices(uint64_t Offset, uint64_t HowMany, std::vector<GWObjects::BlackListedDevice> & Devices ); | ||||||
| 		bool UpdateBlackListDevice(std::string & SerialNumber, GWObjects::BlackListedDevice & Device); | 		bool UpdateBlackListDevice(std::string & SerialNumber, GWObjects::BlackListedDevice & Device); | ||||||
|  | 		uint64_t GetBlackListDeviceCount(); | ||||||
|  |  | ||||||
| 		bool SetLifetimeStats(std::string & SerialNumber, std::string & Stats); | 		bool SetLifetimeStats(std::string & SerialNumber, std::string & Stats); | ||||||
| 		bool GetLifetimeStats(std::string & SerialNumber, std::string & Stats); | 		bool GetLifetimeStats(std::string & SerialNumber, std::string & Stats); | ||||||
| 		bool ResetLifetimeStats(std::string & SerialNumber); | 		bool ResetLifetimeStats(std::string & SerialNumber); | ||||||
|   | |||||||
| @@ -27,18 +27,18 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	int TelemetryStream::Start() { | 	int TelemetryStream::Start() { | ||||||
| 		ReactorPool_.Start(); | 		ReactorPool_.Start(); | ||||||
| 		Runner.start(*this); | 		Runner_.start(*this); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void TelemetryStream::Stop() { | 	void TelemetryStream::Stop() { | ||||||
|  | 	    Logger_.notice("Stopping reactors..."); | ||||||
|  | 	    ReactorPool_.Stop(); | ||||||
|  |  | ||||||
| 		if(Running_) { | 		if(Running_) { | ||||||
| 			Running_ = false; | 			Running_ = false; | ||||||
| 			Runner.join(); | 			Runner_.join(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		Logger_.notice("Stopping reactors..."); |  | ||||||
| 		ReactorPool_.Stop(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool TelemetryStream::CreateEndpoint(const std::string &SerialNumber, std::string &EndPoint, std::string &UUID) { | 	bool TelemetryStream::CreateEndpoint(const std::string &SerialNumber, std::string &EndPoint, std::string &UUID) { | ||||||
| @@ -46,7 +46,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 		Poco::URI	Public(MicroService::instance().ConfigGetString("openwifi.system.uri.public")); | 		Poco::URI	Public(MicroService::instance().ConfigGetString("openwifi.system.uri.public")); | ||||||
| 		Poco::URI	U; | 		Poco::URI	U; | ||||||
| 		UUID = MicroService::instance().CreateUUID(); | 		UUID = MicroService::CreateUUID(); | ||||||
| 		U.setScheme("wss"); | 		U.setScheme("wss"); | ||||||
| 		U.setHost(Public.getHost()); | 		U.setHost(Public.getHost()); | ||||||
| 		U.setPort(Public.getPort()); | 		U.setPort(Public.getPort()); | ||||||
| @@ -69,7 +69,7 @@ namespace OpenWifi { | |||||||
| 	void TelemetryStream::UpdateEndPoint(const std::string &SerialNumber, const std::string &PayLoad) { | 	void TelemetryStream::UpdateEndPoint(const std::string &SerialNumber, const std::string &PayLoad) { | ||||||
| 		std::lock_guard	G(QueueMutex_); | 		std::lock_guard	G(QueueMutex_); | ||||||
| 		Queue_.push(QueueUpdate{.SerialNumber=SerialNumber,.Payload=PayLoad}); | 		Queue_.push(QueueUpdate{.SerialNumber=SerialNumber,.Payload=PayLoad}); | ||||||
| 		Runner.wakeUp(); | 		Runner_.wakeUp(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void TelemetryStream::run() { | 	void TelemetryStream::run() { | ||||||
|   | |||||||
| @@ -101,8 +101,8 @@ namespace OpenWifi { | |||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		static TelemetryStream *instance() { | 		static TelemetryStream *instance() { | ||||||
| 			static TelemetryStream instance; | 		    static TelemetryStream * instance_ = new TelemetryStream; | ||||||
| 			return &instance; | 			return instance_; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		int Start() override; | 		int Start() override; | ||||||
| @@ -120,7 +120,7 @@ namespace OpenWifi { | |||||||
| 		std::map<std::string, std::set<std::string>>	SerialNumbers_;		//	serialNumber -> uuid | 		std::map<std::string, std::set<std::string>>	SerialNumbers_;		//	serialNumber -> uuid | ||||||
| 		TelemetryReactorPool							ReactorPool_; | 		TelemetryReactorPool							ReactorPool_; | ||||||
| 		std::mutex										QueueMutex_; | 		std::mutex										QueueMutex_; | ||||||
| 		Poco::Thread									Runner; | 		Poco::Thread									Runner_; | ||||||
| 		std::queue<QueueUpdate>							Queue_; | 		std::queue<QueueUpdate>							Queue_; | ||||||
| 		TelemetryStream() noexcept: | 		TelemetryStream() noexcept: | ||||||
| 			SubSystemServer("TelemetryServer", "TELEMETRY-SVR", "openwifi.telemetry") | 			SubSystemServer("TelemetryServer", "TELEMETRY-SVR", "openwifi.telemetry") | ||||||
|   | |||||||
| @@ -28,12 +28,6 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| 	WebSocketServer::WebSocketServer() noexcept: |  | ||||||
| 	  	SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") |  | ||||||
|     { |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	bool WebSocketServer::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) { | 	bool WebSocketServer::ValidateCertificate(const std::string & ConnectionId, const Poco::Crypto::X509Certificate & Certificate) { | ||||||
| 		if(IsCertOk()) { | 		if(IsCertOk()) { | ||||||
| 			Logger_.debug(Poco::format("CERTIFICATE(%s): issuer='%s' cn='%s'", ConnectionId, Certificate.issuerName(),Certificate.commonName())); | 			Logger_.debug(Poco::format("CERTIFICATE(%s): issuer='%s' cn='%s'", ConnectionId, Certificate.issuerName(),Certificate.commonName())); | ||||||
| @@ -218,7 +212,7 @@ namespace OpenWifi { | |||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		uint64_t GoodConfig=ConfigurationCache().CurrentConfig(SerialNumber_); | 		uint64_t GoodConfig=ConfigurationCache().CurrentConfig(SerialNumber_); | ||||||
| 		if(GoodConfig && (GoodConfig==UUID || GoodConfig==Conn_->PendingUUID)) | 		if(GoodConfig && (GoodConfig==UUID || GoodConfig==Conn_->Conn_.PendingUUID)) | ||||||
| 			return false; | 			return false; | ||||||
|  |  | ||||||
| 		GWObjects::Device	D; | 		GWObjects::Device	D; | ||||||
| @@ -231,10 +225,10 @@ namespace OpenWifi { | |||||||
| 				return false; | 				return false; | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			Conn_->PendingUUID = D.UUID; | 			Conn_->Conn_.PendingUUID = D.UUID; | ||||||
| 			GWObjects::CommandDetails  Cmd; | 			GWObjects::CommandDetails  Cmd; | ||||||
| 			Cmd.SerialNumber = SerialNumber_; | 			Cmd.SerialNumber = SerialNumber_; | ||||||
| 			Cmd.UUID = MicroService::instance().CreateUUID(); | 			Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 			Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM; | 			Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM; | ||||||
| 			Cmd.Status = uCentralProtocol::PENDING; | 			Cmd.Status = uCentralProtocol::PENDING; | ||||||
| 			Cmd.Command = uCentralProtocol::CONFIGURE; | 			Cmd.Command = uCentralProtocol::CONFIGURE; | ||||||
| @@ -334,7 +328,7 @@ namespace OpenWifi { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if(Conn_!= nullptr) | 		if(Conn_!= nullptr) | ||||||
| 			Conn_->LastContact = std::time(nullptr); | 			Conn_->Conn_.LastContact = std::time(nullptr); | ||||||
|  |  | ||||||
| 		switch(EventType) { | 		switch(EventType) { | ||||||
| 			case uCentralProtocol::ET_CONNECT: { | 			case uCentralProtocol::ET_CONNECT: { | ||||||
| @@ -347,12 +341,12 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 						Conn_ = DeviceRegistry()->Register(Serial, this); | 						Conn_ = DeviceRegistry()->Register(Serial, this); | ||||||
| 						SerialNumber_ = Serial; | 						SerialNumber_ = Serial; | ||||||
| 						Conn_->SerialNumber = Serial; | 						Conn_->Conn_.SerialNumber = Serial; | ||||||
| 						Conn_->UUID = UUID; | 						Conn_->Conn_.UUID = UUID; | ||||||
| 						Conn_->Firmware = Firmware; | 						Conn_->Conn_.Firmware = Firmware; | ||||||
| 						Conn_->PendingUUID = 0; | 						Conn_->Conn_.PendingUUID = 0; | ||||||
| 						Conn_->LastContact = std::time(nullptr); | 						Conn_->Conn_.LastContact = std::time(nullptr); | ||||||
| 						Conn_->Address = Utils::FormatIPv6(WS_->peerAddress().toString()); | 						Conn_->Conn_.Address = Utils::FormatIPv6(WS_->peerAddress().toString()); | ||||||
| 						CId_ = SerialNumber_ + "@" + CId_ ; | 						CId_ = SerialNumber_ + "@" + CId_ ; | ||||||
|  |  | ||||||
| 						//	We need to verify the certificate if we have one | 						//	We need to verify the certificate if we have one | ||||||
| @@ -365,7 +359,7 @@ namespace OpenWifi { | |||||||
| 							else | 							else | ||||||
| 								Logger_.information(Poco::format("CONNECT(%s): Authenticated but not validated. Serial='%s' CN='%s'", CId_, Serial, CN_)); | 								Logger_.information(Poco::format("CONNECT(%s): Authenticated but not validated. Serial='%s' CN='%s'", CId_, Serial, CN_)); | ||||||
| 						} | 						} | ||||||
| 						Conn_->VerifiedCertificate = CertValidation_; | 						Conn_->Conn_.VerifiedCertificate = CertValidation_; | ||||||
|  |  | ||||||
| 						if (Daemon()->AutoProvisioning() && !StorageService()->DeviceExists(SerialNumber_)) { | 						if (Daemon()->AutoProvisioning() && !StorageService()->DeviceExists(SerialNumber_)) { | ||||||
| 							StorageService()->CreateDefaultDevice(SerialNumber_, Capabilities, Firmware, Compatible_); | 							StorageService()->CreateDefaultDevice(SerialNumber_, Capabilities, Firmware, Compatible_); | ||||||
| @@ -375,12 +369,14 @@ namespace OpenWifi { | |||||||
| 								StorageService()->SetConnectInfo(SerialNumber_, Firmware ); | 								StorageService()->SetConnectInfo(SerialNumber_, Firmware ); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 						Conn_->Compatible = Compatible_; |  | ||||||
|  |  | ||||||
|  | 						Conn_->Conn_.Compatible = Compatible_; | ||||||
| 						StatsProcessor_ = std::make_unique<StateProcessor>(Conn_, Logger_); | 						StatsProcessor_ = std::make_unique<StateProcessor>(Conn_, Logger_); | ||||||
| 						StatsProcessor_->Initialize(Serial); | 						StatsProcessor_->Initialize(Serial); | ||||||
| 						LookForUpgrade(UUID); | 						LookForUpgrade(UUID); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 						if(KafkaManager()->Enabled()) { | 						if(KafkaManager()->Enabled()) { | ||||||
| 							Poco::JSON::Stringifier		Stringify; | 							Poco::JSON::Stringifier		Stringify; | ||||||
| 							ParamsObj->set(uCentralProtocol::CONNECTIONIP,CId_); | 							ParamsObj->set(uCentralProtocol::CONNECTIONIP,CId_); | ||||||
| @@ -416,7 +412,7 @@ namespace OpenWifi { | |||||||
| 						else | 						else | ||||||
| 							Logger_.debug(Poco::format("STATE(%s): UUID=%Lu Updating for CMD=%s.", CId_, | 							Logger_.debug(Poco::format("STATE(%s): UUID=%Lu Updating for CMD=%s.", CId_, | ||||||
| 													   UUID, request_uuid)); | 													   UUID, request_uuid)); | ||||||
| 						Conn_->UUID = UUID; | 						Conn_->Conn_.UUID = UUID; | ||||||
| 						LookForUpgrade(UUID); | 						LookForUpgrade(UUID); | ||||||
| 						GWObjects::Statistics	Stats{ .SerialNumber = SerialNumber_, .UUID = UUID, .Data = State}; | 						GWObjects::Statistics	Stats{ .SerialNumber = SerialNumber_, .UUID = UUID, .Data = State}; | ||||||
| 						Stats.Recorded = std::time(nullptr); | 						Stats.Recorded = std::time(nullptr); | ||||||
| @@ -425,8 +421,7 @@ namespace OpenWifi { | |||||||
| 							StorageService()->SetCommandResult(request_uuid, State); | 							StorageService()->SetCommandResult(request_uuid, State); | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| 						if (StatsProcessor_) | 						StatsProcessor_->Add(State); | ||||||
| 							StatsProcessor_->Add(State); |  | ||||||
|  |  | ||||||
| 						if(KafkaManager()->Enabled()) { | 						if(KafkaManager()->Enabled()) { | ||||||
| 							Poco::JSON::Stringifier		Stringify; | 							Poco::JSON::Stringifier		Stringify; | ||||||
| @@ -465,7 +460,7 @@ namespace OpenWifi { | |||||||
| 							Logger_.debug(Poco::format("HEALTHCHECK(%s): UUID=%Lu Updating for CMD=%s.", | 							Logger_.debug(Poco::format("HEALTHCHECK(%s): UUID=%Lu Updating for CMD=%s.", | ||||||
| 													   CId_, UUID, request_uuid)); | 													   CId_, UUID, request_uuid)); | ||||||
|  |  | ||||||
| 						Conn_->UUID = UUID; | 						Conn_->Conn_.UUID = UUID; | ||||||
| 						LookForUpgrade(UUID); | 						LookForUpgrade(UUID); | ||||||
|  |  | ||||||
| 						GWObjects::HealthCheck Check; | 						GWObjects::HealthCheck Check; | ||||||
| @@ -520,7 +515,7 @@ namespace OpenWifi { | |||||||
| 														   .Severity = Severity, | 														   .Severity = Severity, | ||||||
| 														   .Recorded = (uint64_t)time(nullptr), | 														   .Recorded = (uint64_t)time(nullptr), | ||||||
| 														   .LogType = 0, | 														   .LogType = 0, | ||||||
| 														   .UUID = Conn_->UUID}; | 														   .UUID = Conn_->Conn_.UUID}; | ||||||
| 						StorageService()->AddLog(DeviceLog); | 						StorageService()->AddLog(DeviceLog); | ||||||
| 					} else { | 					} else { | ||||||
| 						Logger_.warning(Poco::format("LOG(%s): Missing parameters.", CId_)); | 						Logger_.warning(Poco::format("LOG(%s): Missing parameters.", CId_)); | ||||||
| @@ -616,7 +611,7 @@ namespace OpenWifi { | |||||||
| 						if(ParamsObj->get(uCentralProtocol::REBOOT).toString()=="true") { | 						if(ParamsObj->get(uCentralProtocol::REBOOT).toString()=="true") { | ||||||
| 							GWObjects::CommandDetails  Cmd; | 							GWObjects::CommandDetails  Cmd; | ||||||
| 							Cmd.SerialNumber = SerialNumber_; | 							Cmd.SerialNumber = SerialNumber_; | ||||||
| 							Cmd.UUID = MicroService::instance().CreateUUID(); | 							Cmd.UUID = MicroService::CreateUUID(); | ||||||
| 							Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM; | 							Cmd.SubmittedBy = uCentralProtocol::SUBMITTED_BY_SYSTEM; | ||||||
| 							Cmd.Status = uCentralProtocol::PENDING; | 							Cmd.Status = uCentralProtocol::PENDING; | ||||||
| 							Cmd.Command = uCentralProtocol::REBOOT; | 							Cmd.Command = uCentralProtocol::REBOOT; | ||||||
| @@ -736,16 +731,26 @@ namespace OpenWifi { | |||||||
|                 Logger_.information(Poco::format("DISCONNECT(%s): device has disconnected.", CId_)); |                 Logger_.information(Poco::format("DISCONNECT(%s): device has disconnected.", CId_)); | ||||||
| 				return delete this; | 				return delete this; | ||||||
|             } else { |             } else { | ||||||
|  |  | ||||||
|  |             	if (Conn_ != nullptr) { | ||||||
|  |             		Conn_->Conn_.RX += IncomingSize; | ||||||
|  |             		Conn_->Conn_.MessageCount++; | ||||||
|  |             	} | ||||||
|  |  | ||||||
|                 switch (Op) { |                 switch (Op) { | ||||||
|                     case Poco::Net::WebSocket::FRAME_OP_PING: { |                     case Poco::Net::WebSocket::FRAME_OP_PING: { | ||||||
| 							Logger_.debug(Poco::format("WS-PING(%s): received. PONG sent back.", CId_)); | 							Logger_.debug(Poco::format("WS-PING(%s): received. PONG sent back.", CId_)); | ||||||
| 							WS_->sendFrame("", 0, | 							WS_->sendFrame("", 0, | ||||||
| 										   (int)Poco::Net::WebSocket::FRAME_OP_PONG | | 										   (int)Poco::Net::WebSocket::FRAME_OP_PONG | | ||||||
| 											   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN); | 											   (int)Poco::Net::WebSocket::FRAME_FLAG_FIN); | ||||||
|  | 							if (Conn_ != nullptr) { | ||||||
|  | 								Conn_->Conn_.MessageCount++; | ||||||
|  | 							} | ||||||
|  |  | ||||||
| 							if (KafkaManager()->Enabled() && Conn_) { | 							if (KafkaManager()->Enabled() && Conn_) { | ||||||
| 								Poco::JSON::Object PingObject; | 								Poco::JSON::Object PingObject; | ||||||
| 								Poco::JSON::Object PingDetails; | 								Poco::JSON::Object PingDetails; | ||||||
| 								PingDetails.set(uCentralProtocol::FIRMWARE, Conn_->Firmware); | 								PingDetails.set(uCentralProtocol::FIRMWARE, Conn_->Conn_.Firmware); | ||||||
| 								PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_); | 								PingDetails.set(uCentralProtocol::SERIALNUMBER, SerialNumber_); | ||||||
| 								PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_); | 								PingDetails.set(uCentralProtocol::COMPATIBLE, Compatible_); | ||||||
| 								PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_); | 								PingDetails.set(uCentralProtocol::CONNECTIONIP, CId_); | ||||||
| @@ -756,11 +761,13 @@ namespace OpenWifi { | |||||||
| 								KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, | 								KafkaManager()->PostMessage(KafkaTopics::CONNECTION, SerialNumber_, | ||||||
| 															OS.str()); | 															OS.str()); | ||||||
| 							} | 							} | ||||||
|  | 							return; | ||||||
| 						} | 						} | ||||||
|                         break; |                         break; | ||||||
|  |  | ||||||
|                     case Poco::Net::WebSocket::FRAME_OP_PONG: { |                     case Poco::Net::WebSocket::FRAME_OP_PONG: { | ||||||
|                         	Logger_.debug(Poco::format("PONG(%s): received and ignored.",CId_)); |                         	Logger_.debug(Poco::format("PONG(%s): received and ignored.",CId_)); | ||||||
|  | 							return; | ||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|  |  | ||||||
| @@ -790,6 +797,7 @@ namespace OpenWifi { | |||||||
| 								Logger_.error(Poco::format("FRAME(%s): illegal transaction header, missing 'jsonrpc'",CId_)); | 								Logger_.error(Poco::format("FRAME(%s): illegal transaction header, missing 'jsonrpc'",CId_)); | ||||||
| 								Errors_++; | 								Errors_++; | ||||||
| 							} | 							} | ||||||
|  | 							return; | ||||||
| 	                    } | 	                    } | ||||||
|     	                break; |     	                break; | ||||||
|  |  | ||||||
| @@ -804,11 +812,6 @@ namespace OpenWifi { | |||||||
|                         } |                         } | ||||||
|                         break; |                         break; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (Conn_ != nullptr) { |  | ||||||
|                         Conn_->RX += IncomingSize; |  | ||||||
|                         Conn_->MessageCount++; |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         catch (const Poco::Net::ConnectionResetException & E) |         catch (const Poco::Net::ConnectionResetException & E) | ||||||
| @@ -885,7 +888,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 		auto BytesSent = WS_->sendFrame(Payload.c_str(),(int)Payload.size()); | 		auto BytesSent = WS_->sendFrame(Payload.c_str(),(int)Payload.size()); | ||||||
| 		if(Conn_) | 		if(Conn_) | ||||||
| 			Conn_->TX += BytesSent; | 			Conn_->Conn_.TX += BytesSent; | ||||||
| 		return  BytesSent == Payload.size(); | 		return  BytesSent == Payload.size(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -102,7 +102,7 @@ namespace OpenWifi { | |||||||
| 		std::unique_ptr<Poco::Net::WebSocket> WS_; | 		std::unique_ptr<Poco::Net::WebSocket> WS_; | ||||||
| 		std::string                         SerialNumber_; | 		std::string                         SerialNumber_; | ||||||
| 		std::string 						Compatible_; | 		std::string 						Compatible_; | ||||||
| 		GWObjects::ConnectionState 	* Conn_ = nullptr; | 		std::shared_ptr<DeviceRegistry::ConnectionEntry> 	Conn_; | ||||||
| 		bool                                Registered_ = false ; | 		bool                                Registered_ = false ; | ||||||
| 		std::string 						CId_; | 		std::string 						CId_; | ||||||
| 		std::string							CN_; | 		std::string							CN_; | ||||||
| @@ -117,8 +117,8 @@ namespace OpenWifi { | |||||||
| 	class WebSocketServer : public SubSystemServer { | 	class WebSocketServer : public SubSystemServer { | ||||||
| 	  public: | 	  public: | ||||||
| 		static WebSocketServer *instance() { | 		static WebSocketServer *instance() { | ||||||
| 			static WebSocketServer instance; | 		    static WebSocketServer *instance_ = new WebSocketServer; | ||||||
| 			return &instance; | 			return instance_; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		int Start() override; | 		int Start() override; | ||||||
| @@ -134,7 +134,11 @@ namespace OpenWifi { | |||||||
| 		Poco::Net::SocketReactor		Reactor_; | 		Poco::Net::SocketReactor		Reactor_; | ||||||
| 		Poco::Thread					ReactorThread_; | 		Poco::Thread					ReactorThread_; | ||||||
| 		ReactorPool						ReactorPool_; | 		ReactorPool						ReactorPool_; | ||||||
| 		WebSocketServer() noexcept; |  | ||||||
|  | 		WebSocketServer() noexcept: | ||||||
|  | 		    SubSystemServer("WebSocketServer", "WS-SVR", "ucentral.websocket") { | ||||||
|  |  | ||||||
|  | 		} | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline WebSocketServer * WebSocketServer() { return WebSocketServer::instance(); } | 	inline WebSocketServer * WebSocketServer() { return WebSocketServer::instance(); } | ||||||
|   | |||||||
| @@ -2,8 +2,7 @@ | |||||||
| // Created by stephane bourque on 2021-09-14. | // Created by stephane bourque on 2021-09-14. | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef OWPROV_CONFIGURATIONVALIDATOR_H | #pragma once | ||||||
| #define OWPROV_CONFIGURATIONVALIDATOR_H |  | ||||||
|  |  | ||||||
| #include <nlohmann/json-schema.hpp> | #include <nlohmann/json-schema.hpp> | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
| @@ -43,4 +42,3 @@ namespace OpenWifi { | |||||||
|     inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); } |     inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); } | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif //OWPROV_CONFIGURATIONVALIDATOR_H |  | ||||||
|   | |||||||
| @@ -2,8 +2,7 @@ | |||||||
| // Created by stephane bourque on 2021-10-08. | // Created by stephane bourque on 2021-10-08. | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef OWPROV_COUNTRYCODES_H | #pragma once | ||||||
| #define OWPROV_COUNTRYCODES_H |  | ||||||
|  |  | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <string> | #include <string> | ||||||
| @@ -270,4 +269,3 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif //OWPROV_COUNTRYCODES_H |  | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ | |||||||
| //	Created by Stephane Bourque on 2021-03-04. | //	Created by Stephane Bourque on 2021-03-04. | ||||||
| //	Arilia Wireless Inc. | //	Arilia Wireless Inc. | ||||||
| // | // | ||||||
| #ifndef UCENTRALGW_KAFKA_TOPICS_H |  | ||||||
| #define UCENTRALGW_KAFKA_TOPICS_H | #pragma once | ||||||
|  |  | ||||||
| namespace OpenWifi::KafkaTopics { | namespace OpenWifi::KafkaTopics { | ||||||
| 	static const std::string HEALTHCHECK{"healthcheck"}; | 	static const std::string HEALTHCHECK{"healthcheck"}; | ||||||
| @@ -37,4 +37,3 @@ namespace OpenWifi::KafkaTopics { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif // UCENTRALGW_KAFKA_TOPICS_H |  | ||||||
|   | |||||||
| @@ -6,8 +6,7 @@ | |||||||
| //	Arilia Wireless Inc. | //	Arilia Wireless Inc. | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef OPENWIFI_MICROSERVICE_H | #pragma once | ||||||
| #define OPENWIFI_MICROSERVICE_H |  | ||||||
|  |  | ||||||
| #include <array> | #include <array> | ||||||
| #include <iostream> | #include <iostream> | ||||||
| @@ -20,6 +19,7 @@ | |||||||
| #include <regex> | #include <regex> | ||||||
| #include <random> | #include <random> | ||||||
| #include <iomanip> | #include <iomanip> | ||||||
|  | #include <queue> | ||||||
|  |  | ||||||
| using namespace std::chrono_literals; | using namespace std::chrono_literals; | ||||||
|  |  | ||||||
| @@ -58,15 +58,99 @@ using namespace std::chrono_literals; | |||||||
| #include "Poco/Net/HTTPSClientSession.h" | #include "Poco/Net/HTTPSClientSession.h" | ||||||
| #include "Poco/Net/NetworkInterface.h" | #include "Poco/Net/NetworkInterface.h" | ||||||
| #include "Poco/ExpireLRUCache.h" | #include "Poco/ExpireLRUCache.h" | ||||||
|  | #include "Poco/JSON/Object.h" | ||||||
|  | #include "Poco/JSON/Parser.h" | ||||||
|  | #include "Poco/StringTokenizer.h" | ||||||
|  |  | ||||||
| #include "cppkafka/cppkafka.h" | #include "cppkafka/cppkafka.h" | ||||||
|  |  | ||||||
| #include "framework/OpenWifiTypes.h" |  | ||||||
| #include "framework/KafkaTopics.h" | #include "framework/KafkaTopics.h" | ||||||
| #include "framework/RESTAPI_protocol.h" | #include "framework/RESTAPI_protocol.h" | ||||||
| #include "framework/RESTAPI_errors.h" | #include "framework/RESTAPI_errors.h" | ||||||
| #include "framework/uCentral_Protocol.h" | #include "framework/uCentral_Protocol.h" | ||||||
| #include "RESTObjects/RESTAPI_SecurityObjects.h" | #include "RESTObjects/RESTAPI_SecurityObjects.h" | ||||||
|  | #include "nlohmann/json.hpp" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     enum UNAUTHORIZED_REASON { | ||||||
|  |         SUCCESS=0, | ||||||
|  |         PASSWORD_CHANGE_REQUIRED, | ||||||
|  |         INVALID_CREDENTIALS, | ||||||
|  |         PASSWORD_ALREADY_USED, | ||||||
|  |         USERNAME_PENDING_VERIFICATION, | ||||||
|  |         PASSWORD_INVALID, | ||||||
|  |         INTERNAL_ERROR, | ||||||
|  |         ACCESS_DENIED, | ||||||
|  |         INVALID_TOKEN, | ||||||
|  |         EXPIRED_TOKEN, | ||||||
|  |         RATE_LIMIT_EXCEEDED | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | 	class AppServiceRegistry { | ||||||
|  | 	  public: | ||||||
|  | 		inline AppServiceRegistry(); | ||||||
|  |  | ||||||
|  | 		static AppServiceRegistry & instance() { | ||||||
|  | 		    static AppServiceRegistry *instance_= new AppServiceRegistry; | ||||||
|  | 			return *instance_; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline ~AppServiceRegistry() { | ||||||
|  | 			Save(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline void Save() { | ||||||
|  | 			std::istringstream  IS( to_string(Registry_)); | ||||||
|  | 			std::ofstream       OF; | ||||||
|  | 			OF.open(FileName,std::ios::binary | std::ios::trunc); | ||||||
|  | 			Poco::StreamCopier::copyStream(IS, OF); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline void Set(const char *Key, uint64_t Value ) { | ||||||
|  | 			Registry_[Key] = Value; | ||||||
|  | 			Save(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline void Set(const char *Key, const std::string &Value ) { | ||||||
|  | 			Registry_[Key] = Value; | ||||||
|  | 			Save(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline void Set(const char *Key, bool Value ) { | ||||||
|  | 			Registry_[Key] = Value; | ||||||
|  | 			Save(); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline bool Get(const char *Key, bool & Value ) { | ||||||
|  | 			if(Registry_[Key].is_boolean()) { | ||||||
|  | 				Value = Registry_[Key].get<bool>(); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline bool Get(const char *Key, uint64_t & Value ) { | ||||||
|  | 			if(Registry_[Key].is_number_unsigned()) { | ||||||
|  | 				Value = Registry_[Key].get<uint64_t>(); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		inline bool Get(const char *Key, std::string & Value ) { | ||||||
|  | 			if(Registry_[Key].is_string()) { | ||||||
|  | 				Value = Registry_[Key].get<std::string>(); | ||||||
|  | 				return true; | ||||||
|  | 			} | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 	  private: | ||||||
|  | 		std::string         FileName; | ||||||
|  | 		nlohmann::json      Registry_; | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  |  | ||||||
| namespace OpenWifi::RESTAPI_utils { | namespace OpenWifi::RESTAPI_utils { | ||||||
|  |  | ||||||
| @@ -86,12 +170,13 @@ namespace OpenWifi::RESTAPI_utils { | |||||||
|         Obj.set(Field,S); |         Obj.set(Field,S); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const std::vector<Types::StringPair> & S) { |     inline void field_to_json(Poco::JSON::Object &Obj, const char *Field, const Types::StringPairVec & S) { | ||||||
|         Poco::JSON::Array   Array; |         Poco::JSON::Array   Array; | ||||||
|         for(const auto &i:S) { |         for(const auto &i:S) { | ||||||
|             Poco::JSON::Object  O; |             Poco::JSON::Object  O; | ||||||
|             O.set("tag",i.first); |             O.set("tag",i.first); | ||||||
|             O.set("value", i.second); |             O.set("value", i.second); | ||||||
|  |             Array.add(O); | ||||||
|         } |         } | ||||||
|         Obj.set(Field,Array); |         Obj.set(Field,Array); | ||||||
|     } |     } | ||||||
| @@ -129,7 +214,6 @@ namespace OpenWifi::RESTAPI_utils { | |||||||
|         Obj.set(Field,A); |         Obj.set(Field,A); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     template<typename T> void field_to_json(Poco::JSON::Object &Obj, |     template<typename T> void field_to_json(Poco::JSON::Object &Obj, | ||||||
|             const char *Field, |             const char *Field, | ||||||
|             const T &V, |             const T &V, | ||||||
| @@ -159,6 +243,7 @@ namespace OpenWifi::RESTAPI_utils { | |||||||
|             V = (Obj->get(Field).toString() == "true"); |             V = (Obj->get(Field).toString() == "true"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     inline void field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, Types::StringPairVec &Vec) { |     inline void field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, Types::StringPairVec &Vec) { | ||||||
|         if(Obj->isArray(Field)) { |         if(Obj->isArray(Field)) { | ||||||
|             auto O = Obj->getArray(Field); |             auto O = Obj->getArray(Field); | ||||||
| @@ -368,11 +453,12 @@ namespace OpenWifi::RESTAPI_utils { | |||||||
|         try { |         try { | ||||||
|             Poco::JSON::Parser P; |             Poco::JSON::Parser P; | ||||||
|             auto Object = P.parse(S).template extract<Poco::JSON::Array::Ptr>(); |             auto Object = P.parse(S).template extract<Poco::JSON::Array::Ptr>(); | ||||||
|             for (auto const &i : *Object) { |             for (const auto &i : *Object) { | ||||||
|                 auto InnerObject = i.template extract<Poco::JSON::Array::Ptr>(); |                 auto InnerObject = i.template extract<Poco::JSON::Array::Ptr>(); | ||||||
|                 if(InnerObject->size()==2) { |                 if(InnerObject->size()==2) { | ||||||
|                     Types::StringPair P{InnerObject->get(0).toString(), InnerObject->get(1).toString()}; |                     auto S1 = InnerObject->getElement<std::string>(0); | ||||||
|                     R.push_back(P); |                     auto S2 = InnerObject->getElement<std::string>(1); | ||||||
|  |                     R.push_back(std::make_pair(S1,S2)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } catch (...) { |         } catch (...) { | ||||||
| @@ -717,6 +803,20 @@ namespace OpenWifi::Utils { | |||||||
|         return R; |         return R; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [[nodiscard]] inline std::string IntToSerialNumber(uint64_t S) { | ||||||
|  |         char b[16]; | ||||||
|  |         for(int i=0;i<12;++i) { | ||||||
|  |             int B = (S & 0x0f); | ||||||
|  |             if(B<10) | ||||||
|  |                 b[11-i] = B+'0'; | ||||||
|  |             else | ||||||
|  |                 b[11-i] = B - 10 + 'a'; | ||||||
|  |             S >>= 4 ; | ||||||
|  |         } | ||||||
|  |         b[12]=0; | ||||||
|  |         return b; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     [[nodiscard]] inline bool SerialNumberMatch(const std::string &S1, const std::string &S2, int Bits=2) { |     [[nodiscard]] inline bool SerialNumberMatch(const std::string &S1, const std::string &S2, int Bits=2) { | ||||||
|         auto S1_i = SerialNumberToInt(S1); |         auto S1_i = SerialNumberToInt(S1); | ||||||
| @@ -766,16 +866,13 @@ namespace OpenWifi::Utils { | |||||||
|         return Result; |         return Result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     inline void SaveSystemId(uint64_t Id); |  | ||||||
|  |  | ||||||
|     [[nodiscard]] inline uint64_t InitializeSystemId() { |     [[nodiscard]] inline uint64_t InitializeSystemId() { | ||||||
|         std::random_device	RDev; |         std::random_device	RDev; | ||||||
|         std::srand(RDev()); |         std::srand(RDev()); | ||||||
|         std::chrono::high_resolution_clock	Clock; |         std::chrono::high_resolution_clock	Clock; | ||||||
|         auto Now = Clock.now().time_since_epoch().count(); |         auto Now = Clock.now().time_since_epoch().count(); | ||||||
|         auto S = (GetDefaultMacAsInt64() + std::rand() + Now)  ; |         auto S = (GetDefaultMacAsInt64() + std::rand() + Now)  ; | ||||||
|         SaveSystemId(S); | 		OpenWifi::AppServiceRegistry().Set("systemid",S); | ||||||
|         std::cout << "ID: " << S << std::endl; |  | ||||||
|         return S; |         return S; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -924,6 +1021,7 @@ namespace OpenWifi { | |||||||
|     static const std::string uSERVICE_SUBCRIBER{ "owsub"}; |     static const std::string uSERVICE_SUBCRIBER{ "owsub"}; | ||||||
|     static const std::string uSERVICE_INSTALLER{ "owinst"}; |     static const std::string uSERVICE_INSTALLER{ "owinst"}; | ||||||
|  |  | ||||||
|  |  | ||||||
| 	class MyErrorHandler : public Poco::ErrorHandler { | 	class MyErrorHandler : public Poco::ErrorHandler { | ||||||
| 	  public: | 	  public: | ||||||
| 		explicit MyErrorHandler(Poco::Util::Application &App) : App_(App) {} | 		explicit MyErrorHandler(Poco::Util::Application &App) : App_(App) {} | ||||||
| @@ -1355,8 +1453,8 @@ namespace OpenWifi { | |||||||
| 	    }; | 	    }; | ||||||
|  |  | ||||||
| 	    static RESTAPI_RateLimiter *instance() { | 	    static RESTAPI_RateLimiter *instance() { | ||||||
| 	        static RESTAPI_RateLimiter instance; | 	        static RESTAPI_RateLimiter * instance_ = new RESTAPI_RateLimiter; | ||||||
| 	        return &instance; | 	        return instance_; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() final { return 0;}; | 	    inline int Start() final { return 0;}; | ||||||
| @@ -1366,18 +1464,18 @@ namespace OpenWifi { | |||||||
| 	        Poco::URI   uri(R.getURI()); | 	        Poco::URI   uri(R.getURI()); | ||||||
| 	        auto H = str_hash(uri.getPath() + R.clientAddress().host().toString()); | 	        auto H = str_hash(uri.getPath() + R.clientAddress().host().toString()); | ||||||
| 	        auto E = Cache_.get(H); | 	        auto E = Cache_.get(H); | ||||||
| 	        const auto p1 = std::chrono::system_clock::now(); | 	        auto Now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); | ||||||
| 	        auto Now = std::chrono::duration_cast<std::chrono::milliseconds>(p1.time_since_epoch()).count(); |  | ||||||
| 	        if(E.isNull()) { | 	        if(E.isNull()) { | ||||||
| 	            Cache_.add(H,ClientCacheEntry{.Start=Now, .Count=1}); | 	            Cache_.add(H,ClientCacheEntry{.Start=Now, .Count=1}); | ||||||
| 	            Logger_.warning(Poco::format("RATE-LIMIT-EXCEEDED: from '%s'", R.clientAddress().toString())); |  | ||||||
| 	            return false; | 	            return false; | ||||||
| 	        } | 	        } | ||||||
| 	        if((Now-E->Start)<Period) { | 	        if((Now-E->Start)<Period) { | ||||||
| 	            E->Count++; | 	            E->Count++; | ||||||
| 	            Cache_.update(H,E); | 	            Cache_.update(H,E); | ||||||
| 	            if(E->Count > MaxCalls) | 	            if(E->Count > MaxCalls) { | ||||||
|  | 	                Logger_.warning(Poco::format("RATE-LIMIT-EXCEEDED: from '%s'", R.clientAddress().toString())); | ||||||
| 	                return true; | 	                return true; | ||||||
|  | 	            } | ||||||
| 	            return false; | 	            return false; | ||||||
| 	        } | 	        } | ||||||
| 	        E->Start = Now; | 	        E->Start = Now; | ||||||
| @@ -1445,20 +1543,23 @@ namespace OpenWifi { | |||||||
| 	            Request = &RequestIn; | 	            Request = &RequestIn; | ||||||
| 	            Response = &ResponseIn; | 	            Response = &ResponseIn; | ||||||
|  |  | ||||||
| 	            if(RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(RequestIn,MyRates_.Interval, MyRates_.MaxCalls)) | 	            if(RateLimited_ && RESTAPI_RateLimiter()->IsRateLimited(RequestIn,MyRates_.Interval, MyRates_.MaxCalls)) { | ||||||
| 	                return; | 	                return UnAuthorized("Rate limit exceeded.",RATE_LIMIT_EXCEEDED); | ||||||
|  | 	            } | ||||||
|  |  | ||||||
| 	            if (!ContinueProcessing()) | 	            if (!ContinueProcessing()) | ||||||
| 	                return; | 	                return; | ||||||
|  |  | ||||||
| 	            if (AlwaysAuthorize_ && !IsAuthorized()) { | 	            bool Expired=false; | ||||||
| 	                return; | 	            if (AlwaysAuthorize_ && !IsAuthorized(Expired)) { | ||||||
|  | 	                if(Expired) | ||||||
|  | 	                    return UnAuthorized(RESTAPI::Errors::ExpiredToken, EXPIRED_TOKEN); | ||||||
|  | 	                return UnAuthorized(RESTAPI::Errors::InvalidCredentials, ACCESS_DENIED); | ||||||
| 	            } | 	            } | ||||||
|  |  | ||||||
| 	            std::string Reason; | 	            std::string Reason; | ||||||
| 	            if(!RoleIsAuthorized(RequestIn.getURI(), Request->getMethod(), Reason)) { | 	            if(!RoleIsAuthorized(RequestIn.getURI(), Request->getMethod(), Reason)) { | ||||||
|                     UnAuthorized(Reason); |                     return UnAuthorized(Reason, ACCESS_DENIED); | ||||||
|                     return; |  | ||||||
| 	            } | 	            } | ||||||
|  |  | ||||||
| 	            ParseParameters(); | 	            ParseParameters(); | ||||||
| @@ -1678,10 +1779,10 @@ namespace OpenWifi { | |||||||
| 	        Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | 	        Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void UnAuthorized(const std::string & Reason = "") { | 	    inline void UnAuthorized(const std::string & Reason = "", int Code = INVALID_CREDENTIALS ) { | ||||||
| 	        PrepareResponse(Poco::Net::HTTPResponse::HTTP_FORBIDDEN); | 	        PrepareResponse(Poco::Net::HTTPResponse::HTTP_FORBIDDEN); | ||||||
| 	        Poco::JSON::Object	ErrorObject; | 	        Poco::JSON::Object	ErrorObject; | ||||||
| 	        ErrorObject.set("ErrorCode",403); | 	        ErrorObject.set("ErrorCode",Code); | ||||||
| 	        ErrorObject.set("ErrorDetails",Request->getMethod()); | 	        ErrorObject.set("ErrorDetails",Request->getMethod()); | ||||||
| 	        ErrorObject.set("ErrorDescription",Reason.empty() ? "No access allowed." : Reason) ; | 	        ErrorObject.set("ErrorDescription",Reason.empty() ? "No access allowed." : Reason) ; | ||||||
| 	        std::ostream &Answer = Response->send(); | 	        std::ostream &Answer = Response->send(); | ||||||
| @@ -1796,7 +1897,7 @@ namespace OpenWifi { | |||||||
| 	        return true; | 	        return true; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline bool IsAuthorized(); | 	    inline bool IsAuthorized(bool & Expired); | ||||||
|  |  | ||||||
| 	        inline void ReturnObject(Poco::JSON::Object &Object) { | 	        inline void ReturnObject(Poco::JSON::Object &Object) { | ||||||
| 	            PrepareResponse(); | 	            PrepareResponse(); | ||||||
| @@ -1817,7 +1918,7 @@ namespace OpenWifi { | |||||||
| 	            QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, ""); | 	            QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, ""); | ||||||
| 	            QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0); | 	            QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0); | ||||||
| 	            QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0); | 	            QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0); | ||||||
| 	            QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 1); | 	            QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 0); | ||||||
| 	            QB_.Limit = GetParameter(RESTAPI::Protocol::LIMIT, 100); | 	            QB_.Limit = GetParameter(RESTAPI::Protocol::LIMIT, 100); | ||||||
| 	            QB_.Filter = GetParameter(RESTAPI::Protocol::FILTER, ""); | 	            QB_.Filter = GetParameter(RESTAPI::Protocol::FILTER, ""); | ||||||
| 	            QB_.Select = GetParameter(RESTAPI::Protocol::SELECT, ""); | 	            QB_.Select = GetParameter(RESTAPI::Protocol::SELECT, ""); | ||||||
| @@ -1829,7 +1930,7 @@ namespace OpenWifi { | |||||||
| 	            QB_.AdditionalInfo = GetBoolParameter(RESTAPI::Protocol::WITHEXTENDEDINFO,false); | 	            QB_.AdditionalInfo = GetBoolParameter(RESTAPI::Protocol::WITHEXTENDEDINFO,false); | ||||||
|  |  | ||||||
| 	            if(QB_.Offset<1) | 	            if(QB_.Offset<1) | ||||||
| 	                QB_.Offset=1; | 	                QB_.Offset=0; | ||||||
| 	            return true; | 	            return true; | ||||||
| 	        } | 	        } | ||||||
|  |  | ||||||
| @@ -1998,6 +2099,50 @@ namespace OpenWifi { | |||||||
| 	    Poco::JSON::Object      Body_; | 	    Poco::JSON::Object      Body_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  |     class KafkaProducer : public Poco::Runnable { | ||||||
|  |     public: | ||||||
|  |         inline void run(); | ||||||
|  |         void Start() { | ||||||
|  |             if(!Running_) { | ||||||
|  |                 Running_=true; | ||||||
|  |                 Worker_.start(*this); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         void Stop() { | ||||||
|  |             if(Running_) { | ||||||
|  |                 Running_=false; | ||||||
|  |                 Worker_.wakeUp(); | ||||||
|  |                 Worker_.join(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     private: | ||||||
|  |         std::mutex          Mutex_; | ||||||
|  |         Poco::Thread        Worker_; | ||||||
|  |         std::atomic_bool    Running_=false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     class KafkaConsumer : public Poco::Runnable { | ||||||
|  |     public: | ||||||
|  |         inline void run(); | ||||||
|  |         void Start() { | ||||||
|  |             if(!Running_) { | ||||||
|  |                 Running_=true; | ||||||
|  |                 Worker_.start(*this); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         void Stop() { | ||||||
|  |             if(Running_) { | ||||||
|  |                 Running_=false; | ||||||
|  |                 Worker_.wakeUp(); | ||||||
|  |                 Worker_.join(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     private: | ||||||
|  |         std::mutex          Mutex_; | ||||||
|  |         Poco::Thread        Worker_; | ||||||
|  |         std::atomic_bool    Running_=false; | ||||||
|  |     }; | ||||||
|  |  | ||||||
| 	class KafkaManager : public SubSystemServer { | 	class KafkaManager : public SubSystemServer { | ||||||
| 	public: | 	public: | ||||||
| 	    struct KMessage { | 	    struct KMessage { | ||||||
| @@ -2006,33 +2151,32 @@ namespace OpenWifi { | |||||||
| 	        PayLoad; | 	        PayLoad; | ||||||
| 	    }; | 	    }; | ||||||
|  |  | ||||||
|  | 	    friend class KafkaConsumer; | ||||||
|  | 	    friend class KafkaProducer; | ||||||
|  |  | ||||||
| 	    inline void initialize(Poco::Util::Application & self) override; | 	    inline void initialize(Poco::Util::Application & self) override; | ||||||
|  |  | ||||||
| 	    static KafkaManager *instance() { | 	    static KafkaManager *instance() { | ||||||
| 	        static KafkaManager instance; | 	        static KafkaManager * instance_ = new KafkaManager; | ||||||
| 	        return &instance; | 	        return instance_; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override { | 	    inline int Start() override { | ||||||
| 	        if(!KafkaEnabled_) | 	        if(!KafkaEnabled_) | ||||||
| 	            return 0; | 	            return 0; | ||||||
| 	        ProducerThr_ = std::make_unique<std::thread>([this]() { this->ProducerThr(); }); | 	        ConsumerThr_.Start(); | ||||||
| 	        ConsumerThr_ = std::make_unique<std::thread>([this]() { this->ConsumerThr(); }); | 	        ProducerThr_.Start(); | ||||||
| 	        return 0; | 	        return 0; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
| 	        if(KafkaEnabled_) { | 	        if(KafkaEnabled_) { | ||||||
| 	            ProducerRunning_ = ConsumerRunning_ = false; | 	            ProducerThr_.Stop(); | ||||||
| 	            ProducerThr_->join(); | 	            ConsumerThr_.Stop(); | ||||||
| 	            ConsumerThr_->join(); |  | ||||||
| 	            return; | 	            return; | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void ProducerThr(); |  | ||||||
| 	    inline void ConsumerThr(); |  | ||||||
|  |  | ||||||
| 	    inline void PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage = true  ) { | 	    inline void PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage = true  ) { | ||||||
| 	        if(KafkaEnabled_) { | 	        if(KafkaEnabled_) { | ||||||
| 	            std::lock_guard G(Mutex_); | 	            std::lock_guard G(Mutex_); | ||||||
| @@ -2085,18 +2229,13 @@ namespace OpenWifi { | |||||||
| 	    // void WakeUp(); | 	    // void WakeUp(); | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
| 	    std::mutex 						ProducerMutex_; |  | ||||||
| 	    std::mutex						ConsumerMutex_; |  | ||||||
| 	    bool 							KafkaEnabled_ = false; | 	    bool 							KafkaEnabled_ = false; | ||||||
| 	    std::atomic_bool 				ProducerRunning_ = false; |  | ||||||
| 	    std::atomic_bool 				ConsumerRunning_ = false; |  | ||||||
| 	    std::queue<KMessage>			Queue_; | 	    std::queue<KMessage>			Queue_; | ||||||
| 	    std::string 					SystemInfoWrapper_; | 	    std::string 					SystemInfoWrapper_; | ||||||
| 	    std::unique_ptr<std::thread>	ConsumerThr_; |  | ||||||
| 	    std::unique_ptr<std::thread>	ProducerThr_; |  | ||||||
| 	    int                       		FunctionId_=1; | 	    int                       		FunctionId_=1; | ||||||
| 	    Types::NotifyTable        		Notifiers_; | 	    Types::NotifyTable        		Notifiers_; | ||||||
| 	    std::unique_ptr<cppkafka::Configuration>    Config_; | 	    KafkaProducer                   ProducerThr_; | ||||||
|  | 	    KafkaConsumer                   ConsumerThr_; | ||||||
|  |  | ||||||
| 	    inline void PartitionAssignment(const cppkafka::TopicPartitionList& partitions) { | 	    inline void PartitionAssignment(const cppkafka::TopicPartitionList& partitions) { | ||||||
| 	        Logger_.information(Poco::format("Partition assigned: %Lu...",(uint64_t )partitions.front().get_partition())); | 	        Logger_.information(Poco::format("Partition assigned: %Lu...",(uint64_t )partitions.front().get_partition())); | ||||||
| @@ -2121,8 +2260,8 @@ namespace OpenWifi { | |||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    static AuthClient *instance() { | 	    static AuthClient *instance() { | ||||||
| 	        static AuthClient instance; | 	        static AuthClient * instance_ = new AuthClient; | ||||||
| 	        return &instance; | 	        return instance_; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override { | 	    inline int Start() override { | ||||||
| @@ -2130,25 +2269,20 @@ namespace OpenWifi { | |||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
|  | 	        Cache_.clear(); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void RemovedCachedToken(const std::string &Token) { | 	    inline void RemovedCachedToken(const std::string &Token) { | ||||||
| 	        std::lock_guard	G(Mutex_); | 	        std::lock_guard	G(Mutex_); | ||||||
| 	        UserCache_.erase(Token); | 	        Cache_.remove(Token); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline static bool IsTokenExpired(const SecurityObjects::WebToken &T) { | 	    inline static bool IsTokenExpired(const SecurityObjects::WebToken &T) { | ||||||
| 	        return ((T.expires_in_+T.created_)<std::time(nullptr)); | 	        return ((T.expires_in_+T.created_)<std::time(nullptr)); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline bool IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) { | 	    inline bool RetrieveTokenInformation(const std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired) { | ||||||
| 	        std::lock_guard G(Mutex_); | 	        try { | ||||||
|  |  | ||||||
| 	        auto User = UserCache_.find(SessionToken); |  | ||||||
| 	        if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) { |  | ||||||
| 	            UInfo = User->second; |  | ||||||
| 	            return true; |  | ||||||
| 	        } else { |  | ||||||
| 	            Types::StringPairVec QueryData; | 	            Types::StringPairVec QueryData; | ||||||
| 	            QueryData.push_back(std::make_pair("token",SessionToken)); | 	            QueryData.push_back(std::make_pair("token",SessionToken)); | ||||||
| 	            OpenAPIRequestGet	Req(    uSERVICE_SECURITY, | 	            OpenAPIRequestGet	Req(    uSERVICE_SECURITY, | ||||||
| @@ -2158,49 +2292,39 @@ namespace OpenWifi { | |||||||
| 	            Poco::JSON::Object::Ptr Response; | 	            Poco::JSON::Object::Ptr Response; | ||||||
| 	            if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { | 	            if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
| 	                if(Response->has("tokenInfo") && Response->has("userInfo")) { | 	                if(Response->has("tokenInfo") && Response->has("userInfo")) { | ||||||
| 	                    SecurityObjects::UserInfoAndPolicy	P; | 	                    UInfo.from_json(Response); | ||||||
| 	                    P.from_json(Response); | 	                    if(IsTokenExpired(UInfo.webtoken)) { | ||||||
| 	                    UserCache_[SessionToken] = P; | 	                        Expired = true; | ||||||
| 	                    UInfo = P; | 	                        return false; | ||||||
|  | 	                    } | ||||||
|  | 	                    Expired = false; | ||||||
|  | 	                    Cache_.update(SessionToken, UInfo); | ||||||
|  | 	                    return true; | ||||||
| 	                } | 	                } | ||||||
| 	                return true; |  | ||||||
| 	            } | 	            } | ||||||
|  | 	        } catch (...) { | ||||||
|  |  | ||||||
| 	        } | 	        } | ||||||
|  | 	        Expired = false; | ||||||
| 	        return false; | 	        return false; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline bool IsTokenAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) { |         inline bool IsAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired) { | ||||||
| 	        std::lock_guard G(Mutex_); | 	        auto User = Cache_.get(SessionToken); | ||||||
|  | 	        if(!User.isNull()) { | ||||||
| 	        auto User = UserCache_.find(SessionToken); | 	            if(IsTokenExpired(User->webtoken)) { | ||||||
| 	        if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) { | 	                Expired = true; | ||||||
| 	            UInfo = User->second; | 	                return false; | ||||||
| 	            return true; |  | ||||||
| 	        } else { |  | ||||||
| 	            Types::StringPairVec QueryData; |  | ||||||
| 	            QueryData.push_back(std::make_pair("token",SessionToken)); |  | ||||||
| 	            OpenAPIRequestGet	Req(uSERVICE_SECURITY, |  | ||||||
|                                          "/api/v1/validateToken", |  | ||||||
|                                          QueryData, |  | ||||||
|                                          5000); |  | ||||||
| 	            Poco::JSON::Object::Ptr Response; |  | ||||||
| 	            if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { |  | ||||||
| 	                if(Response->has("tokenInfo") && Response->has("userInfo")) { |  | ||||||
| 	                    SecurityObjects::UserInfoAndPolicy	P; |  | ||||||
| 	                    P.from_json(Response); |  | ||||||
| 	                    UserCache_[SessionToken] = P; |  | ||||||
| 	                    UInfo = P; |  | ||||||
| 	                } |  | ||||||
| 	                return true; |  | ||||||
| 	            } | 	            } | ||||||
|  | 	            Expired = false; | ||||||
|  |                 UInfo = *User; | ||||||
|  |                 return true; | ||||||
| 	        } | 	        } | ||||||
| 	        return false; | 	        return RetrieveTokenInformation(SessionToken, UInfo, Expired); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	private: | 	private: | ||||||
| 	    OpenWifi::SecurityObjects::UserInfoCache 		UserCache_; | 	    Poco::ExpireLRUCache<std::string,OpenWifi::SecurityObjects::UserInfoAndPolicy>      Cache_{1024,1200000 }; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline AuthClient * AuthClient() { return AuthClient::instance(); } | 	inline AuthClient * AuthClient() { return AuthClient::instance(); } | ||||||
| @@ -2260,14 +2384,14 @@ namespace OpenWifi { | |||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    static ALBHealthCheckServer *instance() { | 	    static ALBHealthCheckServer *instance() { | ||||||
| 	        static ALBHealthCheckServer instance; | 	        static ALBHealthCheckServer * instance = new ALBHealthCheckServer; | ||||||
| 	        return &instance; | 	        return instance; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override; | 	    inline int Start() override; | ||||||
|  |  | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
| 	        if(Server_) | 	        if(Running_) | ||||||
| 	            Server_->stop(); | 	            Server_->stop(); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| @@ -2275,6 +2399,7 @@ namespace OpenWifi { | |||||||
| 	    std::unique_ptr<Poco::Net::HTTPServer>   	Server_; | 	    std::unique_ptr<Poco::Net::HTTPServer>   	Server_; | ||||||
| 	    std::unique_ptr<Poco::Net::ServerSocket> 	Socket_; | 	    std::unique_ptr<Poco::Net::ServerSocket> 	Socket_; | ||||||
| 	    int                                     	Port_ = 0; | 	    int                                     	Port_ = 0; | ||||||
|  | 	    std::atomic_bool                            Running_=false; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline ALBHealthCheckServer * ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } | 	inline ALBHealthCheckServer * ALBHealthCheckServer() { return ALBHealthCheckServer::instance(); } | ||||||
| @@ -2289,17 +2414,18 @@ namespace OpenWifi { | |||||||
| 	class RESTAPI_server : public SubSystemServer { | 	class RESTAPI_server : public SubSystemServer { | ||||||
| 	public: | 	public: | ||||||
| 	    static RESTAPI_server *instance() { | 	    static RESTAPI_server *instance() { | ||||||
| 	        static RESTAPI_server instance; | 	        static RESTAPI_server *instance_ = new RESTAPI_server; | ||||||
| 	        return &instance; | 	        return instance_; | ||||||
| 	    } | 	    } | ||||||
| 	    int Start() override; | 	    int Start() override; | ||||||
| 	    inline void Stop() override { | 	    inline void Stop() override { | ||||||
| 	        Logger_.information("Stopping "); | 	        Logger_.information("Stopping "); | ||||||
| 	        for( const auto & svr : RESTServers_ ) | 	        for( const auto & svr : RESTServers_ ) | ||||||
| 	            svr->stop(); | 	            svr->stop(); | ||||||
|  | 	        Pool_.joinAll(); | ||||||
| 	        RESTServers_.clear(); | 	        RESTServers_.clear(); | ||||||
|  |  | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void reinitialize(Poco::Util::Application &self) override; | 	    inline void reinitialize(Poco::Util::Application &self) override; | ||||||
|  |  | ||||||
| 	    inline Poco::Net::HTTPRequestHandler *CallServer(const char *Path) { | 	    inline Poco::Net::HTTPRequestHandler *CallServer(const char *Path) { | ||||||
| @@ -2354,7 +2480,7 @@ namespace OpenWifi { | |||||||
| 	        if(!Svr.RootCA().empty()) | 	        if(!Svr.RootCA().empty()) | ||||||
| 	            Svr.LogCas(Logger_); | 	            Svr.LogCas(Logger_); | ||||||
|  |  | ||||||
| 	        auto Params = new Poco::Net::HTTPServerParams; | 	        Poco::Net::HTTPServerParams::Ptr Params = new Poco::Net::HTTPServerParams; | ||||||
| 	        Params->setMaxThreads(50); | 	        Params->setMaxThreads(50); | ||||||
| 	        Params->setMaxQueued(200); | 	        Params->setMaxQueued(200); | ||||||
| 	        Params->setKeepAlive(true); | 	        Params->setKeepAlive(true); | ||||||
| @@ -2371,8 +2497,8 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	public: | 	public: | ||||||
| 	    static RESTAPI_InternalServer *instance() { | 	    static RESTAPI_InternalServer *instance() { | ||||||
| 	        static RESTAPI_InternalServer instance; | 	        static RESTAPI_InternalServer *instance_ = new RESTAPI_InternalServer; | ||||||
| 	        return &instance; | 	        return instance_; | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline int Start() override; | 	    inline int Start() override; | ||||||
| @@ -2380,7 +2506,7 @@ namespace OpenWifi { | |||||||
| 	        Logger_.information("Stopping "); | 	        Logger_.information("Stopping "); | ||||||
| 	        for( const auto & svr : RESTServers_ ) | 	        for( const auto & svr : RESTServers_ ) | ||||||
| 	            svr->stop(); | 	            svr->stop(); | ||||||
| 	        RESTServers_.clear(); | 	        Pool_.stopAll(); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    inline void reinitialize(Poco::Util::Application &self) override; | 	    inline void reinitialize(Poco::Util::Application &self) override; | ||||||
| @@ -2397,7 +2523,6 @@ namespace OpenWifi { | |||||||
| 	    RESTAPI_InternalServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "openwifi.internal.restapi") | 	    RESTAPI_InternalServer() noexcept: SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "openwifi.internal.restapi") | ||||||
| 	    { | 	    { | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); }; | 	inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); }; | ||||||
| @@ -2415,7 +2540,7 @@ namespace OpenWifi { | |||||||
| 	    } | 	    } | ||||||
| 	private: | 	private: | ||||||
| 	    Poco::Logger    & Logger_; | 	    Poco::Logger    & Logger_; | ||||||
| 	    RESTAPI_GenericServer   &Server_; | 	    RESTAPI_GenericServer   & Server_; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	inline int RESTAPI_InternalServer::Start() { | 	inline int RESTAPI_InternalServer::Start() { | ||||||
| @@ -2454,6 +2579,8 @@ namespace OpenWifi { | |||||||
| 		uint64_t 		LastUpdate=0; | 		uint64_t 		LastUpdate=0; | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 	class SubSystemServer; | 	class SubSystemServer; | ||||||
| 	typedef std::map<uint64_t, MicroServiceMeta>	MicroServiceMetaMap; | 	typedef std::map<uint64_t, MicroServiceMeta>	MicroServiceMetaMap; | ||||||
| 	typedef std::vector<MicroServiceMeta>			MicroServiceMetaVec; | 	typedef std::vector<MicroServiceMeta>			MicroServiceMetaVec; | ||||||
| @@ -2474,11 +2601,13 @@ namespace OpenWifi { | |||||||
| 			DAEMON_BUS_TIMER(BusTimer), | 			DAEMON_BUS_TIMER(BusTimer), | ||||||
| 			SubSystems_(std::move(Subsystems)) { | 			SubSystems_(std::move(Subsystems)) { | ||||||
| 		    instance_ = this; | 		    instance_ = this; | ||||||
|  | 		    RandomEngine_.seed(std::chrono::steady_clock::now().time_since_epoch().count()); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		[[nodiscard]] std::string Version() { return Version_; } | 		[[nodiscard]] std::string Version() { return Version_; } | ||||||
| 		[[nodiscard]] const Poco::SharedPtr<Poco::Crypto::RSAKey> & Key() { return AppKey_; } | 		[[nodiscard]] const Poco::SharedPtr<Poco::Crypto::RSAKey> & Key() { return AppKey_; } | ||||||
| 		[[nodiscard]] inline const std::string & DataDir() { return DataDir_; } | 		[[nodiscard]] inline const std::string & DataDir() { return DataDir_; } | ||||||
|  | 		[[nodiscard]] inline const std::string & WWWAssetsDir() { return WWWAssetsDir_; } | ||||||
| 		[[nodiscard]] bool Debug() const { return DebugMode_; } | 		[[nodiscard]] bool Debug() const { return DebugMode_; } | ||||||
| 		[[nodiscard]] uint64_t ID() const { return ID_; } | 		[[nodiscard]] uint64_t ID() const { return ID_; } | ||||||
| 		[[nodiscard]] std::string Hash() const { return MyHash_; }; | 		[[nodiscard]] std::string Hash() const { return MyHash_; }; | ||||||
| @@ -2491,6 +2620,13 @@ namespace OpenWifi { | |||||||
| 		static inline uint64_t GetPID() { return Poco::Process::id(); }; | 		static inline uint64_t GetPID() { return Poco::Process::id(); }; | ||||||
| 		[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; }; | 		[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; }; | ||||||
| 		[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;}; | 		[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;}; | ||||||
|  | 		[[nodiscard]] inline uint64_t Random(uint64_t ceiling) { | ||||||
|  | 		    return (RandomEngine_() % ceiling); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		[[nodiscard]] inline uint64_t Random(uint64_t min, uint64_t max) { | ||||||
|  | 		    return ((RandomEngine_() % (max-min)) + min); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		inline void Exit(int Reason); | 		inline void Exit(int Reason); | ||||||
| 		inline void BusMessageReceived(const std::string &Key, const std::string & Message); | 		inline void BusMessageReceived(const std::string &Key, const std::string & Message); | ||||||
| @@ -2512,7 +2648,7 @@ namespace OpenWifi { | |||||||
| 		inline void InitializeSubSystemServers(); | 		inline void InitializeSubSystemServers(); | ||||||
| 		inline void StartSubSystemServers(); | 		inline void StartSubSystemServers(); | ||||||
| 		inline void StopSubSystemServers(); | 		inline void StopSubSystemServers(); | ||||||
| 		[[nodiscard]] inline std::string CreateUUID(); | 		[[nodiscard]] static inline std::string CreateUUID(); | ||||||
| 		inline bool SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level); | 		inline bool SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level); | ||||||
| 		inline void Reload(const std::string &Sub); | 		inline void Reload(const std::string &Sub); | ||||||
| 		inline Types::StringVec GetSubSystems() const; | 		inline Types::StringVec GetSubSystems() const; | ||||||
| @@ -2542,9 +2678,10 @@ namespace OpenWifi { | |||||||
| 		std::string                 ConfigFileName_; | 		std::string                 ConfigFileName_; | ||||||
| 		Poco::UUIDGenerator         UUIDGenerator_; | 		Poco::UUIDGenerator         UUIDGenerator_; | ||||||
| 		uint64_t                    ID_ = 1; | 		uint64_t                    ID_ = 1; | ||||||
| 		Poco::SharedPtr<Poco::Crypto::RSAKey>	AppKey_ = nullptr; | 		Poco::SharedPtr<Poco::Crypto::RSAKey>	AppKey_; | ||||||
| 		bool                        DebugMode_ = false; | 		bool                        DebugMode_ = false; | ||||||
| 		std::string 				DataDir_; | 		std::string 				DataDir_; | ||||||
|  | 		std::string                 WWWAssetsDir_; | ||||||
| 		SubSystemVec			    SubSystems_; | 		SubSystemVec			    SubSystems_; | ||||||
| 		Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory(); | 		Poco::Crypto::CipherFactory & CipherFactory_ = Poco::Crypto::CipherFactory::defaultFactory(); | ||||||
| 		Poco::Crypto::Cipher        * Cipher_ = nullptr; | 		Poco::Crypto::Cipher        * Cipher_ = nullptr; | ||||||
| @@ -2557,6 +2694,7 @@ namespace OpenWifi { | |||||||
| 		std::string 				Version_{std::string(APP_VERSION) + "("+ BUILD_NUMBER + ")"}; | 		std::string 				Version_{std::string(APP_VERSION) + "("+ BUILD_NUMBER + ")"}; | ||||||
| 		BusEventManager				BusEventManager_; | 		BusEventManager				BusEventManager_; | ||||||
| 		std::mutex 					InfraMutex_; | 		std::mutex 					InfraMutex_; | ||||||
|  | 		std::default_random_engine  RandomEngine_; | ||||||
|  |  | ||||||
| 		std::string DAEMON_PROPERTIES_FILENAME; | 		std::string DAEMON_PROPERTIES_FILENAME; | ||||||
| 		std::string DAEMON_ROOT_ENV_VAR; | 		std::string DAEMON_ROOT_ENV_VAR; | ||||||
| @@ -2733,6 +2871,9 @@ namespace OpenWifi { | |||||||
| 	            logger().log(E); | 	            logger().log(E); | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
|  | 	    WWWAssetsDir_ = ConfigPath("openwifi.restapi.wwwassets",""); | ||||||
|  | 	    if(WWWAssetsDir_.empty()) | ||||||
|  | 	        WWWAssetsDir_ = DataDir_; | ||||||
|  |  | ||||||
| 	    LoadMyConfig(); | 	    LoadMyConfig(); | ||||||
|  |  | ||||||
| @@ -2839,13 +2980,42 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	inline void MicroService::StopSubSystemServers() { | 	inline void MicroService::StopSubSystemServers() { | ||||||
| 	    BusEventManager_.Stop(); | 	    BusEventManager_.Stop(); | ||||||
| 	    for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i) | 	    for(auto i=SubSystems_.rbegin(); i!=SubSystems_.rend(); ++i) { | ||||||
| 	        (*i)->Stop(); | 			(*i)->Stop(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	[[nodiscard]] inline std::string MicroService::CreateUUID() { | 	[[nodiscard]] inline std::string MicroService::CreateUUID() { | ||||||
| 	    return UUIDGenerator_.create().toString(); |         static std::random_device              rd; | ||||||
| 	} |         static std::mt19937_64                 gen(rd()); | ||||||
|  |         static std::uniform_int_distribution<> dis(0, 15); | ||||||
|  |         static std::uniform_int_distribution<> dis2(8, 11); | ||||||
|  |  | ||||||
|  |         std::stringstream ss; | ||||||
|  |         int i; | ||||||
|  |         ss << std::hex; | ||||||
|  |         for (i = 0; i < 8; i++) { | ||||||
|  |             ss << dis(gen); | ||||||
|  |         } | ||||||
|  |         ss << "-"; | ||||||
|  |         for (i = 0; i < 4; i++) { | ||||||
|  |             ss << dis(gen); | ||||||
|  |         } | ||||||
|  |         ss << "-4"; | ||||||
|  |         for (i = 0; i < 3; i++) { | ||||||
|  |             ss << dis(gen); | ||||||
|  |         } | ||||||
|  |         ss << "-"; | ||||||
|  |         ss << dis2(gen); | ||||||
|  |         for (i = 0; i < 3; i++) { | ||||||
|  |             ss << dis(gen); | ||||||
|  |         } | ||||||
|  |         ss << "-"; | ||||||
|  |         for (i = 0; i < 12; i++) { | ||||||
|  |             ss << dis(gen); | ||||||
|  |         }; | ||||||
|  |         return ss.str(); | ||||||
|  |     } | ||||||
|  |  | ||||||
| 	inline bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) { | 	inline bool MicroService::SetSubsystemLogLevel(const std::string &SubSystem, const std::string &Level) { | ||||||
| 	    try { | 	    try { | ||||||
| @@ -2858,7 +3028,6 @@ namespace OpenWifi { | |||||||
| 	            } | 	            } | ||||||
| 	            return true; | 	            return true; | ||||||
| 	        } else { | 	        } else { | ||||||
| 	            // std::cout << "Sub:" << SubSystem << " Level:" << Level << std::endl; |  | ||||||
| 	            for (auto i : SubSystems_) { | 	            for (auto i : SubSystems_) { | ||||||
| 	                if (Sub == Poco::toLower(i->Name())) { | 	                if (Sub == Poco::toLower(i->Name())) { | ||||||
| 	                    i->Logger().setLevel(P); | 	                    i->Logger().setLevel(P); | ||||||
| @@ -3008,13 +3177,28 @@ namespace OpenWifi { | |||||||
| 	        StartSubSystemServers(); | 	        StartSubSystemServers(); | ||||||
| 	        waitForTerminationRequest(); | 	        waitForTerminationRequest(); | ||||||
| 	        StopSubSystemServers(); | 	        StopSubSystemServers(); | ||||||
|  |  | ||||||
| 	        logger.notice(Poco::format("Stopped %s...",DAEMON_APP_NAME)); | 	        logger.notice(Poco::format("Stopped %s...",DAEMON_APP_NAME)); | ||||||
| 	    } | 	    } | ||||||
|  |  | ||||||
| 	    return Application::EXIT_OK; | 	    return Application::EXIT_OK; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	AppServiceRegistry::AppServiceRegistry() { | ||||||
|  | 		FileName = MicroService::instance().DataDir() + "/registry.json"; | ||||||
|  | 		Poco::File F(FileName); | ||||||
|  |  | ||||||
|  | 		try { | ||||||
|  | 			if(F.exists()) { | ||||||
|  | 				std::ostringstream  OS; | ||||||
|  | 				std::ifstream       IF(FileName); | ||||||
|  | 				Poco::StreamCopier::copyStream(IF, OS); | ||||||
|  | 				Registry_ = nlohmann::json::parse(OS.str()); | ||||||
|  | 			} | ||||||
|  | 		} catch (...) { | ||||||
|  | 			Registry_ = nlohmann::json::parse("{}"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	inline void SubSystemServer::initialize(Poco::Util::Application &self) { | 	inline void SubSystemServer::initialize(Poco::Util::Application &self) { | ||||||
| 	    Logger_.notice("Initializing..."); | 	    Logger_.notice("Initializing..."); | ||||||
| 	    auto i = 0; | 	    auto i = 0; | ||||||
| @@ -3072,6 +3256,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	inline int ALBHealthCheckServer::Start() { | 	inline int ALBHealthCheckServer::Start() { | ||||||
| 	    if(MicroService::instance().ConfigGetBool("alb.enable",false)) { | 	    if(MicroService::instance().ConfigGetBool("alb.enable",false)) { | ||||||
|  | 	        Running_=true; | ||||||
| 	        Port_ = (int)MicroService::instance().ConfigGetInt("alb.port",15015); | 	        Port_ = (int)MicroService::instance().ConfigGetInt("alb.port",15015); | ||||||
| 	        Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_); | 	        Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_); | ||||||
| 	        auto Params = new Poco::Net::HTTPServerParams; | 	        auto Params = new Poco::Net::HTTPServerParams; | ||||||
| @@ -3116,41 +3301,42 @@ namespace OpenWifi { | |||||||
| 	    KafkaEnabled_ = MicroService::instance().ConfigGetBool("openwifi.kafka.enable",false); | 	    KafkaEnabled_ = MicroService::instance().ConfigGetBool("openwifi.kafka.enable",false); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void KafkaManager::ProducerThr() { | 	inline void KafkaProducer::run() { | ||||||
| 	    cppkafka::Configuration Config({ | 	    cppkafka::Configuration Config({ | ||||||
| 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||||
| 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") } | 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") } | ||||||
| 	    }); | 	    }); | ||||||
| 	    SystemInfoWrapper_ = 	R"lit({ "system" : { "id" : )lit" + | 	    KafkaManager()->SystemInfoWrapper_ = 	R"lit({ "system" : { "id" : )lit" + | ||||||
| 	            std::to_string(MicroService::instance().ID()) + | 	            std::to_string(MicroService::instance().ID()) + | ||||||
| 	            R"lit( , "host" : ")lit" + MicroService::instance().PrivateEndPoint() + | 	            R"lit( , "host" : ")lit" + MicroService::instance().PrivateEndPoint() + | ||||||
| 	            R"lit(" } , "payload" : )lit" ; | 	            R"lit(" } , "payload" : )lit" ; | ||||||
| 	    cppkafka::Producer	Producer(Config); | 	    cppkafka::Producer	Producer(Config); | ||||||
| 	    ProducerRunning_ = true; | 	    Running_ = true; | ||||||
| 	    while(ProducerRunning_) { | 	    while(Running_) { | ||||||
| 	        std::this_thread::sleep_for(std::chrono::milliseconds(200)); | 	        std::this_thread::sleep_for(std::chrono::milliseconds(200)); | ||||||
| 	        try | 	        try | ||||||
| 	        { | 	        { | ||||||
| 	            std::lock_guard G(ProducerMutex_); | 	            std::lock_guard G(Mutex_); | ||||||
| 	            auto Num=0; | 	            auto Num=0; | ||||||
| 	            while (!Queue_.empty()) { | 	            while (!KafkaManager()->Queue_.empty()) { | ||||||
| 	                const auto M = Queue_.front(); | 	                const auto M = KafkaManager()->Queue_.front(); | ||||||
| 	                Producer.produce( | 	                Producer.produce( | ||||||
| 	                        cppkafka::MessageBuilder(M.Topic).key(M.Key).payload(M.PayLoad)); | 	                        cppkafka::MessageBuilder(M.Topic).key(M.Key).payload(M.PayLoad)); | ||||||
| 	                Queue_.pop(); | 	                KafkaManager()->Queue_.pop(); | ||||||
| 	                Num++; | 	                Num++; | ||||||
| 	            } | 	            } | ||||||
| 	            if(Num) | 	            if(Num) | ||||||
| 	                Producer.flush(); | 	                Producer.flush(); | ||||||
| 	        } catch (const cppkafka::HandleException &E ) { | 	        } catch (const cppkafka::HandleException &E ) { | ||||||
| 	            Logger_.warning(Poco::format("Caught a Kafka exception (producer): %s",std::string{E.what()})); | 	            KafkaManager()->Logger_.warning(Poco::format("Caught a Kafka exception (producer): %s",std::string{E.what()})); | ||||||
| 	        } catch (const Poco::Exception &E) { | 	        } catch (const Poco::Exception &E) { | ||||||
| 	            Logger_.log(E); | 	            KafkaManager()->Logger_.log(E); | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
|  | 	    Producer.flush(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void KafkaManager::ConsumerThr() { | 	inline void KafkaConsumer::run() { | ||||||
| 	    cppkafka::Configuration Config({ | 	    cppkafka::Configuration Config({ | ||||||
| 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | 	        { "client.id", MicroService::instance().ConfigGetString("openwifi.kafka.client.id") }, | ||||||
| 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }, | 	        { "metadata.broker.list", MicroService::instance().ConfigGetString("openwifi.kafka.brokerlist") }, | ||||||
| @@ -3170,13 +3356,13 @@ namespace OpenWifi { | |||||||
| 	    cppkafka::Consumer Consumer(Config); | 	    cppkafka::Consumer Consumer(Config); | ||||||
| 	    Consumer.set_assignment_callback([this](cppkafka::TopicPartitionList& partitions) { | 	    Consumer.set_assignment_callback([this](cppkafka::TopicPartitionList& partitions) { | ||||||
| 	        if(!partitions.empty()) { | 	        if(!partitions.empty()) { | ||||||
| 	            Logger_.information(Poco::format("Partition assigned: %Lu...", | 	            KafkaManager()->Logger_.information(Poco::format("Partition assigned: %Lu...", | ||||||
|                                                  (uint64_t)partitions.front().get_partition())); |                                                  (uint64_t)partitions.front().get_partition())); | ||||||
| 	        } | 	        } | ||||||
| 	    }); | 	    }); | ||||||
| 	    Consumer.set_revocation_callback([this](const cppkafka::TopicPartitionList& partitions) { | 	    Consumer.set_revocation_callback([this](const cppkafka::TopicPartitionList& partitions) { | ||||||
| 	        if(!partitions.empty()) { | 	        if(!partitions.empty()) { | ||||||
| 	            Logger_.information(Poco::format("Partition revocation: %Lu...", | 	            KafkaManager()->Logger_.information(Poco::format("Partition revocation: %Lu...", | ||||||
|                                                  (uint64_t)partitions.front().get_partition())); |                                                  (uint64_t)partitions.front().get_partition())); | ||||||
| 	        } | 	        } | ||||||
| 	    }); | 	    }); | ||||||
| @@ -3185,13 +3371,13 @@ namespace OpenWifi { | |||||||
| 	    auto BatchSize = MicroService::instance().ConfigGetInt("openwifi.kafka.consumer.batchsize",20); | 	    auto BatchSize = MicroService::instance().ConfigGetInt("openwifi.kafka.consumer.batchsize",20); | ||||||
|  |  | ||||||
| 	    Types::StringVec    Topics; | 	    Types::StringVec    Topics; | ||||||
| 	    for(const auto &i:Notifiers_) | 	    for(const auto &i:KafkaManager()->Notifiers_) | ||||||
| 	        Topics.push_back(i.first); | 	        Topics.push_back(i.first); | ||||||
|  |  | ||||||
| 	    Consumer.subscribe(Topics); | 	    Consumer.subscribe(Topics); | ||||||
|  |  | ||||||
| 	    ConsumerRunning_ = true; | 	    Running_ = true; | ||||||
| 	    while(ConsumerRunning_) { | 	    while(Running_) { | ||||||
| 	        try { | 	        try { | ||||||
| 	            std::vector<cppkafka::Message> MsgVec = Consumer.poll_batch(BatchSize, std::chrono::milliseconds(200)); | 	            std::vector<cppkafka::Message> MsgVec = Consumer.poll_batch(BatchSize, std::chrono::milliseconds(200)); | ||||||
| 	            for(auto const &Msg:MsgVec) { | 	            for(auto const &Msg:MsgVec) { | ||||||
| @@ -3199,14 +3385,14 @@ namespace OpenWifi { | |||||||
| 	                    continue; | 	                    continue; | ||||||
| 	                if (Msg.get_error()) { | 	                if (Msg.get_error()) { | ||||||
| 	                    if (!Msg.is_eof()) { | 	                    if (!Msg.is_eof()) { | ||||||
| 	                        Logger_.error(Poco::format("Error: %s", Msg.get_error().to_string())); | 	                        KafkaManager()->Logger_.error(Poco::format("Error: %s", Msg.get_error().to_string())); | ||||||
| 	                    }if(!AutoCommit) | 	                    }if(!AutoCommit) | ||||||
| 	                        Consumer.async_commit(Msg); | 	                        Consumer.async_commit(Msg); | ||||||
| 	                    continue; | 	                    continue; | ||||||
| 	                } | 	                } | ||||||
| 	                std::lock_guard G(ConsumerMutex_); | 	                std::lock_guard G(Mutex_); | ||||||
| 	                auto It = Notifiers_.find(Msg.get_topic()); | 	                auto It = KafkaManager()->Notifiers_.find(Msg.get_topic()); | ||||||
| 	                if (It != Notifiers_.end()) { | 	                if (It != KafkaManager()->Notifiers_.end()) { | ||||||
| 	                    Types::TopicNotifyFunctionList &FL = It->second; | 	                    Types::TopicNotifyFunctionList &FL = It->second; | ||||||
| 	                    std::string Key{Msg.get_key()}; | 	                    std::string Key{Msg.get_key()}; | ||||||
| 	                    std::string Payload{Msg.get_payload()}; | 	                    std::string Payload{Msg.get_payload()}; | ||||||
| @@ -3219,11 +3405,12 @@ namespace OpenWifi { | |||||||
| 	                    Consumer.async_commit(Msg); | 	                    Consumer.async_commit(Msg); | ||||||
| 	            } | 	            } | ||||||
| 	        } catch (const cppkafka::HandleException &E) { | 	        } catch (const cppkafka::HandleException &E) { | ||||||
| 	            Logger_.warning(Poco::format("Caught a Kafka exception (consumer): %s",std::string{E.what()})); | 	            KafkaManager()->Logger_.warning(Poco::format("Caught a Kafka exception (consumer): %s",std::string{E.what()})); | ||||||
| 	        } catch (const Poco::Exception &E) { | 	        } catch (const Poco::Exception &E) { | ||||||
| 	            Logger_.log(E); | 	            KafkaManager()->Logger_.log(E); | ||||||
| 	        } | 	        } | ||||||
| 	    } | 	    } | ||||||
|  | 	    Consumer.unsubscribe(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	inline void RESTAPI_server::reinitialize(Poco::Util::Application &self) { | 	inline void RESTAPI_server::reinitialize(Poco::Util::Application &self) { | ||||||
| @@ -3444,11 +3631,9 @@ namespace OpenWifi { | |||||||
|                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { |                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|                     //	                std::cout << "Response OK" << std::endl; |  | ||||||
|                 } else { |                 } else { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|                     //	                std::cout << "Response: " << Response.getStatus() << std::endl; |  | ||||||
|                 } |                 } | ||||||
|                 return Response.getStatus(); |                 return Response.getStatus(); | ||||||
|             } |             } | ||||||
| @@ -3494,11 +3679,9 @@ namespace OpenWifi { | |||||||
|                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { |                 if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|                     //	                std::cout << "Response OK" << std::endl; |  | ||||||
|                 } else { |                 } else { | ||||||
|                     Poco::JSON::Parser	P; |                     Poco::JSON::Parser	P; | ||||||
|                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |                     ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); | ||||||
|                     //	                std::cout << "Response: " << Response.getStatus() << std::endl; |  | ||||||
|                 } |                 } | ||||||
|                 return Response.getStatus(); |                 return Response.getStatus(); | ||||||
|             } |             } | ||||||
| @@ -3524,9 +3707,9 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
| #ifdef    TIP_SECURITY_SERVICE | #ifdef    TIP_SECURITY_SERVICE | ||||||
|     [[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ); |     [[nodiscard]] bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired ); | ||||||
| #endif | #endif | ||||||
|     inline bool RESTAPIHandler::IsAuthorized() { |     inline bool RESTAPIHandler::IsAuthorized( bool & Expired ) { | ||||||
|         if(Internal_) { |         if(Internal_) { | ||||||
|             auto Allowed = MicroService::instance().IsValidAPIKEY(*Request); |             auto Allowed = MicroService::instance().IsValidAPIKEY(*Request); | ||||||
|             if(!Allowed) { |             if(!Allowed) { | ||||||
| @@ -3556,9 +3739,9 @@ namespace OpenWifi { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| #ifdef    TIP_SECURITY_SERVICE | #ifdef    TIP_SECURITY_SERVICE | ||||||
|             if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_)) { |             if (AuthServiceIsAuthorized(*Request, SessionToken_, UserInfo_, Expired)) { | ||||||
| #else | #else | ||||||
|             if (AuthClient()->IsAuthorized(*Request, SessionToken_, UserInfo_)) { |             if (AuthClient()->IsAuthorized( SessionToken_, UserInfo_, Expired)) { | ||||||
| #endif | #endif | ||||||
|                 if(Server_.LogIt(Request->getMethod(),true)) { |                 if(Server_.LogIt(Request->getMethod(),true)) { | ||||||
|                     Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s", |                     Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s", | ||||||
| @@ -3575,7 +3758,6 @@ namespace OpenWifi { | |||||||
|                                                Utils::FormatIPv6(Request->clientAddress().toString()), |                                                Utils::FormatIPv6(Request->clientAddress().toString()), | ||||||
|                                                Request->getMethod(), Request->getURI())); |                                                Request->getMethod(), Request->getURI())); | ||||||
|                 } |                 } | ||||||
|                 UnAuthorized(); |  | ||||||
|             } |             } | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| @@ -3585,40 +3767,14 @@ namespace OpenWifi { | |||||||
| } | } | ||||||
|  |  | ||||||
| namespace OpenWifi::Utils { | namespace OpenWifi::Utils { | ||||||
|         inline void SaveSystemId(uint64_t Id) { | 	[[nodiscard]] inline uint64_t GetSystemId() { | ||||||
|             try { | 		uint64_t ID=0; | ||||||
|                 std::ofstream O; | 		if(!AppServiceRegistry().Get("systemid",ID)) { | ||||||
|                 O.open(MicroService::instance().DataDir() + "/system.id",std::ios::binary | std::ios::trunc); | 			return InitializeSystemId(); | ||||||
|                 O << Id; | 		} | ||||||
|                 O.close(); | 		return ID; | ||||||
|             } catch (...) | 	} | ||||||
|             { | } | ||||||
|                 std::cout << "Could not save system ID" << std::endl; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         [[nodiscard]] inline uint64_t GetSystemId() { |  | ||||||
|             uint64_t ID=0; |  | ||||||
|  |  | ||||||
|             // if the system ID file exists, open and read it. |  | ||||||
|             Poco::File	SID( MicroService::instance().DataDir() + "/system.id"); |  | ||||||
|             try { |  | ||||||
|                 if (SID.exists()) { |  | ||||||
|                     std::ifstream I; |  | ||||||
|                     I.open(SID.path()); |  | ||||||
|                     I >> ID; |  | ||||||
|                     I.close(); |  | ||||||
|                     if (ID == 0) |  | ||||||
|                         return InitializeSystemId(); |  | ||||||
|                     return ID; |  | ||||||
|                 } else { |  | ||||||
|                     return InitializeSystemId(); |  | ||||||
|                 } |  | ||||||
|             } catch (...) { |  | ||||||
|                 return InitializeSystemId(); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| namespace OpenWifi::CIDR { | namespace OpenWifi::CIDR { | ||||||
|  |  | ||||||
| @@ -3759,5 +3915,3 @@ namespace OpenWifi::CIDR { | |||||||
|         return std::all_of(cbegin(Ranges), cend(Ranges), ValidateRange); |         return std::all_of(cbegin(Ranges), cend(Ranges), ValidateRange); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif // UCENTRALGW_MICROSERVICE_H |  | ||||||
|   | |||||||
| @@ -1,103 +1,40 @@ | |||||||
| // | // | ||||||
| //	License type: BSD 3-Clause License | // Created by stephane bourque on 2021-11-16. | ||||||
| //	License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE |  | ||||||
| // |  | ||||||
| //	Created by Stephane Bourque on 2021-03-04. |  | ||||||
| //	Arilia Wireless Inc. |  | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef UCENTRALGW_UCENTRALTYPES_H | #pragma once | ||||||
| #define UCENTRALGW_UCENTRALTYPES_H |  | ||||||
|  |  | ||||||
| #include <vector> |  | ||||||
| #include <string> |  | ||||||
| #include <map> | #include <map> | ||||||
| #include <functional> |  | ||||||
| #include <list> |  | ||||||
| #include <utility> | #include <utility> | ||||||
|  | #include <vector> | ||||||
|  | #include <functional> | ||||||
|  | #include <string> | ||||||
| #include <queue> | #include <queue> | ||||||
|  | #include <list> | ||||||
| #include "Poco/StringTokenizer.h" | #include <set> | ||||||
| #include "Poco/JSON/Parser.h" |  | ||||||
| #include "Poco/JSON/Stringifier.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi::Types { | namespace OpenWifi::Types { | ||||||
|     typedef std::pair<std::string,std::string>              StringPair; |     typedef std::pair<std::string,std::string>              StringPair; | ||||||
| 	typedef std::vector<StringPair>	                        StringPairVec; |     typedef std::vector<StringPair>	                        StringPairVec; | ||||||
|     typedef std::queue<StringPair>	                        StringPairQueue; |     typedef std::queue<StringPair>	                        StringPairQueue; | ||||||
| 	typedef std::vector<std::string>						StringVec; |     typedef std::vector<std::string>						StringVec; | ||||||
| 	typedef std::set<std::string>                           StringSet; |     typedef std::set<std::string>                           StringSet; | ||||||
| 	typedef std::map<std::string,std::set<std::string>>		StringMapStringSet; |     typedef std::map<std::string,std::set<std::string>>		StringMapStringSet; | ||||||
| 	typedef std::function<void(std::string, std::string)>   TopicNotifyFunction; |     typedef std::function<void(std::string, std::string)>   TopicNotifyFunction; | ||||||
| 	typedef std::list<std::pair<TopicNotifyFunction,int>>   TopicNotifyFunctionList; |     typedef std::list<std::pair<TopicNotifyFunction,int>>   TopicNotifyFunctionList; | ||||||
| 	typedef std::map<std::string, TopicNotifyFunctionList>  NotifyTable; |     typedef std::map<std::string, TopicNotifyFunctionList>  NotifyTable; | ||||||
|     typedef std::map<std::string,uint64_t>                  CountedMap; |     typedef std::map<std::string,uint64_t>                  CountedMap; | ||||||
|     typedef std::vector<uint64_t>                           TagList; |     typedef std::vector<uint64_t>                           TagList; | ||||||
|     typedef std::string                                     UUID_t; |     typedef std::string                                     UUID_t; | ||||||
|     typedef std::vector<UUID_t>                             UUIDvec_t; |     typedef std::vector<UUID_t>                             UUIDvec_t; | ||||||
|  | } | ||||||
|  |  | ||||||
|     inline void UpdateCountedMap(CountedMap &M, const std::string &S, uint64_t Increment=1) { | namespace OpenWifi { | ||||||
|  |     inline void UpdateCountedMap(OpenWifi::Types::CountedMap &M, const std::string &S, uint64_t Increment=1) { | ||||||
|         auto it = M.find(S); |         auto it = M.find(S); | ||||||
|         if(it==M.end()) |         if(it==M.end()) | ||||||
|             M[S] = Increment; |             M[S] = Increment; | ||||||
|         else |         else | ||||||
|             it->second += Increment; |             it->second += Increment; | ||||||
|     } |     } | ||||||
|  | } | ||||||
|     inline std::string to_string( const StringVec &V) { |  | ||||||
|         Poco::JSON::Array   O; |  | ||||||
|         for(const auto &i:V) { |  | ||||||
|             O.add(i); |  | ||||||
|         } |  | ||||||
|         std::stringstream SS; |  | ||||||
|         Poco::JSON::Stringifier::stringify(O,SS); |  | ||||||
|         return SS.str(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     inline std::string to_string( const StringPairVec &V) { |  | ||||||
|         Poco::JSON::Array   O; |  | ||||||
|         for(const auto &i:V) { |  | ||||||
|             Poco::JSON::Array OO; |  | ||||||
|             OO.add(i.first); |  | ||||||
|             OO.add(i.second); |  | ||||||
|             O.add(OO); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         std::stringstream SS; |  | ||||||
|         Poco::JSON::Stringifier::stringify(O,SS); |  | ||||||
|         return SS.str(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     inline void from_string(const std::string &S, StringPairVec &V) { |  | ||||||
|         try { |  | ||||||
|             Poco::JSON::Parser      P; |  | ||||||
|             auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>(); |  | ||||||
|  |  | ||||||
|             for(const auto &i:*O) { |  | ||||||
|                 auto Inner = i.extract<Poco::JSON::Array::Ptr>(); |  | ||||||
|                 for(const auto &j:*Inner) { |  | ||||||
|                     auto S1 = i[0].toString(); |  | ||||||
|                     auto S2 = i[1].toString(); |  | ||||||
|                     V.push_back(std::make_pair(S1,S2)); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } catch (...) { |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     inline void from_string(const std::string &S, StringVec &V) { |  | ||||||
|         try { |  | ||||||
|             Poco::JSON::Parser      P; |  | ||||||
|             auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>(); |  | ||||||
|  |  | ||||||
|             for(auto const &i:*O) { |  | ||||||
|                 V.push_back(i.toString()); |  | ||||||
|             } |  | ||||||
|         } catch (...) { |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| #endif // UCENTRALGW_UCENTRALTYPES_H |  | ||||||
|   | |||||||
| @@ -2,8 +2,7 @@ | |||||||
| // Created by stephane bourque on 2021-09-12. | // Created by stephane bourque on 2021-09-12. | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef OWPROV_RESTAPI_ERRORS_H | #pragma once | ||||||
| #define OWPROV_RESTAPI_ERRORS_H |  | ||||||
|  |  | ||||||
| namespace OpenWifi::RESTAPI::Errors { | namespace OpenWifi::RESTAPI::Errors { | ||||||
|     static const std::string MissingUUID{"Missing UUID."}; |     static const std::string MissingUUID{"Missing UUID."}; | ||||||
| @@ -47,13 +46,18 @@ namespace OpenWifi::RESTAPI::Errors { | |||||||
|     static const std::string IdMustBe0{"To create a user, you must set the ID to 0"}; |     static const std::string IdMustBe0{"To create a user, you must set the ID to 0"}; | ||||||
|     static const std::string InvalidUserRole{"Invalid userRole."}; |     static const std::string InvalidUserRole{"Invalid userRole."}; | ||||||
|     static const std::string InvalidEmailAddress{"Invalid email address."}; |     static const std::string InvalidEmailAddress{"Invalid email address."}; | ||||||
|     static const std::string InvalidPassword{"Invalid password."}; |  | ||||||
|     static const std::string PasswordRejected{"Password was rejected. This maybe an old password."}; |     static const std::string PasswordRejected{"Password was rejected. This maybe an old password."}; | ||||||
|     static const std::string InvalidIPRanges{"Invalid IP range specifications."}; |     static const std::string InvalidIPRanges{"Invalid IP range specifications."}; | ||||||
|     static const std::string InvalidLOrderBy{"Invalid orderBy specification."}; |     static const std::string InvalidLOrderBy{"Invalid orderBy specification."}; | ||||||
|     static const std::string NeedMobileNumber{"You must provide at least one validated phone number."}; |     static const std::string NeedMobileNumber{"You must provide at least one validated phone number."}; | ||||||
|     static const std::string BadMFAMethod{"MFA only supports sms or email."}; |     static const std::string BadMFAMethod{"MFA only supports sms or email."}; | ||||||
|  |     static const std::string InvalidCredentials{"Invalid credentials (username/password)."}; | ||||||
|  |     static const std::string InvalidPassword{"Password does not conform to basic password rules."}; | ||||||
|  |     static const std::string UserPendingVerification{"User access denied pending email verification."}; | ||||||
|  |     static const std::string PasswordMustBeChanged{"Password must be changed."}; | ||||||
|  |     static const std::string UnrecognizedRequest{"Ill-formed request. Please consult documentation."}; | ||||||
|  |     static const std::string MissingAuthenticationInformation{"Missing authentication information."}; | ||||||
|  |     static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."}; | ||||||
|  |     static const std::string ExpiredToken{"Token has expired, user must login."}; | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif //OWPROV_RESTAPI_ERRORS_H |  | ||||||
|   | |||||||
| @@ -6,8 +6,7 @@ | |||||||
| //	Arilia Wireless Inc. | //	Arilia Wireless Inc. | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef UCENTRALGW_RESTAPI_PROTOCOL_H | #pragma once | ||||||
| #define UCENTRALGW_RESTAPI_PROTOCOL_H |  | ||||||
|  |  | ||||||
| namespace OpenWifi::RESTAPI::Protocol { | namespace OpenWifi::RESTAPI::Protocol { | ||||||
| 	static const char * CAPABILITIES = "capabilities"; | 	static const char * CAPABILITIES = "capabilities"; | ||||||
| @@ -136,5 +135,3 @@ namespace OpenWifi::RESTAPI::Protocol { | |||||||
|     static const char * UI = "UI"; |     static const char * UI = "UI"; | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif // UCENTRALGW_RESTAPI_PROTOCOL_H |  | ||||||
|   | |||||||
| @@ -2,8 +2,7 @@ | |||||||
| // Created by stephane bourque on 2021-10-06. | // Created by stephane bourque on 2021-10-06. | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef OPENWIFI_STORAGE_H | #pragma once | ||||||
| #define OPENWIFI_STORAGE_H |  | ||||||
|  |  | ||||||
| #include "Poco/Data/Session.h" | #include "Poco/Data/Session.h" | ||||||
| #include "Poco/Data/SessionPool.h" | #include "Poco/Data/SessionPool.h" | ||||||
| @@ -26,13 +25,6 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     class StorageClass : public SubSystemServer { |     class StorageClass : public SubSystemServer { | ||||||
|     public: |     public: | ||||||
| /*        static StorageClass *instance() { |  | ||||||
|             if (instance_ == nullptr) { |  | ||||||
|                 instance_ = new StorageClass; |  | ||||||
|             } |  | ||||||
|             return instance_; |  | ||||||
|         } |  | ||||||
| */ |  | ||||||
|         StorageClass() noexcept: |         StorageClass() noexcept: | ||||||
|             SubSystemServer("StorageClass", "STORAGE-SVR", "storage") |             SubSystemServer("StorageClass", "STORAGE-SVR", "storage") | ||||||
|         { |         { | ||||||
| @@ -56,18 +48,18 @@ namespace OpenWifi { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         void Stop() override { |         void Stop() override { | ||||||
|  |             Pool_->shutdown(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { |         [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { | ||||||
|             if(dbType_==sqlite) { |             if(dbType_==sqlite) { | ||||||
|                 return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " "; |                 return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " "; | ||||||
|             } else if(dbType_==pgsql) { |             } else if(dbType_==pgsql) { | ||||||
|                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; |                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; | ||||||
|             } else if(dbType_==mysql) { |             } else if(dbType_==mysql) { | ||||||
|                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; |                 return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; | ||||||
|             } |             } | ||||||
|             return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; |             return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " "; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         inline std::string ConvertParams(const std::string & S) const { |         inline std::string ConvertParams(const std::string & S) const { | ||||||
| @@ -96,15 +88,13 @@ namespace OpenWifi { | |||||||
|         inline int Setup_PostgreSQL(); |         inline int Setup_PostgreSQL(); | ||||||
|  |  | ||||||
|     protected: |     protected: | ||||||
|         std::unique_ptr<Poco::Data::SessionPool>        	Pool_; |     	Poco::SharedPtr<Poco::Data::SessionPool>    Pool_; | ||||||
|         std::unique_ptr<Poco::Data::SQLite::Connector>  	SQLiteConn_; |         Poco::Data::SQLite::Connector  	            SQLiteConn_; | ||||||
|         std::unique_ptr<Poco::Data::PostgreSQL::Connector>  PostgresConn_; |         Poco::Data::PostgreSQL::Connector           PostgresConn_; | ||||||
|         std::unique_ptr<Poco::Data::MySQL::Connector>       MySQLConn_; |         Poco::Data::MySQL::Connector                MySQLConn_; | ||||||
|         DBType                                              dbType_ = sqlite; |         DBType                                      dbType_ = sqlite; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| //    inline StorageClass * Storage() { return StorageClass::instance(); } |  | ||||||
|  |  | ||||||
| #ifdef	SMALL_BUILD | #ifdef	SMALL_BUILD | ||||||
|     int Service::Setup_MySQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } |     int Service::Setup_MySQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } | ||||||
|     int Service::Setup_PostgreSQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } |     int Service::Setup_PostgreSQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } | ||||||
| @@ -116,9 +106,8 @@ namespace OpenWifi { | |||||||
|         auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db"); |         auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db"); | ||||||
|         auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64); |         auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64); | ||||||
|         auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.sqlite.idletime", 60); |         auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.sqlite.idletime", 60); | ||||||
|         SQLiteConn_ = std::make_unique<Poco::Data::SQLite::Connector>(); |         SQLiteConn_.registerConnector(); | ||||||
|         SQLiteConn_->registerConnector(); |         Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(SQLiteConn_.name(), DBName, 4, NumSessions, IdleTime)); | ||||||
|         Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_->name(), DBName, 4, NumSessions, IdleTime); |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -141,9 +130,8 @@ namespace OpenWifi { | |||||||
|                 ";port=" + Port + |                 ";port=" + Port + | ||||||
|                 ";compress=true;auto-reconnect=true"; |                 ";compress=true;auto-reconnect=true"; | ||||||
|  |  | ||||||
|         MySQLConn_ = std::make_unique<Poco::Data::MySQL::Connector>(); |         MySQLConn_.registerConnector(); | ||||||
|         MySQLConn_->registerConnector(); |         Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(MySQLConn_.name(), ConnectionStr, 4, NumSessions, IdleTime)); | ||||||
|         Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); |  | ||||||
|  |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| @@ -168,14 +156,11 @@ namespace OpenWifi { | |||||||
|                 " port=" + Port + |                 " port=" + Port + | ||||||
|                 " connect_timeout=" + ConnectionTimeout; |                 " connect_timeout=" + ConnectionTimeout; | ||||||
|  |  | ||||||
|         PostgresConn_ = std::make_unique<Poco::Data::PostgreSQL::Connector>(); |         PostgresConn_.registerConnector(); | ||||||
|         PostgresConn_->registerConnector(); |         Pool_ = Poco::SharedPtr<Poco::Data::SessionPool>(new Poco::Data::SessionPool(PostgresConn_.name(), ConnectionStr, 4, NumSessions, IdleTime)); | ||||||
|         Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); |  | ||||||
|  |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif //OPENWIFI_STORAGE_H |  | ||||||
|   | |||||||
| @@ -6,8 +6,7 @@ | |||||||
| //	Arilia Wireless Inc. | //	Arilia Wireless Inc. | ||||||
| // | // | ||||||
|  |  | ||||||
| #ifndef __OPENWIFI_ORM_H__ | #pragma once | ||||||
| #define __OPENWIFI_ORM_H__ |  | ||||||
|  |  | ||||||
| #include <string> | #include <string> | ||||||
| #include <memory> | #include <memory> | ||||||
| @@ -755,4 +754,3 @@ namespace ORM { | |||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif |  | ||||||
| @@ -5,9 +5,7 @@ | |||||||
| //	Created by Stephane Bourque on 2021-03-04. | //	Created by Stephane Bourque on 2021-03-04. | ||||||
| //	Arilia Wireless Inc. | //	Arilia Wireless Inc. | ||||||
| // | // | ||||||
|  | #pragma once | ||||||
| #ifndef UCENTRALGW_UCENTRALPROTOCOL_H |  | ||||||
| #define UCENTRALGW_UCENTRALPROTOCOL_H |  | ||||||
|  |  | ||||||
| #include "Poco/String.h" | #include "Poco/String.h" | ||||||
|  |  | ||||||
| @@ -130,5 +128,3 @@ namespace OpenWifi::uCentralProtocol { | |||||||
| 			return ET_UNKNOWN; | 			return ET_UNKNOWN; | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
|  |  | ||||||
| #endif // UCENTRALGW_UCENTRALPROTOCOL_H |  | ||||||
|   | |||||||
| @@ -175,6 +175,25 @@ namespace OpenWifi { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	uint64_t Storage::GetBlackListDeviceCount() { | ||||||
|  | 		try { | ||||||
|  | 			Poco::Data::Session Sess = Pool_->get(); | ||||||
|  | 			Poco::Data::Statement Select(Sess); | ||||||
|  |  | ||||||
|  | 			std::string St{"SELECT Count(*) FROM BlackList"}; | ||||||
|  | 			uint64_t Count = 0 ; | ||||||
|  |  | ||||||
|  | 			Select << ConvertParams(St), | ||||||
|  | 			Poco::Data::Keywords::into(Count); | ||||||
|  |  | ||||||
|  | 			Select.execute(); | ||||||
|  | 			return Count; | ||||||
|  | 		} catch (const Poco::Exception &E) { | ||||||
|  | 			Logger_.log(E); | ||||||
|  | 		} | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	bool Storage::IsBlackListed(std::string &SerialNumber) { | 	bool Storage::IsBlackListed(std::string &SerialNumber) { | ||||||
| 		try { | 		try { | ||||||
| 			Poco::Data::Session Sess = Pool_->get(); | 			Poco::Data::Session Sess = Pool_->get(); | ||||||
|   | |||||||
| @@ -7,10 +7,11 @@ | |||||||
| // | // | ||||||
|  |  | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
|  | #include "CentralConfig.h" | ||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "Poco/JSON/Object.h" | #include "Poco/JSON/Object.h" | ||||||
| #include "Poco/Data/RecordSet.h" | #include "Poco/Data/RecordSet.h" | ||||||
|  | #include "CapabilitiesCache.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -25,23 +26,11 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 			uint64_t Now = std::time(nullptr); | 			uint64_t Now = std::time(nullptr); | ||||||
|  |  | ||||||
| 			//	Find compatible in the capabilities... | 			OpenWifi::Config::Capabilities	Caps(Capabilities); | ||||||
| 			std::string Compatible; |  | ||||||
|  |  | ||||||
| 			Poco::JSON::Parser	P; | 			Compat = Caps.Compatible(); | ||||||
| 			Poco::JSON::Parser      IncomingParser; | 			if(!Caps.Compatible().empty() && !Caps.Platform().empty()) | ||||||
| 			Poco::JSON::Object::Ptr Obj = IncomingParser.parse(Capabilities).extract<Poco::JSON::Object::Ptr>(); | 				CapabilitiesCache::instance()->Add(Caps.Compatible(),Caps.Platform()); | ||||||
| 			Poco::DynamicStruct ds = *Obj; |  | ||||||
|  |  | ||||||
| 			if(ds.contains("compatible")) { |  | ||||||
| 				Compat = Compatible = ds["compatible"].toString(); |  | ||||||
| 			} else { |  | ||||||
| 				//	Maybe this is an old firmware |  | ||||||
| 				auto TmpCompatible = ds["model"]["id"].toString(); |  | ||||||
|  |  | ||||||
| 				for(const auto &i:TmpCompatible) |  | ||||||
| 					Compatible += (char) ( i==',' ? '_' : i); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			std::string St{"SELECT SerialNumber FROM Capabilities WHERE SerialNumber=?"}; | 			std::string St{"SELECT SerialNumber FROM Capabilities WHERE SerialNumber=?"}; | ||||||
| 			Select << ConvertParams(St), | 			Select << ConvertParams(St), | ||||||
| @@ -49,7 +38,10 @@ namespace OpenWifi { | |||||||
| 				Poco::Data::Keywords::use(SerialNumber); | 				Poco::Data::Keywords::use(SerialNumber); | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|  |  | ||||||
| 			{ std::lock_guard	G(Mutex_); CapsCache_[Compatible] = Capabilities; } | 			{ | ||||||
|  | 				std::lock_guard	G(Mutex_); | ||||||
|  | 				CapsCache_[Compat] = Capabilities; | ||||||
|  | 			} | ||||||
|  |  | ||||||
| 			if (SS.empty()) { | 			if (SS.empty()) { | ||||||
| 				Logger_.information("Adding capabilities for " + SerialNumber); | 				Logger_.information("Adding capabilities for " + SerialNumber); | ||||||
| @@ -78,7 +70,7 @@ namespace OpenWifi { | |||||||
| 				Update.execute(); | 				Update.execute(); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			Storage::SetDeviceCompatibility(SerialNumber, Compatible); | 			Storage::SetDeviceCompatibility(SerialNumber, Compat); | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		catch (const Poco::Exception &E) { | 		catch (const Poco::Exception &E) { | ||||||
|   | |||||||
| @@ -157,9 +157,8 @@ typedef Poco::Tuple< | |||||||
| 			bool DatesIncluded = (FromDate != 0 || ToDate != 0); | 			bool DatesIncluded = (FromDate != 0 || ToDate != 0); | ||||||
|  |  | ||||||
| 			std::string Fields{ | 			std::string Fields{ | ||||||
| 				"SELECT " + | 				"SELECT " + DB_Command_SelectFields + " FROM CommandList " }; | ||||||
| 					DB_Command_SelectFields + |  | ||||||
| 					" FROM CommandList ORDER BY UUID ASC "}; |  | ||||||
| 			std::string IntroStatement = SerialNumber.empty() | 			std::string IntroStatement = SerialNumber.empty() | ||||||
| 											 ? Fields + std::string(DatesIncluded ? "WHERE " : "") | 											 ? Fields + std::string(DatesIncluded ? "WHERE " : "") | ||||||
| 											 : Fields + "WHERE SerialNumber='" + SerialNumber + "'" + | 											 : Fields + "WHERE SerialNumber='" + SerialNumber + "'" + | ||||||
| @@ -177,7 +176,12 @@ typedef Poco::Tuple< | |||||||
|  |  | ||||||
| 			Poco::Data::Statement Select(Sess); | 			Poco::Data::Statement Select(Sess); | ||||||
|  |  | ||||||
| 			Select << 	IntroStatement + DateSelector + ComputeRange(Offset, HowMany), | 			std::string FullQuery = IntroStatement + DateSelector + | ||||||
|  | 					" ORDER BY Submitted ASC " + ComputeRange(Offset, HowMany); | ||||||
|  |  | ||||||
|  | 			// std::cout << "Offset: " << Offset << "  >>  " << FullQuery << std::endl; | ||||||
|  |  | ||||||
|  | 			Select << 	FullQuery, | ||||||
| 				Poco::Data::Keywords::into(Records); | 				Poco::Data::Keywords::into(Records); | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
| 			for (const auto &i : Records) { | 			for (const auto &i : Records) { | ||||||
| @@ -355,12 +359,10 @@ typedef Poco::Tuple< | |||||||
|  |  | ||||||
| 			std::string st{"SELECT " + | 			std::string st{"SELECT " + | ||||||
| 							   DB_Command_SelectFields + | 							   DB_Command_SelectFields + | ||||||
| 							   " FROM CommandList WHERE SerialNumber=? ORDER BY Submitted DESC"}; | 							   " FROM CommandList WHERE SerialNumber=? ORDER BY Submitted DESC " + ComputeRange(0, HowMany)}; | ||||||
|  |  | ||||||
| 			Select << 	ConvertParams(st), | 			Select << 	ConvertParams(st), | ||||||
| 						Poco::Data::Keywords::into(Records), | 						Poco::Data::Keywords::into(Records), | ||||||
| 						Poco::Data::Keywords::use(SerialNumber), | 						Poco::Data::Keywords::use(SerialNumber); | ||||||
| 						Poco::Data::Keywords::limit(HowMany); |  | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|  |  | ||||||
| 			for (auto i : Records) { | 			for (auto i : Records) { | ||||||
| @@ -677,7 +679,7 @@ typedef Poco::Tuple< | |||||||
| 			while(More) { | 			while(More) { | ||||||
| 				auto Command = RSet[0].convert<std::string>(); | 				auto Command = RSet[0].convert<std::string>(); | ||||||
| 				if(!Command.empty()) | 				if(!Command.empty()) | ||||||
| 					Types::UpdateCountedMap(R,Command); | 					UpdateCountedMap(R,Command); | ||||||
| 				More = RSet.moveNext(); | 				More = RSet.moveNext(); | ||||||
| 			} | 			} | ||||||
| 			return true; | 			return true; | ||||||
|   | |||||||
| @@ -12,18 +12,51 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| 	/* | 	const static std::string	DB_DefConfig_SelectFields_ForCreation{ | ||||||
| 	 *  Data model for DefaultConfigurations: | 		"Name VARCHAR(30) PRIMARY KEY, " | ||||||
|  | 		"Configuration TEXT, " | ||||||
|  | 		"Models TEXT, " | ||||||
|  | 		"Description TEXT, " | ||||||
|  | 		"Created BIGINT , " | ||||||
|  | 		"LastModified BIGINT)"}; | ||||||
|  |  | ||||||
| 		Table name: DefaultConfigs | 	const static std::string	DB_DefConfig_SelectFields{ | ||||||
|  | 		"Name, " | ||||||
|  | 		"Configuration, " | ||||||
|  | 		"Models, " | ||||||
|  | 		"Description, " | ||||||
|  | 		"Created, " | ||||||
|  | 		"LastModified "}; | ||||||
|  |  | ||||||
| 					"Name VARCHAR(30) PRIMARY KEY, " | 	const static std::string 	DB_DefConfig_InsertValues{"?,?,?,?,?,?"}; | ||||||
| 					"Configuration TEXT, " |  | ||||||
| 					"Models TEXT, " | 	typedef Poco::Tuple< | ||||||
| 					"Description TEXT, " | 		std::string, | ||||||
| 					"Created BIGINT , " | 		std::string, | ||||||
| 					"LastModified BIGINT)", now; | 		std::string, | ||||||
| 	 */ | 		std::string, | ||||||
|  | 		uint64_t, | ||||||
|  | 		uint64_t | ||||||
|  | 	> DefConfigRecordTuple; | ||||||
|  | 	typedef std::vector<DefConfigRecordTuple> DefConfigRecordList; | ||||||
|  |  | ||||||
|  | 	void Convert(const DefConfigRecordTuple &R, GWObjects::DefaultConfiguration & T) { | ||||||
|  | 		T.Name = R.get<0>(); | ||||||
|  | 		T.Configuration = R.get<1>(); | ||||||
|  | 		T.Models = R.get<2>(); | ||||||
|  | 		T.Description = R.get<3>(); | ||||||
|  | 		T.Created = R.get<4>(); | ||||||
|  | 		T.LastModified = R.get<5>(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	void Convert(const GWObjects::DefaultConfiguration & R, DefConfigRecordTuple &T) { | ||||||
|  | 		T.set<0>(R.Name); | ||||||
|  | 		T.set<1>(R.Configuration); | ||||||
|  | 		T.set<2>(R.Models); | ||||||
|  | 		T.set<3>(R.Description); | ||||||
|  | 		T.set<4>(R.Created); | ||||||
|  | 		T.set<5>(R.LastModified); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	bool Storage::CreateDefaultConfiguration(std::string &Name, GWObjects::DefaultConfiguration &DefConfig) { | 	bool Storage::CreateDefaultConfiguration(std::string &Name, GWObjects::DefaultConfiguration &DefConfig) { | ||||||
| 		try { | 		try { | ||||||
| @@ -38,43 +71,27 @@ namespace OpenWifi { | |||||||
| 				Name; | 				Name; | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|  |  | ||||||
| 			if (TmpName.empty()) { | 			if (!TmpName.empty()) | ||||||
|  | 				return false; | ||||||
|  |  | ||||||
| 				Config::Config Cfg(DefConfig.Configuration); | 			Config::Config Cfg(DefConfig.Configuration); | ||||||
| 	/* |  | ||||||
| 						 "Name VARCHAR(30) PRIMARY KEY, " |  | ||||||
| 						"Configuration TEXT, " |  | ||||||
| 						"Models TEXT, " |  | ||||||
| 						"Description TEXT, " |  | ||||||
| 						"Created BIGINT , " |  | ||||||
| 						"LastModified BIGINT)", now; |  | ||||||
|  |  | ||||||
| 	 */ | 			if (Cfg.Valid()) { | ||||||
|  | 				uint64_t Now = std::time(nullptr); | ||||||
|  | 				Poco::Data::Statement   Insert(Sess); | ||||||
|  |  | ||||||
| 				if (Cfg.Valid()) { | 				std::string St{"INSERT INTO DefaultConfigs " + DB_DefConfig_SelectFields + ") " | ||||||
| 					uint64_t Now = std::time(nullptr); | 						"VALUES(" + DB_DefConfig_InsertValues + ")"}; | ||||||
| 					Poco::Data::Statement   Insert(Sess); |  | ||||||
|  |  | ||||||
| 					std::string St{"INSERT INTO DefaultConfigs (Name, Configuration, Models, Description, Created, LastModified) " | 				DefConfigRecordTuple R; | ||||||
| 								   "VALUES(?,?,?,?,?,?)"}; | 				Convert(DefConfig,R); | ||||||
|  | 				Insert  << ConvertParams(St), | ||||||
| 					Insert  << ConvertParams(St), | 					Poco::Data::Keywords::use(R); | ||||||
| 						Poco::Data::Keywords::use(Name), | 				Insert.execute(); | ||||||
| 						Poco::Data::Keywords::use(DefConfig.Configuration), | 				return true; | ||||||
| 						Poco::Data::Keywords::use(DefConfig.Models), |  | ||||||
| 						Poco::Data::Keywords::use(DefConfig.Description), |  | ||||||
| 						Poco::Data::Keywords::use(Now), |  | ||||||
| 						Poco::Data::Keywords::use(Now); |  | ||||||
|  |  | ||||||
| 					Insert.execute(); |  | ||||||
|  |  | ||||||
| 					return true; |  | ||||||
| 				} else { |  | ||||||
| 					Logger_.warning("Cannot create device: invalid configuration."); |  | ||||||
| 					return false; |  | ||||||
| 				} |  | ||||||
| 			} else { | 			} else { | ||||||
| 				Logger_.warning("Default configuration already exists."); | 				Logger_.warning("Cannot create device: invalid configuration."); | ||||||
|  | 				return false; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		catch (const Poco::Exception &E) { | 		catch (const Poco::Exception &E) { | ||||||
| @@ -115,16 +132,16 @@ namespace OpenWifi { | |||||||
| 				uint64_t Now = time(nullptr); | 				uint64_t Now = time(nullptr); | ||||||
| 				Poco::Data::Statement   Update(Sess); | 				Poco::Data::Statement   Update(Sess); | ||||||
|  |  | ||||||
| 				std::string St{"UPDATE DefaultConfigs SET Configuration=?,  Models=?,  Description=?,  LastModified=?  WHERE Name=?"}; | 				std::string St{"UPDATE DefaultConfigs SET Name=?, Configuration=?,  Models=?,  Description=?,  Created=? , LastModified=?  WHERE Name=?"}; | ||||||
|  |  | ||||||
|  | 				DefConfigRecordTuple R; | ||||||
|  | 				Convert(DefConfig, R); | ||||||
|  |  | ||||||
| 				Update << ConvertParams(St), | 				Update << ConvertParams(St), | ||||||
| 					Poco::Data::Keywords::use(DefConfig.Configuration), | 					Poco::Data::Keywords::use(R), | ||||||
| 					Poco::Data::Keywords::use(DefConfig.Models), |  | ||||||
| 					Poco::Data::Keywords::use(DefConfig.Description), |  | ||||||
| 					Poco::Data::Keywords::use(Now), |  | ||||||
| 					Poco::Data::Keywords::use(Name); | 					Poco::Data::Keywords::use(Name); | ||||||
|  |  | ||||||
| 				Update.execute(); | 				Update.execute(); | ||||||
|  |  | ||||||
| 				return true; | 				return true; | ||||||
| 			} else { | 			} else { | ||||||
| 				Logger_.warning( | 				Logger_.warning( | ||||||
| @@ -144,30 +161,20 @@ namespace OpenWifi { | |||||||
| 			Poco::Data::Session     Sess = Pool_->get(); | 			Poco::Data::Session     Sess = Pool_->get(); | ||||||
| 			Poco::Data::Statement   Select(Sess); | 			Poco::Data::Statement   Select(Sess); | ||||||
|  |  | ||||||
| 			std::string St{"SELECT " | 			std::string St{"SELECT " + DB_DefConfig_SelectFields + | ||||||
| 						   "Name, " | 						   " FROM DefaultConfigs WHERE Name=?"}; | ||||||
| 						   "Configuration, " |  | ||||||
| 						   "Models, " |  | ||||||
| 						   "Description, " |  | ||||||
| 						   "Created, " |  | ||||||
| 						   "LastModified " |  | ||||||
| 						   "FROM DefaultConfigs WHERE Name=?"}; |  | ||||||
|  |  | ||||||
|  | 			DefConfigRecordTuple R; | ||||||
| 			Select << ConvertParams(St), | 			Select << ConvertParams(St), | ||||||
| 				Poco::Data::Keywords::into(DefConfig.Name), | 				Poco::Data::Keywords::into(R), | ||||||
| 				Poco::Data::Keywords::into(DefConfig.Configuration), |  | ||||||
| 				Poco::Data::Keywords::into(DefConfig.Models), |  | ||||||
| 				Poco::Data::Keywords::into(DefConfig.Description), |  | ||||||
| 				Poco::Data::Keywords::into(DefConfig.Created), |  | ||||||
| 				Poco::Data::Keywords::into(DefConfig.LastModified), |  | ||||||
| 				Poco::Data::Keywords::use(Name); | 				Poco::Data::Keywords::use(Name); | ||||||
|  |  | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|  |  | ||||||
| 			if (DefConfig.Name.empty()) | 			if (!DefConfig.Name.empty()) { | ||||||
| 				return false; | 				Convert(R,DefConfig); | ||||||
|  | 				return true; | ||||||
| 			return true; | 			} | ||||||
|  | 			return false; | ||||||
| 		} | 		} | ||||||
| 		catch (const Poco::Exception &E) { | 		catch (const Poco::Exception &E) { | ||||||
| 			Logger_.warning(Poco::format("%s(%s): Failed with: %s", std::string(__func__), Name, E.displayText())); | 			Logger_.warning(Poco::format("%s(%s): Failed with: %s", std::string(__func__), Name, E.displayText())); | ||||||
| @@ -177,43 +184,19 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	bool Storage::GetDefaultConfigurations(uint64_t From, uint64_t HowMany, | 	bool Storage::GetDefaultConfigurations(uint64_t From, uint64_t HowMany, | ||||||
| 										   std::vector<GWObjects::DefaultConfiguration> &DefConfigs) { | 										   std::vector<GWObjects::DefaultConfiguration> &DefConfigs) { | ||||||
| 		typedef Poco::Tuple< |  | ||||||
| 			std::string, |  | ||||||
| 			std::string, |  | ||||||
| 			std::string, |  | ||||||
| 			std::string, |  | ||||||
| 			uint64_t, |  | ||||||
| 			uint64_t> DeviceRecord; |  | ||||||
| 		typedef std::vector<DeviceRecord> RecordList; |  | ||||||
|  |  | ||||||
| 		RecordList Records; |  | ||||||
|  |  | ||||||
| 		try { | 		try { | ||||||
| 			Poco::Data::Session     Sess = Pool_->get(); | 			Poco::Data::Session     Sess = Pool_->get(); | ||||||
| 			Poco::Data::Statement   Select(Sess); | 			Poco::Data::Statement   Select(Sess); | ||||||
|  |  | ||||||
| 			Select << "SELECT " | 			DefConfigRecordList Records; | ||||||
| 					  "Name, " | 			Select << "SELECT "  + DB_DefConfig_SelectFields + | ||||||
| 					  "Configuration, " | 					  " FROM DefaultConfigs ORDER BY NAME ASC " + ComputeRange(From, HowMany) , | ||||||
| 					  "Models, " | 					Poco::Data::Keywords::into(Records); | ||||||
| 					  "Description, " |  | ||||||
| 					  "Created, " |  | ||||||
| 					  "LastModified " |  | ||||||
| 					  "FROM DefaultConfigs ORDER BY NAME ASC " + |  | ||||||
| 						  ComputeRange(From, HowMany), |  | ||||||
| 				Poco::Data::Keywords::into(Records); |  | ||||||
|  |  | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|  |  | ||||||
| 			for (auto i: Records) { | 			for (auto i: Records) { | ||||||
| 				GWObjects::DefaultConfiguration R{ | 				GWObjects::DefaultConfiguration R; | ||||||
| 					.Name           = i.get<0>(), | 				Convert(i,R); | ||||||
| 					.Configuration  = i.get<1>(), |  | ||||||
| 					.Models         = i.get<2>(), |  | ||||||
| 					.Description    = i.get<3>(), |  | ||||||
| 					.Created        = i.get<4>(), |  | ||||||
| 					.LastModified   = i.get<5>()}; |  | ||||||
|  |  | ||||||
| 				DefConfigs.push_back(R); | 				DefConfigs.push_back(R); | ||||||
| 			} | 			} | ||||||
| 			return true; | 			return true; | ||||||
| @@ -224,67 +207,41 @@ namespace OpenWifi { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool FindInList(const std::string &Model, const std::string &List) { |  | ||||||
| 		unsigned long P = 0; |  | ||||||
| 		std::string Token; |  | ||||||
|  |  | ||||||
| 		while (P < List.size()) { |  | ||||||
| 			auto P2 = List.find_first_of(',', P); |  | ||||||
| 			if (P2 == std::string::npos) { |  | ||||||
| 				Token = List.substr(P); |  | ||||||
| 				if (Model.find(Token) != std::string::npos) |  | ||||||
| 					return true; |  | ||||||
| 				return false; |  | ||||||
| 			} else { |  | ||||||
| 				Token = List.substr(P, P2); |  | ||||||
| 				if (Model.find(Token) != std::string::npos) |  | ||||||
| 					return true; |  | ||||||
| 			} |  | ||||||
| 			P = P2 + 1; |  | ||||||
| 		} |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool Storage::FindDefaultConfigurationForModel(const std::string &Model, GWObjects::DefaultConfiguration &DefConfig) { | 	bool Storage::FindDefaultConfigurationForModel(const std::string &Model, GWObjects::DefaultConfiguration &DefConfig) { | ||||||
| 		try { | 		try { | ||||||
| 			typedef Poco::Tuple< | 			DefConfigRecordList Records; | ||||||
| 				std::string, |  | ||||||
| 				std::string, |  | ||||||
| 				std::string, |  | ||||||
| 				std::string, |  | ||||||
| 				uint64_t, |  | ||||||
| 				uint64_t> DeviceRecord; |  | ||||||
| 			typedef std::vector<DeviceRecord> RecordList; |  | ||||||
| 			RecordList Records; |  | ||||||
|  |  | ||||||
| 			Poco::Data::Session     Sess = Pool_->get(); | 			Poco::Data::Session     Sess = Pool_->get(); | ||||||
| 			Poco::Data::Statement   Select(Sess); | 			Poco::Data::Statement   Select(Sess); | ||||||
|  |  | ||||||
| 			Select << "SELECT " | 			Select << "SELECT "  + DB_DefConfig_SelectFields + " FROM DefaultConfigs", | ||||||
| 					  "Name, " |  | ||||||
| 					  "Configuration, " |  | ||||||
| 					  "Models, " |  | ||||||
| 					  "Description, " |  | ||||||
| 					  "Created, " |  | ||||||
| 					  "LastModified " |  | ||||||
| 					  "FROM DefaultConfigs ORDER BY NAME ASC " + |  | ||||||
| 						  ComputeRange(1,1), |  | ||||||
| 				Poco::Data::Keywords::into(Records); | 				Poco::Data::Keywords::into(Records); | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|  |  | ||||||
| 			for (auto i: Records) { | 			for (auto i: Records) { | ||||||
| 				DefConfig.Models = i.get<2>(); | 				GWObjects::DefaultConfiguration Config; | ||||||
| 				if (FindInList(Model, DefConfig.Models)) { | 				Convert(i,Config); | ||||||
| 					DefConfig.Name = i.get<0>(); |  | ||||||
| 					Logger_.information(Poco::format("AUTO-PROVISIONING: found default configuration '%s' for model:%s", | 				//	We need to account for possible old values in config... | ||||||
| 													 DefConfig.Name, Model)); | 				if(Config.Models[0]!='[') { | ||||||
| 					DefConfig.Name = i.get<0>(); | 					if(Config.Models.empty()) | ||||||
| 					DefConfig.Configuration = i.get<1>(); | 						Config.Models = "[]"; | ||||||
| 					DefConfig.Models = i.get<2>(); | 					else | ||||||
| 					DefConfig.Description = i.get<3>(); | 						Config.Models = "[" + Config.Models + "]"; | ||||||
| 					DefConfig.Created = i.get<4>(); | 				} | ||||||
| 					DefConfig.LastModified = i.get<5>(); |  | ||||||
| 					return true; | 				try { | ||||||
|  | 					Poco::JSON::Parser P; | ||||||
|  | 					auto List = P.parse(Config.Models).extract<Poco::JSON::Array::Ptr>(); | ||||||
|  |  | ||||||
|  | 					for(const auto &j:*List) { | ||||||
|  | 						if(j.toString()=="*" || j.toString()==Model) { | ||||||
|  | 							DefConfig = Config; | ||||||
|  | 							return true; | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} catch(...) { | ||||||
|  | 					// if we had problems parsing this entry, just skip it. | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			Logger_.information(Poco::format("AUTO-PROVISIONING: no default configuration for model:%s", Model)); | 			Logger_.information(Poco::format("AUTO-PROVISIONING: no default configuration for model:%s", Model)); | ||||||
| @@ -296,5 +253,20 @@ namespace OpenWifi { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	uint64_t Storage::GetDefaultConfigurationsCount() { | ||||||
|  | 		uint64_t Count = 0; | ||||||
|  | 		try { | ||||||
|  | 			Poco::Data::Session     Sess = Pool_->get(); | ||||||
|  | 			Poco::Data::Statement   Select(Sess); | ||||||
|  | 			Select << "SELECT Count(*) from DefaultConfigs" , | ||||||
|  | 				Poco::Data::Keywords::into(Count); | ||||||
|  | 			Select.execute(); | ||||||
|  | 			return Count; | ||||||
|  | 		} | ||||||
|  | 		catch (const Poco::Exception &E) { | ||||||
|  | 			Logger_.warning(Poco::format("%s: Failed with: %s", std::string(__func__), E.displayText())); | ||||||
|  | 		} | ||||||
|  | 		return Count; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -16,6 +16,7 @@ | |||||||
| #include "StateProcessor.h" | #include "StateProcessor.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "CapabilitiesCache.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -265,7 +266,10 @@ namespace OpenWifi { | |||||||
| 		Config::Capabilities 			Caps(Capabilities); | 		Config::Capabilities 			Caps(Capabilities); | ||||||
| 		GWObjects::DefaultConfiguration DefConfig; | 		GWObjects::DefaultConfiguration DefConfig; | ||||||
|  |  | ||||||
| 		if (FindDefaultConfigurationForModel(Caps.Model(), DefConfig)) { | 		if(!Caps.Platform().empty() && !Caps.Compatible().empty()) | ||||||
|  | 			CapabilitiesCache::instance()->Add(Caps.Compatible(),Caps.Platform()); | ||||||
|  |  | ||||||
|  | 		if (FindDefaultConfigurationForModel(Compat, DefConfig)) { | ||||||
| 			Config::Config NewConfig(DefConfig.Configuration); | 			Config::Config NewConfig(DefConfig.Configuration); | ||||||
| 			NewConfig.SetUUID(Now); | 			NewConfig.SetUUID(Now); | ||||||
| 			D.Configuration = NewConfig.get(); | 			D.Configuration = NewConfig.get(); | ||||||
| @@ -282,6 +286,7 @@ namespace OpenWifi { | |||||||
| 		D.Manufacturer = Caps.Model(); | 		D.Manufacturer = Caps.Model(); | ||||||
| 		D.Firmware = Firmware; | 		D.Firmware = Firmware; | ||||||
| 		D.Notes = SecurityObjects::NoteInfoVec { SecurityObjects::NoteInfo{ (uint64_t)std::time(nullptr), "", "Auto-provisioned."}}; | 		D.Notes = SecurityObjects::NoteInfoVec { SecurityObjects::NoteInfo{ (uint64_t)std::time(nullptr), "", "Auto-provisioned."}}; | ||||||
|  |  | ||||||
| 		return CreateDevice(D); | 		return CreateDevice(D); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -722,19 +727,19 @@ namespace OpenWifi { | |||||||
| 				auto SerialNumber = RSet[0].convert<std::string>(); | 				auto SerialNumber = RSet[0].convert<std::string>(); | ||||||
| 				auto DeviceType = RSet[1].convert<std::string>(); | 				auto DeviceType = RSet[1].convert<std::string>(); | ||||||
| 				auto Revision = RSet[2].convert<std::string>(); | 				auto Revision = RSet[2].convert<std::string>(); | ||||||
| 				Types::UpdateCountedMap(Dashboard.vendors, OUIServer()->GetManufacturer(SerialNumber)); | 				UpdateCountedMap(Dashboard.vendors, OUIServer()->GetManufacturer(SerialNumber)); | ||||||
| 				Types::UpdateCountedMap(Dashboard.deviceType, DeviceType); | 				UpdateCountedMap(Dashboard.deviceType, DeviceType); | ||||||
|  |  | ||||||
| 				GWObjects::ConnectionState	ConnState; | 				GWObjects::ConnectionState	ConnState; | ||||||
| 				if(DeviceRegistry()->GetState(SerialNumber, ConnState)) { | 				if(DeviceRegistry()->GetState(SerialNumber, ConnState)) { | ||||||
| 					Types::UpdateCountedMap(Dashboard.status, ConnState.Connected ? "connected" : "not connected"); | 					UpdateCountedMap(Dashboard.status, ConnState.Connected ? "connected" : "not connected"); | ||||||
| 					Types::UpdateCountedMap(Dashboard.certificates, ComputeCertificateTag(ConnState.VerifiedCertificate)); | 					UpdateCountedMap(Dashboard.certificates, ComputeCertificateTag(ConnState.VerifiedCertificate)); | ||||||
| 					Types::UpdateCountedMap(Dashboard.lastContact, ComputeUpLastContactTag(ConnState.LastContact)); | 					UpdateCountedMap(Dashboard.lastContact, ComputeUpLastContactTag(ConnState.LastContact)); | ||||||
| 					GWObjects::HealthCheck	HC; | 					GWObjects::HealthCheck	HC; | ||||||
| 					if(DeviceRegistry()->GetHealthcheck(SerialNumber,HC)) | 					if(DeviceRegistry()->GetHealthcheck(SerialNumber,HC)) | ||||||
| 						Types::UpdateCountedMap(Dashboard.healths, ComputeSanityTag(HC.Sanity)); | 						UpdateCountedMap(Dashboard.healths, ComputeSanityTag(HC.Sanity)); | ||||||
| 					else | 					else | ||||||
| 						Types::UpdateCountedMap(Dashboard.healths, ComputeSanityTag(100)); | 						UpdateCountedMap(Dashboard.healths, ComputeSanityTag(100)); | ||||||
| 					std::string LastStats; | 					std::string LastStats; | ||||||
| 					if(DeviceRegistry()->GetStatistics(SerialNumber, LastStats) && !LastStats.empty()) { | 					if(DeviceRegistry()->GetStatistics(SerialNumber, LastStats) && !LastStats.empty()) { | ||||||
| 						Poco::JSON::Parser	P; | 						Poco::JSON::Parser	P; | ||||||
| @@ -744,34 +749,33 @@ namespace OpenWifi { | |||||||
| 						if(RawObject->has("unit")) { | 						if(RawObject->has("unit")) { | ||||||
| 							auto Unit = RawObject->getObject("unit"); | 							auto Unit = RawObject->getObject("unit"); | ||||||
| 							if (Unit->has("uptime")) { | 							if (Unit->has("uptime")) { | ||||||
| 								Types::UpdateCountedMap(Dashboard.upTimes, ComputeUpTimeTag(Unit->get("uptime"))); | 								UpdateCountedMap(Dashboard.upTimes, ComputeUpTimeTag(Unit->get("uptime"))); | ||||||
| 							} | 							} | ||||||
| 							if (Unit->has("memory")) { | 							if (Unit->has("memory")) { | ||||||
| 								auto Memory = Unit->getObject("memory"); | 								auto Memory = Unit->getObject("memory"); | ||||||
| 								uint64_t Free = Memory->get("free"); | 								uint64_t Free = Memory->get("free"); | ||||||
| 								uint64_t Total = Memory->get("total"); | 								uint64_t Total = Memory->get("total"); | ||||||
| 								Types::UpdateCountedMap(Dashboard.memoryUsed, ComputeFreeMemoryTag(Free, Total)); | 								UpdateCountedMap(Dashboard.memoryUsed, ComputeFreeMemoryTag(Free, Total)); | ||||||
| 							} | 							} | ||||||
| 							if (Unit->has("load")) { | 							if (Unit->has("load")) { | ||||||
| 								auto Load = Unit->getArray("load"); | 								auto Load = Unit->getArray("load"); | ||||||
| 								Types::UpdateCountedMap(Dashboard.load1, | 								UpdateCountedMap(Dashboard.load1, | ||||||
| 														ComputeLoadTag(Load->getElement<uint64_t>(0))); | 														ComputeLoadTag(Load->getElement<uint64_t>(0))); | ||||||
| 								Types::UpdateCountedMap(Dashboard.load5, | 								UpdateCountedMap(Dashboard.load5, | ||||||
| 														ComputeLoadTag(Load->getElement<uint64_t>(1))); | 														ComputeLoadTag(Load->getElement<uint64_t>(1))); | ||||||
| 								Types::UpdateCountedMap(Dashboard.load15, | 								UpdateCountedMap(Dashboard.load15, | ||||||
| 														ComputeLoadTag(Load->getElement<uint64_t>(2))); | 														ComputeLoadTag(Load->getElement<uint64_t>(2))); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| 						uint64_t 	Associations_2G, Associations_5G; | 						uint64_t 	Associations_2G, Associations_5G; | ||||||
| 						StateProcessor::GetAssociations(RawObject, Associations_2G, Associations_5G); | 						StateProcessor::GetAssociations(RawObject, Associations_2G, Associations_5G); | ||||||
| 						Types::UpdateCountedMap(Dashboard.associations, "2G", Associations_2G); | 						UpdateCountedMap(Dashboard.associations, "2G", Associations_2G); | ||||||
| 						Types::UpdateCountedMap(Dashboard.associations, "5G", Associations_5G); | 						UpdateCountedMap(Dashboard.associations, "5G", Associations_5G); | ||||||
|  |  | ||||||
| 					} | 					} | ||||||
| 					Types::UpdateCountedMap(Dashboard.status, ConnState.Connected ? "connected" : "not connected"); | 					UpdateCountedMap(Dashboard.status, ConnState.Connected ? "connected" : "not connected"); | ||||||
| 				} else { | 				} else { | ||||||
| 					Types::UpdateCountedMap(Dashboard.status, "not connected"); | 					UpdateCountedMap(Dashboard.status, "not connected"); | ||||||
| 				} | 				} | ||||||
| 				More = RSet.moveNext(); | 				More = RSet.moveNext(); | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -114,7 +114,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 			std::string st{"SELECT " + DB_HealthCheckSelectFields + " FROM HealthChecks WHERE SerialNumber=? ORDER BY Recorded DESC "}; | 			std::string st{"SELECT " + DB_HealthCheckSelectFields + " FROM HealthChecks WHERE SerialNumber=? ORDER BY Recorded DESC "}; | ||||||
|  |  | ||||||
| 			Select << 	ConvertParams(st) + ComputeRange(1,HowMany), | 			Select << 	ConvertParams(st) + ComputeRange(0,HowMany), | ||||||
| 						Poco::Data::Keywords::into(Records), | 						Poco::Data::Keywords::into(Records), | ||||||
| 						Poco::Data::Keywords::use(SerialNumber); | 						Poco::Data::Keywords::use(SerialNumber); | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|   | |||||||
| @@ -161,7 +161,7 @@ namespace OpenWifi { | |||||||
| 			Poco::Data::Statement   Select(Sess); | 			Poco::Data::Statement   Select(Sess); | ||||||
|  |  | ||||||
|  |  | ||||||
| 			std::string st{"SELECT " + DB_LogsSelectFields + " FROM DeviceLogs WHERE SerialNumber=? AND LogType=? ORDER BY Recorded DESC " + ComputeRange(1, HowMany)}; | 			std::string st{"SELECT " + DB_LogsSelectFields + " FROM DeviceLogs WHERE SerialNumber=? AND LogType=? ORDER BY Recorded DESC " + ComputeRange(0, HowMany)}; | ||||||
| 			Select << 	ConvertParams(st), | 			Select << 	ConvertParams(st), | ||||||
| 						Poco::Data::Keywords::into(Records), | 						Poco::Data::Keywords::into(Records), | ||||||
| 						Poco::Data::Keywords::use(SerialNumber), | 						Poco::Data::Keywords::use(SerialNumber), | ||||||
|   | |||||||
| @@ -112,7 +112,7 @@ namespace OpenWifi { | |||||||
| 			std::string St{"SELECT " + | 			std::string St{"SELECT " + | ||||||
| 						   		DB_StatsSelectFields + | 						   		DB_StatsSelectFields + | ||||||
| 						   		" FROM Statistics WHERE SerialNumber=? ORDER BY Recorded DESC "}; | 						   		" FROM Statistics WHERE SerialNumber=? ORDER BY Recorded DESC "}; | ||||||
| 			Select << 	ConvertParams(St) + ComputeRange(1, HowMany), | 			Select << 	ConvertParams(St) + ComputeRange(0, HowMany), | ||||||
| 						Poco::Data::Keywords::into(Records), | 						Poco::Data::Keywords::into(Records), | ||||||
| 						Poco::Data::Keywords::use(SerialNumber); | 						Poco::Data::Keywords::use(SerialNumber); | ||||||
| 			Select.execute(); | 			Select.execute(); | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ fi | |||||||
| token="" | token="" | ||||||
| result_file=result.json | result_file=result.json | ||||||
| username="tip@ucentral.com" | username="tip@ucentral.com" | ||||||
| password="openwifi" | password="Snoopy99!!!" | ||||||
| browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl) | browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl) | ||||||
| browser="" | browser="" | ||||||
|  |  | ||||||
| @@ -137,7 +137,7 @@ deletecommand() { | |||||||
| } | } | ||||||
|  |  | ||||||
| listcommands() { | listcommands() { | ||||||
|   curl  ${FLAGS} -X GET "https://${OWGW}/api/v1/commands?serialNumber=$1&limit=3000" \ |   curl  ${FLAGS} -X GET "https://${OWGW}/api/v1/commands?serialNumber=$1&limit=300" \ | ||||||
|         -H "accept: application/json" \ |         -H "accept: application/json" \ | ||||||
|         -H "Authorization: Bearer ${token}"  > ${result_file} |         -H "Authorization: Bearer ${token}"  > ${result_file} | ||||||
|   jq < ${result_file} |   jq < ${result_file} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Dmitry Dunaev
					Dmitry Dunaev