1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 4 #pragma once 5 6 #include "app.hpp" 7 #include "dbus_utility.hpp" 8 #include "query.hpp" 9 #include "registries/privilege_registry.hpp" 10 11 #include <boost/url/format.hpp> 12 #include <nlohmann/json.hpp> 13 #include <sdbusplus/asio/property.hpp> 14 15 #include <optional> 16 #include <string_view> 17 #include <variant> 18 namespace redfish 19 { 20 21 inline std::string getRoleFromPrivileges(std::string_view priv) 22 { 23 if (priv == "priv-admin") 24 { 25 return "Administrator"; 26 } 27 if (priv == "priv-user") 28 { 29 return "ReadOnly"; 30 } 31 if (priv == "priv-operator") 32 { 33 return "Operator"; 34 } 35 return ""; 36 } 37 38 inline std::optional<nlohmann::json::array_t> 39 getAssignedPrivFromRole(std::string_view role) 40 { 41 nlohmann::json::array_t privArray; 42 if (role == "Administrator") 43 { 44 privArray.emplace_back("Login"); 45 privArray.emplace_back("ConfigureManager"); 46 privArray.emplace_back("ConfigureUsers"); 47 privArray.emplace_back("ConfigureSelf"); 48 privArray.emplace_back("ConfigureComponents"); 49 } 50 else if (role == "Operator") 51 { 52 privArray.emplace_back("Login"); 53 privArray.emplace_back("ConfigureSelf"); 54 privArray.emplace_back("ConfigureComponents"); 55 } 56 else if (role == "ReadOnly") 57 { 58 privArray.emplace_back("Login"); 59 privArray.emplace_back("ConfigureSelf"); 60 } 61 else 62 { 63 return std::nullopt; 64 } 65 return privArray; 66 } 67 68 inline void requestRoutesRoles(App& app) 69 { 70 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Roles/<str>/") 71 .privileges(redfish::privileges::getRole) 72 .methods(boost::beast::http::verb::get)( 73 [&app](const crow::Request& req, 74 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 75 const std::string& roleId) { 76 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 77 { 78 return; 79 } 80 81 std::optional<nlohmann::json::array_t> privArray = 82 getAssignedPrivFromRole(roleId); 83 if (!privArray) 84 { 85 messages::resourceNotFound(asyncResp->res, "Role", roleId); 86 87 return; 88 } 89 90 asyncResp->res.jsonValue["@odata.type"] = "#Role.v1_2_2.Role"; 91 asyncResp->res.jsonValue["Name"] = "User Role"; 92 asyncResp->res.jsonValue["Description"] = roleId + " User Role"; 93 asyncResp->res.jsonValue["OemPrivileges"] = 94 nlohmann::json::array(); 95 asyncResp->res.jsonValue["IsPredefined"] = true; 96 asyncResp->res.jsonValue["Id"] = roleId; 97 asyncResp->res.jsonValue["RoleId"] = roleId; 98 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 99 "/redfish/v1/AccountService/Roles/{}", roleId); 100 asyncResp->res.jsonValue["AssignedPrivileges"] = 101 std::move(*privArray); 102 }); 103 } 104 105 inline void requestRoutesRoleCollection(App& app) 106 { 107 BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Roles/") 108 .privileges(redfish::privileges::getRoleCollection) 109 .methods(boost::beast::http::verb::get)( 110 [&app](const crow::Request& req, 111 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 112 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 113 { 114 return; 115 } 116 117 asyncResp->res.jsonValue["@odata.id"] = 118 "/redfish/v1/AccountService/Roles"; 119 asyncResp->res.jsonValue["@odata.type"] = 120 "#RoleCollection.RoleCollection"; 121 asyncResp->res.jsonValue["Name"] = "Roles Collection"; 122 asyncResp->res.jsonValue["Description"] = "BMC User Roles"; 123 124 dbus::utility::getProperty<std::vector<std::string>>( 125 "xyz.openbmc_project.User.Manager", 126 "/xyz/openbmc_project/user", 127 "xyz.openbmc_project.User.Manager", "AllPrivileges", 128 [asyncResp](const boost::system::error_code& ec, 129 const std::vector<std::string>& privList) { 130 if (ec) 131 { 132 messages::internalError(asyncResp->res); 133 return; 134 } 135 nlohmann::json& memberArray = 136 asyncResp->res.jsonValue["Members"]; 137 memberArray = nlohmann::json::array(); 138 for (const std::string& priv : privList) 139 { 140 std::string role = getRoleFromPrivileges(priv); 141 if (!role.empty()) 142 { 143 nlohmann::json::object_t member; 144 member["@odata.id"] = boost::urls::format( 145 "/redfish/v1/AccountService/Roles/{}", 146 role); 147 memberArray.emplace_back(std::move(member)); 148 } 149 } 150 asyncResp->res.jsonValue["Members@odata.count"] = 151 memberArray.size(); 152 }); 153 }); 154 } 155 156 } // namespace redfish 157