mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralgw.git
				synced 2025-11-04 04:37:46 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			229 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//
 | 
						|
//	License type: BSD 3-Clause License
 | 
						|
//	License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
 | 
						|
//
 | 
						|
//	Created by Stephane Bourque on 2021-03-04.
 | 
						|
//	Arilia Wireless Inc.
 | 
						|
//
 | 
						|
 | 
						|
#include "Poco/Array.h"
 | 
						|
#include "Poco/JSON/Stringifier.h"
 | 
						|
 | 
						|
#include "AP_WS_Server.h"
 | 
						|
#include "Poco/StringTokenizer.h"
 | 
						|
#include "RESTAPI/RESTAPI_device_helper.h"
 | 
						|
#include "RESTAPI_devices_handler.h"
 | 
						|
#include "StorageService.h"
 | 
						|
#include "framework/orm.h"
 | 
						|
#include "framework/ow_constants.h"
 | 
						|
 | 
						|
namespace OpenWifi {
 | 
						|
 | 
						|
	bool PrepareOrderBy(const std::string &OrderByListRaw, std::string &OrderByString) {
 | 
						|
		auto OrderByList = ORM::Escape(OrderByListRaw);
 | 
						|
		auto items = Poco::StringTokenizer(OrderByList, ",");
 | 
						|
		std::string ItemList;
 | 
						|
 | 
						|
		Types::StringVec Fields;
 | 
						|
		Storage::GetDeviceDbFieldList(Fields);
 | 
						|
 | 
						|
		std::set<std::string> FieldNames;
 | 
						|
		for (const auto &field : Fields)
 | 
						|
			FieldNames.insert(Poco::toLower(field));
 | 
						|
 | 
						|
		for (const auto &i : items) {
 | 
						|
			auto T = Poco::StringTokenizer(i, ":");
 | 
						|
			if (T.count() != 2) {
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
			if (T[1] != "a" && T[1] != "d") {
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
			if (!ItemList.empty())
 | 
						|
				ItemList += " , ";
 | 
						|
			auto hint = FieldNames.find(Poco::toLower(T[0]));
 | 
						|
			if (hint == FieldNames.end()) {
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
			ItemList += T[0] + (T[1] == "a" ? " ASC" : " DESC");
 | 
						|
		}
 | 
						|
 | 
						|
		if (!ItemList.empty()) {
 | 
						|
			OrderByString = " ORDER BY " + ItemList;
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	void RESTAPI_devices_handler::DoGet() {
 | 
						|
 | 
						|
		if (GetBoolParameter("connectionStatistics")) {
 | 
						|
			GWObjects::DeviceConnectionStatistics DCS;
 | 
						|
			Poco::JSON::Object Answer;
 | 
						|
 | 
						|
			AP_WS_Server()->AverageDeviceStatistics(DCS.connectedDevices, DCS.averageConnectionTime,
 | 
						|
													DCS.connectingDevices);
 | 
						|
			DCS.to_json(Answer);
 | 
						|
			return ReturnObject(Answer);
 | 
						|
		}
 | 
						|
 | 
						|
		if (GetBoolParameter("orderSpec")) {
 | 
						|
			Types::StringVec Fields;
 | 
						|
			Storage::GetDeviceDbFieldList(Fields);
 | 
						|
			std::sort(Fields.begin(), Fields.end());
 | 
						|
			Poco::JSON::Object Answer;
 | 
						|
			RESTAPI_utils::field_to_json(Answer, "list", Fields);
 | 
						|
			return ReturnObject(Answer);
 | 
						|
		}
 | 
						|
 | 
						|
		std::string OrderBy{" ORDER BY serialNumber ASC "}, Arg;
 | 
						|
		if (HasParameter("orderBy", Arg)) {
 | 
						|
			if (!PrepareOrderBy(Arg, OrderBy)) {
 | 
						|
				return BadRequest(RESTAPI::Errors::InvalidLOrderBy);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		auto platform = Poco::toLower(GetParameter("platform", ""));
 | 
						|
		auto serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
 | 
						|
		auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
 | 
						|
		auto completeInfo = GetBoolParameter("completeInfo", false);
 | 
						|
		auto includeProvisioned = GetBoolParameter("includeProvisioned", true);
 | 
						|
 | 
						|
		if(!platform.empty() && (platform!=Platforms::AP && platform!=Platforms::SWITCH && platform!="all")) {
 | 
						|
			return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
						|
		}
 | 
						|
 | 
						|
		if(platform=="all")
 | 
						|
			platform="";
 | 
						|
 | 
						|
		Poco::JSON::Object RetObj;
 | 
						|
		if (!QB_.Select.empty()) {
 | 
						|
			Poco::JSON::Array Objects;
 | 
						|
			for (auto &i : SelectedRecords()) {
 | 
						|
				auto &SerialNumber = i;
 | 
						|
				if (!Utils::ValidSerialNumber(i))
 | 
						|
					continue;
 | 
						|
				GWObjects::Device D;
 | 
						|
				if (StorageService()->GetDevice(SerialNumber, D)) {
 | 
						|
					if (completeInfo) {
 | 
						|
						Poco::JSON::Object FullDeviceInfo;
 | 
						|
						CompleteDeviceInfo(D, FullDeviceInfo);
 | 
						|
						Objects.add(FullDeviceInfo);
 | 
						|
					} else {
 | 
						|
						Poco::JSON::Object Obj;
 | 
						|
						if (deviceWithStatus)
 | 
						|
							D.to_json_with_status(Obj);
 | 
						|
						else
 | 
						|
							D.to_json(Obj);
 | 
						|
						Objects.add(Obj);
 | 
						|
					}
 | 
						|
				} else {
 | 
						|
					Logger_.error(fmt::format("DEVICE({}): device in select cannot be found.", i));
 | 
						|
				}
 | 
						|
			}
 | 
						|
			if (deviceWithStatus)
 | 
						|
				RetObj.set(RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
 | 
						|
			else
 | 
						|
				RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
 | 
						|
 | 
						|
		} else if (QB_.CountOnly) {
 | 
						|
			uint64_t Count = 0;
 | 
						|
			if (StorageService()->GetDeviceCount(Count, platform, includeProvisioned)) {
 | 
						|
				return ReturnCountOnly(Count);
 | 
						|
			}
 | 
						|
		} else if (serialOnly) {
 | 
						|
			std::vector<std::string> SerialNumbers;
 | 
						|
			StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy, platform, includeProvisioned);
 | 
						|
			Poco::JSON::Array Objects;
 | 
						|
			for (const auto &i : SerialNumbers) {
 | 
						|
				Objects.add(i);
 | 
						|
			}
 | 
						|
			RetObj.set(RESTAPI::Protocol::SERIALNUMBERS, Objects);
 | 
						|
		} else if (GetBoolParameter("health")) {
 | 
						|
			auto lowLimit = GetParameter("lowLimit",30);
 | 
						|
			auto highLimit = GetParameter("highLimit",80);
 | 
						|
			std::vector<std::string>	SerialNumbers;
 | 
						|
			AP_WS_Server()->GetHealthDevices(lowLimit,highLimit,SerialNumbers);
 | 
						|
 | 
						|
			Poco::JSON::Array Objects;
 | 
						|
			for(const auto &s:SerialNumbers)
 | 
						|
				Objects.add(s);
 | 
						|
			RetObj.set("serialNumbers", Objects);
 | 
						|
		} else {
 | 
						|
			std::vector<GWObjects::Device> Devices;
 | 
						|
			StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices, OrderBy, platform, includeProvisioned);
 | 
						|
			Poco::JSON::Array Objects;
 | 
						|
			for (const auto &i : Devices) {
 | 
						|
				Poco::JSON::Object Obj;
 | 
						|
				if (deviceWithStatus)
 | 
						|
					i.to_json_with_status(Obj);
 | 
						|
				else
 | 
						|
					i.to_json(Obj);
 | 
						|
				Objects.add(Obj);
 | 
						|
			}
 | 
						|
			if (deviceWithStatus)
 | 
						|
				RetObj.set(RESTAPI::Protocol::DEVICESWITHSTATUS, Objects);
 | 
						|
			else
 | 
						|
				RetObj.set(RESTAPI::Protocol::DEVICES, Objects);
 | 
						|
		}
 | 
						|
		ReturnObject(RetObj);
 | 
						|
	}
 | 
						|
 | 
						|
	static bool ValidMacPatternOnlyChars(const std::string &s) {
 | 
						|
		return std::for_each(s.begin(),s.end(),[](const char c) {
 | 
						|
			if(c=='%') return true;
 | 
						|
			if(c>='0' && c<='9') return true;
 | 
						|
			if(c>='a' && c<='f') return true;
 | 
						|
			return false;
 | 
						|
 		});
 | 
						|
	}
 | 
						|
 | 
						|
	void RESTAPI_devices_handler::DoDelete() {
 | 
						|
 | 
						|
		if(!RESTAPI_utils::IsRootOrAdmin(UserInfo_.userinfo)) {
 | 
						|
			return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED);
 | 
						|
		}
 | 
						|
 | 
						|
		if(GetBoolParameter("simulatedDevices",false)) {
 | 
						|
			auto F = []() ->void {
 | 
						|
				StorageService()->DeleteSimulatedDevice("");
 | 
						|
			};
 | 
						|
			std::thread T(F);
 | 
						|
			T.detach();
 | 
						|
			return OK();
 | 
						|
		}
 | 
						|
 | 
						|
		if(!QB_.Select.empty() && !Utils::ValidSerialNumbers(QB_.Select)) {
 | 
						|
			return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
						|
		}
 | 
						|
 | 
						|
		if(!QB_.Select.empty()) {
 | 
						|
			for(auto &serialNumber:QB_.Select) {
 | 
						|
				StorageService()->DeleteDevice(serialNumber);
 | 
						|
			}
 | 
						|
			return OK();
 | 
						|
		}
 | 
						|
 | 
						|
		auto SimulatedOnly = GetBoolParameter("simulatedOnly",false);
 | 
						|
		auto oldestContact = GetParameter("oldestContact",0);
 | 
						|
		if(oldestContact!=0) {
 | 
						|
			StorageService()->DeleteDevices(oldestContact,SimulatedOnly);
 | 
						|
			return OK();
 | 
						|
		}
 | 
						|
 | 
						|
		auto macPattern = GetParameter("macPattern","");
 | 
						|
		if(macPattern.empty()) {
 | 
						|
			return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
						|
		}
 | 
						|
 | 
						|
		//	rules out wrong values.
 | 
						|
		Poco::toLowerInPlace(macPattern);
 | 
						|
		Poco::replaceInPlace(macPattern,"*","%");
 | 
						|
		if(!ValidMacPatternOnlyChars(macPattern)) {
 | 
						|
			return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
						|
		}
 | 
						|
 | 
						|
		StorageService()->DeleteDevices(macPattern, SimulatedOnly);
 | 
						|
		return OK();
 | 
						|
	}
 | 
						|
 | 
						|
} // namespace OpenWifi
 |