mirror of
https://github.com/Telecominfraproject/wlan-cloud-owprov.git
synced 2025-11-01 19:17:47 +00:00
731 lines
22 KiB
C++
731 lines
22 KiB
C++
//
|
|
// Created by stephane bourque on 2021-10-18.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include "Poco/StringTokenizer.h"
|
|
#include "RESTObjects/RESTAPI_ProvObjects.h"
|
|
#include "StorageService.h"
|
|
#include "framework/ConfigurationValidator.h"
|
|
#include "libs/croncpp.h"
|
|
#include "sdks/SDK_sec.h"
|
|
|
|
namespace OpenWifi {
|
|
|
|
inline static void AddInfoBlock(const ProvObjects::ObjectInfo &O, Poco::JSON::Object &J) {
|
|
J.set("name", O.name);
|
|
J.set("description", O.description);
|
|
J.set("id", O.id);
|
|
}
|
|
|
|
template <typename R, typename Q = decltype(R{}.entity)>
|
|
void Extend_entity(const R &T, Poco::JSON::Object &EI) {
|
|
if constexpr (std::is_same_v<Q, std::string>) {
|
|
if (!T.entity.empty()) {
|
|
Poco::JSON::Object EntObj;
|
|
ProvObjects::Entity Entity;
|
|
if (StorageService()->EntityDB().GetRecord("id", T.entity, Entity)) {
|
|
AddInfoBlock(Entity.info, EntObj);
|
|
}
|
|
EI.set("entity", EntObj);
|
|
}
|
|
}
|
|
}
|
|
template <typename... Ts> void Extend_entity(Ts... args) {
|
|
static_assert(sizeof...(args) == 2);
|
|
}
|
|
|
|
template <typename R, typename Q = decltype(R{}.managementPolicy)>
|
|
void Extend_managementPolicy(const R &T, Poco::JSON::Object &EI) {
|
|
if constexpr (std::is_same_v<Q, std::string>) {
|
|
if (!T.managementPolicy.empty()) {
|
|
Poco::JSON::Object PolObj;
|
|
ProvObjects::ManagementPolicy Policy;
|
|
if (StorageService()->PolicyDB().GetRecord("id", T.managementPolicy, Policy)) {
|
|
AddInfoBlock(Policy.info, PolObj);
|
|
}
|
|
EI.set("managementPolicy", PolObj);
|
|
}
|
|
}
|
|
}
|
|
template <typename... Ts> void Extend_managementPolicy(Ts... args) {
|
|
static_assert(sizeof...(args) == 2);
|
|
}
|
|
|
|
template <typename R, typename Q = decltype(R{}.venue)>
|
|
void Extend_venue(const R &T, Poco::JSON::Object &EI) {
|
|
if constexpr (std::is_same_v<Q, std::string>) {
|
|
if (!T.venue.empty()) {
|
|
Poco::JSON::Object VenObj;
|
|
ProvObjects::Venue Venue;
|
|
if (StorageService()->VenueDB().GetRecord("id", T.venue, Venue)) {
|
|
AddInfoBlock(Venue.info, VenObj);
|
|
}
|
|
EI.set("venue", VenObj);
|
|
}
|
|
}
|
|
}
|
|
template <typename... Ts> void Extend_venue(Ts... args) { static_assert(sizeof...(args) == 2); }
|
|
|
|
template <typename R, typename Q = decltype(R{}.contact)>
|
|
void Extend_contact(const R &T, Poco::JSON::Object &EI) {
|
|
if constexpr (std::is_same_v<Q, std::string>) {
|
|
if (!T.contact.empty()) {
|
|
Poco::JSON::Object ConObj;
|
|
ProvObjects::Contact Contact;
|
|
if (StorageService()->ContactDB().GetRecord("id", T.contact, Contact)) {
|
|
AddInfoBlock(Contact.info, ConObj);
|
|
}
|
|
EI.set("contact", ConObj);
|
|
}
|
|
}
|
|
}
|
|
template <typename... Ts> void Extend_contact(Ts... args) {
|
|
static_assert(sizeof...(args) == 2);
|
|
}
|
|
|
|
template <typename R, typename Q = decltype(R{}.location)>
|
|
void Extend_location(const R &T, Poco::JSON::Object &EI) {
|
|
if constexpr (std::is_same_v<Q, std::string>) {
|
|
if (!T.location.empty()) {
|
|
Poco::JSON::Object LocObj;
|
|
ProvObjects::Location Location;
|
|
if (StorageService()->LocationDB().GetRecord("id", T.location, Location)) {
|
|
AddInfoBlock(Location.info, LocObj);
|
|
}
|
|
EI.set("location", LocObj);
|
|
}
|
|
}
|
|
}
|
|
template <typename... Ts> void Extend_location(Ts... args) {
|
|
static_assert(sizeof...(args) == 2);
|
|
}
|
|
|
|
template <typename R, typename Q = decltype(R{}.deviceConfiguration)>
|
|
void Extend_deviceConfiguration(const R &T, Poco::JSON::Object &EI) {
|
|
if constexpr (std::is_same_v<Q, std::string>) {
|
|
if (!T.deviceConfiguration.empty()) {
|
|
Poco::JSON::Object DevObj;
|
|
ProvObjects::DeviceConfiguration DevConf;
|
|
if (StorageService()->ConfigurationDB().GetRecord("id", T.deviceConfiguration,
|
|
DevConf)) {
|
|
AddInfoBlock(DevConf.info, DevObj);
|
|
}
|
|
EI.set("deviceConfiguration", DevObj);
|
|
}
|
|
}
|
|
if constexpr (std::is_same_v<Q, Types::UUIDvec_t>) {
|
|
if (!T.deviceConfiguration.empty()) {
|
|
Poco::JSON::Array ObjArr;
|
|
ProvObjects::DeviceConfiguration DevConf;
|
|
for (const auto &i : T.deviceConfiguration) {
|
|
if (StorageService()->ConfigurationDB().GetRecord("id", i, DevConf)) {
|
|
Poco::JSON::Object InnerObj;
|
|
AddInfoBlock(DevConf.info, InnerObj);
|
|
ObjArr.add(InnerObj);
|
|
}
|
|
}
|
|
EI.set("deviceConfiguration", ObjArr);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename... Ts> void Extend_deviceConfiguration(Ts... args) {
|
|
static_assert(sizeof...(args) == 2);
|
|
}
|
|
|
|
template <typename R> bool AddExtendedInfo(const R &T, Poco::JSON::Object &O) {
|
|
Poco::JSON::Object EI;
|
|
Extend_entity(T, EI);
|
|
Extend_deviceConfiguration(T, EI);
|
|
Extend_location(T, EI);
|
|
Extend_contact(T, EI);
|
|
Extend_venue(T, EI);
|
|
Extend_managementPolicy(T, EI);
|
|
O.set("extendedInfo", EI);
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
void MakeJSONObjectArray(const char *ArrayName, const std::vector<T> &V, RESTAPIHandler &R) {
|
|
Poco::JSON::Array ObjArray;
|
|
for (const auto &i : V) {
|
|
Poco::JSON::Object Obj;
|
|
i.to_json(Obj);
|
|
if (R.NeedAdditionalInfo())
|
|
AddExtendedInfo(i, Obj);
|
|
ObjArray.add(Obj);
|
|
}
|
|
Poco::JSON::Object Answer;
|
|
Answer.set(ArrayName, ObjArray);
|
|
return R.ReturnObject(Answer);
|
|
}
|
|
|
|
inline static bool is_uuid(const std::string &u) { return u.find('-') != std::string::npos; }
|
|
|
|
template <typename DB>
|
|
void ReturnRecordList(const char *ArrayName, DB &DBInstance, RESTAPIHandler &R) {
|
|
Poco::JSON::Array ObjArr;
|
|
for (const auto &i : R.SelectedRecords()) {
|
|
ProvObjects::InventoryTag E;
|
|
if (DBInstance.GetRecord(is_uuid(i) ? "id" : "serialNumber", i, E)) {
|
|
Poco::JSON::Object Obj;
|
|
E.to_json(Obj);
|
|
if (R.NeedAdditionalInfo())
|
|
AddExtendedInfo(E, Obj);
|
|
ObjArr.add(Obj);
|
|
} else {
|
|
return R.BadRequest(RESTAPI::Errors::UnknownId);
|
|
}
|
|
}
|
|
Poco::JSON::Object Answer;
|
|
Answer.set(ArrayName, ObjArr);
|
|
return R.ReturnObject(Answer);
|
|
}
|
|
|
|
template <typename DB, typename Record>
|
|
void ReturnRecordList(const char *ArrayName, DB &DBInstance, RESTAPIHandler &R) {
|
|
Poco::JSON::Array ObjArr;
|
|
for (const auto &i : R.SelectedRecords()) {
|
|
Record E;
|
|
if (DBInstance.GetRecord("id", i, E)) {
|
|
Poco::JSON::Object Obj;
|
|
E.to_json(Obj);
|
|
if (R.NeedAdditionalInfo())
|
|
AddExtendedInfo(E, Obj);
|
|
ObjArr.add(Obj);
|
|
} else {
|
|
return R.BadRequest(RESTAPI::Errors::UnknownId);
|
|
}
|
|
}
|
|
Poco::JSON::Object Answer;
|
|
Answer.set(ArrayName, ObjArr);
|
|
return R.ReturnObject(Answer);
|
|
}
|
|
|
|
inline bool NormalizeMac(std::string &Mac) {
|
|
Poco::replaceInPlace(Mac, ":", "");
|
|
Poco::replaceInPlace(Mac, "-", "");
|
|
if (Mac.size() != 12)
|
|
return false;
|
|
for (const auto &i : Mac) {
|
|
if (!std::isxdigit(i))
|
|
return false;
|
|
}
|
|
Poco::toLowerInPlace(Mac);
|
|
return true;
|
|
}
|
|
|
|
typedef std::tuple<std::string, std::string, std::string> triplet_t;
|
|
|
|
inline void AddLocationTriplet(const std::string &id, std::vector<triplet_t> &IDs) {
|
|
ProvObjects::Location L;
|
|
if (StorageService()->LocationDB().GetRecord("id", id, L)) {
|
|
IDs.emplace_back(std::make_tuple(L.info.name, L.info.description, L.info.id));
|
|
}
|
|
}
|
|
|
|
inline void AddLocationTriplet(const std::vector<std::string> &id,
|
|
std::vector<triplet_t> &IDs) {
|
|
for (const auto &i : id)
|
|
AddLocationTriplet(i, IDs);
|
|
}
|
|
|
|
inline void GetLocationsForEntity(const std::string &ID, std::vector<triplet_t> &IDs) {
|
|
ProvObjects::Entity Existing;
|
|
if (StorageService()->EntityDB().template GetRecord("id", ID, Existing)) {
|
|
if (!Existing.locations.empty()) {
|
|
AddLocationTriplet(Existing.locations, IDs);
|
|
}
|
|
if (!Existing.parent.empty()) {
|
|
GetLocationsForEntity(Existing.parent, IDs);
|
|
}
|
|
if (ID == EntityDB::RootUUID())
|
|
return;
|
|
}
|
|
}
|
|
|
|
inline void GetLocationsForVenue(const std::string &ID, std::vector<triplet_t> &IDs) {
|
|
ProvObjects::Venue Existing;
|
|
if (StorageService()->VenueDB().template GetRecord("id", ID, Existing)) {
|
|
if (!Existing.parent.empty()) {
|
|
GetLocationsForVenue(Existing.parent, IDs);
|
|
}
|
|
ProvObjects::Entity E;
|
|
if (StorageService()->EntityDB().GetRecord("id", Existing.entity, E)) {
|
|
AddLocationTriplet(E.locations, IDs);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
template <typename DB>
|
|
void ListHandler(const char *BlockName, DB &DBInstance, RESTAPIHandler &R) {
|
|
auto Entity = R.GetParameter("entity", "");
|
|
auto Venue = R.GetParameter("venue", "");
|
|
|
|
typedef typename DB::RecordVec RecVec;
|
|
typedef typename DB::RecordName RecType;
|
|
|
|
if constexpr (std::is_same_v<RecType, ProvObjects::Venue>) {
|
|
auto LocationsForVenue = R.GetParameter("locationsForVenue", "");
|
|
if (!LocationsForVenue.empty()) {
|
|
std::vector<triplet_t> IDs;
|
|
GetLocationsForVenue(LocationsForVenue, IDs);
|
|
Poco::JSON::Array A;
|
|
for (const auto &[name, description, uuid] : IDs) {
|
|
Poco::JSON::Object O;
|
|
O.set("name", name);
|
|
O.set("description", description);
|
|
O.set("uuid", uuid);
|
|
A.add(O);
|
|
}
|
|
Poco::JSON::Object Answer;
|
|
Answer.set("locations", A);
|
|
return R.ReturnObject(Answer);
|
|
}
|
|
}
|
|
|
|
if (!R.QB_.Select.empty()) {
|
|
return ReturnRecordList<decltype(DBInstance), RecType>(BlockName, DBInstance, R);
|
|
}
|
|
if (!Entity.empty()) {
|
|
RecVec Entries;
|
|
DBInstance.GetRecords(R.QB_.Offset, R.QB_.Limit, Entries, " entity=' " + Entity + "'");
|
|
if (R.QB_.CountOnly)
|
|
return R.ReturnCountOnly(Entries.size());
|
|
return MakeJSONObjectArray(BlockName, Entries, R);
|
|
}
|
|
if (!Venue.empty()) {
|
|
RecVec Entries;
|
|
DBInstance.GetRecords(R.QB_.Offset, R.QB_.Limit, Entries, " venue=' " + Venue + "'");
|
|
if (R.QB_.CountOnly)
|
|
return R.ReturnCountOnly(Entries.size());
|
|
return MakeJSONObjectArray(BlockName, Entries, R);
|
|
} else if (R.QB_.CountOnly) {
|
|
Poco::JSON::Object Answer;
|
|
auto C = DBInstance.Count();
|
|
return R.ReturnCountOnly(C);
|
|
} else {
|
|
RecVec Entries;
|
|
DBInstance.GetRecords(R.QB_.Offset, R.QB_.Limit, Entries);
|
|
return MakeJSONObjectArray(BlockName, Entries, R);
|
|
}
|
|
}
|
|
|
|
template <typename db_type>
|
|
void ListHandlerForOperator(const char *BlockName, db_type &DB, RESTAPIHandler &R,
|
|
const Types::UUID_t &OperatorId,
|
|
const Types::UUID_t &subscriberId = "") {
|
|
typedef typename db_type::RecordVec RecVec;
|
|
typedef typename db_type::RecordName RecType;
|
|
|
|
auto whereClause =
|
|
subscriberId.empty()
|
|
? fmt::format(" operatorId='{}'", OperatorId)
|
|
: fmt::format(" operatorId='{}' and subscriberId='{}' ", OperatorId, subscriberId);
|
|
|
|
if (R.QB_.CountOnly) {
|
|
auto Count = DB.Count(whereClause);
|
|
return R.ReturnCountOnly(Count);
|
|
}
|
|
|
|
if (!R.QB_.Select.empty()) {
|
|
return ReturnRecordList<decltype(DB), RecType>(BlockName, DB, R);
|
|
}
|
|
|
|
RecVec Entries;
|
|
DB.GetRecords(R.QB_.Offset, R.QB_.Limit, Entries, whereClause);
|
|
return MakeJSONObjectArray(BlockName, Entries, R);
|
|
}
|
|
|
|
template <typename db_type, typename ObjectDB>
|
|
void MoveUsage(db_type &DB_InUse, ObjectDB &DB, const std::string &From, const std::string &To,
|
|
const std::string &Id) {
|
|
if (From != To) {
|
|
if (!From.empty())
|
|
DB_InUse.DeleteInUse("id", From, DB.Prefix(), Id);
|
|
if (!To.empty())
|
|
DB_InUse.AddInUse("id", To, DB.Prefix(), Id);
|
|
}
|
|
}
|
|
|
|
template <typename db_type, typename ObjectDB>
|
|
void MoveUsage(db_type &DB_InUse, ObjectDB &DB, const Types::UUIDvec_t &From,
|
|
const Types::UUIDvec_t &To, const std::string &Id) {
|
|
if (From != To) {
|
|
if (!From.empty()) {
|
|
for (const auto &i : From)
|
|
DB_InUse.DeleteInUse("id", i, DB.Prefix(), Id);
|
|
}
|
|
if (!To.empty()) {
|
|
for (const auto &i : To)
|
|
DB_InUse.AddInUse("id", i, DB.Prefix(), Id);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename db_type>
|
|
void MoveChild(db_type &DB, const std::string &Parent, const std::string &Child,
|
|
const std::string &Id) {
|
|
if (Parent != Child) {
|
|
if (!Parent.empty())
|
|
DB.InUse.DeleteInUse("id", Parent, Id);
|
|
if (!Child.empty())
|
|
DB.AddInUse("id", Child, Id);
|
|
}
|
|
}
|
|
|
|
template <typename db_type, typename Member>
|
|
void RemoveMembership(db_type &DB, Member T, const std::string &Obj, const std::string &Id) {
|
|
if (!Obj.empty())
|
|
DB.ManipulateVectorMember(T, "id", Obj, Id, false);
|
|
}
|
|
|
|
template <typename db_type, typename Member>
|
|
void AddMembership(db_type &DB, Member T, const std::string &Obj, const std::string &Id) {
|
|
if (!Obj.empty())
|
|
DB.ManipulateVectorMember(T, "id", Obj, Id, true);
|
|
}
|
|
|
|
template <typename db_type, typename Member>
|
|
void ManageMembership(db_type &DB, Member T, const std::string &From, const std::string &To,
|
|
const std::string &Id) {
|
|
RemoveMembership(DB, T, From, Id);
|
|
AddMembership(DB, T, To, Id);
|
|
}
|
|
|
|
template <typename db_type, typename Member>
|
|
void ManageMembership(db_type &DB, Member T, const Types::UUIDvec_t &From,
|
|
const Types::UUIDvec_t &To, const std::string &Id) {
|
|
if (From != To) {
|
|
for (const auto &i : From) {
|
|
RemoveMembership(DB, T, i, Id);
|
|
}
|
|
for (const auto &i : To) {
|
|
AddMembership(DB, T, i, Id);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename Member, typename Rec, typename db_type>
|
|
bool CreateMove(const Poco::JSON::Object::Ptr &RawObj, const char *fieldname, Member T,
|
|
Rec &Existing, std::string &From, std::string &To, db_type &TheDB) {
|
|
if (RawObj->has(fieldname)) {
|
|
From = Existing.*T;
|
|
To = RawObj->get(fieldname).toString();
|
|
if (!To.empty() && !TheDB.Exists("id", To))
|
|
return false;
|
|
Existing.*T = To;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
inline std::string FindParentEntity(const ProvObjects::Venue &V) {
|
|
if (V.parent.empty())
|
|
return V.entity;
|
|
ProvObjects::Venue P;
|
|
if (StorageService()->VenueDB().GetRecord("id", V.parent, P))
|
|
return FindParentEntity(P);
|
|
return EntityDB::RootUUID();
|
|
}
|
|
|
|
inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config,
|
|
std::vector<std::string> &Errors) {
|
|
static const std::vector<std::string> SectionNames{
|
|
"globals", "interfaces", "metrics", "radios", "services", "unit",
|
|
"definitions", "ethernet", "switch", "config-raw", "third-party"};
|
|
|
|
for (const auto &i : Config.configuration) {
|
|
Poco::JSON::Parser P;
|
|
if (i.name.empty()) {
|
|
Errors.push_back("Name is empty");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
auto Blocks = P.parse(i.configuration).extract<Poco::JSON::Object::Ptr>();
|
|
auto N = Blocks->getNames();
|
|
for (const auto &j : N) {
|
|
if (std::find(SectionNames.cbegin(), SectionNames.cend(), j) ==
|
|
SectionNames.cend()) {
|
|
Errors.push_back("Unknown block name");
|
|
return false;
|
|
}
|
|
}
|
|
} catch (const Poco::JSON::JSONException &E) {
|
|
Errors.push_back("Invalid JSON document");
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
if (ValidateUCentralConfiguration(i.configuration, Errors, true)) {
|
|
// std::cout << "Block: " << i.name << " is valid" << std::endl;
|
|
} else {
|
|
return false;
|
|
}
|
|
} catch (...) {
|
|
Errors.push_back("Invalid configuration caused an exception");
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <typename Type>
|
|
std::map<std::string, std::string> CreateObjects(Type &NewObject, RESTAPIHandler &R,
|
|
std::vector<std::string> &Errors) {
|
|
std::map<std::string, std::string> Result;
|
|
|
|
auto createObjects = R.GetParameter("createObjects", "");
|
|
if (!createObjects.empty()) {
|
|
Poco::JSON::Parser P;
|
|
auto Objects = P.parse(createObjects).extract<Poco::JSON::Object::Ptr>();
|
|
if (Objects->isArray("objects")) {
|
|
auto ObjectsArray = Objects->getArray("objects");
|
|
for (const auto &i : *ObjectsArray) {
|
|
auto Object = i.extract<Poco::JSON::Object::Ptr>();
|
|
if (Object->has("location")) {
|
|
auto LocationDetails =
|
|
Object->get("location").extract<Poco::JSON::Object::Ptr>();
|
|
ProvObjects::Location LC;
|
|
if (LC.from_json(LocationDetails)) {
|
|
if constexpr (std::is_same_v<Type, ProvObjects::Venue>) {
|
|
std::string ParentEntity = FindParentEntity(NewObject);
|
|
ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, LC.info);
|
|
LC.entity = ParentEntity;
|
|
if (StorageService()->LocationDB().CreateRecord(LC)) {
|
|
NewObject.location = LC.info.id;
|
|
AddMembership(StorageService()->EntityDB(),
|
|
&ProvObjects::Entity::locations, ParentEntity,
|
|
LC.info.id);
|
|
Result["location"] = LC.info.id;
|
|
}
|
|
}
|
|
if constexpr (std::is_same_v<Type, ProvObjects::Operator>) {
|
|
std::string ParentEntity = FindParentEntity(NewObject);
|
|
ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, LC.info);
|
|
LC.entity = ParentEntity;
|
|
if (StorageService()->LocationDB().CreateRecord(LC)) {
|
|
NewObject.location = LC.info.id;
|
|
AddMembership(StorageService()->EntityDB(),
|
|
&ProvObjects::Entity::locations, ParentEntity,
|
|
LC.info.id);
|
|
Result["location"] = LC.info.id;
|
|
}
|
|
}
|
|
} else {
|
|
Errors.push_back("Invalid JSON document");
|
|
break;
|
|
}
|
|
} else if (Object->has("contact")) {
|
|
auto ContactDetails =
|
|
Object->get("contact").extract<Poco::JSON::Object::Ptr>();
|
|
ProvObjects::Contact CC;
|
|
if (CC.from_json(ContactDetails)) {
|
|
std::cout << "contact decoded: " << CC.info.name << std::endl;
|
|
} else {
|
|
std::cout << "contact not decoded." << std::endl;
|
|
}
|
|
} else if (Object->has("configuration")) {
|
|
auto ConfigurationDetails =
|
|
Object->get("configuration")
|
|
.template extract<Poco::JSON::Object::Ptr>();
|
|
ProvObjects::DeviceConfiguration DC;
|
|
if (DC.from_json(ConfigurationDetails)) {
|
|
if constexpr (std::is_same_v<Type, ProvObjects::InventoryTag>) {
|
|
if (!ValidateConfigBlock(DC, Errors)) {
|
|
break;
|
|
}
|
|
ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, DC.info);
|
|
if (StorageService()->ConfigurationDB().CreateRecord(DC)) {
|
|
NewObject.deviceConfiguration = DC.info.id;
|
|
Result["configuration"] = DC.info.id;
|
|
}
|
|
}
|
|
} else {
|
|
Errors.push_back("Invalid JSON document");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
inline bool ValidSchedule(const std::string &v) {
|
|
try {
|
|
auto cron = cron::make_cron(v);
|
|
return true;
|
|
} catch (cron::bad_cronexpr const &ex) {
|
|
}
|
|
return false;
|
|
}
|
|
|
|
inline bool ValidRRM(const std::string &v) {
|
|
if ((v == "no") || (v == "inherit"))
|
|
return true;
|
|
try {
|
|
Poco::JSON::Parser P;
|
|
auto O = P.parse(v).extract<Poco::JSON::Object::Ptr>();
|
|
|
|
ProvObjects::RRMDetails D;
|
|
if (D.from_json(O)) {
|
|
return ValidSchedule(D.schedule);
|
|
}
|
|
} catch (...) {
|
|
}
|
|
return false;
|
|
}
|
|
|
|
inline bool ValidDeviceRules(const ProvObjects::DeviceRules &DR) {
|
|
return (ValidRRM(DR.rrm)) &&
|
|
(DR.firmwareUpgrade == "yes" || DR.firmwareUpgrade == "no" ||
|
|
DR.firmwareUpgrade == "inherit") &&
|
|
(DR.rcOnly == "yes" || DR.rcOnly == "no" || DR.rcOnly == "inherit");
|
|
}
|
|
|
|
inline bool ValidDeviceRules(const ProvObjects::DeviceRules &DR, RESTAPIHandler &H) {
|
|
if (ValidDeviceRules(DR))
|
|
return true;
|
|
H.BadRequest(RESTAPI::Errors::InvalidRRM);
|
|
return false;
|
|
}
|
|
|
|
inline bool ValidSourceIP([[maybe_unused]] const std::vector<std::string> &IPs) { return true; }
|
|
|
|
inline bool ValidPeriod(const std::string &P) {
|
|
return (P == "hourly" || P == "daily" || P == "monthly" || P == "yearly" ||
|
|
P == "quarterly" || P == "lifetime" || P == "custom1" || P == "custom2" ||
|
|
P == "custom3" || P == "custom4");
|
|
}
|
|
|
|
inline bool ValidContactType(const std::string &contact) {
|
|
auto C = Poco::toLower(contact);
|
|
return (C == "subscriber" || C == "user" || C == "installer" || C == "csr" ||
|
|
C == "manager" || C == "businessowner" || C == "technician" || C == "corporate");
|
|
}
|
|
|
|
inline bool ValidContactType(const std::string &contact, RESTAPIHandler &H) {
|
|
auto C = Poco::toLower(contact);
|
|
if (C == "subscriber" || C == "user" || C == "installer" || C == "csr" || C == "manager" ||
|
|
C == "businessowner" || C == "technician" || C == "corporate")
|
|
return true;
|
|
H.BadRequest(RESTAPI::Errors::InvalidContactType);
|
|
return false;
|
|
}
|
|
|
|
inline bool ValidLocationType(const std::string &location) {
|
|
auto C = Poco::toLower(location);
|
|
return (C == "service" || C == "equipment" || C == "auto" || C == "manual" ||
|
|
C == "special" || C == "unknown" || C == "corporate");
|
|
}
|
|
|
|
inline bool ValidLocationType(const std::string &location, RESTAPIHandler &H) {
|
|
auto C = Poco::toLower(location);
|
|
if ((C == "service" || C == "equipment" || C == "auto" || C == "manual" || C == "special" ||
|
|
C == "unknown" || C == "corporate"))
|
|
return true;
|
|
H.BadRequest(RESTAPI::Errors::InvalidLocationType);
|
|
return false;
|
|
}
|
|
|
|
template <typename DBType>
|
|
bool ValidDbId(const Types::UUID_t &uuid, DBType &DB, bool AllowEmpty,
|
|
const RESTAPI::Errors::msg &Error, RESTAPIHandler &H) {
|
|
if (!AllowEmpty && uuid.empty()) {
|
|
H.BadRequest(Error);
|
|
return false;
|
|
}
|
|
if (uuid.empty())
|
|
return true;
|
|
if (!DB.Exists("id", uuid)) {
|
|
H.BadRequest(Error);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
inline bool ValidSubscriberId(const Types::UUID_t &uuid, bool AllowEmpty, RESTAPIHandler &H) {
|
|
if (!AllowEmpty && uuid.empty()) {
|
|
H.BadRequest(RESTAPI::Errors::InvalidSubscriberId);
|
|
return false;
|
|
}
|
|
if (uuid.empty())
|
|
return true;
|
|
SecurityObjects::UserInfo NewSubInfo;
|
|
if (!SDK::Sec::Subscriber::Get(&H, uuid, NewSubInfo)) {
|
|
H.BadRequest(RESTAPI::Errors::InvalidSubscriberId);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
inline bool ValidSubscriberId(const Types::UUID_t &uuid, bool AllowEmpty, std::string &email,
|
|
RESTAPIHandler &H) {
|
|
if (!AllowEmpty && uuid.empty()) {
|
|
H.BadRequest(RESTAPI::Errors::InvalidSubscriberId);
|
|
return false;
|
|
}
|
|
if (uuid.empty())
|
|
return true;
|
|
SecurityObjects::UserInfo NewSubInfo;
|
|
if (!SDK::Sec::Subscriber::Get(&H, uuid, NewSubInfo)) {
|
|
H.BadRequest(RESTAPI::Errors::InvalidSubscriberId);
|
|
return false;
|
|
}
|
|
email = NewSubInfo.email;
|
|
return true;
|
|
}
|
|
|
|
inline bool ValidSerialNumber(const std::string &serialNumber, bool AllowEmpty,
|
|
RESTAPIHandler &H) {
|
|
if (!AllowEmpty && serialNumber.empty()) {
|
|
H.BadRequest(RESTAPI::Errors::InvalidSerialNumber);
|
|
return false;
|
|
}
|
|
|
|
if (!Utils::ValidSerialNumber(serialNumber)) {
|
|
H.BadRequest(RESTAPI::Errors::InvalidSerialNumber);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template <typename DBType, typename DBRecordType>
|
|
void ReturnUpdatedObject(DBType &DB, const DBRecordType &R, RESTAPIHandler &H) {
|
|
if (DB.UpdateRecord("id", R.info.id, R)) {
|
|
DBRecordType Updated;
|
|
DB.GetRecord("id", R.info.id, Updated);
|
|
Poco::JSON::Object Answer;
|
|
Updated.to_json(Answer);
|
|
return H.ReturnObject(Answer);
|
|
} else {
|
|
H.InternalError(RESTAPI::Errors::RecordNotUpdated);
|
|
}
|
|
}
|
|
|
|
template <typename DBType, typename DBRecordType>
|
|
void ReturnCreatedObject(DBType &DB, const DBRecordType &R, RESTAPIHandler &H) {
|
|
if (DB.CreateRecord(R)) {
|
|
DBRecordType Updated;
|
|
DB.GetRecord("id", R.info.id, Updated);
|
|
Poco::JSON::Object Answer;
|
|
Updated.to_json(Answer);
|
|
return H.ReturnObject(Answer);
|
|
} else {
|
|
H.InternalError(RESTAPI::Errors::RecordNotCreated);
|
|
}
|
|
}
|
|
|
|
template <typename DBType> void ReturnFieldList(DBType &DB, RESTAPIHandler &H) {
|
|
Types::StringVec Fields;
|
|
DB.GetFieldNames(Fields);
|
|
Poco::JSON::Object Answer;
|
|
RESTAPI_utils::field_to_json(Answer, "list", Fields);
|
|
return H.ReturnObject(Answer);
|
|
}
|
|
} // namespace OpenWifi
|