1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
2 
3 #include "remote/variablequeryhandler.hpp"
4 #include "remote/httputility.hpp"
5 #include "remote/filterutility.hpp"
6 #include "base/configtype.hpp"
7 #include "base/scriptglobal.hpp"
8 #include "base/logger.hpp"
9 #include "base/serializer.hpp"
10 #include "base/namespace.hpp"
11 #include <set>
12 
13 using namespace icinga;
14 
15 REGISTER_URLHANDLER("/v1/variables", VariableQueryHandler);
16 
17 class VariableTargetProvider final : public TargetProvider
18 {
19 public:
20 	DECLARE_PTR_TYPEDEFS(VariableTargetProvider);
21 
GetTargetForVar(const String & name,const Value & value)22 	static Dictionary::Ptr GetTargetForVar(const String& name, const Value& value)
23 	{
24 		return new Dictionary({
25 			{ "name", name },
26 			{ "type", value.GetReflectionType()->GetName() },
27 			{ "value", value }
28 		});
29 	}
30 
FindTargets(const String & type,const std::function<void (const Value &)> & addTarget) const31 	void FindTargets(const String& type,
32 		const std::function<void (const Value&)>& addTarget) const override
33 	{
34 		{
35 			Namespace::Ptr globals = ScriptGlobal::GetGlobals();
36 			ObjectLock olock(globals);
37 			for (const Namespace::Pair& kv : globals) {
38 				addTarget(GetTargetForVar(kv.first, kv.second->Get()));
39 			}
40 		}
41 	}
42 
GetTargetByName(const String & type,const String & name) const43 	Value GetTargetByName(const String& type, const String& name) const override
44 	{
45 		return GetTargetForVar(name, ScriptGlobal::Get(name));
46 	}
47 
IsValidType(const String & type) const48 	bool IsValidType(const String& type) const override
49 	{
50 		return type == "Variable";
51 	}
52 
GetPluralName(const String & type) const53 	String GetPluralName(const String& type) const override
54 	{
55 		return "variables";
56 	}
57 };
58 
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)59 bool VariableQueryHandler::HandleRequest(
60 	AsioTlsStream& stream,
61 	const ApiUser::Ptr& user,
62 	boost::beast::http::request<boost::beast::http::string_body>& request,
63 	const Url::Ptr& url,
64 	boost::beast::http::response<boost::beast::http::string_body>& response,
65 	const Dictionary::Ptr& params,
66 	boost::asio::yield_context& yc,
67 	HttpServerConnection& server
68 )
69 {
70 	namespace http = boost::beast::http;
71 
72 	if (url->GetPath().size() > 3)
73 		return false;
74 
75 	if (request.method() != http::verb::get)
76 		return false;
77 
78 	QueryDescription qd;
79 	qd.Types.insert("Variable");
80 	qd.Permission = "variables";
81 	qd.Provider = new VariableTargetProvider();
82 
83 	params->Set("type", "Variable");
84 
85 	if (url->GetPath().size() >= 3)
86 		params->Set("variable", url->GetPath()[2]);
87 
88 	std::vector<Value> objs;
89 
90 	try {
91 		objs = FilterUtility::GetFilterTargets(qd, params, user, "variable");
92 	} catch (const std::exception& ex) {
93 		HttpUtility::SendJsonError(response, params, 404,
94 			"No variables found.",
95 			DiagnosticInformation(ex));
96 		return true;
97 	}
98 
99 	ArrayData results;
100 
101 	for (const Dictionary::Ptr& var : objs) {
102 		results.emplace_back(new Dictionary({
103 			{ "name", var->Get("name") },
104 			{ "type", var->Get("type") },
105 			{ "value", Serialize(var->Get("value"), 0) }
106 		}));
107 	}
108 
109 	Dictionary::Ptr result = new Dictionary({
110 		{ "results", new Array(std::move(results)) }
111 	});
112 
113 	response.result(http::status::ok);
114 	HttpUtility::SendJsonBody(response, params, result);
115 
116 	return true;
117 }
118 
119