diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:32:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-13 11:32:39 +0000 |
commit | 56ae875861ab260b80a030f50c4aff9f9dc8fff0 (patch) | |
tree | 531412110fc901a5918c7f7442202804a83cada9 /lib/remote/modifyobjecthandler.cpp | |
parent | Initial commit. (diff) | |
download | icinga2-56ae875861ab260b80a030f50c4aff9f9dc8fff0.tar.xz icinga2-56ae875861ab260b80a030f50c4aff9f9dc8fff0.zip |
Adding upstream version 2.14.2.upstream/2.14.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | lib/remote/modifyobjecthandler.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/lib/remote/modifyobjecthandler.cpp b/lib/remote/modifyobjecthandler.cpp new file mode 100644 index 0000000..d6fa98b --- /dev/null +++ b/lib/remote/modifyobjecthandler.cpp @@ -0,0 +1,168 @@ +/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ + +#include "remote/modifyobjecthandler.hpp" +#include "remote/configobjectslock.hpp" +#include "remote/httputility.hpp" +#include "remote/filterutility.hpp" +#include "remote/apiaction.hpp" +#include "base/exception.hpp" +#include <boost/algorithm/string/case_conv.hpp> +#include <set> + +using namespace icinga; + +REGISTER_URLHANDLER("/v1/objects", ModifyObjectHandler); + +bool ModifyObjectHandler::HandleRequest( + AsioTlsStream& stream, + const ApiUser::Ptr& user, + boost::beast::http::request<boost::beast::http::string_body>& request, + const Url::Ptr& url, + boost::beast::http::response<boost::beast::http::string_body>& response, + const Dictionary::Ptr& params, + boost::asio::yield_context& yc, + HttpServerConnection& server +) +{ + namespace http = boost::beast::http; + + if (url->GetPath().size() < 3 || url->GetPath().size() > 4) + return false; + + if (request.method() != http::verb::post) + return false; + + Type::Ptr type = FilterUtility::TypeFromPluralName(url->GetPath()[2]); + + if (!type) { + HttpUtility::SendJsonError(response, params, 400, "Invalid type specified."); + return true; + } + + QueryDescription qd; + qd.Types.insert(type->GetName()); + qd.Permission = "objects/modify/" + type->GetName(); + + params->Set("type", type->GetName()); + + if (url->GetPath().size() >= 4) { + String attr = type->GetName(); + boost::algorithm::to_lower(attr); + params->Set(attr, url->GetPath()[3]); + } + + std::vector<Value> objs; + + try { + objs = FilterUtility::GetFilterTargets(qd, params, user); + } catch (const std::exception& ex) { + HttpUtility::SendJsonError(response, params, 404, + "No objects found.", + DiagnosticInformation(ex)); + return true; + } + + Value attrsVal = params->Get("attrs"); + + if (attrsVal.GetReflectionType() != Dictionary::TypeInstance && attrsVal.GetType() != ValueEmpty) { + HttpUtility::SendJsonError(response, params, 400, + "Invalid type for 'attrs' attribute specified. Dictionary type is required." + "Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?"); + return true; + } + + Dictionary::Ptr attrs = attrsVal; + + Value restoreAttrsVal = params->Get("restore_attrs"); + + if (restoreAttrsVal.GetReflectionType() != Array::TypeInstance && restoreAttrsVal.GetType() != ValueEmpty) { + HttpUtility::SendJsonError(response, params, 400, + "Invalid type for 'restore_attrs' attribute specified. Array type is required."); + return true; + } + + Array::Ptr restoreAttrs = restoreAttrsVal; + + if (!(attrs || restoreAttrs)) { + HttpUtility::SendJsonError(response, params, 400, + "Missing both 'attrs' and 'restore_attrs'. " + "Or is this a POST query and you missed adding a 'X-HTTP-Method-Override: GET' header?"); + return true; + } + + bool verbose = false; + + if (params) + verbose = HttpUtility::GetLastParameter(params, "verbose"); + + ConfigObjectsSharedLock lock (std::try_to_lock); + + if (!lock) { + HttpUtility::SendJsonError(response, params, 503, "Icinga is reloading"); + return true; + } + + ArrayData results; + + for (const ConfigObject::Ptr& obj : objs) { + Dictionary::Ptr result1 = new Dictionary(); + + result1->Set("type", type->GetName()); + result1->Set("name", obj->GetName()); + + String key; + + try { + if (restoreAttrs) { + ObjectLock oLock (restoreAttrs); + + for (auto& attr : restoreAttrs) { + key = attr; + obj->RestoreAttribute(key); + } + } + } catch (const std::exception& ex) { + result1->Set("code", 500); + result1->Set("status", "Attribute '" + key + "' could not be restored: " + DiagnosticInformation(ex, false)); + + if (verbose) + result1->Set("diagnostic_information", DiagnosticInformation(ex)); + + results.push_back(std::move(result1)); + continue; + } + + try { + if (attrs) { + ObjectLock olock(attrs); + for (const Dictionary::Pair& kv : attrs) { + key = kv.first; + obj->ModifyAttribute(kv.first, kv.second); + } + } + } catch (const std::exception& ex) { + result1->Set("code", 500); + result1->Set("status", "Attribute '" + key + "' could not be set: " + DiagnosticInformation(ex, false)); + + if (verbose) + result1->Set("diagnostic_information", DiagnosticInformation(ex)); + + results.push_back(std::move(result1)); + continue; + } + + result1->Set("code", 200); + result1->Set("status", "Attributes updated."); + + results.push_back(std::move(result1)); + } + + Dictionary::Ptr result = new Dictionary({ + { "results", new Array(std::move(results)) } + }); + + response.result(http::status::ok); + HttpUtility::SendJsonBody(response, params, result); + + return true; +} |