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