diff --git a/repertory/librepertory/include/rpc/common.hpp b/repertory/librepertory/include/rpc/common.hpp new file mode 100644 index 00000000..b7ed4bf5 --- /dev/null +++ b/repertory/librepertory/include/rpc/common.hpp @@ -0,0 +1,82 @@ +/* + Copyright <2018-2025> + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ +#ifndef REPERTORY_INCLUDE_RPC_COMMON_HPP_ +#define REPERTORY_INCLUDE_RPC_COMMON_HPP_ + +#include "utils/base64.hpp" +#include "utils/error_utils.hpp" +#include "utils/string.hpp" + +namespace repertory::rpc { +[[nodiscard]] auto check_authorization(const auto &cfg, + const httplib::Request &req) -> bool { + REPERTORY_USES_FUNCTION_NAME(); + + if (cfg.get_api_auth().empty() || cfg.get_api_user().empty()) { + utils::error::raise_error(function_name, + "authorization user or password is not set"); + return false; + } + + auto authorization = req.get_header_value("Authorization"); + if (authorization.empty()) { + utils::error::raise_error(function_name, + "'Authorization' header is not set"); + return false; + } + + auto auth_parts = utils::string::split(authorization, ' ', true); + if (auth_parts.empty()) { + utils::error::raise_error(function_name, "'Authorization' header is empty"); + return false; + } + + auto auth_type = auth_parts[0U]; + if (auth_type != "Basic") { + utils::error::raise_error(function_name, + "authorization type is not 'Basic'"); + return false; + } + + auto data = macaron::Base64::Decode(authorization.substr(6U)); + auto auth_str = std::string(data.begin(), data.end()); + + auto auth = utils::string::split(auth_str, ':', false); + if (auth.size() < 2U) { + utils::error::raise_error(function_name, "authorization data is not valid"); + return false; + } + + auto user = auth.at(0U); + auth.erase(auth.begin()); + + auto pwd = utils::string::join(auth, ':'); + if ((user != cfg.get_api_user()) || (pwd != cfg.get_api_auth())) { + utils::error::raise_error(function_name, "authorization failed"); + return false; + } + + return true; +} +} // namespace repertory::rpc + +#endif // REPERTORY_INCLUDE_RPC_COMMON_HPP_ diff --git a/repertory/librepertory/include/rpc/server/server.hpp b/repertory/librepertory/include/rpc/server/server.hpp index 48735e10..5892d732 100644 --- a/repertory/librepertory/include/rpc/server/server.hpp +++ b/repertory/librepertory/include/rpc/server/server.hpp @@ -40,8 +40,6 @@ private: std::mutex start_stop_mutex_; private: - [[nodiscard]] auto check_authorization(const httplib::Request &req) -> bool; - void handle_get_config(const httplib::Request &req, httplib::Response &res); void handle_get_config_value_by_name(const httplib::Request &req, diff --git a/repertory/librepertory/src/rpc/server/server.cpp b/repertory/librepertory/src/rpc/server/server.cpp index a98d7428..b6a67d72 100644 --- a/repertory/librepertory/src/rpc/server/server.cpp +++ b/repertory/librepertory/src/rpc/server/server.cpp @@ -28,6 +28,7 @@ #include "events/types/service_stop_begin.hpp" #include "events/types/service_stop_end.hpp" #include "events/types/unmount_requested.hpp" +#include "rpc/common.hpp" #include "utils/base64.hpp" #include "utils/error_utils.hpp" #include "utils/string.hpp" @@ -35,54 +36,6 @@ namespace repertory { server::server(app_config &config) : config_(config) {} -auto server::check_authorization(const httplib::Request &req) -> bool { - REPERTORY_USES_FUNCTION_NAME(); - - if (config_.get_api_auth().empty() || config_.get_api_user().empty()) { - utils::error::raise_error(function_name, - "authorization user or password is not set"); - return false; - } - - auto authorization = req.get_header_value("Authorization"); - if (authorization.empty()) { - utils::error::raise_error(function_name, "Authorization header is not set"); - return false; - } - - auto auth_parts = utils::string::split(authorization, ' ', true); - if (auth_parts.empty()) { - utils::error::raise_error(function_name, "Authorization header is empty"); - return false; - } - - auto auth_type = auth_parts[0U]; - if (auth_type != "Basic") { - utils::error::raise_error(function_name, "Authorization is not Basic"); - return false; - } - - auto data = macaron::Base64::Decode(authorization.substr(6U)); - auto auth_str = std::string(data.begin(), data.end()); - - auto auth = utils::string::split(auth_str, ':', false); - if (auth.size() < 2U) { - utils::error::raise_error(function_name, "Authorization is not valid"); - return false; - } - - auto user = auth.at(0U); - auth.erase(auth.begin()); - - auto pwd = utils::string::join(auth, ':'); - if ((user != config_.get_api_user()) || (pwd != config_.get_api_auth())) { - utils::error::raise_error(function_name, "Authorization failed"); - return false; - } - - return true; -} - void server::handle_get_config(const httplib::Request & /*req*/, httplib::Response &res) { auto data = config_.get_json(); @@ -173,7 +126,7 @@ void server::start() { server_->set_pre_routing_handler( [this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse { - if (check_authorization(req)) { + if (rpc::check_authorization(config_, req)) { return httplib::Server::HandlerResponse::Unhandled; } diff --git a/repertory/repertory/include/ui/handlers.hpp b/repertory/repertory/include/ui/handlers.hpp index 30b6e629..5bade93e 100644 --- a/repertory/repertory/include/ui/handlers.hpp +++ b/repertory/repertory/include/ui/handlers.hpp @@ -56,9 +56,6 @@ private: private: console_consumer console{}; - -private: - [[nodiscard]] auto check_authorization(const httplib::Request &req) -> bool; }; } // namespace repertory::ui diff --git a/repertory/repertory/src/ui/handlers.cpp b/repertory/repertory/src/ui/handlers.cpp index f2ce3b56..2046c6da 100644 --- a/repertory/repertory/src/ui/handlers.cpp +++ b/repertory/repertory/src/ui/handlers.cpp @@ -22,6 +22,7 @@ #include "ui/handlers.hpp" #include "events/event_system.hpp" +#include "rpc/common.hpp" #include "types/repertory.hpp" #include "utils/base64.hpp" #include "utils/error_utils.hpp" @@ -34,7 +35,7 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) server_->set_pre_routing_handler( [this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse { - if (check_authorization(req)) { + if (rpc::check_authorization(*config_, req)) { return httplib::Server::HandlerResponse::Unhandled; } @@ -92,54 +93,4 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) } handlers::~handlers() { event_system::instance().stop(); } - -auto handlers::check_authorization(const httplib::Request &req) -> bool { - REPERTORY_USES_FUNCTION_NAME(); - - if (config_->get_api_auth().empty() || config_->get_api_user().empty()) { - utils::error::raise_error(function_name, - "authorization user or password is not set"); - return false; - } - - auto authorization = req.get_header_value("Authorization"); - if (authorization.empty()) { - utils::error::raise_error(function_name, - "'Authorization' header is not set"); - return false; - } - - auto auth_parts = utils::string::split(authorization, ' ', true); - if (auth_parts.empty()) { - utils::error::raise_error(function_name, "'Authorization' header is empty"); - return false; - } - - auto auth_type = auth_parts[0U]; - if (auth_type != "Basic") { - utils::error::raise_error(function_name, - "authorization type is not 'Basic'"); - return false; - } - - auto data = macaron::Base64::Decode(authorization.substr(6U)); - auto auth_str = std::string(data.begin(), data.end()); - - auto auth = utils::string::split(auth_str, ':', false); - if (auth.size() < 2U) { - utils::error::raise_error(function_name, "authorization data is not valid"); - return false; - } - - auto user = auth.at(0U); - auth.erase(auth.begin()); - - auto pwd = utils::string::join(auth, ':'); - if ((user != config_->get_api_user()) || (pwd != config_->get_api_auth())) { - utils::error::raise_error(function_name, "authorization failed"); - return false; - } - - return true; -} } // namespace repertory::ui