1 #pragma once
2
3 #include "event_service_store.hpp"
4 #include "logging.hpp"
5 #include "str_utility.hpp"
6
7 #include <nlohmann/json.hpp>
8
9 #include <algorithm>
10 #include <format>
11 #include <ranges>
12 #include <string>
13 #include <string_view>
14 #include <vector>
15
16 namespace redfish
17 {
18
getRegistryAndMessageKey(const std::string & messageID,std::string & registryName,std::string & messageKey)19 inline void getRegistryAndMessageKey(const std::string& messageID,
20 std::string& registryName,
21 std::string& messageKey)
22 {
23 // Redfish MessageIds are in the form
24 // RegistryName.MajorVersion.MinorVersion.MessageKey, so parse it to find
25 // the right Message
26 std::vector<std::string> fields;
27 fields.reserve(4);
28 bmcweb::split(fields, messageID, '.');
29 if (fields.size() == 4)
30 {
31 registryName = fields[0];
32 messageKey = fields[3];
33 }
34 }
35
eventMatchesFilter(const persistent_data::UserSubscription & userSub,const nlohmann::json::object_t & eventMessage,std::string_view resType)36 inline bool eventMatchesFilter(const persistent_data::UserSubscription& userSub,
37 const nlohmann::json::object_t& eventMessage,
38 std::string_view resType)
39 {
40 // If resourceTypes list is empty, assume all
41 if (!userSub.resourceTypes.empty())
42 {
43 // Search the resourceTypes list for the subscription.
44 auto resourceTypeIndex = std::ranges::find_if(
45 userSub.resourceTypes, [resType](const std::string& rtEntry) {
46 return rtEntry == resType;
47 });
48 if (resourceTypeIndex == userSub.resourceTypes.end())
49 {
50 BMCWEB_LOG_DEBUG("Not subscribed to this resource");
51 return false;
52 }
53 BMCWEB_LOG_DEBUG("ResourceType {} found in the subscribed list",
54 resType);
55 }
56
57 // If registryPrefixes list is empty, don't filter events
58 // send everything.
59 if (!userSub.registryPrefixes.empty())
60 {
61 auto eventJson = eventMessage.find("MessageId");
62 if (eventJson == eventMessage.end())
63 {
64 return false;
65 }
66
67 const std::string* messageId =
68 eventJson->second.get_ptr<const std::string*>();
69 if (messageId == nullptr)
70 {
71 BMCWEB_LOG_ERROR("MessageId wasn't a string???");
72 return false;
73 }
74
75 std::string registry;
76 std::string messageKey;
77 getRegistryAndMessageKey(*messageId, registry, messageKey);
78
79 auto obj = std::ranges::find(userSub.registryPrefixes, registry);
80 if (obj == userSub.registryPrefixes.end())
81 {
82 return false;
83 }
84 }
85
86 if (!userSub.originResources.empty())
87 {
88 auto eventJson = eventMessage.find("OriginOfCondition");
89 if (eventJson == eventMessage.end())
90 {
91 return false;
92 }
93
94 const std::string* originOfCondition =
95 eventJson->second.get_ptr<const std::string*>();
96 if (originOfCondition == nullptr)
97 {
98 BMCWEB_LOG_ERROR("OriginOfCondition wasn't a string???");
99 return false;
100 }
101
102 auto obj =
103 std::ranges::find(userSub.originResources, *originOfCondition);
104
105 if (obj == userSub.originResources.end())
106 {
107 return false;
108 }
109 }
110
111 // If registryMsgIds list is empty, assume all
112 if (!userSub.registryMsgIds.empty())
113 {
114 auto eventJson = eventMessage.find("MessageId");
115 if (eventJson == eventMessage.end())
116 {
117 BMCWEB_LOG_DEBUG("'MessageId' not present");
118 return false;
119 }
120
121 const std::string* messageId =
122 eventJson->second.get_ptr<const std::string*>();
123 if (messageId == nullptr)
124 {
125 BMCWEB_LOG_ERROR("EventType wasn't a string???");
126 return false;
127 }
128
129 std::string registry;
130 std::string messageKey;
131 getRegistryAndMessageKey(*messageId, registry, messageKey);
132
133 BMCWEB_LOG_DEBUG("extracted registry {}", registry);
134 BMCWEB_LOG_DEBUG("extracted message key {}", messageKey);
135
136 auto obj = std::ranges::find(
137 userSub.registryMsgIds, std::format("{}.{}", registry, messageKey));
138 if (obj == userSub.registryMsgIds.end())
139 {
140 BMCWEB_LOG_DEBUG("did not find registry {} in registryMsgIds",
141 registry);
142 BMCWEB_LOG_DEBUG("registryMsgIds has {} entries",
143 userSub.registryMsgIds.size());
144 return false;
145 }
146 }
147
148 return true;
149 }
150
151 } // namespace redfish
152