diff --git a/repertory/librepertory/include/types/repertory.hpp b/repertory/librepertory/include/types/repertory.hpp index 4ede7062..38be342e 100644 --- a/repertory/librepertory/include/types/repertory.hpp +++ b/repertory/librepertory/include/types/repertory.hpp @@ -307,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}; diff --git a/repertory/librepertory/src/types/repertory.cpp b/repertory/librepertory/src/types/repertory.cpp index ce662556..6f342cd7 100644 --- a/repertory/librepertory/src/types/repertory.cpp +++ b/repertory/librepertory/src/types/repertory.cpp @@ -21,6 +21,7 @@ */ #include "types/repertory.hpp" +#include "app_config.hpp" #include "types/startup_exception.hpp" #include "utils/string.hpp" @@ -191,4 +192,34 @@ auto api_error_to_string(const api_error &error) -> const std::string & { return LOOKUP.at(error); } + +auto provider_type_from_string(std::string_view type, + provider_type default_type) -> provider_type { + auto type_lower = utils::string::to_lower(std::string{type}); + if (type_lower == "encrypt") { + return provider_type::encrypt; + } + + if (type_lower == "remote") { + return provider_type::remote; + } + + if (type_lower == "s3") { + return provider_type::s3; + } + + if (type_lower == "sia") { + return provider_type::sia; + } + + if (type_lower == "unknown") { + return provider_type::unknown; + } + + return default_type; +} + +auto provider_type_to_string(provider_type type) -> std::string { + return app_config::get_provider_name(type); +} } // namespace repertory diff --git a/repertory/repertory/include/ui/handlers.hpp b/repertory/repertory/include/ui/handlers.hpp index f168b3cb..0fecf440 100644 --- a/repertory/repertory/include/ui/handlers.hpp +++ b/repertory/repertory/include/ui/handlers.hpp @@ -56,6 +56,12 @@ private: private: console_consumer console; + +private: + [[nodiscard]] static auto read_process(provider_type type, + std::string_view name, + std::string_view command) + -> std::vector; }; } // namespace repertory::ui diff --git a/repertory/repertory/src/ui/handlers.cpp b/repertory/repertory/src/ui/handlers.cpp index 3a3b3c9b..588e642e 100644 --- a/repertory/repertory/src/ui/handlers.cpp +++ b/repertory/repertory/src/ui/handlers.cpp @@ -25,10 +25,11 @@ #include "events/event_system.hpp" #include "rpc/common.hpp" #include "types/repertory.hpp" +#include "utils/collection.hpp" #include "utils/error_utils.hpp" #include "utils/file.hpp" #include "utils/path.hpp" -#include +#include "utils/string.hpp" namespace repertory::ui { handlers::handlers(mgmt_app_config *config, httplib::Server *server) @@ -71,6 +72,27 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) res.status = http_error_codes::internal_error; }); + server->Get("/api/v1/mount", [](const httplib::Request &req, auto &&res) { + auto prov = provider_type_from_string(req.get_param_value("type")); + + auto lines = + handlers::read_process(prov, req.get_param_value("name"), "-dc"); + + if (lines.at(0U) != "0") { + throw utils::error::create_exception(function_name, { + "command failed", + lines.at(0U), + }); + } + + lines.erase(lines.begin()); + + auto result = nlohmann::json::parse(utils::string::join(lines, '\n')); + fmt::println("{}", result.dump()); + res.set_content(result.dump(), "application/json"); + res.status = http_error_codes::ok; + }); + server->Get("/api/v1/mount_list", [](auto && /* req */, auto &&res) { auto data_dir = utils::file::directory{app_config::get_root_data_directory()}; @@ -131,4 +153,59 @@ handlers::handlers(mgmt_app_config *config, httplib::Server *server) } handlers::~handlers() { event_system::instance().stop(); } + +auto handlers::read_process(provider_type type, std::string_view name, + std::string_view command) + -> std::vector { + REPERTORY_USES_FUNCTION_NAME(); + + std::string str_type; + switch (type) { + case provider_type::encrypt: + str_type = "-en"; + break; + + case provider_type::remote: { + auto parts = utils::string::split(name, '_', false); + str_type = fmt::format("-rm {}:{}", parts[0U], parts[1U]); + } break; + + case provider_type::s3: + str_type = fmt::format("-s3 -na {}", name); + break; + + case provider_type::sia: + str_type = fmt::format("-na {}", name); + break; + + default: + throw utils::error::create_exception( + function_name, { + fmt::format("`{}` is not supported", name), + }); + } + + auto cmd_line = fmt::format("repertory {} {}", str_type, command); + fmt::println("{}", cmd_line); + + auto *pipe = popen(cmd_line.c_str(), "r"); + if (pipe == nullptr) { + return {}; + } + + std::string data; + std::array buffer{}; + while (feof(pipe) == 0) { + auto *str = fgets(buffer.data(), buffer.size(), pipe); + if (str != nullptr) { + data.insert(data.end(), buffer.begin(), + std::next(buffer.begin(), static_cast( + strnlen(str, buffer.size())))); + } + } + pclose(pipe); + + return utils::string::split(utils::string::replace(data, "\r", ""), '\n', + false); +} } // namespace repertory::ui diff --git a/web/repertory/lib/models/mount.dart b/web/repertory/lib/models/mount.dart index 0f6f2893..fdbb9dbd 100644 --- a/web/repertory/lib/models/mount.dart +++ b/web/repertory/lib/models/mount.dart @@ -1,10 +1,34 @@ +import 'dart:convert'; + import 'package:flutter/foundation.dart'; +import 'package:http/http.dart' as http; import 'package:repertory/types/mount_config.dart'; class Mount with ChangeNotifier { final MountConfig mountConfig; - Mount(this.mountConfig); + Mount(this.mountConfig) { + _fetch(); + } String get name => mountConfig.name; String get type => mountConfig.type; + + Future _fetch() async { + final response = await http.get( + Uri.parse( + Uri.encodeFull('${Uri.base.origin}/api/v1/mount?name=$name&type=$type'), + ), + ); + + if (response.statusCode == 200) { + mountConfig.updateSettings(jsonDecode(response.body)); + + notifyListeners(); + return; + } + } + + void refresh() { + _fetch(); + } } diff --git a/web/repertory/lib/types/mount_config.dart b/web/repertory/lib/types/mount_config.dart index 85a245b0..62cfbb64 100644 --- a/web/repertory/lib/types/mount_config.dart +++ b/web/repertory/lib/types/mount_config.dart @@ -1,12 +1,20 @@ +import 'package:collection/collection.dart'; + class MountConfig { final String _name; final String _type; + Map _settings = {}; MountConfig({required name, required type}) : _name = name, _type = type; + UnmodifiableMapView get items => UnmodifiableMapView(_settings); String get name => _name; String get type => _type; factory MountConfig.fromJson(String type, String name) { return MountConfig(name: name, type: type); } + + void updateSettings(Map settings) { + _settings = settings; + } }