blob: b4fe0883e9af02f700a0750e8ce5d4497e43099b [file] [log] [blame]
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +01001/*
Ed Tanous6be832e2024-09-10 11:44:48 -07002Copyright (c) 2018 Intel Corporation
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +010015*/
16#pragma once
Borawski.Lukasz43a095a2018-02-19 15:39:01 +010017
Paul Fertserce22f602024-06-03 20:53:16 +000018#include "account_service.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080019#include "app.hpp"
Paul Fertser29aab242024-06-12 19:28:47 +000020#include "cookies.hpp"
Kowalski, Kamilf4c4dcf2018-01-29 14:55:35 +010021#include "error_messages.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080022#include "http/utility.hpp"
Ed Tanous52cc1122020-07-18 13:51:21 -070023#include "persistent_data.hpp"
Ed Tanous3ccb3ad2023-01-13 17:40:03 -080024#include "query.hpp"
25#include "registries/privilege_registry.hpp"
26#include "utils/json_utils.hpp"
John Edward Broadbent7e860f12021-04-08 15:57:16 -070027
Ed Tanousef4c65b2023-04-24 15:28:50 -070028#include <boost/url/format.hpp>
29
Ed Tanous89cda632024-04-16 08:45:54 -070030#include <string>
31#include <vector>
32
Ed Tanous1abe55e2018-09-05 08:30:59 -070033namespace redfish
34{
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +010035
Ed Tanous4f48d5f2021-06-21 08:27:45 -070036inline void fillSessionObject(crow::Response& res,
37 const persistent_data::UserSession& session)
Ed Tanous1abe55e2018-09-05 08:30:59 -070038{
Ed Tanousfaa34cc2021-06-03 13:27:02 -070039 res.jsonValue["Id"] = session.uniqueId;
40 res.jsonValue["UserName"] = session.username;
Paul Fertserce22f602024-06-03 20:53:16 +000041 nlohmann::json::array_t roles;
42 roles.emplace_back(redfish::getRoleIdFromPrivilege(session.userRole));
43 res.jsonValue["Roles"] = std::move(roles);
Ed Tanousef4c65b2023-04-24 15:28:50 -070044 res.jsonValue["@odata.id"] = boost::urls::format(
45 "/redfish/v1/SessionService/Sessions/{}", session.uniqueId);
Paul Fertserce22f602024-06-03 20:53:16 +000046 res.jsonValue["@odata.type"] = "#Session.v1_7_0.Session";
Ed Tanousfaa34cc2021-06-03 13:27:02 -070047 res.jsonValue["Name"] = "User Session";
48 res.jsonValue["Description"] = "Manager User Session";
49 res.jsonValue["ClientOriginIPAddress"] = session.clientIp;
Ed Tanousbb759e32022-08-02 17:07:54 -070050 if (session.clientId)
51 {
52 res.jsonValue["Context"] = *session.clientId;
53 }
Ed Tanousfaa34cc2021-06-03 13:27:02 -070054}
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +010055
Ed Tanous724340d2022-03-14 09:10:07 -070056inline void
Ed Tanousa1e08712022-07-07 16:10:39 -070057 handleSessionHead(crow::App& app, const crow::Request& req,
58 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
59 const std::string& /*sessionId*/)
Ed Tanous724340d2022-03-14 09:10:07 -070060{
Carson Labrado3ba00072022-06-06 19:40:56 +000061 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -070062 {
63 return;
64 }
Ed Tanousa1e08712022-07-07 16:10:39 -070065 asyncResp->res.addHeader(
66 boost::beast::http::field::link,
67 "</redfish/v1/JsonSchemas/Session/Session.json>; rel=describedby");
68}
69
70inline void
71 handleSessionGet(crow::App& app, const crow::Request& req,
72 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
73 const std::string& sessionId)
74{
Ed Tanous65ffbcb2023-05-16 08:54:11 -070075 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
76 {
77 return;
78 }
79 asyncResp->res.addHeader(
80 boost::beast::http::field::link,
81 "</redfish/v1/JsonSchemas/Session/Session.json>; rel=describedby");
Ed Tanousa1e08712022-07-07 16:10:39 -070082
Ed Tanous724340d2022-03-14 09:10:07 -070083 // Note that control also reaches here via doPost and doDelete.
84 auto session =
85 persistent_data::SessionStore::getInstance().getSessionByUid(sessionId);
86
87 if (session == nullptr)
88 {
89 messages::resourceNotFound(asyncResp->res, "Session", sessionId);
90 return;
91 }
92
93 fillSessionObject(asyncResp->res, *session);
94}
95
96inline void
Ed Tanous45ca1b82022-03-25 13:07:27 -070097 handleSessionDelete(crow::App& app, const crow::Request& req,
Ed Tanous724340d2022-03-14 09:10:07 -070098 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
99 const std::string& sessionId)
100{
Carson Labrado3ba00072022-06-06 19:40:56 +0000101 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -0700102 {
103 return;
104 }
Ed Tanous724340d2022-03-14 09:10:07 -0700105 auto session =
106 persistent_data::SessionStore::getInstance().getSessionByUid(sessionId);
107
108 if (session == nullptr)
109 {
110 messages::resourceNotFound(asyncResp->res, "Session", sessionId);
111 return;
112 }
113
114 // Perform a proper ConfigureSelf authority check. If a
115 // session is being used to DELETE some other user's session,
116 // then the ConfigureSelf privilege does not apply. In that
117 // case, perform the authority check again without the user's
118 // ConfigureSelf privilege.
wukaihua-fii-na0fd29862022-05-18 09:19:16 +0800119 if (req.session != nullptr && !session->username.empty() &&
120 session->username != req.session->username)
Ed Tanous724340d2022-03-14 09:10:07 -0700121 {
122 Privileges effectiveUserPrivileges =
Ninad Palsule3e72c202023-03-27 17:19:55 -0500123 redfish::getUserPrivileges(*req.session);
Ed Tanous724340d2022-03-14 09:10:07 -0700124
125 if (!effectiveUserPrivileges.isSupersetOf({"ConfigureUsers"}))
126 {
127 messages::insufficientPrivilege(asyncResp->res);
128 return;
129 }
130 }
131
Paul Fertser29aab242024-06-12 19:28:47 +0000132 if (session->cookieAuth)
133 {
134 bmcweb::clearSessionCookies(asyncResp->res);
135 }
136
Ed Tanous724340d2022-03-14 09:10:07 -0700137 persistent_data::SessionStore::getInstance().removeSession(session);
138 messages::success(asyncResp->res);
139}
140
141inline nlohmann::json getSessionCollectionMembers()
142{
Ed Tanous89cda632024-04-16 08:45:54 -0700143 std::vector<std::string> sessionIds =
144 persistent_data::SessionStore::getInstance().getAllUniqueIds();
Ed Tanous724340d2022-03-14 09:10:07 -0700145 nlohmann::json ret = nlohmann::json::array();
Ed Tanous89cda632024-04-16 08:45:54 -0700146 for (const std::string& uid : sessionIds)
Ed Tanous724340d2022-03-14 09:10:07 -0700147 {
Ed Tanous14766872022-03-15 10:44:42 -0700148 nlohmann::json::object_t session;
Ed Tanousef4c65b2023-04-24 15:28:50 -0700149 session["@odata.id"] =
Ed Tanous89cda632024-04-16 08:45:54 -0700150 boost::urls::format("/redfish/v1/SessionService/Sessions/{}", uid);
Patrick Williamsb2ba3072023-05-12 10:27:39 -0500151 ret.emplace_back(std::move(session));
Ed Tanous724340d2022-03-14 09:10:07 -0700152 }
153 return ret;
154}
155
Ed Tanousa1e08712022-07-07 16:10:39 -0700156inline void handleSessionCollectionHead(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700157 crow::App& app, const crow::Request& req,
Ed Tanous724340d2022-03-14 09:10:07 -0700158 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
159{
Carson Labrado3ba00072022-06-06 19:40:56 +0000160 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -0700161 {
162 return;
163 }
Ed Tanousa1e08712022-07-07 16:10:39 -0700164 asyncResp->res.addHeader(
165 boost::beast::http::field::link,
166 "</redfish/v1/JsonSchemas/SessionCollection.json>; rel=describedby");
167}
168
169inline void handleSessionCollectionGet(
170 crow::App& app, const crow::Request& req,
171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
172{
Ed Tanous01a89a12022-08-05 09:18:54 -0700173 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
174 {
175 return;
176 }
177 asyncResp->res.addHeader(
178 boost::beast::http::field::link,
179 "</redfish/v1/JsonSchemas/SessionCollection.json>; rel=describedby");
180
Ed Tanous724340d2022-03-14 09:10:07 -0700181 asyncResp->res.jsonValue["Members"] = getSessionCollectionMembers();
182 asyncResp->res.jsonValue["Members@odata.count"] =
183 asyncResp->res.jsonValue["Members"].size();
184 asyncResp->res.jsonValue["@odata.type"] =
185 "#SessionCollection.SessionCollection";
186 asyncResp->res.jsonValue["@odata.id"] =
Gunnar Mills7a859ff2024-03-04 23:04:45 -0700187 "/redfish/v1/SessionService/Sessions";
Ed Tanous724340d2022-03-14 09:10:07 -0700188 asyncResp->res.jsonValue["Name"] = "Session Collection";
189 asyncResp->res.jsonValue["Description"] = "Session Collection";
190}
191
192inline void handleSessionCollectionMembersGet(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700193 crow::App& app, const crow::Request& req,
Ed Tanous724340d2022-03-14 09:10:07 -0700194 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
195{
Carson Labrado3ba00072022-06-06 19:40:56 +0000196 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -0700197 {
198 return;
199 }
Ed Tanous724340d2022-03-14 09:10:07 -0700200 asyncResp->res.jsonValue = getSessionCollectionMembers();
201}
202
Ed Tanous4ee8e212022-05-28 09:42:51 -0700203inline void handleSessionCollectionPost(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700204 crow::App& app, const crow::Request& req,
Ed Tanous724340d2022-03-14 09:10:07 -0700205 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
206{
Carson Labrado3ba00072022-06-06 19:40:56 +0000207 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -0700208 {
209 return;
210 }
Ed Tanous724340d2022-03-14 09:10:07 -0700211 std::string username;
212 std::string password;
Ed Tanousbb759e32022-08-02 17:07:54 -0700213 std::optional<std::string> clientId;
Ravi Teja2ccce1f2024-08-10 04:05:36 -0500214 std::optional<std::string> token;
Ed Tanous724340d2022-03-14 09:10:07 -0700215 if (!json_util::readJsonPatch(req, asyncResp->res, "UserName", username,
Ravi Teja2ccce1f2024-08-10 04:05:36 -0500216 "Password", password, "Token", token,
217 "Context", clientId))
Ed Tanous724340d2022-03-14 09:10:07 -0700218 {
219 return;
220 }
Ed Tanous724340d2022-03-14 09:10:07 -0700221 if (password.empty() || username.empty() ||
222 asyncResp->res.result() != boost::beast::http::status::ok)
223 {
224 if (username.empty())
225 {
226 messages::propertyMissing(asyncResp->res, "UserName");
227 }
228
229 if (password.empty())
230 {
231 messages::propertyMissing(asyncResp->res, "Password");
232 }
233
234 return;
235 }
236
Ravi Teja2ccce1f2024-08-10 04:05:36 -0500237 int pamrc = pamAuthenticateUser(username, password, token);
Ed Tanous724340d2022-03-14 09:10:07 -0700238 bool isConfigureSelfOnly = pamrc == PAM_NEW_AUTHTOK_REQD;
239 if ((pamrc != PAM_SUCCESS) && !isConfigureSelfOnly)
240 {
Ed Tanous39662a32023-02-06 15:09:46 -0800241 messages::resourceAtUriUnauthorized(asyncResp->res, req.url(),
Ed Tanous724340d2022-03-14 09:10:07 -0700242 "Invalid username or password");
243 return;
244 }
Ed Tanous724340d2022-03-14 09:10:07 -0700245
246 // User is authenticated - create session
247 std::shared_ptr<persistent_data::UserSession> session =
248 persistent_data::SessionStore::getInstance().generateUserSession(
249 username, req.ipAddress, clientId,
Ed Tanous89cda632024-04-16 08:45:54 -0700250 persistent_data::SessionType::Session, isConfigureSelfOnly);
Brad Bishop02e53ae2022-07-29 14:38:40 -0400251 if (session == nullptr)
252 {
253 messages::internalError(asyncResp->res);
254 return;
255 }
256
Paul Fertser29aab242024-06-12 19:28:47 +0000257 // When session is created by webui-vue give it session cookies as a
258 // non-standard Redfish extension. This is needed for authentication for
259 // WebSockets-based functionality.
260 if (!req.getHeaderValue("X-Requested-With").empty())
261 {
262 bmcweb::setSessionCookies(asyncResp->res, *session);
263 }
264 else
265 {
266 asyncResp->res.addHeader("X-Auth-Token", session->sessionToken);
267 }
268
Ed Tanous724340d2022-03-14 09:10:07 -0700269 asyncResp->res.addHeader(
270 "Location", "/redfish/v1/SessionService/Sessions/" + session->uniqueId);
271 asyncResp->res.result(boost::beast::http::status::created);
272 if (session->isConfigureSelfOnly)
273 {
274 messages::passwordChangeRequired(
275 asyncResp->res,
Ed Tanousef4c65b2023-04-24 15:28:50 -0700276 boost::urls::format("/redfish/v1/AccountService/Accounts/{}",
277 session->username));
Ed Tanous724340d2022-03-14 09:10:07 -0700278 }
279
Paul Fertser478c5a52024-06-26 22:27:59 +0000280 crow::getUserInfo(asyncResp, username, session, [asyncResp, session]() {
281 fillSessionObject(asyncResp->res, *session);
282 });
Ed Tanous724340d2022-03-14 09:10:07 -0700283}
Ed Tanousa1e08712022-07-07 16:10:39 -0700284inline void handleSessionServiceHead(
285 crow::App& app, const crow::Request& req,
286 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
287{
Ed Tanousa1e08712022-07-07 16:10:39 -0700288 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
289 {
290 return;
291 }
292 asyncResp->res.addHeader(
293 boost::beast::http::field::link,
294 "</redfish/v1/JsonSchemas/SessionService/SessionService.json>; rel=describedby");
295}
Ed Tanous724340d2022-03-14 09:10:07 -0700296inline void
Ed Tanous45ca1b82022-03-25 13:07:27 -0700297 handleSessionServiceGet(crow::App& app, const crow::Request& req,
Ed Tanous724340d2022-03-14 09:10:07 -0700298 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
299
300{
Gunnar Mills78e39002023-05-17 11:52:44 -0500301 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
302 {
303 return;
304 }
305 asyncResp->res.addHeader(
306 boost::beast::http::field::link,
307 "</redfish/v1/JsonSchemas/SessionService/SessionService.json>; rel=describedby");
308
Ed Tanous724340d2022-03-14 09:10:07 -0700309 asyncResp->res.jsonValue["@odata.type"] =
310 "#SessionService.v1_0_2.SessionService";
Gunnar Mills7a859ff2024-03-04 23:04:45 -0700311 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/SessionService";
Ed Tanous724340d2022-03-14 09:10:07 -0700312 asyncResp->res.jsonValue["Name"] = "Session Service";
313 asyncResp->res.jsonValue["Id"] = "SessionService";
314 asyncResp->res.jsonValue["Description"] = "Session Service";
315 asyncResp->res.jsonValue["SessionTimeout"] =
316 persistent_data::SessionStore::getInstance().getTimeoutInSeconds();
317 asyncResp->res.jsonValue["ServiceEnabled"] = true;
318
Ed Tanous14766872022-03-15 10:44:42 -0700319 asyncResp->res.jsonValue["Sessions"]["@odata.id"] =
320 "/redfish/v1/SessionService/Sessions";
Ed Tanous724340d2022-03-14 09:10:07 -0700321}
322
323inline void handleSessionServicePatch(
Ed Tanous45ca1b82022-03-25 13:07:27 -0700324 crow::App& app, const crow::Request& req,
Ed Tanous724340d2022-03-14 09:10:07 -0700325 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
326{
Carson Labrado3ba00072022-06-06 19:40:56 +0000327 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
Ed Tanous45ca1b82022-03-25 13:07:27 -0700328 {
329 return;
330 }
Ed Tanous724340d2022-03-14 09:10:07 -0700331 std::optional<int64_t> sessionTimeout;
332 if (!json_util::readJsonPatch(req, asyncResp->res, "SessionTimeout",
333 sessionTimeout))
334 {
335 return;
336 }
337
338 if (sessionTimeout)
339 {
Ed Tanous8ece0e42024-01-02 13:16:50 -0800340 // The minimum & maximum allowed values for session timeout
Ed Tanous724340d2022-03-14 09:10:07 -0700341 // are 30 seconds and 86400 seconds respectively as per the
342 // session service schema mentioned at
343 // https://redfish.dmtf.org/schemas/v1/SessionService.v1_1_7.json
344
345 if (*sessionTimeout <= 86400 && *sessionTimeout >= 30)
346 {
347 std::chrono::seconds sessionTimeoutInseconds(*sessionTimeout);
348 persistent_data::SessionStore::getInstance().updateSessionTimeout(
349 sessionTimeoutInseconds);
350 messages::propertyValueModified(asyncResp->res, "SessionTimeOut",
351 std::to_string(*sessionTimeout));
352 }
353 else
354 {
Ed Tanouse2616cc2022-06-27 12:45:55 -0700355 messages::propertyValueNotInList(asyncResp->res, *sessionTimeout,
Ed Tanous724340d2022-03-14 09:10:07 -0700356 "SessionTimeOut");
357 }
358 }
359}
360
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700361inline void requestRoutesSession(App& app)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700362{
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700363 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/<str>/")
Ed Tanousa1e08712022-07-07 16:10:39 -0700364 .privileges(redfish::privileges::headSession)
365 .methods(boost::beast::http::verb::head)(
366 std::bind_front(handleSessionHead, std::ref(app)));
367
368 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700369 .privileges(redfish::privileges::getSession)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700370 .methods(boost::beast::http::verb::get)(
371 std::bind_front(handleSessionGet, std::ref(app)));
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +0100372
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700373 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/<str>/")
Ed Tanoused398212021-06-09 17:05:54 -0700374 .privileges(redfish::privileges::deleteSession)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700375 .methods(boost::beast::http::verb::delete_)(
376 std::bind_front(handleSessionDelete, std::ref(app)));
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700377
378 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/")
Ed Tanousa1e08712022-07-07 16:10:39 -0700379 .privileges(redfish::privileges::headSessionCollection)
380 .methods(boost::beast::http::verb::head)(
381 std::bind_front(handleSessionCollectionHead, std::ref(app)));
382
383 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/")
Ed Tanoused398212021-06-09 17:05:54 -0700384 .privileges(redfish::privileges::getSessionCollection)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700385 .methods(boost::beast::http::verb::get)(
386 std::bind_front(handleSessionCollectionGet, std::ref(app)));
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700387
Ed Tanouse76cd862022-03-14 09:12:00 -0700388 // Note, the next two routes technically don't match the privilege
Ed Tanous724340d2022-03-14 09:10:07 -0700389 // registry given the way login mechanisms work. The base privilege
390 // registry lists this endpoint as requiring login privilege, but because
391 // this is the endpoint responsible for giving the login privilege, and it
392 // is itself its own route, it needs to not require Login
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700393 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/")
394 .privileges({})
Ed Tanous45ca1b82022-03-25 13:07:27 -0700395 .methods(boost::beast::http::verb::post)(
396 std::bind_front(handleSessionCollectionPost, std::ref(app)));
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +0100397
Ed Tanouse76cd862022-03-14 09:12:00 -0700398 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/Sessions/Members/")
399 .privileges({})
Ed Tanous45ca1b82022-03-25 13:07:27 -0700400 .methods(boost::beast::http::verb::post)(
401 std::bind_front(handleSessionCollectionPost, std::ref(app)));
Ed Tanouse76cd862022-03-14 09:12:00 -0700402
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700403 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/")
Ed Tanousa1e08712022-07-07 16:10:39 -0700404 .privileges(redfish::privileges::headSessionService)
405 .methods(boost::beast::http::verb::head)(
406 std::bind_front(handleSessionServiceHead, std::ref(app)));
407
408 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/")
Ed Tanoused398212021-06-09 17:05:54 -0700409 .privileges(redfish::privileges::getSessionService)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700410 .methods(boost::beast::http::verb::get)(
411 std::bind_front(handleSessionServiceGet, std::ref(app)));
Borawski.Lukasz5d27b852018-02-08 13:24:24 +0100412
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700413 BMCWEB_ROUTE(app, "/redfish/v1/SessionService/")
Ed Tanoused398212021-06-09 17:05:54 -0700414 .privileges(redfish::privileges::patchSessionService)
Ed Tanous45ca1b82022-03-25 13:07:27 -0700415 .methods(boost::beast::http::verb::patch)(
416 std::bind_front(handleSessionServicePatch, std::ref(app)));
Ed Tanousfaa34cc2021-06-03 13:27:02 -0700417}
Borawski.Lukasz5d27b852018-02-08 13:24:24 +0100418
Ed Tanous1abe55e2018-09-05 08:30:59 -0700419} // namespace redfish