icinga2/lib/remote/eventshandler.cpp
Yonas Habteab 91c7e60df8 Replace all existing copyright headers with SPDX headers
I've used the following command to replace the original copyright header
lines in a C-style comment block:

```
$ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f -exec perl -pi -e 's{/\*[^*]*\(\s*c\s*\)\s*(\d{4})\s*Icinga\s+GmbH[^*]*\*/}{// SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n// SPDX-License-Identifier: GPL-2.0-or-later}gi' {} +
```

For files that use shell-style comments (#) like CMakeLists.txt, I've
used this command:

```
$ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f -exec perl -pi -e 's{#.*\(\s*c\s*\)\s(\d{4})\sIcinga\s+GmbH.*}{# SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n# SPDX-License-Identifier: GPL-2.0-or-later}gi' {} +
```

And for SQL files:

```
$ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f \( -name '*.sql' \) -exec perl -pi -e 's{--.*\(c\)\s(\d{4})\sIcinga\sGmbH.*}{-- SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n-- SPDX-License-Identifier: GPL-2.0-or-later}gi' {} +
$ find . \( -type d \( -name '\..*' -o -name third-party -o -name scripts -o -name prefix -o -name malloc -o -name server -o -name docker -o -name build -o -name doc \) -prune \) -o -type f \( -name '*.sql' \) -exec perl -pi -e 's{-- Copyright \(c\)\s(\d{4})\sIcinga\s+Development\sTeam.*}{-- SPDX-FileCopyrightText: \1 Icinga GmbH <https://icinga.com>\n-- SPDX-License-Identifier: GPL-2.0-or-later}gi' {} +
```
2026-02-04 14:00:05 +01:00

120 lines
3.1 KiB
C++

// SPDX-FileCopyrightText: 2012 Icinga GmbH <https://icinga.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "remote/eventshandler.hpp"
#include "remote/httputility.hpp"
#include "remote/filterutility.hpp"
#include "config/configcompiler.hpp"
#include "config/expression.hpp"
#include "base/defer.hpp"
#include "base/io-engine.hpp"
#include "base/objectlock.hpp"
#include "base/json.hpp"
#include <boost/asio/buffer.hpp>
#include <boost/asio/write.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <map>
#include <set>
using namespace icinga;
REGISTER_URLHANDLER("/v1/events", EventsHandler);
const std::map<String, EventType> l_EventTypes ({
{"AcknowledgementCleared", EventType::AcknowledgementCleared},
{"AcknowledgementSet", EventType::AcknowledgementSet},
{"CheckResult", EventType::CheckResult},
{"CommentAdded", EventType::CommentAdded},
{"CommentRemoved", EventType::CommentRemoved},
{"DowntimeAdded", EventType::DowntimeAdded},
{"DowntimeRemoved", EventType::DowntimeRemoved},
{"DowntimeStarted", EventType::DowntimeStarted},
{"DowntimeTriggered", EventType::DowntimeTriggered},
{"Flapping", EventType::Flapping},
{"Notification", EventType::Notification},
{"StateChange", EventType::StateChange},
{"ObjectCreated", EventType::ObjectCreated},
{"ObjectDeleted", EventType::ObjectDeleted},
{"ObjectModified", EventType::ObjectModified}
});
const String l_ApiQuery ("<API query>");
bool EventsHandler::HandleRequest(
const WaitGroup::Ptr&,
const HttpApiRequest& request,
HttpApiResponse& response,
boost::asio::yield_context& yc
)
{
namespace asio = boost::asio;
namespace http = boost::beast::http;
auto url = request.Url();
auto user = request.User();
auto params = request.Params();
if (url->GetPath().size() != 2)
return false;
if (request.method() != http::verb::post)
return false;
if (request.version() == 10) {
HttpUtility::SendJsonError(response, params, 400, "HTTP/1.0 not supported for event streams.");
return true;
}
Array::Ptr types = params->Get("types");
if (!types) {
HttpUtility::SendJsonError(response, params, 400, "'types' query parameter is required.");
return true;
}
{
ObjectLock olock(types);
for (String type : types) {
FilterUtility::CheckPermission(user, "events/" + type);
}
}
std::set<EventType> eventTypes;
{
ObjectLock olock(types);
for (String type : types) {
auto typeId (l_EventTypes.find(type));
if (typeId != l_EventTypes.end()) {
eventTypes.emplace(typeId->second);
}
}
}
EventsSubscriber subscriber (std::move(eventTypes), HttpUtility::GetLastParameter(params, "filter"), l_ApiQuery);
IoBoundWorkSlot dontLockTheIoThread (yc);
response.result(http::status::ok);
response.set(http::field::content_type, "application/json");
response.StartStreaming(true);
// Send response headers before waiting for the first event.
response.Flush(yc);
auto encoder = response.GetJsonEncoder();
for (;;) {
auto event (subscriber.GetInbox()->Shift(yc));
if (response.IsClientDisconnected()) {
return true;
}
if (event) {
encoder.Encode(event);
response.body() << '\n';
response.Flush(yc);
}
}
}