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