diff --git a/.cspell/words.txt b/.cspell/words.txt index 105d1a80..8b743f2b 100644 --- a/.cspell/words.txt +++ b/.cspell/words.txt @@ -154,8 +154,10 @@ mtune musl-libc nana ncrypt +nlohmann nlohmann_json nmakeprg +nohup nominmax ntstatus nullptr diff --git a/config.sh b/config.sh index a2290464..7e647523 100755 --- a/config.sh +++ b/config.sh @@ -19,6 +19,8 @@ PROJECT_APP_LIST=(${PROJECT_NAME}) PROJECT_PRIVATE_KEY=${DEVELOPER_PRIVATE_KEY} PROJECT_PUBLIC_KEY=${DEVELOPER_PUBLIC_KEY} +PROJECT_FLUTTER_BASE_HREF="/ui/" + PROJECT_ENABLE_WIN32_LONG_PATH_NAMES=OFF PROJECT_ENABLE_BACKWARD_CPP=OFF diff --git a/repertory/librepertory/include/app_config.hpp b/repertory/librepertory/include/app_config.hpp index 572a135e..7d825e3e 100644 --- a/repertory/librepertory/include/app_config.hpp +++ b/repertory/librepertory/include/app_config.hpp @@ -52,6 +52,8 @@ public: [[nodiscard]] static auto get_provider_name(const provider_type &prov) -> std::string; + [[nodiscard]] static auto get_root_data_directory() -> std::string; + public: [[nodiscard]] static auto get_stop_requested() -> bool; 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/include/types/repertory.hpp b/repertory/librepertory/include/types/repertory.hpp index fce1cbc2..b5a3fed5 100644 --- a/repertory/librepertory/include/types/repertory.hpp +++ b/repertory/librepertory/include/types/repertory.hpp @@ -38,6 +38,7 @@ constexpr const auto default_retry_read_count{6U}; constexpr const auto default_ring_buffer_file_size{512U}; constexpr const auto default_task_wait_ms{100U}; constexpr const auto default_timeout_ms{60000U}; +constexpr const auto default_ui_mgmt_port{std::uint16_t{30000U}}; constexpr const auto max_ring_buffer_file_size{std::uint16_t(1024U)}; constexpr const auto max_s3_object_name_length{1024U}; constexpr const auto min_cache_size_bytes{ @@ -280,6 +281,8 @@ enum class exit_code : std::int32_t { pin_failed = -16, unpin_failed = -17, init_failed = -18, + ui_mount_failed = -19, + exception = -20, }; enum http_error_codes : std::int32_t { @@ -304,6 +307,13 @@ enum class provider_type : std::size_t { unknown, }; +[[nodiscard]] auto +provider_type_from_string(std::string_view type, + provider_type default_type = provider_type::unknown) + -> provider_type; + +[[nodiscard]] auto provider_type_to_string(provider_type type) -> std::string; + #if defined(_WIN32) struct open_file_data final { PVOID directory_buffer{nullptr}; @@ -487,6 +497,7 @@ inline constexpr const auto JSON_MAX_UPLOAD_COUNT{"MaxUploadCount"}; inline constexpr const auto JSON_MED_FREQ_INTERVAL_SECS{ "MedFreqIntervalSeconds"}; inline constexpr const auto JSON_META{"Meta"}; +inline constexpr const auto JSON_MOUNT_LOCATIONS{"MountLocations"}; inline constexpr const auto JSON_ONLINE_CHECK_RETRY_SECS{ "OnlineCheckRetrySeconds"}; inline constexpr const auto JSON_PATH{"Path"}; diff --git a/repertory/librepertory/include/utils/cli_utils.hpp b/repertory/librepertory/include/utils/cli_utils.hpp index 06ce1f41..c0f9ed01 100644 --- a/repertory/librepertory/include/utils/cli_utils.hpp +++ b/repertory/librepertory/include/utils/cli_utils.hpp @@ -49,6 +49,8 @@ static const option password_option = {"-pw", "--password"}; static const option remote_mount_option = {"-rm", "--remote_mount"}; static const option set_option = {"-set", "--set"}; static const option status_option = {"-status", "--status"}; +static const option ui_option = {"-ui", "--ui"}; +static const option ui_port_option = {"-up", "--ui_port"}; static const option unmount_option = {"-unmount", "--unmount"}; static const option unpin_file_option = {"-uf", "--unpin_file"}; static const option user_option = {"-us", "--user"}; @@ -75,6 +77,8 @@ static const std::vector