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