icinga2/lib/remote/templatequeryhandler.cpp
Johannes Schmidt 749a4b0c89 Remove extra parameters from HTTP handler signature
These parameters are no longer needed since they were only used
by EventsHandler which was refactored in the other commit.
2025-07-14 10:36:59 +02:00

133 lines
3.3 KiB
C++

/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
#include "remote/templatequeryhandler.hpp"
#include "remote/httputility.hpp"
#include "remote/filterutility.hpp"
#include "config/configitem.hpp"
#include "base/configtype.hpp"
#include "base/scriptglobal.hpp"
#include "base/logger.hpp"
#include <boost/algorithm/string/case_conv.hpp>
#include <set>
using namespace icinga;
REGISTER_URLHANDLER("/v1/templates", TemplateQueryHandler);
class TemplateTargetProvider final : public TargetProvider
{
public:
DECLARE_PTR_TYPEDEFS(TemplateTargetProvider);
static Dictionary::Ptr GetTargetForTemplate(const ConfigItem::Ptr& item)
{
DebugInfo di = item->GetDebugInfo();
return new Dictionary({
{ "name", item->GetName() },
{ "type", item->GetType()->GetName() },
{ "location", new Dictionary({
{ "path", di.Path },
{ "first_line", di.FirstLine },
{ "first_column", di.FirstColumn },
{ "last_line", di.LastLine },
{ "last_column", di.LastColumn }
}) }
});
}
void FindTargets(const String& type,
const std::function<void (const Value&)>& addTarget) const override
{
Type::Ptr ptype = Type::GetByName(type);
for (const ConfigItem::Ptr& item : ConfigItem::GetItems(ptype)) {
if (item->IsAbstract())
addTarget(GetTargetForTemplate(item));
}
}
Value GetTargetByName(const String& type, const String& name) const override
{
Type::Ptr ptype = Type::GetByName(type);
ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(ptype, name);
if (!item || !item->IsAbstract())
BOOST_THROW_EXCEPTION(std::invalid_argument("Template does not exist."));
return GetTargetForTemplate(item);
}
bool IsValidType(const String& type) const override
{
Type::Ptr ptype = Type::GetByName(type);
if (!ptype)
return false;
return ConfigObject::TypeInstance->IsAssignableFrom(ptype);
}
String GetPluralName(const String& type) const override
{
return Type::GetByName(type)->GetPluralName();
}
};
bool TemplateQueryHandler::HandleRequest(
const WaitGroup::Ptr&,
HttpRequest& request,
HttpResponse& response,
boost::asio::yield_context& yc
)
{
namespace http = boost::beast::http;
if (request.Url()->GetPath().size() < 3 || request.Url()->GetPath().size() > 4)
return false;
if (request.method() != http::verb::get)
return false;
Type::Ptr type = FilterUtility::TypeFromPluralName(request.Url()->GetPath()[2]);
if (!type) {
response.SendJsonError(request.Params(), 400, "Invalid type specified.");
return true;
}
QueryDescription qd;
qd.Types.insert(type->GetName());
qd.Permission = "templates/query/" + type->GetName();
qd.Provider = new TemplateTargetProvider();
request.Params()->Set("type", type->GetName());
if (request.Url()->GetPath().size() >= 4) {
String attr = type->GetName();
boost::algorithm::to_lower(attr);
request.Params()->Set(attr, request.Url()->GetPath()[3]);
}
std::vector<Value> objs;
try {
objs = FilterUtility::GetFilterTargets(qd, request.Params(), request.User(), "tmpl");
} catch (const std::exception& ex) {
response.SendJsonError(request.Params(), 404,
"No templates found.",
DiagnosticInformation(ex));
return true;
}
Dictionary::Ptr result = new Dictionary({
{ "results", new Array(std::move(objs)) }
});
response.result(http::status::ok);
response.SendJsonBody(result, request.IsPretty());
return true;
}