diff options
Diffstat (limited to 'lib/remote/configpackageshandler.cpp')
-rw-r--r-- | lib/remote/configpackageshandler.cpp | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/lib/remote/configpackageshandler.cpp b/lib/remote/configpackageshandler.cpp new file mode 100644 index 0000000..98b3268 --- /dev/null +++ b/lib/remote/configpackageshandler.cpp @@ -0,0 +1,179 @@ +/* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */ + +#include "remote/configpackageshandler.hpp" +#include "remote/configpackageutility.hpp" +#include "remote/httputility.hpp" +#include "remote/filterutility.hpp" +#include "base/exception.hpp" + +using namespace icinga; + +REGISTER_URLHANDLER("/v1/config/packages", ConfigPackagesHandler); + +bool ConfigPackagesHandler::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() > 4) + return false; + + if (request.method() == http::verb::get) + HandleGet(user, request, url, response, params); + else if (request.method() == http::verb::post) + HandlePost(user, request, url, response, params); + else if (request.method() == http::verb::delete_) + HandleDelete(user, request, url, response, params); + else + return false; + + return true; +} + +void ConfigPackagesHandler::HandleGet( + 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 +) +{ + namespace http = boost::beast::http; + + FilterUtility::CheckPermission(user, "config/query"); + + std::vector<String> packages; + + try { + packages = ConfigPackageUtility::GetPackages(); + } catch (const std::exception& ex) { + HttpUtility::SendJsonError(response, params, 500, "Could not retrieve packages.", + DiagnosticInformation(ex)); + return; + } + + ArrayData results; + + { + std::unique_lock<std::mutex> lock(ConfigPackageUtility::GetStaticPackageMutex()); + + for (const String& package : packages) { + String activeStage; + + try { + activeStage = ConfigPackageUtility::GetActiveStage(package); + } catch (const std::exception&) { } /* Should never happen. */ + + results.emplace_back(new Dictionary({ + { "name", package }, + { "stages", Array::FromVector(ConfigPackageUtility::GetStages(package)) }, + { "active-stage", activeStage } + })); + } + } + + Dictionary::Ptr result = new Dictionary({ + { "results", new Array(std::move(results)) } + }); + + response.result(http::status::ok); + HttpUtility::SendJsonBody(response, params, result); +} + +void ConfigPackagesHandler::HandlePost( + 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 +) +{ + namespace http = boost::beast::http; + + FilterUtility::CheckPermission(user, "config/modify"); + + if (url->GetPath().size() >= 4) + params->Set("package", url->GetPath()[3]); + + String packageName = HttpUtility::GetLastParameter(params, "package"); + + if (!ConfigPackageUtility::ValidatePackageName(packageName)) { + HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'."); + return; + } + + try { + std::unique_lock<std::mutex> lock(ConfigPackageUtility::GetStaticPackageMutex()); + + ConfigPackageUtility::CreatePackage(packageName); + } catch (const std::exception& ex) { + HttpUtility::SendJsonError(response, params, 500, "Could not create package '" + packageName + "'.", + DiagnosticInformation(ex)); + return; + } + + Dictionary::Ptr result1 = new Dictionary({ + { "code", 200 }, + { "package", packageName }, + { "status", "Created package." } + }); + + Dictionary::Ptr result = new Dictionary({ + { "results", new Array({ result1 }) } + }); + + response.result(http::status::ok); + HttpUtility::SendJsonBody(response, params, result); +} + +void ConfigPackagesHandler::HandleDelete( + 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 +) +{ + namespace http = boost::beast::http; + + FilterUtility::CheckPermission(user, "config/modify"); + + if (url->GetPath().size() >= 4) + params->Set("package", url->GetPath()[3]); + + String packageName = HttpUtility::GetLastParameter(params, "package"); + + if (!ConfigPackageUtility::ValidatePackageName(packageName)) { + HttpUtility::SendJsonError(response, params, 400, "Invalid package name '" + packageName + "'."); + return; + } + + try { + ConfigPackageUtility::DeletePackage(packageName); + } catch (const std::exception& ex) { + HttpUtility::SendJsonError(response, params, 500, "Failed to delete package '" + packageName + "'.", + DiagnosticInformation(ex)); + return; + } + + Dictionary::Ptr result1 = new Dictionary({ + { "code", 200 }, + { "package", packageName }, + { "status", "Deleted package." } + }); + + Dictionary::Ptr result = new Dictionary({ + { "results", new Array({ result1 }) } + }); + + response.result(http::status::ok); + HttpUtility::SendJsonBody(response, params, result); +} |