Files
wlan-cloud-owprov/src/RESTAPI/RESTAPI_entity_handler.cpp
2023-02-21 13:34:41 -08:00

181 lines
5.5 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 "RESTAPI_entity_handler.h"
#include "RESTAPI_db_helpers.h"
#include "RESTObjects/RESTAPI_ProvObjects.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "StorageService.h"
#include "framework/CIDR.h"
namespace OpenWifi {
void RESTAPI_entity_handler::DoGet() {
std::string UUID = GetBinding("uuid", "");
ProvObjects::Entity Existing;
if (UUID.empty() || !DB_.GetRecord("id", UUID, Existing)) {
return NotFound();
}
Poco::JSON::Object Answer;
Existing.to_json(Answer);
if (NeedAdditionalInfo())
AddExtendedInfo(Existing, Answer);
ReturnObject(Answer);
}
void RESTAPI_entity_handler::DoDelete() {
std::string UUID = GetBinding("uuid", "");
ProvObjects::Entity Existing;
if (UUID.empty() || !DB_.GetRecord("id", UUID, Existing)) {
return NotFound();
}
if (UUID == EntityDB::RootUUID()) {
return BadRequest(RESTAPI::Errors::CannotDeleteRoot);
}
if (!Existing.children.empty() || !Existing.devices.empty() || !Existing.venues.empty() ||
!Existing.locations.empty() || !Existing.contacts.empty() ||
!Existing.configurations.empty()) {
return BadRequest(RESTAPI::Errors::StillInUse);
}
MoveUsage(StorageService()->PolicyDB(), DB_, Existing.managementPolicy, "",
Existing.info.id);
DB_.DeleteRecord("id", UUID);
DB_.DeleteChild("id", Existing.parent, UUID);
return OK();
}
void RESTAPI_entity_handler::DoPost() {
std::string UUID = GetBinding("uuid", "");
if (UUID.empty()) {
return BadRequest(RESTAPI::Errors::MissingUUID);
}
if (UUID == EntityDB::RootUUID()) {
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
const auto &RawObject = ParsedBody_;
ProvObjects::Entity NewEntity;
if (!NewEntity.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if ((RawObject->has("deviceRules") && !ValidDeviceRules(NewEntity.deviceRules, *this))) {
return;
}
if (!ProvObjects::CreateObjectInfo(RawObject, UserInfo_.userinfo, NewEntity.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
// When creating an entity, it cannot have any relations other that parent, notes, name,
// description. Everything else must be conveyed through PUT.
NewEntity.info.id = (UUID == EntityDB::RootUUID()) ? UUID : MicroServiceCreateUUID();
if (UUID == EntityDB::RootUUID()) {
NewEntity.parent = "";
} else if (NewEntity.parent.empty() || !DB_.Exists("id", NewEntity.parent)) {
return BadRequest(RESTAPI::Errors::ParentUUIDMustExist);
}
if (!NewEntity.managementPolicy.empty() &&
!StorageService()->PolicyDB().Exists("id", NewEntity.managementPolicy)) {
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
}
if (!NewEntity.sourceIP.empty() && !CIDR::ValidateIpRanges(NewEntity.sourceIP)) {
return BadRequest(RESTAPI::Errors::InvalidIPRanges);
}
NewEntity.venues.clear();
NewEntity.children.clear();
NewEntity.contacts.clear();
NewEntity.locations.clear();
NewEntity.deviceConfiguration.clear();
NewEntity.managementRoles.clear();
if (DB_.CreateRecord(NewEntity)) {
MoveUsage(StorageService()->PolicyDB(), DB_, "", NewEntity.managementPolicy,
NewEntity.info.id);
DB_.AddChild("id", NewEntity.parent, NewEntity.info.id);
Poco::JSON::Object Answer;
NewEntity.to_json(Answer);
return ReturnObject(Answer);
}
InternalError(RESTAPI::Errors::RecordNotCreated);
}
/*
* Put is a complex operation, it contains commands only.
* addContact=UUID, delContact=UUID,
* addLocation=UUID, delLocation=UUID,
* addVenue=UUID, delVenue=UUID,
* addEntity=UUID, delEntity=UUID
* addDevice=UUID, delDevice=UUID
*/
void RESTAPI_entity_handler::DoPut() {
std::string UUID = GetBinding("uuid", "");
ProvObjects::Entity Existing;
if (UUID.empty() || !DB_.GetRecord("id", UUID, Existing)) {
return NotFound();
}
const auto &RawObject = ParsedBody_;
ProvObjects::Entity NewEntity;
if (!NewEntity.from_json(RawObject)) {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
}
if ((RawObject->has("deviceRules") && !ValidDeviceRules(NewEntity.deviceRules, *this))) {
return;
}
if (!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) {
return BadRequest(RESTAPI::Errors::NameMustBeSet);
}
std::string FromPolicy, ToPolicy;
if (!CreateMove(RawObject, "managementPolicy", &EntityDB::RecordName::managementPolicy,
Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB()))
return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID);
if (RawObject->has("sourceIP")) {
if (!NewEntity.sourceIP.empty() && !CIDR::ValidateIpRanges(NewEntity.sourceIP)) {
return BadRequest(RESTAPI::Errors::InvalidIPRanges);
}
Existing.sourceIP = NewEntity.sourceIP;
}
RESTAPI::Errors::msg Error;
if (!StorageService()->Validate(Parameters_, Error)) {
return BadRequest(Error);
}
if (RawObject->has("deviceRules"))
Existing.deviceRules = NewEntity.deviceRules;
if (DB_.UpdateRecord("id", UUID, Existing)) {
MoveUsage(StorageService()->PolicyDB(), DB_, FromPolicy, ToPolicy, Existing.info.id);
Poco::JSON::Object Answer;
ProvObjects::Entity NewRecord;
StorageService()->EntityDB().GetRecord("id", UUID, NewRecord);
NewRecord.to_json(Answer);
return ReturnObject(Answer);
}
InternalError(RESTAPI::Errors::RecordNotUpdated);
}
} // namespace OpenWifi