xref: /openbmc/bmcweb/redfish-core/include/event_matches_filter.hpp (revision d78572018fc2022091ff8b8eb5a7fef2172ba3d6)
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