mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
				synced 2025-10-31 18:57:51 +00:00 
			
		
		
		
	Compare commits
	
		
			22 Commits
		
	
	
		
			gh-pages
			...
			release/v2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 35ff346901 | ||
|   | 03b39d9d1c | ||
|   | 1a15c4744b | ||
|   | 0417162858 | ||
|   | 75b2b30b67 | ||
|   | 73f96b3ad8 | ||
|   | abc06d7953 | ||
|   | 7993e7d345 | ||
|   | be4549fabb | ||
|   | 92c141e511 | ||
|   | 296713e853 | ||
|   | d6dee68880 | ||
|   | aaffa145ad | ||
|   | c8e894bf79 | ||
|   | 766a608e1b | ||
|   | 333316d7a9 | ||
|   | 6527b45f2f | ||
|   | 76ef41aefe | ||
|   | 7e988c5780 | ||
|   | 2080027d7c | ||
|   | 8966888e6b | ||
|   | f650a6fde4 | 
| @@ -16,6 +16,10 @@ into your own systems. If all you need it to access the uCentralGW for example ( | ||||
| The CLI for the [uCentralGW](https://github.com/telecominfraproject/wlan-cloud-ucentralgw/blob/main/test_scripts/curl/cli) has a very good example of this.  | ||||
| Look for the `setgateway` function. | ||||
|  | ||||
| You may get static page with OpenAPI docs generated from the definition on [GitHub Page](https://telecominfraproject.github.io/wlan-cloud-ucentralsec/). | ||||
|  | ||||
| Also you may use [Swagger UI](https://petstore.swagger.io/#/) with OpenAPI definition file raw link (i.e. [latest version file](https://validator.swagger.io/validator?url=https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentralsec/main/openpapi/owsec.yaml)) to get interactive docs page. | ||||
|  | ||||
| ## Firewall Considerations | ||||
| The entire uCentral systems uses several MicroServices. In order for the whole system to work, you should provide the following port | ||||
| access: | ||||
|   | ||||
| @@ -9,7 +9,7 @@ fullnameOverride: "" | ||||
| images: | ||||
|   owsec: | ||||
|     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec | ||||
|     tag: main | ||||
|     tag: v2.8.0 | ||||
|     pullPolicy: Always | ||||
| #    regcred: | ||||
| #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | ||||
|   | ||||
| @@ -32,53 +32,102 @@ namespace OpenWifi { | ||||
|  */ | ||||
|         static inline bool Can( const SecurityObjects::UserInfo & User, const SecurityObjects::UserInfo & Target, ACL_OPS Op) { | ||||
|  | ||||
|             // rule 0 | ||||
|             if(User.id == Target.id && User.userRole == SecurityObjects::SUBSCRIBER && Op == DELETE) | ||||
|             switch(Op) { | ||||
|                 case DELETE: { | ||||
|                     //  can a user delete themselves - yes - only if not root. We do not want a system to end up rootless | ||||
|                     if(User.id==Target.id) { | ||||
|                         return User.userRole != SecurityObjects::ROOT; | ||||
|                     } | ||||
|                     //  Root can delete anyone | ||||
|                     switch (User.userRole) { | ||||
|                         case SecurityObjects::ROOT: | ||||
|                             return true; | ||||
|  | ||||
|             //  rule 1 | ||||
|             if(User.id == Target.id && Op==DELETE) | ||||
|                         case SecurityObjects::ADMIN: | ||||
|                             return Target.userRole!=SecurityObjects::ROOT && Target.userRole!=SecurityObjects::PARTNER; | ||||
|                         case SecurityObjects::SUBSCRIBER: | ||||
|                             return User.id==Target.id; | ||||
|                         case SecurityObjects::CSR: | ||||
|                             return false; | ||||
|  | ||||
|             //  rule 2 | ||||
|             if(User.userRole==SecurityObjects::ROOT) | ||||
|                 return true; | ||||
|  | ||||
|             //  rule 3 | ||||
|             if(User.id == Target.id) | ||||
|                 return true; | ||||
|  | ||||
|             //  rule 4 | ||||
|             if(Target.userRole==SecurityObjects::ROOT && Op!=READ) | ||||
|                 return false; | ||||
|  | ||||
|             if(Op==CREATE) { | ||||
|                 if(User.userRole==SecurityObjects::ROOT) | ||||
|                     return true; | ||||
|                 if(User.userRole==SecurityObjects::PARTNER && (Target.userRole==SecurityObjects::ADMIN || | ||||
|                     Target.userRole==SecurityObjects::SUBSCRIBER || | ||||
|                     Target.userRole==SecurityObjects::CSR || | ||||
|                     Target.userRole==SecurityObjects::INSTALLER || | ||||
|                     Target.userRole==SecurityObjects::NOC || | ||||
|                     Target.userRole==SecurityObjects::ACCOUNTING)) | ||||
|                     return true; | ||||
|                 if(User.userRole==SecurityObjects::ADMIN && | ||||
|                     (Target.userRole==SecurityObjects::ADMIN || | ||||
|                     Target.userRole==SecurityObjects::SUBSCRIBER || | ||||
|                     Target.userRole==SecurityObjects::CSR || | ||||
|                     Target.userRole==SecurityObjects::INSTALLER || | ||||
|                     Target.userRole==SecurityObjects::NOC || | ||||
|                     Target.userRole==SecurityObjects::ACCOUNTING)) | ||||
|                     return true; | ||||
|                 if(User.userRole==SecurityObjects::ACCOUNTING && | ||||
|                     (Target.userRole==SecurityObjects::SUBSCRIBER || | ||||
|                     Target.userRole==SecurityObjects::INSTALLER || | ||||
|                     Target.userRole==SecurityObjects::CSR)) | ||||
|                     return true; | ||||
|                         case SecurityObjects::SYSTEM: | ||||
|                             return Target.userRole!=SecurityObjects::ROOT && Target.userRole!=SecurityObjects::PARTNER; | ||||
|                         case SecurityObjects::INSTALLER: | ||||
|                             return User.id==Target.id; | ||||
|                         case SecurityObjects::NOC: | ||||
|                             return Target.userRole==SecurityObjects::NOC; | ||||
|                         case SecurityObjects::ACCOUNTING: | ||||
|                             return Target.userRole==SecurityObjects::ACCOUNTING; | ||||
|                         case SecurityObjects::PARTNER: | ||||
|                             return Target.userRole!=SecurityObjects::ROOT; | ||||
|                         default: | ||||
|                             return false; | ||||
|                     } | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|                 case READ: { | ||||
|                     return  User.userRole == SecurityObjects::ROOT || | ||||
|                             User.userRole == SecurityObjects::ADMIN || | ||||
|                             User.userRole == SecurityObjects::PARTNER; | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|                 case CREATE: { | ||||
|                     switch(User.userRole) { | ||||
|                         case SecurityObjects::ROOT: | ||||
|                             return true; | ||||
|                         case SecurityObjects::ADMIN: | ||||
|                             return  Target.userRole!=SecurityObjects::ROOT && | ||||
|                                     Target.userRole!=SecurityObjects::PARTNER; | ||||
|                         case SecurityObjects::SUBSCRIBER: | ||||
|                             return false; | ||||
|                         case SecurityObjects::CSR: | ||||
|                             return Target.userRole==SecurityObjects::CSR; | ||||
|                         case SecurityObjects::SYSTEM: | ||||
|                             return Target.userRole!=SecurityObjects::ROOT && Target.userRole!=SecurityObjects::PARTNER; | ||||
|                         case SecurityObjects::INSTALLER: | ||||
|                             return Target.userRole==SecurityObjects::INSTALLER; | ||||
|                         case SecurityObjects::NOC: | ||||
|                             return Target.userRole==SecurityObjects::NOC; | ||||
|                         case SecurityObjects::ACCOUNTING: | ||||
|                             return Target.userRole==SecurityObjects::ACCOUNTING; | ||||
|                         case SecurityObjects::PARTNER: | ||||
|                             return Target.userRole!=SecurityObjects::ROOT; | ||||
|                         default: | ||||
|                             return false; | ||||
|                     } | ||||
|                 } | ||||
|                 break; | ||||
|  | ||||
|                 case MODIFY: { | ||||
|                     switch(User.userRole) { | ||||
|                         case SecurityObjects::ROOT: | ||||
|                             return true; | ||||
|                         case SecurityObjects::ADMIN: | ||||
|                             return  Target.userRole!=SecurityObjects::ROOT && | ||||
|                                     Target.userRole!=SecurityObjects::PARTNER; | ||||
|                         case SecurityObjects::SUBSCRIBER: | ||||
|                             return  User.id==Target.id; | ||||
|                         case SecurityObjects::CSR: | ||||
|                             return  Target.userRole==SecurityObjects::CSR; | ||||
|                         case SecurityObjects::SYSTEM: | ||||
|                             return  Target.userRole!=SecurityObjects::ROOT && | ||||
|                                     Target.userRole!=SecurityObjects::PARTNER; | ||||
|                         case SecurityObjects::INSTALLER: | ||||
|                             return  Target.userRole==SecurityObjects::INSTALLER; | ||||
|                         case SecurityObjects::NOC: | ||||
|                             return  Target.userRole==SecurityObjects::NOC; | ||||
|                         case SecurityObjects::ACCOUNTING: | ||||
|                             return  Target.userRole==SecurityObjects::ACCOUNTING; | ||||
|                         case SecurityObjects::PARTNER: | ||||
|                             return  Target.userRole!=SecurityObjects::ROOT; | ||||
|                         default: | ||||
|                             return false; | ||||
|                     } | ||||
|                 } | ||||
|                     break; | ||||
|                 default: | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
|     private: | ||||
|  | ||||
|   | ||||
| @@ -51,7 +51,9 @@ namespace OpenWifi::GWObjects { | ||||
| 		field_to_json(Obj,"modified", modified); | ||||
| 		field_to_json(Obj,"locale", locale); | ||||
| 		field_to_json(Obj,"restrictedDevice", restrictedDevice); | ||||
|  | ||||
| 		field_to_json(Obj,"pendingConfiguration", pendingConfiguration); | ||||
| 		field_to_json(Obj,"pendingConfigurationCmd", pendingConfigurationCmd); | ||||
| 		field_to_json(Obj,"restrictionDetails", restrictionDetails); | ||||
| 	} | ||||
|  | ||||
| 	void Device::to_json_with_status(Poco::JSON::Object &Obj) const { | ||||
| @@ -93,6 +95,9 @@ namespace OpenWifi::GWObjects { | ||||
| 			field_from_json(Obj,"entity", entity); | ||||
| 			field_from_json(Obj,"locale", locale); | ||||
| 			field_from_json(Obj,"restrictedDevice", restrictedDevice); | ||||
| 			field_from_json(Obj,"pendingConfiguration", pendingConfiguration); | ||||
| 			field_from_json(Obj,"pendingConfigurationCmd", pendingConfigurationCmd); | ||||
| 			field_from_json(Obj,"restrictionDetails", restrictionDetails); | ||||
| 			return true; | ||||
| 		} catch (const Poco::Exception &E) { | ||||
| 		} | ||||
| @@ -394,6 +399,7 @@ namespace OpenWifi::GWObjects { | ||||
| 		field_to_json(Obj,"secret",secret); | ||||
| 		field_to_json(Obj,"certificate",certificate); | ||||
| 		field_to_json(Obj,"radsec",radsec); | ||||
| 		field_to_json(Obj,"allowSelfSigned",allowSelfSigned); | ||||
| 		field_to_json(Obj,"radsecPort",radsecPort); | ||||
| 		field_to_json(Obj,"radsecSecret",radsecSecret); | ||||
| 		field_to_json(Obj,"radsecCacerts",radsecCacerts); | ||||
| @@ -412,6 +418,7 @@ namespace OpenWifi::GWObjects { | ||||
| 			field_from_json(Obj,"secret",secret); | ||||
| 			field_from_json(Obj,"certificate",certificate); | ||||
| 			field_from_json(Obj,"radsec",radsec); | ||||
| 			field_from_json(Obj,"allowSelfSigned",allowSelfSigned); | ||||
| 			field_from_json(Obj,"radsecSecret",radsecSecret); | ||||
| 			field_from_json(Obj,"radsecPort",radsecPort); | ||||
| 			field_from_json(Obj,"radsecCacerts",radsecCacerts); | ||||
| @@ -439,6 +446,7 @@ namespace OpenWifi::GWObjects { | ||||
| 		field_to_json(Obj,"restricted", restricted); | ||||
| 		field_to_json(Obj,"deferred", deferred); | ||||
| 		field_to_json(Obj,"timeout", timeout); | ||||
| 		field_to_json(Obj,"defaultUploadURI", defaultUploadURI); | ||||
| 	} | ||||
|  | ||||
| 	bool ScriptEntry::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
| @@ -456,6 +464,7 @@ namespace OpenWifi::GWObjects { | ||||
| 			field_from_json(Obj,"restricted", restricted); | ||||
| 			field_from_json(Obj,"deferred", deferred); | ||||
| 			field_from_json(Obj,"timeout", timeout); | ||||
| 			field_from_json(Obj,"defaultUploadURI", defaultUploadURI); | ||||
| 			return true; | ||||
| 		} catch (const Poco::Exception &E) { | ||||
| 		} | ||||
| @@ -475,5 +484,64 @@ namespace OpenWifi::GWObjects { | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	void DeviceRestrictionsKeyInfo::to_json(Poco::JSON::Object &Obj) const { | ||||
| 		field_to_json(Obj,"vendor", vendor); | ||||
| 		field_to_json(Obj,"algo", algo); | ||||
| 	} | ||||
|  | ||||
| 	bool DeviceRestrictionsKeyInfo::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
| 		try { | ||||
| 			field_from_json(Obj,"vendor", vendor); | ||||
| 			field_from_json(Obj,"algo", algo); | ||||
| 			return true; | ||||
| 		} catch (const Poco::Exception &E) { | ||||
| 		} | ||||
| 		return false; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	void DeviceRestrictions::to_json(Poco::JSON::Object &Obj) const { | ||||
| 		field_to_json(Obj,"dfs", dfs); | ||||
| 		field_to_json(Obj,"ssh", ssh); | ||||
| 		field_to_json(Obj,"rtty", rtty); | ||||
| 		field_to_json(Obj,"tty", tty); | ||||
| 		field_to_json(Obj,"developer", developer); | ||||
| 		field_to_json(Obj,"upgrade", upgrade); | ||||
| 		field_to_json(Obj,"commands", commands); | ||||
| 		field_to_json(Obj,"country", country); | ||||
| 		field_to_json(Obj,"key_info", key_info); | ||||
| 	} | ||||
|  | ||||
| 	bool DeviceRestrictions::from_json(const Poco::JSON::Object::Ptr &Obj) { | ||||
| 		try { | ||||
| 			field_from_json(Obj,"dfs", dfs); | ||||
| 			field_from_json(Obj,"ssh", ssh); | ||||
| 			field_from_json(Obj,"rtty", rtty); | ||||
| 			field_from_json(Obj,"tty", tty); | ||||
| 			field_from_json(Obj,"developer", developer); | ||||
| 			field_from_json(Obj,"upgrade", upgrade); | ||||
| 			field_from_json(Obj,"commands", commands); | ||||
| 			field_from_json(Obj,"country", country); | ||||
| 			field_from_json(Obj,"key_info", key_info); | ||||
| 			return true; | ||||
| 		} catch (const Poco::Exception &E) { | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	bool DeviceRestrictionsKeyInfo::operator!=(const OpenWifi::GWObjects::DeviceRestrictionsKeyInfo &T) const { | ||||
| 		return (T.algo!=algo) || (T.vendor!=vendor); | ||||
| 	} | ||||
|  | ||||
| 	bool DeviceRestrictions::operator!=(const OpenWifi::GWObjects::DeviceRestrictions &T) const { | ||||
| 		return (	(T.dfs!=dfs)					|| | ||||
| 					(T.rtty!=rtty)					|| | ||||
| 					(T.upgrade!=upgrade)		|| | ||||
| 					(T.commands != commands)		|| | ||||
| 					(T.developer != developer)		|| | ||||
| 					(T.ssh !=ssh) 					|| | ||||
| 					(T.key_info != key_info)		|| | ||||
| 					(T.country != country) ); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -47,6 +47,33 @@ namespace OpenWifi::GWObjects { | ||||
| 		void to_json(Poco::JSON::Object &Obj) const; | ||||
| 	}; | ||||
|  | ||||
| 	struct DeviceRestrictionsKeyInfo { | ||||
| 		std::string 	vendor; | ||||
| 		std::string 	algo; | ||||
|  | ||||
| 		bool operator !=(const DeviceRestrictionsKeyInfo &b) const; | ||||
|  | ||||
| 		void to_json(Poco::JSON::Object &Obj) const; | ||||
| 		bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
| 	}; | ||||
|  | ||||
| 	struct DeviceRestrictions { | ||||
| 		bool    					dfs = false; | ||||
| 		bool    					ssh = false; | ||||
| 		bool    					rtty = false; | ||||
| 		bool    					tty = false; | ||||
| 		bool    					developer = false; | ||||
| 		bool    					upgrade = false; | ||||
| 		bool    					commands = false; | ||||
| 		std::vector<std::string>   	country; | ||||
| 		DeviceRestrictionsKeyInfo	key_info; | ||||
|  | ||||
| 		bool operator !=(const DeviceRestrictions &D) const; | ||||
|  | ||||
| 		void to_json(Poco::JSON::Object &Obj) const; | ||||
| 		bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
| 	}; | ||||
|  | ||||
| 	struct Device { | ||||
| 		std::string SerialNumber; | ||||
| 		std::string DeviceType; | ||||
| @@ -71,6 +98,9 @@ namespace OpenWifi::GWObjects { | ||||
| 		uint64_t 	modified=0; | ||||
| 		std::string locale; | ||||
| 		bool 		restrictedDevice=false; | ||||
| 		std::string pendingConfiguration; | ||||
| 		std::string pendingConfigurationCmd; | ||||
| 		DeviceRestrictions	restrictionDetails; | ||||
|  | ||||
| 		void to_json(Poco::JSON::Object &Obj) const; | ||||
| 		void to_json_with_status(Poco::JSON::Object &Obj) const; | ||||
| @@ -230,6 +260,7 @@ namespace OpenWifi::GWObjects { | ||||
| 		Types::StringVec 	restricted; | ||||
| 		bool				deferred=false; | ||||
| 		std::uint64_t 		timeout=30; | ||||
| 		std::string 		defaultUploadURI; | ||||
|  | ||||
| 		void to_json(Poco::JSON::Object &Obj) const; | ||||
| 		bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
| @@ -265,6 +296,7 @@ namespace OpenWifi::GWObjects { | ||||
| 		std::string secret; | ||||
| 		std::string certificate; | ||||
| 		bool 		radsec=false; | ||||
| 		bool 		allowSelfSigned=false; | ||||
| 		uint16_t 	radsecPort=2083; | ||||
| 		std::string radsecSecret; | ||||
| 		std::string radsecKey; | ||||
| @@ -306,4 +338,5 @@ namespace OpenWifi::GWObjects { | ||||
| 		void to_json(Poco::JSON::Object &Obj) const; | ||||
| 		bool from_json(const Poco::JSON::Object::Ptr &Obj); | ||||
| 	}; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -51,7 +51,13 @@ namespace OpenWifi { | ||||
|             poco_information(Logger(),"Starting..."); | ||||
| 			Running_=true; | ||||
| 			Port_ = (int)MicroServiceConfigGetInt("alb.port",15015); | ||||
| 			Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_); | ||||
| 			Poco::Net::IPAddress Addr(Poco::Net::IPAddress::wildcard( | ||||
| 				Poco::Net::Socket::supportsIPv6() ? Poco::Net::AddressFamily::IPv6 | ||||
| 												  : Poco::Net::AddressFamily::IPv4)); | ||||
| 			Poco::Net::SocketAddress SockAddr(Addr, Port_); | ||||
| 			Poco::Net::ServerSocket ClientSocket(SockAddr, 64); | ||||
|  | ||||
| 			Socket_ = std::make_unique<Poco::Net::ServerSocket>(SockAddr, Port_); | ||||
| 			auto Params = new Poco::Net::HTTPServerParams; | ||||
| 			Params->setName("ws:alb"); | ||||
| 			Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger()), *Socket_, Params); | ||||
|   | ||||
| @@ -19,10 +19,9 @@ | ||||
| namespace OpenWifi { | ||||
|  | ||||
| static const std::string GitUCentralJSONSchemaFile{ | ||||
| 	"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"}; | ||||
| 	"https://raw.githubusercontent.com/Telecominfraproject/wlan-ucentral-schema/main/ucentral.schema.json"}; | ||||
|  | ||||
| static json DefaultUCentralSchema = R"( | ||||
|  | ||||
| { | ||||
|     "$id": "https://openwrt.org/ucentral.schema.json", | ||||
|     "$schema": "http://json-schema.org/draft-07/schema#", | ||||
| @@ -49,7 +48,7 @@ static json DefaultUCentralSchema = R"( | ||||
|         "switch": { | ||||
|             "$ref": "#/$defs/switch" | ||||
|         }, | ||||
| 		"radiosgrep": { | ||||
|         "radios": { | ||||
|             "type": "array", | ||||
|             "items": { | ||||
|                 "$ref": "#/$defs/radio" | ||||
| @@ -201,7 +200,8 @@ static json DefaultUCentralSchema = R"( | ||||
|                     ] | ||||
|                 }, | ||||
|                 "wireless-multimedia": { | ||||
| 					"anyOf": [{ | ||||
|                     "anyOf": [ | ||||
|                         { | ||||
|                             "$ref": "#/$defs/globals.wireless-multimedia.table" | ||||
|                         }, | ||||
|                         { | ||||
| @@ -395,7 +395,8 @@ static json DefaultUCentralSchema = R"( | ||||
|                     ] | ||||
|                 }, | ||||
|                 "channel": { | ||||
| 					"oneOf": [{ | ||||
|                     "oneOf": [ | ||||
|                         { | ||||
|                             "type": "integer", | ||||
|                             "maximum": 196, | ||||
|                             "minimum": 1 | ||||
| @@ -1004,7 +1005,8 @@ static json DefaultUCentralSchema = R"( | ||||
|             } | ||||
|         }, | ||||
|         "interface.broad-band": { | ||||
| 			"oneOf": [{ | ||||
|             "oneOf": [ | ||||
|                 { | ||||
|                     "$ref": "#/$defs/interface.broad-band.wwan" | ||||
|                 }, | ||||
|                 { | ||||
| @@ -1261,7 +1263,8 @@ static json DefaultUCentralSchema = R"( | ||||
|                                 "minimum": 1 | ||||
|                             }, | ||||
|                             "value": { | ||||
| 								"anyOf": [{ | ||||
|                                 "anyOf": [ | ||||
|                                     { | ||||
|                                         "type": "integer", | ||||
|                                         "maximum": 4294967295, | ||||
|                                         "minimum": 0 | ||||
| @@ -1272,7 +1275,8 @@ static json DefaultUCentralSchema = R"( | ||||
|                                 ] | ||||
|                             } | ||||
|                         }, | ||||
| 						"examples": [{ | ||||
|                         "examples": [ | ||||
|                             { | ||||
|                                 "id": 27, | ||||
|                                 "value": 900 | ||||
|                             }, | ||||
| @@ -1336,7 +1340,8 @@ static json DefaultUCentralSchema = R"( | ||||
|                     } | ||||
|                 }, | ||||
|                 "authentication": { | ||||
| 					"allOf": [{ | ||||
|                     "allOf": [ | ||||
|                         { | ||||
|                             "$ref": "#/$defs/interface.ssid.radius.server" | ||||
|                         }, | ||||
|                         { | ||||
| @@ -1351,7 +1356,8 @@ static json DefaultUCentralSchema = R"( | ||||
|                     ] | ||||
|                 }, | ||||
|                 "accounting": { | ||||
| 					"allOf": [{ | ||||
|                     "allOf": [ | ||||
|                         { | ||||
|                             "$ref": "#/$defs/interface.ssid.radius.server" | ||||
|                         }, | ||||
|                         { | ||||
| @@ -1554,13 +1560,15 @@ static json DefaultUCentralSchema = R"( | ||||
|                                 ] | ||||
|                             } | ||||
|                         }, | ||||
| 						"examples": [{ | ||||
|                         "examples": [ | ||||
|                             { | ||||
|                                 "width": 32, | ||||
|                                 "height": 32, | ||||
|                                 "type": "image/png", | ||||
|                                 "language": "eng", | ||||
|                                 "icon": "R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" | ||||
| 						}] | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 }, | ||||
|                 "wan-metrics": { | ||||
| @@ -1806,7 +1814,8 @@ static json DefaultUCentralSchema = R"( | ||||
|             } | ||||
|         }, | ||||
|         "interface.tunnel": { | ||||
| 			"oneOf": [{ | ||||
|             "oneOf": [ | ||||
|                 { | ||||
|                     "$ref": "#/$defs/interface.tunnel.mesh" | ||||
|                 }, | ||||
|                 { | ||||
| @@ -2630,12 +2639,12 @@ static json DefaultUCentralSchema = R"( | ||||
|             return; | ||||
|  | ||||
|         std::string GitSchema; | ||||
| 		if(MicroServiceConfigGetBool("ucentral.datamodel.internal",true)) { | ||||
| 		// if(MicroServiceConfigGetBool("ucentral.datamodel.internal",true)) { | ||||
| 			RootSchema_ = DefaultUCentralSchema; | ||||
| 			poco_information(Logger(),"Using uCentral validation from built-in default."); | ||||
| 			Initialized_ = Working_ = true; | ||||
| 			return; | ||||
| 		} | ||||
| 		// } | ||||
|  | ||||
|         try { | ||||
| 			auto GitURI = MicroServiceConfigGetString("ucentral.datamodel.uri",GitUCentralJSONSchemaFile); | ||||
| @@ -2749,7 +2758,7 @@ static json DefaultUCentralSchema = R"( | ||||
|             if(std::regex_match(value,host_regex)) | ||||
|                 return; | ||||
|             throw std::invalid_argument(value + " is not a proper FQDN."); | ||||
|         } else if(format == "fqdn") { | ||||
|         } else if(format == "fqdn" || format=="uc-fqdn") { | ||||
|             if(std::regex_match(value,host_regex)) | ||||
|                 return; | ||||
|             throw std::invalid_argument(value + " is not a proper FQDN."); | ||||
|   | ||||
| @@ -102,6 +102,48 @@ namespace OpenWifi { | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::TimeoutException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::TimeoutException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::NoThreadAvailableException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::NoThreadAvailableException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::OutOfMemoryException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::OutOfMemoryException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::BadCastException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::BadCastException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::DataException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::DataException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::PoolOverflowException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::PoolOverflowException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::SystemException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::SystemException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
| 													  E.displayText(), | ||||
| 													  E.message(), | ||||
| 													  E.what())); | ||||
| 			} catch (const Poco::RuntimeException &E) { | ||||
| 				poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} thr_id={} code={} text={} msg={} what={}", | ||||
| 													  t_name, t_id, E.code(), | ||||
|   | ||||
| @@ -633,6 +633,18 @@ namespace OpenWifi { | ||||
| 			ReturnObject(Answer); | ||||
| 		} | ||||
|  | ||||
| 		template<typename T> void Object(const char *Name, const std::vector<T> & Objects) { | ||||
| 			Poco::JSON::Object  Answer; | ||||
| 			RESTAPI_utils::field_to_json(Answer,Name,Objects); | ||||
| 			ReturnObject(Answer); | ||||
| 		} | ||||
|  | ||||
| 		template <typename T> void Object(const T &O) { | ||||
| 			Poco::JSON::Object  Answer; | ||||
| 			O.to_json(Answer); | ||||
| 			ReturnObject(Answer); | ||||
| 		} | ||||
|  | ||||
| 		Poco::Logger & Logger() { return Logger_; } | ||||
|  | ||||
| 		virtual void DoGet() = 0 ; | ||||
|   | ||||
| @@ -119,7 +119,7 @@ namespace OpenWifi { | ||||
| 	} | ||||
|  | ||||
| 	bool UI_WebSocketClientServer::SendToUser(const std::string &UserName, std::uint64_t id, const std::string &Payload) { | ||||
| 		std::lock_guard G(Mutex_); | ||||
| 		std::lock_guard G(LocalMutex_); | ||||
|  | ||||
| 		for(const auto &Client:Clients_) { | ||||
| 			if(Client.second->UserName_ == UserName) { | ||||
| @@ -139,7 +139,7 @@ namespace OpenWifi { | ||||
| 	} | ||||
|  | ||||
| 	void UI_WebSocketClientServer::SendToAll(std::uint64_t id, const std::string &Payload) { | ||||
| 		std::lock_guard G(Mutex_); | ||||
| 		std::lock_guard G(LocalMutex_); | ||||
|  | ||||
| 		for(const auto &Client:Clients_) { | ||||
| 			try { | ||||
| @@ -189,7 +189,6 @@ namespace OpenWifi { | ||||
| 	void UI_WebSocketClientServer::OnSocketReadable([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ReadableNotification> &pNf) { | ||||
|  | ||||
|         UI_WebSocketClientServer::ClientList::iterator Client; | ||||
|  | ||||
|         std::lock_guard     G(LocalMutex_); | ||||
|  | ||||
| 		try { | ||||
| @@ -295,6 +294,7 @@ namespace OpenWifi { | ||||
|  | ||||
| 	void UI_WebSocketClientServer::OnSocketShutdown([[maybe_unused]] const Poco::AutoPtr<Poco::Net::ShutdownNotification> &pNf) { | ||||
|         try { | ||||
| 			std::lock_guard     G(LocalMutex_); | ||||
| 			auto Client = Clients_.find(pNf->socket().impl()->sockfd()); | ||||
|             if (Client == end(Clients_)) | ||||
|                 return; | ||||
|   | ||||
| @@ -231,7 +231,9 @@ namespace OpenWifi::RESTAPI::Errors { | ||||
| 	static const struct msg DeviceIsRestricted{1151,"Device is protected by regulation. This function is not allowed."}; | ||||
| 	static const struct msg InvalidURI{1152,"Invalid URI."}; | ||||
| 	static const struct msg InvalidScriptSelection{1153,"Only script or scriptId must be specified. Not both."}; | ||||
| } | ||||
|  | ||||
| 	static const struct msg NoDeviceStatisticsYet{1154,"Device statistics not available yet."}; | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -526,6 +528,63 @@ namespace OpenWifi::uCentralProtocol::Events { | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| namespace OpenWifi::APCommands { | ||||
| 	enum class Commands:uint8_t { | ||||
| 		capabilities, | ||||
| 		logs, | ||||
| 		healthchecks, | ||||
| 		statistics, | ||||
| 		status, | ||||
| 		rtty, | ||||
| 		configure, | ||||
| 		upgrade, | ||||
| 		reboot, | ||||
| 		factory, | ||||
| 		leds, | ||||
| 		trace, | ||||
| 		request, | ||||
| 		wifiscan, | ||||
| 		eventqueue, | ||||
| 		telemetry, | ||||
| 		ping, | ||||
| 		script, | ||||
| 		unknown | ||||
| 	}; | ||||
|  | ||||
| 	inline static const std::vector<const char *> uCentralAPCommands { | ||||
| 		RESTAPI::Protocol::CAPABILITIES, | ||||
| 		RESTAPI::Protocol::LOGS, | ||||
| 		RESTAPI::Protocol::HEALTHCHECKS, | ||||
| 		RESTAPI::Protocol::STATISTICS, | ||||
| 		RESTAPI::Protocol::STATUS, | ||||
| 		RESTAPI::Protocol::RTTY, | ||||
| 		RESTAPI::Protocol::CONFIGURE, | ||||
| 		RESTAPI::Protocol::UPGRADE, | ||||
| 		RESTAPI::Protocol::REBOOT, | ||||
| 		RESTAPI::Protocol::FACTORY, | ||||
| 		RESTAPI::Protocol::LEDS, | ||||
| 		RESTAPI::Protocol::TRACE, | ||||
| 		RESTAPI::Protocol::REQUEST, | ||||
| 		RESTAPI::Protocol::WIFISCAN, | ||||
| 		RESTAPI::Protocol::EVENTQUEUE, | ||||
| 		RESTAPI::Protocol::TELEMETRY, | ||||
| 		RESTAPI::Protocol::PING, | ||||
| 		RESTAPI::Protocol::SCRIPT}; | ||||
|  | ||||
| 	inline const char * to_string(Commands Cmd) { | ||||
| 		return uCentralAPCommands[(uint8_t)Cmd]; | ||||
| 	} | ||||
|  | ||||
| 	inline Commands to_apcommand(const char *cmd) { | ||||
| 		for(auto i=(uint8_t)Commands::capabilities;i!=(uint8_t)Commands::unknown;++i) { | ||||
| 			if(strcmp(uCentralAPCommands[i],cmd)==0) | ||||
| 				return (Commands)i; | ||||
| 		} | ||||
| 		return Commands::unknown; | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| namespace OpenWifi::Provisioning::DeviceClass { | ||||
|  | ||||
|     static const char * ANY = "any"; | ||||
|   | ||||
| @@ -48,7 +48,7 @@ namespace OpenWifi { | ||||
|  | ||||
|     bool ApiKeyDB::RemoveAllApiKeys(const std::string & user_uuid) { | ||||
|         SecurityObjects::ApiKeyEntryList    Keys; | ||||
|         if(StorageService()->ApiKeyDB().GetRecords(0,500,Keys.apiKeys,fmt::format(" userUuid='{} ", user_uuid))) { | ||||
|         if(StorageService()->ApiKeyDB().GetRecords(0,500,Keys.apiKeys,fmt::format(" userUuid='{}' ", user_uuid))) { | ||||
|             for(const auto &key:Keys.apiKeys) { | ||||
|                 AuthService()->RemoveTokenSystemWide(key.apiKey); | ||||
|             } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user