Implement secure key via KDF for transparent data encryption/decryption #60
This commit is contained in:
		| @@ -135,6 +135,10 @@ public: | ||||
|  | ||||
|   [[nodiscard]] auto evict_file(const std::string &api_path) -> bool override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item(const std::string &api_path, | ||||
|                                         directory_item &item) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list override; | ||||
|  | ||||
|   | ||||
| @@ -34,6 +34,10 @@ public: | ||||
|   [[nodiscard]] virtual auto evict_file(const std::string &api_path) | ||||
|       -> bool = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_directory_item(const std::string &api_path, | ||||
|                                                 directory_item &item) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items(const std::string &api_path) const | ||||
|       -> directory_item_list = 0; | ||||
|   | ||||
| @@ -110,6 +110,10 @@ protected: | ||||
|  | ||||
|   [[nodiscard]] auto get_db() const -> const i_meta_db & { return *db3_; } | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_item_impl(const std::string &api_path, bool directory, | ||||
|                           directory_item &item) const -> api_error; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items_impl(const std::string &api_path, | ||||
|                            directory_item_list &list) const -> api_error = 0; | ||||
| @@ -147,6 +151,10 @@ public: | ||||
|                                               std::string &api_path) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item(const std::string &api_path, | ||||
|                                         directory_item &item) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path, | ||||
|                                          directory_item_list &list) const | ||||
|       -> api_error override; | ||||
|   | ||||
| @@ -118,6 +118,10 @@ public: | ||||
|   [[nodiscard]] auto get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_item(const std::string &api_path, | ||||
|                                         directory_item &item) const | ||||
|       -> api_error override; | ||||
|  | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path, | ||||
|                                          directory_item_list &list) const | ||||
|       -> api_error override; | ||||
|   | ||||
| @@ -55,6 +55,10 @@ public: | ||||
|   get_directory_item_count(const std::string &api_path) const | ||||
|       -> std::uint64_t = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto get_directory_item(const std::string &api_path, | ||||
|                                                 directory_item &list) const | ||||
|       -> api_error = 0; | ||||
|  | ||||
|   [[nodiscard]] virtual auto | ||||
|   get_directory_items(const std::string &api_path, | ||||
|                       directory_item_list &list) const -> api_error = 0; | ||||
|   | ||||
| @@ -44,6 +44,8 @@ public: | ||||
|   [[nodiscard]] auto get_directory_items(const std::string &api_path) | ||||
|       -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_item_info(const std::string &api_path) -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_open_files() -> rpc_response; | ||||
|  | ||||
|   [[nodiscard]] auto get_pinned_files() -> rpc_response; | ||||
|   | ||||
| @@ -43,6 +43,9 @@ private: | ||||
|   void handle_get_directory_items(const httplib::Request &req, | ||||
|                                   httplib::Response &res); | ||||
|  | ||||
|   void handle_get_item_info(const httplib::Request &req, | ||||
|                             httplib::Response &res); | ||||
|  | ||||
|   void handle_get_drive_information(const httplib::Request &req, | ||||
|                                     httplib::Response &res); | ||||
|  | ||||
|   | ||||
| @@ -45,6 +45,7 @@ namespace rpc_method { | ||||
| const std::string get_config = "get_config"; | ||||
| const std::string get_config_value_by_name = "get_config_value_by_name"; | ||||
| const std::string get_directory_items = "get_directory_items"; | ||||
| const std::string get_item_info = "get_item_info"; | ||||
| const std::string get_drive_information = "get_drive_information"; | ||||
| const std::string get_open_files = "get_open_files"; | ||||
| const std::string get_pinned_files = "get_pinned_files"; | ||||
|   | ||||
| @@ -39,6 +39,7 @@ inline const option generate_config_option = {"-gc", "--generate_config"}; | ||||
| inline const option get_option = {"-get", "--get"}; | ||||
| inline const option get_directory_items_option = {"-gdi", | ||||
|                                                   "--get_directory_items"}; | ||||
| inline const option get_item_info_option = {"-gi", "--get_item_info"}; | ||||
| inline const option get_pinned_files_option = {"-gpf", "--get_pinned_files"}; | ||||
| inline const option help_option = {"-h", "--help"}; | ||||
| inline const option hidden_option = {"-hidden", "--hidden"}; | ||||
| @@ -69,6 +70,7 @@ inline const std::vector<option> option_list = { | ||||
|     generate_config_option, | ||||
|     get_option, | ||||
|     get_directory_items_option, | ||||
|     get_item_info_option, | ||||
|     get_pinned_files_option, | ||||
|     help_option, | ||||
|     hidden_option, | ||||
|   | ||||
| @@ -223,6 +223,20 @@ auto file_manager::get_directory_items(const std::string &api_path) const | ||||
|   return list; | ||||
| } | ||||
|  | ||||
| auto file_manager::get_directory_item(const std::string &api_path, | ||||
|                                       directory_item &item) const -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   auto ret = provider_.get_directory_item(api_path, item); | ||||
|   if (ret == api_error::success) { | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   utils::error::raise_api_path_error(function_name, api_path, ret, | ||||
|                                      "failed to get directory item"); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto file_manager::get_next_handle() -> std::uint64_t { | ||||
|   if (++next_handle_ == 0U) { | ||||
|     ++next_handle_; | ||||
|   | ||||
| @@ -275,6 +275,54 @@ auto base_provider::get_api_path_from_source(const std::string &source_path, | ||||
|   return db3_->get_api_path(source_path, api_path); | ||||
| } | ||||
|  | ||||
| auto base_provider::get_directory_item_impl(const std::string &api_path, | ||||
|                                             bool directory, | ||||
|                                             directory_item &item) const | ||||
|     -> api_error { | ||||
|   filesystem_item fsi{}; | ||||
|   auto ret = get_filesystem_item(api_path, directory, fsi); | ||||
|   if (ret != api_error::success) { | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   api_meta_map meta; | ||||
|   ret = get_item_meta(api_path, meta); | ||||
|   if (ret != api_error::success) { | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   item = { | ||||
|       .api_path = fsi.api_path, | ||||
|       .api_parent = fsi.api_parent, | ||||
|       .directory = fsi.directory, | ||||
|       .size = fsi.size, | ||||
|       .meta = meta, | ||||
|   }; | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto base_provider::get_directory_item(const std::string &api_path, | ||||
|                                        directory_item &item) const | ||||
|     -> api_error { | ||||
|   REPERTORY_USES_FUNCTION_NAME(); | ||||
|  | ||||
|   try { | ||||
|     bool directory{}; | ||||
|     auto ret = is_directory(api_path, directory); | ||||
|     if (ret != api_error::success) { | ||||
|       return ret; | ||||
|     } | ||||
|  | ||||
|     return get_directory_item_impl(api_path, directory, item); | ||||
|   } catch (const std::exception &e) { | ||||
|     utils::error::raise_api_path_error(function_name, api_path, e, | ||||
|                                        "failed to get directory items"); | ||||
|   } | ||||
|  | ||||
|   return api_error::error; | ||||
| } | ||||
|  | ||||
| auto base_provider::get_directory_items(const std::string &api_path, | ||||
|                                         directory_item_list &list) const | ||||
|     -> api_error { | ||||
|   | ||||
| @@ -199,6 +199,38 @@ auto encrypt_provider::get_directory_item_count( | ||||
|   return count; | ||||
| } | ||||
|  | ||||
| auto encrypt_provider::get_directory_item(const std::string &api_path, | ||||
|                                           directory_item &item) const | ||||
|     -> api_error { | ||||
|   bool directory{}; | ||||
|   auto ret = is_directory(api_path, directory); | ||||
|   if (ret != api_error::success) { | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   filesystem_item fsi{}; | ||||
|   ret = get_filesystem_item(api_path, directory, fsi); | ||||
|   if (ret != api_error::success) { | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   api_meta_map meta; | ||||
|   ret = get_item_meta(api_path, meta); | ||||
|   if (ret != api_error::success) { | ||||
|     return ret; | ||||
|   } | ||||
|  | ||||
|   item = { | ||||
|       .api_path = fsi.api_path, | ||||
|       .api_parent = fsi.api_parent, | ||||
|       .directory = fsi.directory, | ||||
|       .size = fsi.size, | ||||
|       .meta = meta, | ||||
|   }; | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| auto encrypt_provider::get_directory_items(const std::string &api_path, | ||||
|                                            directory_item_list &list) const | ||||
|     -> api_error { | ||||
|   | ||||
| @@ -142,6 +142,35 @@ auto client::get_directory_items(const std::string &api_path) -> rpc_response { | ||||
|   }; | ||||
| } | ||||
|  | ||||
| auto client::get_item_info(const std::string &api_path) -> rpc_response { | ||||
|   auto base_url = | ||||
|       "http://" + host_info_.host + ":" + std::to_string(host_info_.port); | ||||
|  | ||||
|   httplib::Params params{{"api_path", api_path}}; | ||||
|   httplib::Client cli{base_url}; | ||||
|   cli.set_basic_auth(host_info_.user, | ||||
|                      rpc::create_password_hash(host_info_.password)); | ||||
|  | ||||
|   auto resp = cli.Get("/api/v1/" + rpc_method::get_item_info, params, {}); | ||||
|   if (resp.error() != httplib::Error::Success) { | ||||
|     return rpc_response{ | ||||
|         .response_type = rpc_response_type::http_error, | ||||
|         .data = {{"error", httplib::to_string(resp.error())}}, | ||||
|     }; | ||||
|   } | ||||
|   if (resp->status != http_error_codes::ok) { | ||||
|     return rpc_response{ | ||||
|         .response_type = rpc_response_type::http_error, | ||||
|         .data = {{"error", std::to_string(resp->status)}}, | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   return rpc_response{ | ||||
|       .response_type = rpc_response_type::success, | ||||
|       .data = json::parse(resp->body), | ||||
|   }; | ||||
| } | ||||
|  | ||||
| auto client::get_open_files() -> rpc_response { | ||||
|   auto base_url = | ||||
|       "http://" + host_info_.host + ":" + std::to_string(host_info_.port); | ||||
|   | ||||
| @@ -50,6 +50,20 @@ void full_server::handle_get_directory_items(const httplib::Request &req, | ||||
|   res.status = http_error_codes::ok; | ||||
| } | ||||
|  | ||||
| void full_server::handle_get_item_info(const httplib::Request &req, | ||||
|                                        httplib::Response &res) { | ||||
|   auto api_path = utils::path::create_api_path(req.get_param_value("api_path")); | ||||
|   directory_item item; | ||||
|   auto ret = fm_.get_directory_item(api_path, item); | ||||
|   if (ret == api_error::success) { | ||||
|     res.set_content(json(item).dump(), "application/json"); | ||||
|     res.status = http_error_codes::ok; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   res.status = http_error_codes::not_found; | ||||
| } | ||||
|  | ||||
| void full_server::handle_get_drive_information(const httplib::Request & /*req*/, | ||||
|                                                httplib::Response &res) { | ||||
|   res.set_content( | ||||
| @@ -178,6 +192,11 @@ void full_server::initialize(httplib::Server &inst) { | ||||
|              handle_get_directory_items(std::forward<decltype(req)>(req), | ||||
|                                         std::forward<decltype(res)>(res)); | ||||
|            }); | ||||
|   inst.Get("/api/v1/" + rpc_method::get_item_info, | ||||
|            [this](auto &&req, auto &&res) { | ||||
|              handle_get_item_info(std::forward<decltype(req)>(req), | ||||
|                                   std::forward<decltype(res)>(res)); | ||||
|            }); | ||||
|   inst.Get("/api/v1/" + rpc_method::get_drive_information, | ||||
|            [this](auto &&req, auto &&res) { | ||||
|              handle_get_drive_information(std::forward<decltype(req)>(req), | ||||
|   | ||||
| @@ -27,6 +27,7 @@ | ||||
| #include "cli/drive_information.hpp" | ||||
| #include "cli/get.hpp" | ||||
| #include "cli/get_directory_items.hpp" | ||||
| #include "cli/get_item_info.hpp" | ||||
| #include "cli/get_pinned_files.hpp" | ||||
| #include "cli/get_version.hpp" | ||||
| #include "cli/help.hpp" | ||||
| @@ -62,6 +63,8 @@ inline const std::unordered_map<utils::cli::option, action, option_hasher> | ||||
|          cli::actions::drive_information}, | ||||
|         {utils::cli::options::get_directory_items_option, | ||||
|          cli::actions::get_directory_items}, | ||||
|         {utils::cli::options::get_item_info_option, | ||||
|          cli::actions::get_item_info}, | ||||
|         {utils::cli::options::get_option, cli::actions::get}, | ||||
|         {utils::cli::options::get_pinned_files_option, | ||||
|          cli::actions::get_pinned_files}, | ||||
|   | ||||
| @@ -54,4 +54,4 @@ get_directory_items(std::vector<const char *> args, | ||||
| } | ||||
| } // namespace repertory::cli::actions | ||||
|  | ||||
| #endif // REPERTORY_INCLUDE_CLI_GETDIRECTORYITEMS_HPP_ | ||||
| #endif // REPERTORY_INCLUDE_CLI_GET_DIRECTORY_ITEMS_HPP_ | ||||
|   | ||||
							
								
								
									
										56
									
								
								repertory/repertory/include/cli/get_item_info.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								repertory/repertory/include/cli/get_item_info.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| /* | ||||
|   Copyright <2018-2025> <scott.e.graves@protonmail.com> | ||||
|  | ||||
|   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_CLI_GET_ITEM_INFO_HPP_ | ||||
| #define REPERTORY_INCLUDE_CLI_GET_ITEM_INFO_HPP_ | ||||
|  | ||||
| #include "cli/common.hpp" | ||||
|  | ||||
| namespace repertory::cli::actions { | ||||
| [[nodiscard]] inline auto | ||||
| get_item_info(std::vector<const char *> args, const std::string &data_directory, | ||||
|               provider_type prov, const std::string & /* unique_id */, | ||||
|               std::string user, std::string password) -> exit_code { | ||||
|   std::string data; | ||||
|   auto ret = utils::cli::parse_string_option( | ||||
|       args, repertory::utils::cli::options::get_item_info_option, data); | ||||
|   if (ret == exit_code::success) { | ||||
|     auto port = app_config::default_api_port(prov); | ||||
|     utils::cli::get_api_authentication_data(user, password, port, prov, | ||||
|                                             data_directory); | ||||
|     auto response = client({.host = "localhost", | ||||
|                             .password = password, | ||||
|                             .port = port, | ||||
|                             .user = user}) | ||||
|                         .get_item_info(data); | ||||
|     if (response.response_type == rpc_response_type::success) { | ||||
|       std::cout << response.data.dump(2) << std::endl; | ||||
|     } else { | ||||
|       std::cerr << response.data.dump(2) << std::endl; | ||||
|       ret = exit_code::export_failed; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   return ret; | ||||
| } | ||||
| } // namespace repertory::cli::actions | ||||
|  | ||||
| #endif // REPERTORY_INCLUDE_CLI_GET_ITEM_INFO_HPP_ | ||||
| @@ -52,6 +52,10 @@ template <typename drive> inline void help(std::vector<const char *> args) { | ||||
|                "json format" | ||||
|             << std::endl | ||||
|             << "       [API path]" << std::endl; | ||||
|   std::cout << "    -gi,--get_item_info        Get item information in " | ||||
|                "json format" | ||||
|             << std::endl | ||||
|             << "       [API path]" << std::endl; | ||||
|   std::cout | ||||
|       << "    -gpf,--get_pinned_files           Get a list of all pinned files" | ||||
|       << std::endl; | ||||
|   | ||||
| @@ -57,6 +57,10 @@ public: | ||||
|   MOCK_METHOD(std::uint64_t, get_directory_item_count, | ||||
|               (const std::string &api_path), (const, override)); | ||||
|  | ||||
|   MOCK_METHOD(api_error, get_directory_item, | ||||
|               (const std::string &api_path, directory_item &item), | ||||
|               (const, override)); | ||||
|  | ||||
|   MOCK_METHOD(api_error, get_directory_items, | ||||
|               (const std::string &api_path, directory_item_list &list), | ||||
|               (const, override)); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user