12b7981f6SKowalski, Kamil /* 22b7981f6SKowalski, Kamil // Copyright (c) 2018 Intel Corporation 32b7981f6SKowalski, Kamil // 42b7981f6SKowalski, Kamil // Licensed under the Apache License, Version 2.0 (the "License"); 52b7981f6SKowalski, Kamil // you may not use this file except in compliance with the License. 62b7981f6SKowalski, Kamil // You may obtain a copy of the License at 72b7981f6SKowalski, Kamil // 82b7981f6SKowalski, Kamil // http://www.apache.org/licenses/LICENSE-2.0 92b7981f6SKowalski, Kamil // 102b7981f6SKowalski, Kamil // Unless required by applicable law or agreed to in writing, software 112b7981f6SKowalski, Kamil // distributed under the License is distributed on an "AS IS" BASIS, 122b7981f6SKowalski, Kamil // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132b7981f6SKowalski, Kamil // See the License for the specific language governing permissions and 142b7981f6SKowalski, Kamil // limitations under the License. 152b7981f6SKowalski, Kamil */ 162b7981f6SKowalski, Kamil #pragma once 1743a095abSBorawski.Lukasz 18f4c4dcf4SKowalski, Kamil #include "error_messages.hpp" 192b7981f6SKowalski, Kamil #include "node.hpp" 204b1b8683SBorawski.Lukasz #include "persistent_data_middleware.hpp" 212b7981f6SKowalski, Kamil 221abe55efSEd Tanous namespace redfish 231abe55efSEd Tanous { 242b7981f6SKowalski, Kamil 252b7981f6SKowalski, Kamil class SessionCollection; 262b7981f6SKowalski, Kamil 271abe55efSEd Tanous class Sessions : public Node 281abe55efSEd Tanous { 292b7981f6SKowalski, Kamil public: 301abe55efSEd Tanous Sessions(CrowApp& app) : 311abe55efSEd Tanous Node(app, "/redfish/v1/SessionService/Sessions/<str>/", std::string()) 321abe55efSEd Tanous { 33c1a46bd2SBorawski.Lukasz Node::json["@odata.type"] = "#Session.v1_0_2.Session"; 34c1a46bd2SBorawski.Lukasz Node::json["@odata.context"] = "/redfish/v1/$metadata#Session.Session"; 35c1a46bd2SBorawski.Lukasz Node::json["Name"] = "User Session"; 36c1a46bd2SBorawski.Lukasz Node::json["Description"] = "Manager User Session"; 373ebd75f7SEd Tanous 38e0d918bcSEd Tanous entityPrivileges = { 39e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 40e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 41e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 42e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 43e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 44e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 452b7981f6SKowalski, Kamil } 462b7981f6SKowalski, Kamil 472b7981f6SKowalski, Kamil private: 4855c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 491abe55efSEd Tanous const std::vector<std::string>& params) override 501abe55efSEd Tanous { 512b7981f6SKowalski, Kamil auto session = 5255c7b7a2SEd Tanous crow::persistent_data::SessionStore::getInstance().getSessionByUid( 534b1b8683SBorawski.Lukasz params[0]); 542b7981f6SKowalski, Kamil 551abe55efSEd Tanous if (session == nullptr) 561abe55efSEd Tanous { 57*f12894f8SJason M. Bills messages::resourceNotFound(res, "Session", params[0]); 582b7981f6SKowalski, Kamil res.end(); 592b7981f6SKowalski, Kamil return; 602b7981f6SKowalski, Kamil } 612b7981f6SKowalski, Kamil 6255c7b7a2SEd Tanous Node::json["Id"] = session->uniqueId; 63c1a46bd2SBorawski.Lukasz Node::json["UserName"] = session->username; 64c1a46bd2SBorawski.Lukasz Node::json["@odata.id"] = 6555c7b7a2SEd Tanous "/redfish/v1/SessionService/Sessions/" + session->uniqueId; 662b7981f6SKowalski, Kamil 6755c7b7a2SEd Tanous res.jsonValue = Node::json; 682b7981f6SKowalski, Kamil res.end(); 692b7981f6SKowalski, Kamil } 702b7981f6SKowalski, Kamil 7155c7b7a2SEd Tanous void doDelete(crow::Response& res, const crow::Request& req, 721abe55efSEd Tanous const std::vector<std::string>& params) override 731abe55efSEd Tanous { 742b7981f6SKowalski, Kamil // Need only 1 param which should be id of session to be deleted 751abe55efSEd Tanous if (params.size() != 1) 761abe55efSEd Tanous { 77f4c4dcf4SKowalski, Kamil // This should be handled by crow and never happen 781abe55efSEd Tanous BMCWEB_LOG_ERROR << "Session DELETE has been called with invalid " 791abe55efSEd Tanous "number of params"; 80f4c4dcf4SKowalski, Kamil 81*f12894f8SJason M. Bills messages::generalError(res); 822b7981f6SKowalski, Kamil res.end(); 832b7981f6SKowalski, Kamil return; 842b7981f6SKowalski, Kamil } 852b7981f6SKowalski, Kamil 862b7981f6SKowalski, Kamil auto session = 8755c7b7a2SEd Tanous crow::persistent_data::SessionStore::getInstance().getSessionByUid( 884b1b8683SBorawski.Lukasz params[0]); 892b7981f6SKowalski, Kamil 901abe55efSEd Tanous if (session == nullptr) 911abe55efSEd Tanous { 92*f12894f8SJason M. Bills messages::resourceNotFound(res, "Session", params[0]); 932b7981f6SKowalski, Kamil res.end(); 942b7981f6SKowalski, Kamil return; 952b7981f6SKowalski, Kamil } 962b7981f6SKowalski, Kamil 97f4c4dcf4SKowalski, Kamil // DELETE should return representation of object that will be removed 98f4c4dcf4SKowalski, Kamil doGet(res, req, params); 99f4c4dcf4SKowalski, Kamil 1001abe55efSEd Tanous crow::persistent_data::SessionStore::getInstance().removeSession( 1011abe55efSEd Tanous session); 1022b7981f6SKowalski, Kamil } 1032b7981f6SKowalski, Kamil 1042b7981f6SKowalski, Kamil /** 1052b7981f6SKowalski, Kamil * This allows SessionCollection to reuse this class' doGet method, to 1061abe55efSEd Tanous * maintain consistency of returned data, as Collection's doPost should 1071abe55efSEd Tanous * return data for created member which should match member's doGet result 1081abe55efSEd Tanous * in 100% 1092b7981f6SKowalski, Kamil */ 1102b7981f6SKowalski, Kamil friend SessionCollection; 1112b7981f6SKowalski, Kamil }; 1122b7981f6SKowalski, Kamil 1131abe55efSEd Tanous class SessionCollection : public Node 1141abe55efSEd Tanous { 1152b7981f6SKowalski, Kamil public: 1161abe55efSEd Tanous SessionCollection(CrowApp& app) : 1171abe55efSEd Tanous Node(app, "/redfish/v1/SessionService/Sessions/"), memberSession(app) 1181abe55efSEd Tanous { 119c1a46bd2SBorawski.Lukasz Node::json["@odata.type"] = "#SessionCollection.SessionCollection"; 120c1a46bd2SBorawski.Lukasz Node::json["@odata.id"] = "/redfish/v1/SessionService/Sessions/"; 121c1a46bd2SBorawski.Lukasz Node::json["@odata.context"] = 1222b7981f6SKowalski, Kamil "/redfish/v1/$metadata#SessionCollection.SessionCollection"; 123c1a46bd2SBorawski.Lukasz Node::json["Name"] = "Session Collection"; 124c1a46bd2SBorawski.Lukasz Node::json["Description"] = "Session Collection"; 125c1a46bd2SBorawski.Lukasz Node::json["Members@odata.count"] = 0; 126c1a46bd2SBorawski.Lukasz Node::json["Members"] = nlohmann::json::array(); 1273ebd75f7SEd Tanous 128e0d918bcSEd Tanous entityPrivileges = { 129e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 130e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 131e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 132e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 133e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 134e0d918bcSEd Tanous {boost::beast::http::verb::post, {}}}; 1352b7981f6SKowalski, Kamil } 1362b7981f6SKowalski, Kamil 1372b7981f6SKowalski, Kamil private: 13855c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 1391abe55efSEd Tanous const std::vector<std::string>& params) override 1401abe55efSEd Tanous { 14155c7b7a2SEd Tanous std::vector<const std::string*> sessionIds = 14255c7b7a2SEd Tanous crow::persistent_data::SessionStore::getInstance().getUniqueIds( 14355c7b7a2SEd Tanous false, crow::persistent_data::PersistenceType::TIMEOUT); 1442b7981f6SKowalski, Kamil 14555c7b7a2SEd Tanous Node::json["Members@odata.count"] = sessionIds.size(); 146c1a46bd2SBorawski.Lukasz Node::json["Members"] = nlohmann::json::array(); 1471abe55efSEd Tanous for (const std::string* uid : sessionIds) 1481abe55efSEd Tanous { 149c1a46bd2SBorawski.Lukasz Node::json["Members"].push_back( 1502b7981f6SKowalski, Kamil {{"@odata.id", "/redfish/v1/SessionService/Sessions/" + *uid}}); 1512b7981f6SKowalski, Kamil } 1522b7981f6SKowalski, Kamil 15355c7b7a2SEd Tanous res.jsonValue = Node::json; 1542b7981f6SKowalski, Kamil res.end(); 1552b7981f6SKowalski, Kamil } 1562b7981f6SKowalski, Kamil 15755c7b7a2SEd Tanous void doPost(crow::Response& res, const crow::Request& req, 1581abe55efSEd Tanous const std::vector<std::string>& params) override 1591abe55efSEd Tanous { 1609712f8acSEd Tanous std::string username; 1619712f8acSEd Tanous std::string password; 1629712f8acSEd Tanous if (!json_util::readJson(req, res, "UserName", username, "Password", 1639712f8acSEd Tanous password)) 1641abe55efSEd Tanous { 1652b7981f6SKowalski, Kamil res.end(); 1662b7981f6SKowalski, Kamil return; 1672b7981f6SKowalski, Kamil } 1682b7981f6SKowalski, Kamil 169820ce598SEd Tanous if (password.empty() || username.empty() || 170820ce598SEd Tanous res.result() != boost::beast::http::status::ok) 1711abe55efSEd Tanous { 1721abe55efSEd Tanous if (username.empty()) 1731abe55efSEd Tanous { 174*f12894f8SJason M. Bills messages::propertyMissing(res, "UserName", "UserName"); 175f4c4dcf4SKowalski, Kamil } 176f4c4dcf4SKowalski, Kamil 1771abe55efSEd Tanous if (password.empty()) 1781abe55efSEd Tanous { 179*f12894f8SJason M. Bills messages::propertyMissing(res, "Password", "Password"); 180820ce598SEd Tanous } 181820ce598SEd Tanous res.end(); 182820ce598SEd Tanous 183820ce598SEd Tanous return; 184f4c4dcf4SKowalski, Kamil } 1852b7981f6SKowalski, Kamil 1861abe55efSEd Tanous if (!pamAuthenticateUser(username, password)) 1871abe55efSEd Tanous { 188*f12894f8SJason M. Bills messages::resourceAtUriUnauthorized(res, std::string(req.url), 189*f12894f8SJason M. Bills "Invalid username or password"); 190820ce598SEd Tanous res.end(); 1912b7981f6SKowalski, Kamil 192820ce598SEd Tanous return; 1932b7981f6SKowalski, Kamil } 1942b7981f6SKowalski, Kamil 195820ce598SEd Tanous // User is authenticated - create session 196820ce598SEd Tanous std::shared_ptr<crow::persistent_data::UserSession> session = 197820ce598SEd Tanous crow::persistent_data::SessionStore::getInstance() 198820ce598SEd Tanous .generateUserSession(username); 199820ce598SEd Tanous res.addHeader("X-Auth-Token", session->sessionToken); 200820ce598SEd Tanous res.addHeader("Location", "/redfish/v1/SessionService/Sessions/" + 201820ce598SEd Tanous session->uniqueId); 202820ce598SEd Tanous res.result(boost::beast::http::status::created); 203820ce598SEd Tanous memberSession.doGet(res, req, {session->uniqueId}); 2042b7981f6SKowalski, Kamil } 2052b7981f6SKowalski, Kamil 2062b7981f6SKowalski, Kamil /** 2072b7981f6SKowalski, Kamil * Member session to ensure consistency between collection's doPost and 2082b7981f6SKowalski, Kamil * member's doGet, as they should return 100% matching data 2092b7981f6SKowalski, Kamil */ 2102b7981f6SKowalski, Kamil Sessions memberSession; 2112b7981f6SKowalski, Kamil }; 2122b7981f6SKowalski, Kamil 2131abe55efSEd Tanous class SessionService : public Node 2141abe55efSEd Tanous { 2155d27b854SBorawski.Lukasz public: 2161abe55efSEd Tanous SessionService(CrowApp& app) : Node(app, "/redfish/v1/SessionService/") 2171abe55efSEd Tanous { 2185d27b854SBorawski.Lukasz Node::json["@odata.type"] = "#SessionService.v1_0_2.SessionService"; 2195d27b854SBorawski.Lukasz Node::json["@odata.id"] = "/redfish/v1/SessionService/"; 2205d27b854SBorawski.Lukasz Node::json["@odata.context"] = 2215d27b854SBorawski.Lukasz "/redfish/v1/$metadata#SessionService.SessionService"; 2225d27b854SBorawski.Lukasz Node::json["Name"] = "Session Service"; 2236c233015SEd Tanous Node::json["Id"] = "SessionService"; 2245d27b854SBorawski.Lukasz Node::json["Description"] = "Session Service"; 2255d27b854SBorawski.Lukasz Node::json["SessionTimeout"] = 22655c7b7a2SEd Tanous crow::persistent_data::SessionStore::getInstance() 22755c7b7a2SEd Tanous .getTimeoutInSeconds(); 2285d27b854SBorawski.Lukasz Node::json["ServiceEnabled"] = true; 2293ebd75f7SEd Tanous 230e0d918bcSEd Tanous entityPrivileges = { 231e0d918bcSEd Tanous {boost::beast::http::verb::get, {{"Login"}}}, 232e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 233e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, 234e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureManager"}}}, 235e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, 236e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; 2375d27b854SBorawski.Lukasz } 2385d27b854SBorawski.Lukasz 2395d27b854SBorawski.Lukasz private: 24055c7b7a2SEd Tanous void doGet(crow::Response& res, const crow::Request& req, 2411abe55efSEd Tanous const std::vector<std::string>& params) override 2421abe55efSEd Tanous { 24355c7b7a2SEd Tanous res.jsonValue = Node::json; 2445d27b854SBorawski.Lukasz res.end(); 2455d27b854SBorawski.Lukasz } 2465d27b854SBorawski.Lukasz }; 2475d27b854SBorawski.Lukasz 2482b7981f6SKowalski, Kamil } // namespace redfish 249