Files
wlan-cloud-ucentralgw/src/RESTAPI/RESTAPI_devices_handler.cpp
2023-05-22 14:32:23 -07:00

211 lines
6.0 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 serialOnly = GetBoolParameter(RESTAPI::Protocol::SERIALONLY, false);
auto deviceWithStatus = GetBoolParameter(RESTAPI::Protocol::DEVICEWITHSTATUS, false);
auto completeInfo = GetBoolParameter("completeInfo", false);
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 == true) {
uint64_t Count = 0;
if (StorageService()->GetDeviceCount(Count)) {
return ReturnCountOnly(Count);
}
} else if (serialOnly) {
std::vector<std::string> SerialNumbers;
StorageService()->GetDeviceSerialNumbers(QB_.Offset, QB_.Limit, SerialNumbers, OrderBy);
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);
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(!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