Make a few changes to privileges commit

1. Create char* overloads for the things that need it.
2. Fix up a couple errant moves
3. Use the gtest APIs for testing container membership, rather than sort
4. Move the index management to vector rather than map to avoid a lookup
5. Remove errant use of .at()
6. Move privilege comparison into the privilege class, in order to keep
the bitset implementation private.  This removes the requirment on the
forward declaration of PrivilegeProvider, and the use of friend class
7. Remove unimplemented override strcutures.  Feel free to add them
back once implemented
8. Make setSignlePrivilege return a code if the set failed
9. Remove the need for an extra construction of a blank privileges
object for things that require no privileges.

Tested by: updating unit tests with the appropriate APIs.  Relevant
unit tests pass

Change-Id: Ie9cde003b6c865979b4cac086379d0a3473896ce
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
diff --git a/redfish-core/include/node.hpp b/redfish-core/include/node.hpp
index 908d1a6..a33c8e0 100644
--- a/redfish-core/include/node.hpp
+++ b/redfish-core/include/node.hpp
@@ -29,9 +29,7 @@
 class Node {
  public:
   template <typename... Params>
-  Node(CrowApp& app, EntityPrivileges&& entityPrivileges,
-       std::string&& entityUrl, Params... params)
-      : entityPrivileges(std::move(entityPrivileges)) {
+  Node(CrowApp& app, std::string&& entityUrl, Params... params) {
     app.route_dynamic(entityUrl.c_str())
         .methods("GET"_method, "PATCH"_method, "POST"_method,
                  "DELETE"_method)([&](const crow::request& req,
@@ -86,6 +84,8 @@
     }
   }
 
+  OperationMap entityPrivileges;
+
  protected:
   // Node is designed to be an abstract class, so doGet is pure virtual
   virtual void doGet(crow::response& res, const crow::request& req,
@@ -118,8 +118,8 @@
     auto ctx =
         app.template get_context<crow::TokenAuthorization::Middleware>(req);
 
-    if (!entityPrivileges.isMethodAllowedForUser(req.method,
-                                                 ctx.session->username)) {
+    if (!isMethodAllowedForUser(req.method, entityPrivileges,
+                                ctx.session->username)) {
       res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED);
       res.end();
       return;
@@ -148,8 +148,6 @@
     }
     return;
   }
-
-  EntityPrivileges entityPrivileges;
 };
 
 }  // namespace redfish
diff --git a/redfish-core/include/privileges.hpp b/redfish-core/include/privileges.hpp
index 2cc52b5..4014d61 100644
--- a/redfish-core/include/privileges.hpp
+++ b/redfish-core/include/privileges.hpp
@@ -19,13 +19,10 @@
 #include <cstdint>
 #include "crow.h"
 #include <boost/container/flat_map.hpp>
-#include <boost/container/flat_set.hpp>
 #include <boost/optional.hpp>
 
 namespace redfish {
 
-class PrivilegeProvider;
-
 enum class PrivilegeType { BASE, OEM };
 
 /** @brief Max number of privileges per type  */
@@ -34,16 +31,12 @@
 using privilegeBitset = std::bitset<MAX_PRIVILEGE_COUNT>;
 
 /** @brief Number of mappings must be <= MAX_PRIVILEGE_COUNT */
-static const boost::container::flat_map<std::string, size_t>
-    basePrivNameToIndexMap = {{"Login", 0},
-                              {"ConfigureManager", 1},
-                              {"ConfigureComponents", 2},
-                              {"ConfigureSelf", 3},
-                              {"ConfigureUsers", 4}};
+static const std::vector<std::string> privilegeNames{
+    "Login", "ConfigureManager", "ConfigureComponents", "ConfigureSelf",
+    "ConfigureUsers"};
 
 /** @brief Number of mappings must be <= MAX_PRIVILEGE_COUNT */
-static const boost::container::flat_map<std::string, size_t>
-    oemPrivNameToIndexMap = {};
+static const std::vector<std::string> oemPrivilegeNames{};
 
 /**
  * @brief Redfish privileges
@@ -75,29 +68,16 @@
    * @param[in] privilegeList  List of privileges to be activated
    *
    */
-  Privileges(std::initializer_list<std::string> privilegeList) {
-    for (const auto& privilege : privilegeList) {
-      setSinglePrivilege(privilege);
+  Privileges(std::initializer_list<const char*> privilegeList) {
+    for (const char* privilege : privilegeList) {
+      if (!setSinglePrivilege(privilege)) {
+        CROW_LOG_CRITICAL << "Unable to set privilege " << privilege
+                          << "in constructor";
+      }
     }
   }
 
   /**
-   * @brief Retrieves the base privileges bitset
-   *
-   * @return          Bitset representation of base Redfish privileges
-   *
-   */
-  privilegeBitset getBasePrivilegeBitset() const { return basePrivilegeBitset; }
-
-  /**
-   * @brief Retrieves the OEM privileges bitset
-   *
-   * @return          Bitset representation of OEM Redfish privileges
-   *
-   */
-  privilegeBitset getOEMPrivilegeBitset() const { return oemPrivilegeBitset; }
-
-  /**
    * @brief Sets given privilege in the bitset
    *
    * @param[in] privilege  Privilege to be set
@@ -105,17 +85,31 @@
    * @return               None
    *
    */
-  void setSinglePrivilege(const std::string& privilege) {
-    auto index = getBitsetIndexForPrivilege(privilege, PrivilegeType::BASE);
-    if (index) {
-      basePrivilegeBitset.set(*index);
-      return;
+  bool setSinglePrivilege(const char* privilege) {
+    int32_t index = getBitsetIndexForPrivilege(privilege, PrivilegeType::BASE);
+    if (index >= 0) {
+      basePrivilegeBitset.set(index);
+      return true;
     }
 
     index = getBitsetIndexForPrivilege(privilege, PrivilegeType::OEM);
-    if (index) {
-      oemPrivilegeBitset.set(*index);
+    if (index >= 0) {
+      oemPrivilegeBitset.set(index);
+      return true;
     }
+    return false;
+  }
+
+  /**
+   * @brief Sets given privilege in the bitset
+   *
+   * @param[in] privilege  Privilege to be set
+   *
+   * @return               None
+   *
+   */
+  bool setSinglePrivilege(const std::string& privilege) {
+    return setSinglePrivilege(privilege.c_str());
   }
 
   /**
@@ -123,201 +117,125 @@
    *
    * @param[in] type    Base or OEM
    *
-   * @return            Vector of active privileges
+   * @return            Vector of active privileges.  Pointers are valid until
+   * the privilege structure is modified
    *
    */
-  std::vector<std::string> getActivePrivilegeNames(
+  std::vector<const std::string*> getActivePrivilegeNames(
       const PrivilegeType type) const {
-    std::vector<std::string> activePrivileges;
+    std::vector<const std::string*> activePrivileges;
 
     if (type == PrivilegeType::BASE) {
-      for (const auto& pair : basePrivNameToIndexMap) {
-        if (basePrivilegeBitset.test(pair.second)) {
-          activePrivileges.emplace_back(pair.first);
+      for (std::size_t index = 0; index < privilegeNames.size(); index++) {
+        if (basePrivilegeBitset.test(index)) {
+          activePrivileges.emplace_back(&privilegeNames[index]);
         }
       }
     } else {
-      for (const auto& pair : oemPrivNameToIndexMap) {
-        if (oemPrivilegeBitset.test(pair.second)) {
-          activePrivileges.emplace_back(pair.first);
+      for (std::size_t index = 0; index < oemPrivilegeNames.size(); index++) {
+        {
+          if (oemPrivilegeBitset.test(index)) {
+            activePrivileges.emplace_back(&oemPrivilegeNames[index]);
+          }
         }
       }
     }
-
     return activePrivileges;
   }
 
+  /**
+   * @brief Determines if this Privilege set is a superset of the given
+   * privilege set
+   *
+   * @param[in] privilege  Privilege to be checked
+   *
+   * @return               None
+   *
+   */
+  bool isSupersetOf(const Privileges& p) const {
+    bool has_base =
+        (basePrivilegeBitset & p.basePrivilegeBitset) == p.basePrivilegeBitset;
+
+    bool has_oem =
+        (oemPrivilegeBitset & p.oemPrivilegeBitset) == p.oemPrivilegeBitset;
+    return has_base & has_oem;
+  }
+
  private:
-  boost::optional<size_t> getBitsetIndexForPrivilege(
-      const std::string& privilege, const PrivilegeType type) const {
+  int32_t getBitsetIndexForPrivilege(const char* privilege,
+                                     const PrivilegeType type) const {
     if (type == PrivilegeType::BASE) {
-      const auto pair = basePrivNameToIndexMap.find(privilege);
-      if (pair != basePrivNameToIndexMap.end()) {
-        return pair->second;
+      for (std::size_t index = 0; index < privilegeNames.size(); index++) {
+        if (privilege == privilegeNames[index]) {
+          return index;
+        }
       }
     } else {
-      const auto pair = oemPrivNameToIndexMap.find(privilege);
-      if (pair != oemPrivNameToIndexMap.end()) {
-        return pair->second;
+      for (std::size_t index = 0; index < oemPrivilegeNames.size(); index++) {
+        if (privilege == oemPrivilegeNames[index]) {
+          return index;
+        }
       }
     }
 
-    return boost::none;
+    return -1;
   }
 
-  privilegeBitset basePrivilegeBitset;
-  privilegeBitset oemPrivilegeBitset;
-
-  friend class PrivilegeProvider;
+  privilegeBitset basePrivilegeBitset = 0;
+  privilegeBitset oemPrivilegeBitset = 0;
 };
 
 using OperationMap =
     boost::container::flat_map<crow::HTTPMethod, std::vector<Privileges>>;
 
 /**
- * @brief  Class used to store overrides privileges for Redfish
- *         entities
+ * @brief Checks if given privileges allow to call an HTTP method
+ *
+ * @param[in] method       HTTP method
+ * @param[in] user         Privileges
+ *
+ * @return                 True if method allowed, false otherwise
  *
  */
-class EntityPrivilegesOverride {
- protected:
-  /**
-   * @brief Constructs overrides object for given targets
-   *
-   * @param[in] operationMap Operation map to be applied for targets
-   * @param[in] targets      List of targets whOperation map to be applied for
-   * targets
-   *
-   */
-  EntityPrivilegesOverride(OperationMap&& operationMap,
-                           std::initializer_list<std::string>&& targets)
-      : operationMap(std::move(operationMap)), targets(std::move(targets)) {}
-
-  const OperationMap operationMap;
-  const boost::container::flat_set<std::string> targets;
-};
-
-class PropertyOverride : public EntityPrivilegesOverride {
- public:
-  PropertyOverride(OperationMap&& operationMap,
-                   std::initializer_list<std::string>&& targets)
-      : EntityPrivilegesOverride(std::move(operationMap), std::move(targets)) {}
-};
-
-class SubordinateOverride : public EntityPrivilegesOverride {
- public:
-  SubordinateOverride(OperationMap&& operationMap,
-                      std::initializer_list<std::string>&& targets)
-      : EntityPrivilegesOverride(std::move(operationMap), std::move(targets)) {}
-};
-
-class ResourceURIOverride : public EntityPrivilegesOverride {
- public:
-  ResourceURIOverride(OperationMap&& operationMap,
-                      std::initializer_list<std::string>&& targets)
-      : EntityPrivilegesOverride(std::move(operationMap), std::move(targets)) {}
-};
-
-/**
- * @brief  Class used to store privileges for Redfish entities
- *
- */
-class EntityPrivileges {
- public:
-  /**
-   * @brief Constructor for default case with no overrides
-   *
-   * @param[in] operationMap Operation map for the entity
-   *
-   */
-  EntityPrivileges(OperationMap&& operationMap)
-      : operationMap(std::move(operationMap)) {}
-
-  /**
-   * @brief Constructors for overrides
-   *
-   * @param[in] operationMap         Default operation map for the entity
-   * @param[in] propertyOverrides    Vector of property overrides
-   * @param[in] subordinateOverrides Vector of subordinate overrides
-   * @param[in] resourceURIOverrides Vector of resource URI overrides
-   *
-   */
-  EntityPrivileges(OperationMap&& operationMap,
-                   std::vector<PropertyOverride>&& propertyOverrides,
-                   std::vector<SubordinateOverride>&& subordinateOverrides,
-                   std::vector<ResourceURIOverride>&& resourceURIOverrides)
-      : operationMap(std::move(operationMap)),
-        propertyOverrides(std::move(propertyOverrides)),
-        subordinateOverrides(std::move(subordinateOverrides)),
-        resourceURIOverrides(std::move(resourceURIOverrides)) {}
-
-  /**
-   * @brief Checks if a user is allowed to call an HTTP method
-   *
-   * @param[in] method       HTTP method
-   * @param[in] user         Username
-   *
-   * @return                 True if method allowed, false otherwise
-   *
-   */
-  bool isMethodAllowedForUser(const crow::HTTPMethod method,
-                              const std::string& user) const {
-    // TODO: load user privileges from configuration as soon as its available
-    // now we are granting all privileges to everyone.
-    auto userPrivileges =
-        Privileges{"Login", "ConfigureManager", "ConfigureSelf",
-                   "ConfigureUsers", "ConfigureComponents"};
-
-    return isMethodAllowedWithPrivileges(method, userPrivileges);
-  }
-
-  /**
-   * @brief Checks if given privileges allow to call an HTTP method
-   *
-   * @param[in] method       HTTP method
-   * @param[in] user         Privileges
-   *
-   * @return                 True if method allowed, false otherwise
-   *
-   */
-  bool isMethodAllowedWithPrivileges(const crow::HTTPMethod method,
-                                     const Privileges& userPrivileges) const {
-    if (operationMap.find(method) == operationMap.end()) {
-      return false;
-    }
-
-    for (auto& requiredPrivileges : operationMap.at(method)) {
-      // Check if user has required base privileges
-      if (!verifyPrivileges(userPrivileges.getBasePrivilegeBitset(),
-                            requiredPrivileges.getBasePrivilegeBitset())) {
-        continue;
-      }
-
-      // Check if user has required OEM privileges
-      if (!verifyPrivileges(userPrivileges.getOEMPrivilegeBitset(),
-                            requiredPrivileges.getOEMPrivilegeBitset())) {
-        continue;
-      }
-
-      return true;
-    }
+inline bool isMethodAllowedWithPrivileges(const crow::HTTPMethod method,
+                                          const OperationMap& operationMap,
+                                          const Privileges& userPrivileges) {
+  const auto& it = operationMap.find(method);
+  if (it == operationMap.end()) {
     return false;
   }
 
- private:
-  bool verifyPrivileges(const privilegeBitset userPrivilegeBitset,
-                        const privilegeBitset requiredPrivilegeBitset) const {
-    return (userPrivilegeBitset & requiredPrivilegeBitset) ==
-           requiredPrivilegeBitset;
+  // If there are no privileges assigned, assume no privileges required
+  if (it->second.empty()) {
+    return true;
   }
 
-  OperationMap operationMap;
+  for (auto& requiredPrivileges : it->second) {
+    if (userPrivileges.isSupersetOf(requiredPrivileges)) {
+      return true;
+    }
+  }
+  return false;
+}
 
-  // Overrides are not implemented at the moment.
-  std::vector<PropertyOverride> propertyOverrides;
-  std::vector<SubordinateOverride> subordinateOverrides;
-  std::vector<ResourceURIOverride> resourceURIOverrides;
-};
+/**
+ * @brief Checks if a user is allowed to call an HTTP method
+ *
+ * @param[in] method       HTTP method
+ * @param[in] user         Username
+ *
+ * @return                 True if method allowed, false otherwise
+ *
+ */
+inline bool isMethodAllowedForUser(const crow::HTTPMethod method,
+                                   const OperationMap& operationMap,
+                                   const std::string& user) {
+  // TODO: load user privileges from configuration as soon as its available
+  // now we are granting all privileges to everyone.
+  Privileges userPrivileges{"Login", "ConfigureManager", "ConfigureSelf",
+                            "ConfigureUsers", "ConfigureComponents"};
+
+  return isMethodAllowedWithPrivileges(method, operationMap, userPrivileges);
+}
 
 }  // namespace redfish
-
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index dafa605..b58ff11 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -19,19 +19,11 @@
 
 namespace redfish {
 
-static OperationMap accountServiceOpMap = {
-    {crow::HTTPMethod::GET, {{"ConfigureUsers"}, {"ConfigureManager"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureUsers"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureUsers"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureUsers"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureUsers"}}}};
-
 class AccountService : public Node {
  public:
   template <typename CrowApp>
   AccountService(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(accountServiceOpMap)),
+      : Node(app,
              "/redfish/v1/AccountService/") {
     Node::json["@odata.id"] = "/redfish/v1/AccountService";
     Node::json["@odata.type"] = "#AccountService.v1_1_0.AccountService";
@@ -48,6 +40,14 @@
     Node::json["MaxPasswordLength"] = 20;
     Node::json["Accounts"]["@odata.id"] = "/redfish/v1/AccountService/Accounts";
     Node::json["Roles"]["@odata.id"] = "/redfish/v1/AccountService/Roles";
+
+    entityPrivileges = {
+        {crow::HTTPMethod::GET, {{"ConfigureUsers"}, {"ConfigureManager"}}},
+        {crow::HTTPMethod::HEAD, {{"Login"}}},
+        {crow::HTTPMethod::PATCH, {{"ConfigureUsers"}}},
+        {crow::HTTPMethod::PUT, {{"ConfigureUsers"}}},
+        {crow::HTTPMethod::DELETE, {{"ConfigureUsers"}}},
+        {crow::HTTPMethod::POST, {{"ConfigureUsers"}}}};
   }
 
  private:
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 0a56da7..ad042cb 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -19,27 +19,9 @@
 
 namespace redfish {
 
-static OperationMap managerOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
-
-static OperationMap managerCollectionOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
-
 class Manager : public Node {
  public:
-  Manager(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(managerOpMap)),
-             "/redfish/v1/Managers/openbmc/") {
+  Manager(CrowApp& app) : Node(app, "/redfish/v1/Managers/openbmc/") {
     Node::json["@odata.id"] = "/redfish/v1/Managers/openbmc";
     Node::json["@odata.type"] = "#Manager.v1_3_0.Manager";
     Node::json["@odata.context"] = "/redfish/v1/$metadata#Manager.Manager";
@@ -55,6 +37,13 @@
             .system_uuid;
     Node::json["Model"] = "OpenBmc";               // TODO(ed), get model
     Node::json["FirmwareVersion"] = "1234456789";  // TODO(ed), get fwversion
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
   }
 
  private:
@@ -84,9 +73,7 @@
 class ManagerCollection : public Node {
  public:
   ManagerCollection(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(managerCollectionOpMap)),
-             "/redfish/v1/Managers/"),
-        memberManager(app) {
+      : Node(app, "/redfish/v1/Managers/"), memberManager(app) {
     Node::json["@odata.id"] = "/redfish/v1/Managers";
     Node::json["@odata.type"] = "#ManagerCollection.ManagerCollection";
     Node::json["@odata.context"] =
@@ -94,6 +81,13 @@
     Node::json["Name"] = "Manager Collection";
     Node::json["Members@odata.count"] = 1;
     Node::json["Members"] = {{"@odata.id", "/redfish/v1/Managers/openbmc"}};
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
   }
 
  private:
diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp
index 2b45b40..1410122 100644
--- a/redfish-core/lib/network_protocol.hpp
+++ b/redfish-core/lib/network_protocol.hpp
@@ -19,18 +19,10 @@
 
 namespace redfish {
 
-static OperationMap managerNetworkProtocolOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
-
 class NetworkProtocol : public Node {
  public:
   NetworkProtocol(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(managerNetworkProtocolOpMap)),
+      : Node(app,
              "/redfish/v1/Managers/openbmc/NetworkProtocol") {
     Node::json["@odata.type"] =
         "#ManagerNetworkProtocol.v1_1_0.ManagerNetworkProtocol";
@@ -43,6 +35,13 @@
     Node::json["Status"]["Health"] = "OK";
     Node::json["Status"]["HealthRollup"] = "OK";
     Node::json["Status"]["State"] = "Enabled";
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
   }
 
  private:
diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp
index 4225cc1..326d5e0 100644
--- a/redfish-core/lib/redfish_sessions.hpp
+++ b/redfish-core/lib/redfish_sessions.hpp
@@ -20,41 +20,23 @@
 
 namespace redfish {
 
-static OperationMap sessionOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
-
-static OperationMap sessionCollectionOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{}}}};
-
-static OperationMap sessionServiceOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
-
 class SessionCollection;
 
 class Sessions : public Node {
  public:
   Sessions(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(sessionOpMap)),
-             "/redfish/v1/SessionService/Sessions/<str>", std::string()) {
+      : Node(app, "/redfish/v1/SessionService/Sessions/<str>", std::string()) {
     Node::json["@odata.type"] = "#Session.v1_0_2.Session";
     Node::json["@odata.context"] = "/redfish/v1/$metadata#Session.Session";
     Node::json["Name"] = "User Session";
     Node::json["Description"] = "Manager User Session";
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
   }
 
  private:
@@ -112,9 +94,7 @@
 class SessionCollection : public Node {
  public:
   SessionCollection(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(sessionCollectionOpMap)),
-             "/redfish/v1/SessionService/Sessions/"),
-        memberSession(app) {
+      : Node(app, "/redfish/v1/SessionService/Sessions/"), memberSession(app) {
     Node::json["@odata.type"] = "#SessionCollection.SessionCollection";
     Node::json["@odata.id"] = "/redfish/v1/SessionService/Sessions/";
     Node::json["@odata.context"] =
@@ -123,6 +103,13 @@
     Node::json["Description"] = "Session Collection";
     Node::json["Members@odata.count"] = 0;
     Node::json["Members"] = nlohmann::json::array();
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {}}};
   }
 
  private:
@@ -243,9 +230,7 @@
 
 class SessionService : public Node {
  public:
-  SessionService(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(sessionServiceOpMap)),
-             "/redfish/v1/SessionService/") {
+  SessionService(CrowApp& app) : Node(app, "/redfish/v1/SessionService/") {
     Node::json["@odata.type"] = "#SessionService.v1_0_2.SessionService";
     Node::json["@odata.id"] = "/redfish/v1/SessionService/";
     Node::json["@odata.context"] =
@@ -258,6 +243,13 @@
     Node::json["Status"]["Health"] = "OK";
     Node::json["Status"]["HealthRollup"] = "OK";
     Node::json["ServiceEnabled"] = true;
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
   }
 
  private:
diff --git a/redfish-core/lib/roles.hpp b/redfish-core/lib/roles.hpp
index f1a1c61..fc804c2 100644
--- a/redfish-core/lib/roles.hpp
+++ b/redfish-core/lib/roles.hpp
@@ -19,27 +19,10 @@
 
 namespace redfish {
 
-static OperationMap roleOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
-
-static OperationMap roleCollectionOpMap = {
-    {crow::HTTPMethod::GET, {{"Login"}}},
-    {crow::HTTPMethod::HEAD, {{"Login"}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
-
 class Roles : public Node {
  public:
   Roles(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(roleOpMap)),
-             "/redfish/v1/AccountService/Roles/Administrator/") {
+      : Node(app, "/redfish/v1/AccountService/Roles/Administrator/") {
     Node::json["@odata.id"] = "/redfish/v1/AccountService/Roles/Administrator";
     Node::json["@odata.type"] = "#Role.v1_0_2.Role";
     Node::json["@odata.context"] = "/redfish/v1/$metadata#Role.Role";
@@ -51,6 +34,12 @@
                                         "ConfigureUsers", "ConfigureSelf",
                                         "ConfigureComponents"};
     Node::json["OemPrivileges"] = nlohmann::json::array();
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
   }
 
  private:
@@ -64,8 +53,7 @@
 class RoleCollection : public Node {
  public:
   RoleCollection(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(roleCollectionOpMap)),
-             "/redfish/v1/AccountService/Roles/") {
+      : Node(app, "/redfish/v1/AccountService/Roles/") {
     Node::json["@odata.id"] = "/redfish/v1/AccountService/Roles";
     Node::json["@odata.type"] = "#RoleCollection.RoleCollection";
     Node::json["@odata.context"] =
@@ -75,6 +63,13 @@
     Node::json["Members@odata.count"] = 1;
     Node::json["Members"] = {
         {"@odata.id", "/redfish/v1/AccountService/Roles/Administrator"}};
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {{"Login"}}},
+                        {crow::HTTPMethod::HEAD, {{"Login"}}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureManager"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureManager"}}}};
   }
 
  private:
diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp
index 0afc0a2..c57d3e7 100644
--- a/redfish-core/lib/service_root.hpp
+++ b/redfish-core/lib/service_root.hpp
@@ -19,19 +19,9 @@
 
 namespace redfish {
 
-static OperationMap serviceRootOpMap = {
-    {crow::HTTPMethod::GET, {{}}},
-    {crow::HTTPMethod::HEAD, {{}}},
-    {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}},
-    {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}},
-    {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}},
-    {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}};
-
 class ServiceRoot : public Node {
  public:
-  ServiceRoot(CrowApp& app)
-      : Node(app, EntityPrivileges(std::move(serviceRootOpMap)),
-             "/redfish/v1/") {
+  ServiceRoot(CrowApp& app) : Node(app, "/redfish/v1/") {
     Node::json["@odata.type"] = "#ServiceRoot.v1_1_1.ServiceRoot";
     Node::json["@odata.id"] = "/redfish/v1/";
     Node::json["@odata.context"] =
@@ -44,6 +34,13 @@
     Node::json["UUID"] =
         app.template get_middleware<crow::PersistentData::Middleware>()
             .system_uuid;
+
+    entityPrivileges = {{crow::HTTPMethod::GET, {}},
+                        {crow::HTTPMethod::HEAD, {}},
+                        {crow::HTTPMethod::PATCH, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::PUT, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::DELETE, {{"ConfigureComponents"}}},
+                        {crow::HTTPMethod::POST, {{"ConfigureComponents"}}}};
   }
 
  private:
diff --git a/redfish-core/ut/privileges_test.cpp b/redfish-core/ut/privileges_test.cpp
index 193fd7d..36e02c6 100644
--- a/redfish-core/ut/privileges_test.cpp
+++ b/redfish-core/ut/privileges_test.cpp
@@ -7,134 +7,108 @@
 using namespace redfish;
 
 TEST(PrivilegeTest, PrivilegeConstructor) {
-  Privileges privileges = {"Login", "ConfigureManager"};
+  Privileges privileges{"Login", "ConfigureManager"};
 
-  auto activePrivileges =
-      privileges.getActivePrivilegeNames(PrivilegeType::BASE);
-  std::vector<std::string> expectedPrivileges{"Login", "ConfigureManager"};
-
-  std::sort(expectedPrivileges.begin(), expectedPrivileges.end());
-  std::sort(activePrivileges.begin(), activePrivileges.end());
-
-  EXPECT_EQ(expectedPrivileges, activePrivileges);
+  EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+              ::testing::UnorderedElementsAre(
+                  ::testing::Pointee(&"Login"[0]),
+                  ::testing::Pointee(&"ConfigureManager"[0])));
 }
 
 TEST(PrivilegeTest, PrivilegeCheckForNoPrivilegesRequired) {
-  auto userPrivileges = Privileges{"Login"};
-  OperationMap operationMap = {{crow::HTTPMethod::GET, {{}}}};
-  auto entityPrivileges = EntityPrivileges(std::move(operationMap));
+  Privileges userPrivileges{"Login"};
 
-  EXPECT_TRUE(entityPrivileges.isMethodAllowedWithPrivileges(
-      crow::HTTPMethod::GET, userPrivileges));
+  OperationMap entityPrivileges{{crow::HTTPMethod::GET, {{"Login"}}}};
+
+  EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET,
+                                            entityPrivileges, userPrivileges));
 }
 
 TEST(PrivilegeTest, PrivilegeCheckForSingleCaseSuccess) {
   auto userPrivileges = Privileges{"Login"};
-  OperationMap operationMap = {{crow::HTTPMethod::GET, {{"Login"}}}};
-  auto entityPrivileges = EntityPrivileges(std::move(operationMap));
+  OperationMap entityPrivileges{{crow::HTTPMethod::GET, {}}};
 
-  EXPECT_TRUE(entityPrivileges.isMethodAllowedWithPrivileges(
-      crow::HTTPMethod::GET, userPrivileges));
+  EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET,
+                                            entityPrivileges, userPrivileges));
 }
 
 TEST(PrivilegeTest, PrivilegeCheckForSingleCaseFailure) {
   auto userPrivileges = Privileges{"Login"};
-  OperationMap operationMap = {{crow::HTTPMethod::GET, {{"ConfigureManager"}}}};
-  auto entityPrivileges = EntityPrivileges(std::move(operationMap));
+  OperationMap entityPrivileges{
+      {crow::HTTPMethod::GET, {{"ConfigureManager"}}}};
 
-  EXPECT_FALSE(entityPrivileges.isMethodAllowedWithPrivileges(
-      crow::HTTPMethod::GET, userPrivileges));
+  EXPECT_FALSE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET,
+                                             entityPrivileges, userPrivileges));
 }
 
 TEST(PrivilegeTest, PrivilegeCheckForANDCaseSuccess) {
   auto userPrivileges =
       Privileges{"Login", "ConfigureManager", "ConfigureSelf"};
-  OperationMap operationMap = {
+  OperationMap entityPrivileges{
       {crow::HTTPMethod::GET,
        {{"Login", "ConfigureManager", "ConfigureSelf"}}}};
-  auto entityPrivileges = EntityPrivileges(std::move(operationMap));
 
-  EXPECT_TRUE(entityPrivileges.isMethodAllowedWithPrivileges(
-      crow::HTTPMethod::GET, userPrivileges));
+  EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET,
+                                            entityPrivileges, userPrivileges));
 }
 
 TEST(PrivilegeTest, PrivilegeCheckForANDCaseFailure) {
   auto userPrivileges = Privileges{"Login", "ConfigureManager"};
-  OperationMap operationMap = {
+  OperationMap entityPrivileges{
       {crow::HTTPMethod::GET,
        {{"Login", "ConfigureManager", "ConfigureSelf"}}}};
-  auto entityPrivileges = EntityPrivileges(std::move(operationMap));
 
-  EXPECT_FALSE(entityPrivileges.isMethodAllowedWithPrivileges(
-      crow::HTTPMethod::GET, userPrivileges));
+  EXPECT_FALSE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET,
+                                             entityPrivileges, userPrivileges));
 }
 
 TEST(PrivilegeTest, PrivilegeCheckForORCaseSuccess) {
   auto userPrivileges = Privileges{"ConfigureManager"};
-  OperationMap operationMap = {
+  OperationMap entityPrivileges{
       {crow::HTTPMethod::GET, {{"Login"}, {"ConfigureManager"}}}};
-  auto entityPrivileges = EntityPrivileges(std::move(operationMap));
 
-  EXPECT_TRUE(entityPrivileges.isMethodAllowedWithPrivileges(
-      crow::HTTPMethod::GET, userPrivileges));
+  EXPECT_TRUE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET,
+                                            entityPrivileges, userPrivileges));
 }
 
 TEST(PrivilegeTest, PrivilegeCheckForORCaseFailure) {
   auto userPrivileges = Privileges{"ConfigureComponents"};
-  OperationMap operationMap = {
-      {crow::HTTPMethod::GET, {{"Login"}, {"ConfigureManager"}}}};
-  auto entityPrivileges = EntityPrivileges(std::move(operationMap));
+  OperationMap entityPrivileges = OperationMap(
+      {{crow::HTTPMethod::GET, {{"Login"}, {"ConfigureManager"}}}});
 
-  EXPECT_FALSE(entityPrivileges.isMethodAllowedWithPrivileges(
-      crow::HTTPMethod::GET, userPrivileges));
+  EXPECT_FALSE(isMethodAllowedWithPrivileges(crow::HTTPMethod::GET,
+                                             entityPrivileges, userPrivileges));
 }
 
 TEST(PrivilegeTest, DefaultPrivilegeBitsetsAreEmpty) {
   Privileges privileges;
-  EXPECT_TRUE(privileges.getBasePrivilegeBitset() == 0);
-  EXPECT_TRUE(privileges.getOEMPrivilegeBitset() == 0);
-}
 
-TEST(PrivilegeTest, UniqueBitsAssignedForAllPrivilegeNames) {
-  Privileges privileges;
-  std::vector<std::string> expectedPrivileges{
-      "Login", "ConfigureManager", "ConfigureUsers", "ConfigureComponents",
-      "ConfigureSelf"};
+  EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+              ::testing::IsEmpty());
 
-  for (const auto& privilege : expectedPrivileges) {
-    privileges.setSinglePrivilege(privilege);
-  }
-
-  EXPECT_EQ(privileges.getBasePrivilegeBitset().count(),
-            expectedPrivileges.size());
+  EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::OEM),
+              ::testing::IsEmpty());
 }
 
 TEST(PrivilegeTest, GetActivePrivilegeNames) {
   Privileges privileges;
 
-  EXPECT_EQ(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
-            std::vector<std::string>());
+  EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+              ::testing::IsEmpty());
 
-  std::vector<std::string> expectedPrivileges{
+  std::array<const char*, 5> expectedPrivileges{
       "Login", "ConfigureManager", "ConfigureUsers", "ConfigureComponents",
       "ConfigureSelf"};
 
   for (const auto& privilege : expectedPrivileges) {
-    privileges.setSinglePrivilege(privilege);
+    EXPECT_TRUE(privileges.setSinglePrivilege(privilege));
   }
 
-  std::vector<std::string> activePrivileges =
-      privileges.getActivePrivilegeNames(PrivilegeType::BASE);
-
-  std::sort(expectedPrivileges.begin(), expectedPrivileges.end());
-  std::sort(activePrivileges.begin(), activePrivileges.end());
-
-  EXPECT_EQ(activePrivileges, expectedPrivileges);
-}
-
-TEST(PrivilegeTest, PropertyOverrideConstructor) {
-  OperationMap operationMap = {
-      {crow::HTTPMethod::GET, {{"Login"}, {"ConfigureManager"}}}};
-  PropertyOverride propertyOverride(std::move(operationMap),
-                                    {"Password", "Id"});
+  EXPECT_THAT(privileges.getActivePrivilegeNames(PrivilegeType::BASE),
+              ::testing::UnorderedElementsAre(
+                  ::testing::Pointee(expectedPrivileges[0]),
+                  ::testing::Pointee(expectedPrivileges[1]),
+                  ::testing::Pointee(expectedPrivileges[2]),
+                  ::testing::Pointee(expectedPrivileges[3]),
+                  ::testing::Pointee(expectedPrivileges[4])));
 }