Implement secure key via KDF for transparent data encryption/decryption #60
Some checks reported errors
BlockStorage/repertory/pipeline/head Something is wrong with the build of this commit

This commit is contained in:
2025-08-31 12:08:04 -05:00
parent 5a4e1302f1
commit e542aa64ad
16 changed files with 808 additions and 552 deletions

View File

@@ -29,6 +29,13 @@ class i_file_db {
INTERFACE_SETUP(i_file_db); INTERFACE_SETUP(i_file_db);
public: public:
struct directory_data final {
std::string api_path;
std::pair<utils::encryption::kdf_config, utils::encryption::kdf_config>
kdf_configs;
std::string source_path;
};
struct file_info final { struct file_info final {
std::string api_path; std::string api_path;
bool directory{}; bool directory{};
@@ -40,13 +47,14 @@ public:
std::uint64_t file_size{}; std::uint64_t file_size{};
std::vector< std::vector<
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>> std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list{}; iv_list;
std::pair<utils::encryption::kdf_config, utils::encryption::kdf_config>
kdf_configs;
std::string source_path; std::string source_path;
}; };
public: public:
[[nodiscard]] virtual auto add_directory(const std::string &api_path, [[nodiscard]] virtual auto add_or_update_directory(const directory_data &data)
const std::string &source_path)
-> api_error = 0; -> api_error = 0;
[[nodiscard]] virtual auto add_or_update_file(const file_data &data) [[nodiscard]] virtual auto add_or_update_file(const file_data &data)
@@ -68,6 +76,10 @@ public:
get_directory_api_path(const std::string &source_path, get_directory_api_path(const std::string &source_path,
std::string &api_path) const -> api_error = 0; std::string &api_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_directory_data(const std::string &api_path,
directory_data &data) const
-> api_error = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_source_path(const std::string &api_path, get_directory_source_path(const std::string &api_path,
std::string &source_path) const -> api_error = 0; std::string &source_path) const -> api_error = 0;

View File

@@ -67,8 +67,7 @@ private:
rocksdb::Transaction *txn) -> rocksdb::Status; rocksdb::Transaction *txn) -> rocksdb::Status;
public: public:
[[nodiscard]] auto add_directory(const std::string &api_path, [[nodiscard]] auto add_or_update_directory(const directory_data &data)
const std::string &source_path)
-> api_error override; -> api_error override;
[[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data) [[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data)
@@ -90,6 +89,10 @@ public:
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_data(const std::string &api_path,
i_file_db::directory_data &data) const
-> api_error override;
[[nodiscard]] auto get_directory_source_path(const std::string &api_path, [[nodiscard]] auto get_directory_source_path(const std::string &api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;

View File

@@ -42,8 +42,8 @@ private:
utils::db::sqlite::db3_t db_; utils::db::sqlite::db3_t db_;
public: public:
[[nodiscard]] auto add_directory(const std::string &api_path, [[nodiscard]] auto
const std::string &source_path) add_or_update_directory(const i_file_db::directory_data &data)
-> api_error override; -> api_error override;
[[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data) [[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data)
@@ -65,6 +65,10 @@ public:
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_data(const std::string &api_path,
i_file_db::directory_data &data) const
-> api_error override;
[[nodiscard]] auto get_directory_source_path(const std::string &api_path, [[nodiscard]] auto get_directory_source_path(const std::string &api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;

View File

@@ -49,8 +49,8 @@ private:
private: private:
api_item_added_callback api_item_added_; api_item_added_callback api_item_added_;
std::unique_ptr<i_meta_db> db3_; i_file_manager *fm_{nullptr};
i_file_manager *fm_{}; std::unique_ptr<i_meta_db> meta_db_;
private: private:
void add_all_items(stop_type &stop_requested); void add_all_items(stop_type &stop_requested);
@@ -106,9 +106,9 @@ protected:
return config_; return config_;
} }
[[nodiscard]] auto get_db() -> i_meta_db & { return *db3_; } [[nodiscard]] auto get_db() -> i_meta_db & { return *meta_db_; }
[[nodiscard]] auto get_db() const -> const i_meta_db & { return *db3_; } [[nodiscard]] auto get_db() const -> const i_meta_db & { return *meta_db_; }
[[nodiscard]] virtual auto [[nodiscard]] virtual auto
get_directory_items_impl(const std::string &api_path, get_directory_items_impl(const std::string &api_path,

View File

@@ -57,22 +57,26 @@ private:
encrypt_config encrypt_config_; encrypt_config encrypt_config_;
private: private:
std::unique_ptr<i_file_db> db_{nullptr}; std::unique_ptr<i_file_db> file_db_{nullptr};
i_file_manager *fm_{nullptr}; i_file_manager *fm_{nullptr};
utils::hash::hash_256_t master_key_{};
std::unordered_map<std::string, std::shared_ptr<reader_info>> reader_lookup_; std::unordered_map<std::string, std::shared_ptr<reader_info>> reader_lookup_;
std::recursive_mutex reader_lookup_mtx_; std::recursive_mutex reader_lookup_mtx_;
private: private:
static auto create_api_file(const std::string &api_path, bool directory, [[nodiscard]] static auto create_api_file(const std::string &api_path,
const std::string &source_path) -> api_file; bool directory,
const std::string &source_path)
-> api_file;
static void create_item_meta(api_meta_map &meta, bool directory, static void create_item_meta(api_meta_map &meta, bool directory,
const api_file &file); const api_file &file);
auto do_fs_operation(const std::string &api_path, bool directory, [[nodiscard]] auto do_fs_operation(
std::function<api_error(const encrypt_config &cfg, const std::string &api_path, bool directory,
const std::string &source_path)> std::function<api_error(const encrypt_config &cfg,
callback) const -> api_error; const std::string &source_path)> callback) const
-> api_error;
[[nodiscard]] auto get_encrypt_config() const -> const encrypt_config & { [[nodiscard]] auto get_encrypt_config() const -> const encrypt_config & {
return encrypt_config_; return encrypt_config_;

View File

@@ -490,7 +490,7 @@ template <> struct adl_serializer<repertory::encrypt_config> {
} }
if (not repertory::utils::encryption::kdf_config::from_header( if (not repertory::utils::encryption::kdf_config::from_header(
buffer, value.kdf_cfg)) { buffer, value.kdf_cfg, true)) {
throw repertory::utils::error::create_exception( throw repertory::utils::error::create_exception(
function_name, {"failed to parse kdf header"}); function_name, {"failed to parse kdf header"});
} }

View File

@@ -57,12 +57,12 @@ void rdb_file_db::create_or_open(bool clear) {
source_family_ = handles.at(idx++); source_family_ = handles.at(idx++);
} }
auto rdb_file_db::add_directory(const std::string &api_path, auto rdb_file_db::add_or_update_directory(const i_file_db::directory_data &data)
const std::string &source_path) -> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
std::string existing_source_path; std::string existing_source_path;
auto result = get_directory_source_path(api_path, existing_source_path); auto result = get_directory_source_path(data.api_path, existing_source_path);
if (result != api_error::success && if (result != api_error::success &&
result != api_error::directory_not_found) { result != api_error::directory_not_found) {
return result; return result;
@@ -71,23 +71,28 @@ auto rdb_file_db::add_directory(const std::string &api_path,
return perform_action( return perform_action(
function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status { function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status {
if (not existing_source_path.empty()) { if (not existing_source_path.empty()) {
auto res = remove_item(api_path, existing_source_path, txn); auto res = remove_item(data.api_path, existing_source_path, txn);
if (not res.ok() && not res.IsNotFound()) { if (not res.ok() && not res.IsNotFound()) {
return res; return res;
} }
} }
auto res = txn->Put(directory_family_, api_path, source_path); json json_data = {
{"kdf_configs", data.kdf_configs},
{"source_path", data.source_path},
};
auto res = txn->Put(directory_family_, data.api_path, json_data.dump());
if (not res.ok()) { if (not res.ok()) {
return res; return res;
} }
res = txn->Put(path_family_, api_path, source_path); res = txn->Put(path_family_, data.api_path, data.source_path);
if (not res.ok()) { if (not res.ok()) {
return res; return res;
} }
return txn->Put(source_family_, source_path, api_path); return txn->Put(source_family_, data.source_path, data.api_path);
}); });
} }
@@ -113,6 +118,7 @@ auto rdb_file_db::add_or_update_file(const i_file_db::file_data &data)
json json_data = { json json_data = {
{"file_size", data.file_size}, {"file_size", data.file_size},
{"iv", data.iv_list}, {"iv", data.iv_list},
{"kdf_configs", data.kdf_configs},
{"source_path", data.source_path}, {"source_path", data.source_path},
}; };
@@ -207,8 +213,9 @@ auto rdb_file_db::get_api_path(const std::string &source_path,
}); });
} }
auto rdb_file_db::get_directory_api_path( auto rdb_file_db::get_directory_api_path(const std::string &source_path,
const std::string &source_path, std::string &api_path) const -> api_error { std::string &api_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status { auto result = perform_action(function_name, [&]() -> rocksdb::Status {
@@ -231,13 +238,45 @@ auto rdb_file_db::get_directory_api_path(
: result; : result;
} }
auto rdb_file_db::get_directory_source_path( auto rdb_file_db::get_directory_data(const std::string &api_path,
const std::string &api_path, std::string &source_path) const -> api_error { i_file_db::directory_data &data) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status { auto result = perform_action(function_name, [&]() -> rocksdb::Status {
return db_->Get(rocksdb::ReadOptions{}, directory_family_, api_path, std::string value;
&source_path); auto res =
db_->Get(rocksdb::ReadOptions{}, directory_family_, api_path, &value);
if (not res.ok()) {
return res;
}
auto json_data = json::parse(value);
data.api_path = api_path;
json_data.at("kdf_configs").get_to(data.kdf_configs);
data.source_path = json_data.at("source_path").get<std::string>();
return res;
});
return result;
}
auto rdb_file_db::get_directory_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
std::string data;
auto ret =
db_->Get(rocksdb::ReadOptions{}, directory_family_, api_path, &data);
if (ret.ok()) {
source_path =
nlohmann::json::parse(data).at("source_path").get<std::string>();
}
return ret;
}); });
return result == api_error::item_not_found ? api_error::directory_not_found return result == api_error::item_not_found ? api_error::directory_not_found
@@ -285,6 +324,7 @@ auto rdb_file_db::get_file_data(const std::string &api_path,
.get<std::vector< .get<std::vector<
std::array<unsigned char, std::array<unsigned char,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>(); crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>();
json_data.at("kdf_configs").get_to(data.kdf_configs);
data.source_path = json_data.at("source_path").get<std::string>(); data.source_path = json_data.at("source_path").get<std::string>();
return res; return res;
@@ -293,8 +333,9 @@ auto rdb_file_db::get_file_data(const std::string &api_path,
return result; return result;
} }
auto rdb_file_db::get_file_source_path( auto rdb_file_db::get_file_source_path(const std::string &api_path,
const std::string &api_path, std::string &source_path) const -> api_error { std::string &source_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status { auto result = perform_action(function_name, [&]() -> rocksdb::Status {

View File

@@ -43,8 +43,9 @@ const std::map<std::string, std::string> sql_create_tables = {
"(" "("
"source_path TEXT PRIMARY KEY ASC, " "source_path TEXT PRIMARY KEY ASC, "
"api_path TEXT UNIQUE NOT NULL, " "api_path TEXT UNIQUE NOT NULL, "
"iv TEXT DEFAULT '' NOT NULL, "
"directory INTEGER NOT NULL, " "directory INTEGER NOT NULL, "
"iv TEXT DEFAULT '' NOT NULL, "
"kdf_configs TEXT NOT NULL, "
"size INTEGER DEFAULT 0 NOT NULL" "size INTEGER DEFAULT 0 NOT NULL"
");"}, ");"},
}, },
@@ -65,21 +66,23 @@ sqlite_file_db::sqlite_file_db(const app_config &cfg) {
sqlite_file_db::~sqlite_file_db() { db_.reset(); } sqlite_file_db::~sqlite_file_db() { db_.reset(); }
auto sqlite_file_db::add_directory( auto sqlite_file_db::add_or_update_directory(
const std::string &api_path, const std::string &source_path) -> api_error { const i_file_db::directory_data &data) -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto result = utils::db::sqlite::db_insert{*db_, file_table} auto result =
.column_value("api_path", api_path) utils::db::sqlite::db_insert{*db_, file_table}
.column_value("directory", 1) .column_value("api_path", data.api_path)
.column_value("source_path", source_path) .column_value("directory", 1)
.go(); .column_value("kdf_configs", nlohmann::json(data.kdf_configs).dump())
.column_value("source_path", data.source_path)
.go();
if (result.ok()) { if (result.ok()) {
return api_error::success; return api_error::success;
} }
utils::error::raise_api_path_error( utils::error::raise_api_path_error(
function_name, api_path, api_error::error, function_name, data.api_path, api_error::error,
fmt::format("failed to add directory|{}", result.get_error_str())); fmt::format("failed to add directory|{}", result.get_error_str()));
return api_error::error; return api_error::error;
} }
@@ -94,6 +97,7 @@ auto sqlite_file_db::add_or_update_file(const i_file_db::file_data &data)
.column_value("api_path", data.api_path) .column_value("api_path", data.api_path)
.column_value("directory", 0) .column_value("directory", 0)
.column_value("iv", json(data.iv_list).dump()) .column_value("iv", json(data.iv_list).dump())
.column_value("kdf_configs", json(data.kdf_configs).dump())
.column_value("size", static_cast<std::int64_t>(data.file_size)) .column_value("size", static_cast<std::int64_t>(data.file_size))
.column_value("source_path", data.source_path) .column_value("source_path", data.source_path)
.go(); .go();
@@ -182,8 +186,9 @@ auto sqlite_file_db::get_api_path(const std::string &source_path,
return api_error::item_not_found; return api_error::item_not_found;
} }
auto sqlite_file_db::get_directory_api_path( auto sqlite_file_db::get_directory_api_path(const std::string &source_path,
const std::string &source_path, std::string &api_path) const -> api_error { std::string &api_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table} auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("api_path") .column("api_path")
.where("source_path") .where("source_path")
@@ -204,8 +209,39 @@ auto sqlite_file_db::get_directory_api_path(
return api_error::directory_not_found; return api_error::directory_not_found;
} }
auto sqlite_file_db::get_directory_source_path( auto sqlite_file_db::get_directory_data(const std::string &api_path,
const std::string &api_path, std::string &source_path) const -> api_error { i_file_db::directory_data &data) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("kdf_configs")
.column("source_path")
.where("api_path")
.equals(api_path)
.and_()
.where("directory")
.equals(0)
.op()
.limit(1)
.go();
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
data.api_path = api_path;
data.source_path = row->get_column("source_path").get_value<std::string>();
auto str_data = row->get_column("kdf_configs").get_value<std::string>();
if (not str_data.empty()) {
json::parse(str_data).get_to(data.kdf_configs);
}
return api_error::success;
}
return api_error::item_not_found;
}
auto sqlite_file_db::get_directory_source_path(const std::string &api_path,
std::string &source_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table} auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("source_path") .column("source_path")
.where("api_path") .where("api_path")
@@ -226,8 +262,9 @@ auto sqlite_file_db::get_directory_source_path(
return api_error::directory_not_found; return api_error::directory_not_found;
} }
auto sqlite_file_db::get_file_api_path( auto sqlite_file_db::get_file_api_path(const std::string &source_path,
const std::string &source_path, std::string &api_path) const -> api_error { std::string &api_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table} auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("api_path") .column("api_path")
.where("source_path") .where("source_path")
@@ -253,6 +290,7 @@ auto sqlite_file_db::get_file_data(const std::string &api_path,
-> api_error { -> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table} auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("iv") .column("iv")
.column("kdf_configs")
.column("size") .column("size")
.column("source_path") .column("source_path")
.where("api_path") .where("api_path")
@@ -280,14 +318,20 @@ auto sqlite_file_db::get_file_data(const std::string &api_path,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>(); crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>();
} }
str_data = row->get_column("kdf_configs").get_value<std::string>();
if (not str_data.empty()) {
json::parse(str_data).get_to(data.kdf_configs);
}
return api_error::success; return api_error::success;
} }
return api_error::item_not_found; return api_error::item_not_found;
} }
auto sqlite_file_db::get_file_source_path( auto sqlite_file_db::get_file_source_path(const std::string &api_path,
const std::string &api_path, std::string &source_path) const -> api_error { std::string &source_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table} auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("source_path") .column("source_path")
.where("api_path") .where("api_path")
@@ -329,8 +373,9 @@ auto sqlite_file_db::get_item_list(stop_type_callback stop_requested_cb) const
return ret; return ret;
} }
auto sqlite_file_db::get_source_path( auto sqlite_file_db::get_source_path(const std::string &api_path,
const std::string &api_path, std::string &source_path) const -> api_error { std::string &source_path) const
-> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table} auto result = utils::db::sqlite::db_select{*db_, file_table}
.column("source_path") .column("source_path")
.where("api_path") .where("api_path")

View File

@@ -248,7 +248,7 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
stop_type stop_requested{false}; stop_type stop_requested{false};
res = upload_file(api_path, meta[META_SOURCE], stop_requested); res = upload_file(api_path, meta[META_SOURCE], stop_requested);
if (res != api_error::success) { if (res != api_error::success) {
db3_->remove_api_path(api_path); meta_db_->remove_api_path(api_path);
} }
return res; return res;
@@ -272,7 +272,7 @@ auto base_provider::get_api_path_from_source(const std::string &source_path,
return api_error::item_not_found; return api_error::item_not_found;
} }
return db3_->get_api_path(source_path, api_path); return meta_db_->get_api_path(source_path, api_path);
} }
auto base_provider::get_directory_item(const std::string &api_path, auto base_provider::get_directory_item(const std::string &api_path,
@@ -481,25 +481,25 @@ auto base_provider::get_filesystem_item_from_source_path(
auto base_provider::get_item_meta(const std::string &api_path, auto base_provider::get_item_meta(const std::string &api_path,
api_meta_map &meta) const -> api_error { api_meta_map &meta) const -> api_error {
return db3_->get_item_meta(api_path, meta); return meta_db_->get_item_meta(api_path, meta);
} }
auto base_provider::get_item_meta(const std::string &api_path, auto base_provider::get_item_meta(const std::string &api_path,
const std::string &key, const std::string &key,
std::string &value) const -> api_error { std::string &value) const -> api_error {
return db3_->get_item_meta(api_path, key, value); return meta_db_->get_item_meta(api_path, key, value);
} }
auto base_provider::get_pinned_files() const -> std::vector<std::string> { auto base_provider::get_pinned_files() const -> std::vector<std::string> {
return db3_->get_pinned_files(); return meta_db_->get_pinned_files();
} }
auto base_provider::get_total_item_count() const -> std::uint64_t { auto base_provider::get_total_item_count() const -> std::uint64_t {
return db3_->get_total_item_count(); return meta_db_->get_total_item_count();
} }
auto base_provider::get_used_drive_space() const -> std::uint64_t { auto base_provider::get_used_drive_space() const -> std::uint64_t {
return db3_->get_total_size(); return meta_db_->get_total_size();
} }
auto base_provider::is_file_writeable(const std::string &api_path) const auto base_provider::is_file_writeable(const std::string &api_path) const
@@ -530,7 +530,7 @@ void base_provider::process_removed_directories(
continue; continue;
} }
db3_->remove_api_path(item.api_path); meta_db_->remove_api_path(item.api_path);
event_system::instance().raise<directory_removed_externally>( event_system::instance().raise<directory_removed_externally>(
item.api_path, function_name, item.source_path); item.api_path, function_name, item.source_path);
} }
@@ -557,7 +557,7 @@ void base_provider::process_removed_files(std::deque<removed_item> removed_list,
} }
if (not utils::file::file{item.source_path}.exists()) { if (not utils::file::file{item.source_path}.exists()) {
db3_->remove_api_path(item.api_path); meta_db_->remove_api_path(item.api_path);
event_system::instance().raise<file_removed_externally>( event_system::instance().raise<file_removed_externally>(
item.api_path, function_name, item.source_path); item.api_path, function_name, item.source_path);
continue; continue;
@@ -601,7 +601,7 @@ void base_provider::process_removed_files(std::deque<removed_item> removed_list,
continue; continue;
} }
db3_->remove_api_path(item.api_path); meta_db_->remove_api_path(item.api_path);
event_system::instance().raise<file_removed_externally>( event_system::instance().raise<file_removed_externally>(
item.api_path, function_name, item.source_path); item.api_path, function_name, item.source_path);
} }
@@ -612,7 +612,7 @@ void base_provider::process_removed_items(stop_type &stop_requested) {
return stop_requested || app_config::get_stop_requested(); return stop_requested || app_config::get_stop_requested();
}; };
db3_->enumerate_api_path_list( meta_db_->enumerate_api_path_list(
[this, &get_stop_requested](auto &&list) { [this, &get_stop_requested](auto &&list) {
[[maybe_unused]] auto res = [[maybe_unused]] auto res =
std::all_of(list.begin(), list.end(), [&](auto &&api_path) -> bool { std::all_of(list.begin(), list.end(), [&](auto &&api_path) -> bool {
@@ -706,7 +706,7 @@ auto base_provider::remove_file(const std::string &api_path) -> api_error {
const auto remove_file_meta = [this, &api_path, &notify_end]() -> api_error { const auto remove_file_meta = [this, &api_path, &notify_end]() -> api_error {
api_meta_map meta{}; api_meta_map meta{};
auto res = get_item_meta(api_path, meta); auto res = get_item_meta(api_path, meta);
db3_->remove_api_path(api_path); meta_db_->remove_api_path(api_path);
return notify_end(res); return notify_end(res);
}; };
@@ -766,14 +766,14 @@ auto base_provider::remove_directory(const std::string &api_path) -> api_error {
return notify_end(res); return notify_end(res);
} }
db3_->remove_api_path(api_path); meta_db_->remove_api_path(api_path);
return notify_end(api_error::success); return notify_end(api_error::success);
} }
auto base_provider::remove_item_meta(const std::string &api_path, auto base_provider::remove_item_meta(const std::string &api_path,
const std::string &key) -> api_error { const std::string &key) -> api_error {
return db3_->remove_item_meta(api_path, key); return meta_db_->remove_item_meta(api_path, key);
} }
void base_provider::remove_unmatched_source_files(stop_type &stop_requested) { void base_provider::remove_unmatched_source_files(stop_type &stop_requested) {
@@ -831,12 +831,12 @@ void base_provider::remove_unmatched_source_files(stop_type &stop_requested) {
auto base_provider::set_item_meta(const std::string &api_path, auto base_provider::set_item_meta(const std::string &api_path,
const std::string &key, const std::string &key,
const std::string &value) -> api_error { const std::string &value) -> api_error {
return db3_->set_item_meta(api_path, key, value); return meta_db_->set_item_meta(api_path, key, value);
} }
auto base_provider::set_item_meta(const std::string &api_path, auto base_provider::set_item_meta(const std::string &api_path,
const api_meta_map &meta) -> api_error { const api_meta_map &meta) -> api_error {
return db3_->set_item_meta(api_path, meta); return meta_db_->set_item_meta(api_path, meta);
} }
auto base_provider::start(api_item_added_callback api_item_added, auto base_provider::start(api_item_added_callback api_item_added,
@@ -845,8 +845,7 @@ auto base_provider::start(api_item_added_callback api_item_added,
api_item_added_ = api_item_added; api_item_added_ = api_item_added;
fm_ = mgr; fm_ = mgr;
meta_db_ = create_meta_db(config_);
db3_ = create_meta_db(config_);
api_meta_map meta{}; api_meta_map meta{};
if (get_item_meta("/", meta) == api_error::item_not_found) { if (get_item_meta("/", meta) == api_error::item_not_found) {
@@ -906,7 +905,7 @@ auto base_provider::start(api_item_added_callback api_item_added,
void base_provider::stop() { void base_provider::stop() {
cache_size_mgr::instance().stop(); cache_size_mgr::instance().stop();
polling::instance().remove_callback("check_deleted"); polling::instance().remove_callback("check_deleted");
db3_.reset(); meta_db_.reset();
} }
auto base_provider::upload_file(const std::string &api_path, auto base_provider::upload_file(const std::string &api_path,

View File

@@ -22,6 +22,7 @@
#include "providers/encrypt/encrypt_provider.hpp" #include "providers/encrypt/encrypt_provider.hpp"
#include "db/file_db.hpp" #include "db/file_db.hpp"
#include "db/meta_db.hpp"
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/types/directory_removed_externally.hpp" #include "events/types/directory_removed_externally.hpp"
#include "events/types/file_removed_externally.hpp" #include "events/types/file_removed_externally.hpp"
@@ -32,7 +33,8 @@
#include "events/types/service_stop_end.hpp" #include "events/types/service_stop_end.hpp"
#include "types/repertory.hpp" #include "types/repertory.hpp"
#include "types/startup_exception.hpp" #include "types/startup_exception.hpp"
#include "utils/collection.hpp" #include "utils/base64.hpp"
#include "utils/common.hpp"
#include "utils/config.hpp" #include "utils/config.hpp"
#include "utils/encrypting_reader.hpp" #include "utils/encrypting_reader.hpp"
#include "utils/encryption.hpp" #include "utils/encryption.hpp"
@@ -64,7 +66,7 @@ auto encrypt_provider::create_api_file(const std::string &api_path,
directory directory
? 0U ? 0U
: utils::encryption::encrypting_reader::calculate_encrypted_size( : utils::encryption::encrypting_reader::calculate_encrypted_size(
source_path, false); source_path, true);
file.modified_date = times->get(utils::file::time_type::written); file.modified_date = times->get(utils::file::time_type::written);
file.source_path = source_path; file.source_path = source_path;
@@ -163,7 +165,7 @@ auto encrypt_provider::get_api_path_from_source(const std::string &source_path,
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
return db_->get_api_path(source_path, api_path); return file_db_->get_api_path(source_path, api_path);
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex, source_path, utils::error::raise_error(function_name, ex, source_path,
"failed to get api path from source path"); "failed to get api path from source path");
@@ -245,38 +247,38 @@ auto encrypt_provider::get_directory_items(const std::string &api_path,
try { try {
std::string current_api_path; std::string current_api_path;
if (dir_entry->is_directory_item()) { if (dir_entry->is_directory_item()) {
auto result{ auto res{
db_->get_directory_api_path(dir_entry->get_path(), file_db_->get_directory_api_path(dir_entry->get_path(),
current_api_path), current_api_path),
}; };
if (result != api_error::success && if (res != api_error::success &&
result != api_error::directory_not_found) { res != api_error::directory_not_found) {
// TODO raise error // TODO raise error
continue; continue;
} }
if (result == api_error::directory_not_found) { if (res == api_error::directory_not_found) {
process_directory_entry(*dir_entry, cfg, current_api_path); process_directory_entry(*dir_entry, cfg, current_api_path);
result = db_->get_directory_api_path(dir_entry->get_path(), res = file_db_->get_directory_api_path(dir_entry->get_path(),
current_api_path); current_api_path);
if (result != api_error::success && if (res != api_error::success &&
result != api_error::directory_not_found) { res != api_error::directory_not_found) {
// TODO raise error // TODO raise error
continue; continue;
} }
} }
} else { } else {
auto result{ auto res{
db_->get_file_api_path(dir_entry->get_path(), file_db_->get_file_api_path(dir_entry->get_path(),
current_api_path), current_api_path),
}; };
if (result != api_error::success && if (res != api_error::success &&
result != api_error::item_not_found) { res != api_error::item_not_found) {
// TODO raise error // TODO raise error
continue; continue;
} }
if (result == api_error::item_not_found && if (res == api_error::item_not_found &&
not process_directory_entry(*dir_entry, cfg, not process_directory_entry(*dir_entry, cfg,
current_api_path)) { current_api_path)) {
continue; continue;
@@ -357,9 +359,9 @@ auto encrypt_provider::get_file(const std::string &api_path,
} }
std::string source_path; std::string source_path;
auto result{db_->get_file_source_path(api_path, source_path)}; res = file_db_->get_file_source_path(api_path, source_path);
if (result != api_error::success) { if (res != api_error::success) {
return result; return res;
} }
file = create_api_file(api_path, false, source_path); file = create_api_file(api_path, false, source_path);
@@ -414,13 +416,13 @@ auto encrypt_provider::get_file_size(const std::string &api_path,
try { try {
std::string source_path; std::string source_path;
auto result{db_->get_file_source_path(api_path, source_path)}; auto res{file_db_->get_file_source_path(api_path, source_path)};
if (result != api_error::success) { if (res != api_error::success) {
return result; return res;
} }
file_size = utils::encryption::encrypting_reader::calculate_encrypted_size( file_size = utils::encryption::encrypting_reader::calculate_encrypted_size(
source_path, false); source_path, true);
return api_error::success; return api_error::success;
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex, api_path, utils::error::raise_error(function_name, ex, api_path,
@@ -436,9 +438,9 @@ auto encrypt_provider::get_filesystem_item(const std::string &api_path,
-> api_error { -> api_error {
std::string source_path; std::string source_path;
if (directory) { if (directory) {
auto result{db_->get_directory_source_path(api_path, source_path)}; auto res{file_db_->get_directory_source_path(api_path, source_path)};
if (result != api_error::success) { if (res != api_error::success) {
return result; return res;
} }
fsi.api_parent = utils::path::get_parent_api_path(api_path); fsi.api_parent = utils::path::get_parent_api_path(api_path);
@@ -449,16 +451,16 @@ auto encrypt_provider::get_filesystem_item(const std::string &api_path,
return api_error::success; return api_error::success;
} }
auto result{db_->get_file_source_path(api_path, source_path)}; auto res{file_db_->get_file_source_path(api_path, source_path)};
if (result != api_error::success) { if (res != api_error::success) {
return result; return res;
} }
fsi.api_path = api_path; fsi.api_path = api_path;
fsi.api_parent = utils::path::get_parent_api_path(fsi.api_path); fsi.api_parent = utils::path::get_parent_api_path(fsi.api_path);
fsi.directory = false; fsi.directory = false;
fsi.size = utils::encryption::encrypting_reader::calculate_encrypted_size( fsi.size = utils::encryption::encrypting_reader::calculate_encrypted_size(
source_path, false); source_path, true);
fsi.source_path = source_path; fsi.source_path = source_path;
return api_error::success; return api_error::success;
@@ -525,15 +527,15 @@ auto encrypt_provider::get_item_meta(const std::string &api_path,
try { try {
std::string source_path; std::string source_path;
auto result{db_->get_source_path(api_path, source_path)}; auto res{file_db_->get_source_path(api_path, source_path)};
if (result != api_error::success) { if (res != api_error::success) {
return result; return res;
} }
bool is_dir{}; bool is_dir{};
result = is_directory(api_path, is_dir); res = is_directory(api_path, is_dir);
if (result != api_error::success) { if (res != api_error::success) {
return result; return res;
} }
auto file{create_api_file(api_path, is_dir, source_path)}; auto file{create_api_file(api_path, is_dir, source_path)};
@@ -569,7 +571,7 @@ auto encrypt_provider::get_total_item_count() const -> std::uint64_t {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
return db_->count(); return file_db_->count();
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
utils::error::raise_error(function_name, ex, utils::error::raise_error(function_name, ex,
"failed to get total item count"); "failed to get total item count");
@@ -592,11 +594,11 @@ auto encrypt_provider::is_directory(const std::string &api_path,
try { try {
std::string source_path; std::string source_path;
auto result{db_->get_directory_source_path(api_path, source_path)}; auto res{file_db_->get_directory_source_path(api_path, source_path)};
if (result != api_error::success) { if (res != api_error::success) {
if (result != api_error::directory_not_found) { if (res != api_error::directory_not_found) {
return result; return res;
} }
exists = false; exists = false;
@@ -619,10 +621,10 @@ auto encrypt_provider::is_file(const std::string &api_path, bool &exists) const
try { try {
std::string source_path; std::string source_path;
auto result{db_->get_file_source_path(api_path, source_path)}; auto res{file_db_->get_file_source_path(api_path, source_path)};
if (result != api_error::success) { if (res != api_error::success) {
if (result != api_error::item_not_found) { if (res != api_error::item_not_found) {
return result; return res;
} }
exists = false; exists = false;
@@ -661,53 +663,100 @@ auto encrypt_provider::process_directory_entry(
false), false),
}; };
auto current_source_path{cfg.path};
std::string current_api_path;
for (std::size_t part_idx = 1U; part_idx < encrypted_parts.size(); for (std::size_t part_idx = 1U; part_idx < encrypted_parts.size();
++part_idx) { ++part_idx) {
current_source_path = utils::path::combine(
current_source_path, {encrypted_parts.at(part_idx)});
i_file_db::directory_data dir_data{};
std::string dir_api_path;
auto res =
file_db_->get_directory_api_path(current_source_path, dir_api_path);
if (res == api_error::success) {
res = file_db_->get_directory_data(dir_api_path, dir_data);
if (res != api_error::success) {
throw std::runtime_error(
fmt::format("failed to get directory file data|{}",
api_error_to_string(res)));
}
} else if (res == api_error::directory_not_found) {
dir_data.kdf_configs.first = dir_data.kdf_configs.second =
cfg.kdf_cfg;
dir_data.kdf_configs.first.unique_id =
utils::generate_secure_random<std::uint64_t>();
dir_data.kdf_configs.second.unique_id =
utils::generate_secure_random<std::uint64_t>();
dir_data.kdf_configs.first.seal();
dir_data.kdf_configs.second.seal();
} else {
throw std::runtime_error(fmt::format(
"failed to get directory api path|{}", api_error_to_string(res)));
}
auto path_key = dir_data.kdf_configs.second.recreate_subkey(
utils::encryption::kdf_context::path, master_key_);
data_buffer encrypted_data; data_buffer encrypted_data;
utils::encryption::encrypt_data( utils::encryption::encrypt_data(
cfg.encryption_token, path_key,
reinterpret_cast<const unsigned char *>( reinterpret_cast<const unsigned char *>(
encrypted_parts.at(part_idx).c_str()), encrypted_parts.at(part_idx).c_str()),
strnlen(encrypted_parts.at(part_idx).c_str(), strnlen(encrypted_parts.at(part_idx).c_str(),
encrypted_parts.at(part_idx).size()), encrypted_parts.at(part_idx).size()),
encrypted_data); encrypted_data);
encrypted_parts[part_idx] =
utils::collection::to_hex_string(encrypted_data); auto hdr = dir_data.kdf_configs.second.to_header();
encrypted_data.insert(encrypted_data.begin(), hdr.begin(), hdr.end());
encrypted_parts[part_idx] = macaron::Base64::EncodeUrlSafe(
encrypted_data.data(), encrypted_data.size());
if (dir_api_path.empty()) {
current_api_path = utils::path::create_api_path(
current_api_path + '/' + encrypted_parts.at(part_idx));
dir_data.api_path = current_api_path;
dir_data.source_path = current_source_path;
res = file_db_->add_or_update_directory(dir_data);
if (res != api_error::success) {
throw std::runtime_error(
fmt::format("failed to set directory file data|{}",
api_error_to_string(res)));
}
event_system::instance().raise<filesystem_item_added>(
utils::path::get_parent_api_path(dir_api_path), dir_api_path,
true, function_name);
}
} }
std::size_t current_idx{1U}; std::size_t current_idx{1U};
std::string current_encrypted_path{}; std::string current_encrypted_path{};
auto current_source_path{cfg.path}; current_source_path = cfg.path;
for (const auto &part : utils::path::get_parts(dir_path)) { for (const auto &part : utils::path::get_parts(dir_path)) {
current_source_path = utils::path::combine(current_source_path, {part}); current_source_path = utils::path::combine(current_source_path, {part});
std::string current_api_path{}; auto dir_api_path = utils::path::create_api_path(
auto result{ current_encrypted_path + '/' + encrypted_parts.at(current_idx));
db_->get_directory_api_path(current_source_path, current_api_path), i_file_db::directory_data dir_data;
}; auto res = file_db_->get_directory_data(dir_api_path, dir_data);
if (result == api_error::directory_not_found) { if (res == api_error::directory_not_found) {
current_api_path = utils::path::create_api_path( dir_data.source_path = current_api_path;
current_encrypted_path + '/' + encrypted_parts.at(current_idx)); res = file_db_->add_or_update_directory(dir_data);
if (res != api_error::success) {
result = db_->add_directory(current_api_path, current_source_path); throw std::runtime_error(
if (result != api_error::success) {
std::runtime_error(
fmt::format("failed to get directory api path|{}", fmt::format("failed to get directory api path|{}",
api_error_to_string(result))); api_error_to_string(res)));
} }
event_system::instance().raise<filesystem_item_added>( event_system::instance().raise<filesystem_item_added>(
utils::path::get_parent_api_path(current_api_path), utils::path::get_parent_api_path(dir_api_path), dir_api_path,
current_api_path, true, function_name); true, function_name);
} else { } else if (res == api_error::success) {
if (result != api_error::success) {
std::runtime_error(
fmt::format("failed to get directory api path|{}",
api_error_to_string(result)));
}
encrypted_parts[current_idx] = encrypted_parts[current_idx] =
utils::string::split(current_api_path, '/', false)[current_idx]; utils::string::split(dir_api_path, '/', false)[current_idx];
} else {
throw std::runtime_error(fmt::format(
"failed to get directory api path|{}", api_error_to_string(res)));
} }
current_encrypted_path = utils::path::create_api_path( current_encrypted_path = utils::path::create_api_path(
@@ -728,17 +777,16 @@ auto encrypt_provider::process_directory_entry(
utils::path::get_relative_path(dir_entry.get_path(), cfg.path), utils::path::get_relative_path(dir_entry.get_path(), cfg.path),
}; };
i_file_db::file_data data; i_file_db::file_data file_data{};
auto file_res{db_->get_file_data(dir_entry.get_path(), data)}; auto file_res{file_db_->get_file_data(api_path, file_data)};
if (file_res != api_error::success && if (file_res != api_error::success) {
file_res != api_error::item_not_found) {
// TODO raise error // TODO raise error
return false; return false;
} }
std::string api_parent{}; std::string api_parent{};
auto parent_res{ auto parent_res{
db_->get_directory_api_path( file_db_->get_directory_api_path(
utils::path::get_parent_path(dir_entry.get_path()), api_parent), utils::path::get_parent_path(dir_entry.get_path()), api_parent),
}; };
if (parent_res != api_error::success && if (parent_res != api_error::success &&
@@ -757,16 +805,22 @@ auto encrypt_provider::process_directory_entry(
utils::path::strip_to_file_name(relative_path), utils::path::strip_to_file_name(relative_path),
dir_entry.get_path(), dir_entry.get_path(),
[]() -> bool { return app_config::get_stop_requested(); }, []() -> bool { return app_config::get_stop_requested(); },
cfg.encryption_token, utils::path::get_parent_path(relative_path)); master_key_, file_data.kdf_configs,
utils::path::get_parent_path(relative_path));
api_path = utils::path::create_api_path( api_path = utils::path::create_api_path(
api_parent + "/" + reader.get_encrypted_file_name()); api_parent + "/" + reader.get_encrypted_file_name());
file_res = db_->add_or_update_file(i_file_db::file_data{ file_res = file_db_->add_or_update_file(i_file_db::file_data{
.api_path = api_path, .api_path = api_path,
.file_size = dynamic_cast<const utils::file::i_file *>(&dir_entry) .file_size = dynamic_cast<const utils::file::i_file *>(&dir_entry)
->size() ->size()
.value_or(0U), .value_or(0U),
.iv_list = reader.get_iv_list(), .iv_list = reader.get_iv_list(),
.kdf_configs =
{
*reader.get_kdf_config_for_data(),
*reader.get_kdf_config_for_path(),
},
.source_path = dir_entry.get_path(), .source_path = dir_entry.get_path(),
}); });
if (file_res != api_error::success) { if (file_res != api_error::success) {
@@ -795,9 +849,9 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
i_file_db::file_data file_data{}; i_file_db::file_data file_data{};
auto result{db_->get_file_data(api_path, file_data)}; auto res{file_db_->get_file_data(api_path, file_data)};
if (result != api_error::success) { if (res != api_error::success) {
return result; return res;
} }
auto opt_size{utils::file::file{file_data.source_path}.size()}; auto opt_size{utils::file::file{file_data.source_path}.size()};
@@ -822,18 +876,19 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
[&stop_requested]() -> bool { [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested(); return stop_requested || app_config::get_stop_requested();
}, },
cfg.encryption_token, utils::path::get_parent_path(relative_path)); master_key_, file_data.kdf_configs,
utils::path::get_parent_path(relative_path));
reader_lookup_[file_data.source_path] = info; reader_lookup_[file_data.source_path] = info;
file_data.file_size = file_size; file_data.file_size = file_size;
file_data.iv_list = info->reader->get_iv_list(); file_data.iv_list = info->reader->get_iv_list();
result = db_->add_or_update_file(file_data); res = file_db_->add_or_update_file(file_data);
file_data.iv_list.clear(); file_data.iv_list.clear();
if (result != api_error::success) { if (res != api_error::success) {
utils::error::raise_error(function_name, result, file_data.source_path, utils::error::raise_error(function_name, res, file_data.source_path,
"failed to update file"); "failed to update file");
return result; return res;
} }
} else if (not reader_lookup_.contains(file_data.source_path)) { } else if (not reader_lookup_.contains(file_data.source_path)) {
auto info{std::make_shared<reader_info>()}; auto info{std::make_shared<reader_info>()};
@@ -841,7 +896,7 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
[&stop_requested]() -> bool { [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested(); return stop_requested || app_config::get_stop_requested();
}, },
api_path, file_data.source_path, cfg.encryption_token, api_path, file_data.source_path, master_key_, file_data.kdf_configs,
std::move(file_data.iv_list)); std::move(file_data.iv_list));
reader_lookup_[file_data.source_path] = info; reader_lookup_[file_data.source_path] = info;
} }
@@ -858,12 +913,12 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
info->reader->set_read_position(offset); info->reader->set_read_position(offset);
data.resize(size); data.resize(size);
auto res{ auto ret{
utils::encryption::encrypting_reader::reader_function( utils::encryption::encrypting_reader::reader_function(
reinterpret_cast<char *>(data.data()), 1U, data.size(), reinterpret_cast<char *>(data.data()), 1U, data.size(),
info->reader.get()), info->reader.get()),
}; };
return res == 0 ? api_error::os_error : api_error::success; return ret == 0 ? api_error::os_error : api_error::success;
} }
void encrypt_provider::remove_deleted_files(stop_type &stop_requested) { void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
@@ -873,7 +928,7 @@ void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
return stop_requested || app_config::get_stop_requested(); return stop_requested || app_config::get_stop_requested();
}; };
db_->enumerate_item_list( file_db_->enumerate_item_list(
[this, &get_stop_requested](auto &&list) { [this, &get_stop_requested](auto &&list) {
std::vector<i_file_db::file_info> removed_list{}; std::vector<i_file_db::file_info> removed_list{};
for (const auto &item : list) { for (const auto &item : list) {
@@ -893,7 +948,7 @@ void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
return; return;
} }
auto res{db_->remove_item(item.api_path)}; auto res{file_db_->remove_item(item.api_path)};
if (res != api_error::success) { if (res != api_error::success) {
utils::error::raise_api_path_error( utils::error::raise_api_path_error(
function_name, item.api_path, item.source_path, res, function_name, item.api_path, item.source_path, res,
@@ -943,18 +998,37 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
event_system::instance().raise<service_start_begin>(function_name, event_system::instance().raise<service_start_begin>(function_name,
"encrypt_provider"); "encrypt_provider");
db_ = create_file_db(config_); if (encrypt_config_.kdf_cfg.checksum == 0U) {
encrypt_config_.kdf_cfg.seal();
config_.set_encrypt_config(encrypt_config_);
}
if (encrypt_config_.kdf_cfg.checksum !=
encrypt_config_.kdf_cfg.generate_checksum()) {
utils::error::raise_error(
function_name, "existing kdf configuration failed checksum validation");
return false;
}
if (not utils::encryption::recreate_key_argon2id(
get_encrypt_config().encryption_token, get_encrypt_config().kdf_cfg,
master_key_)) {
utils::error::raise_error(function_name,
"failed to recreate master key from kdf config");
return false;
}
file_db_ = create_file_db(config_);
std::string source_path; std::string source_path;
auto result{db_->get_directory_source_path("/", source_path)}; auto res{file_db_->get_directory_source_path("/", source_path)};
if (result != api_error::success && if (res != api_error::success && res != api_error::directory_not_found) {
result != api_error::directory_not_found) {
throw startup_exception( throw startup_exception(
fmt::format("failed to get root|{}", api_error_to_string(result))); fmt::format("failed to get root|{}", api_error_to_string(res)));
} }
auto cfg_path{utils::path::absolute(get_encrypt_config().path)}; auto cfg_path{utils::path::absolute(get_encrypt_config().path)};
if (result == api_error::success) { if (res == api_error::success) {
auto cur_path{utils::path::absolute(source_path)}; auto cur_path{utils::path::absolute(source_path)};
#if defined(_WIN32) #if defined(_WIN32)
if (utils::string::to_lower(cur_path) != if (utils::string::to_lower(cur_path) !=
@@ -966,10 +1040,15 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
"source path has changed|cur|{}|cfg|{}", cur_path, cfg_path)); "source path has changed|cur|{}|cfg|{}", cur_path, cfg_path));
} }
} else { } else {
result = db_->add_directory("/", utils::path::absolute(cfg_path)); i_file_db::directory_data dir_data{
if (result != api_error::success) { .api_path = "/",
.kdf_configs = {},
.source_path = cfg_path,
};
res = file_db_->add_or_update_directory(dir_data);
if (res != api_error::success) {
throw startup_exception( throw startup_exception(
fmt::format("failed to create root|{}", api_error_to_string(result))); fmt::format("failed to create root|{}", api_error_to_string(res)));
} }
} }
@@ -984,7 +1063,7 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
polling::instance().set_callback({ polling::instance().set_callback({
.name = "remove_expired", .name = "remove_expired",
.freq = polling::frequency::high, .freq = polling::frequency::second,
.action = .action =
[this](auto && /* stop_requested */) { remove_expired_files(); }, [this](auto && /* stop_requested */) { remove_expired_files(); },
}); });
@@ -1006,7 +1085,7 @@ void encrypt_provider::stop() {
reader_lookup_.clear(); reader_lookup_.clear();
reader_lookup_lock.unlock(); reader_lookup_lock.unlock();
db_.reset(); file_db_.reset();
event_system::instance().raise<service_stop_end>(function_name, event_system::instance().raise<service_stop_end>(function_name,
"encrypt_provider"); "encrypt_provider");
} }

View File

@@ -1025,7 +1025,8 @@ auto s3_provider::search_keys_for_master_kdf(
std::string token{}; std::string token{};
std::string response_data{}; std::string response_data{};
long response_code{}; long response_code{};
if (not get_object_list(response_data, response_code, "/", "", token)) { if (not get_object_list(response_data, response_code, std::nullopt,
std::nullopt, token)) {
throw utils::error::create_exception(function_name, throw utils::error::create_exception(function_name,
{"failed to get object list"}); {"failed to get object list"});
} }
@@ -1060,9 +1061,10 @@ auto s3_provider::search_keys_for_master_kdf(
auto buffer = macaron::Base64::Decode(object_name); auto buffer = macaron::Base64::Decode(object_name);
if (not utils::encryption::kdf_config::from_header(buffer, if (not utils::encryption::kdf_config::from_header(buffer,
master_kdf_cfg_)) { master_kdf_cfg_)) {
continue; throw std::runtime_error("from_header failed");
} }
} catch (...) { } catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "exception occurred");
continue; continue;
} }

View File

@@ -1,368 +1,370 @@
/* // /*
Copyright <2018-2025> <scott.e.graves@protonmail.com> // Copyright <2018-2025> <scott.e.graves@protonmail.com>
//
Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a
of this software and associated documentation files (the "Software"), to deal // copy of this software and associated documentation files (the "Software"),
in the Software without restriction, including without limitation the rights // to deal in the Software without restriction, including without limitation
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // the rights to use, copy, modify, merge, publish, distribute, sublicense,
copies of the Software, and to permit persons to whom the Software is // and/or sell copies of the Software, and to permit persons to whom the
furnished to do so, subject to the following conditions: // Software is furnished to do so, subject to the following conditions:
//
The above copyright notice and this permission notice shall be included in all // The above copyright notice and this permission notice shall be included in
copies or substantial portions of the Software. // all copies or substantial portions of the Software.
//
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
SOFTWARE. // DEALINGS IN THE SOFTWARE.
*/ // */
//
#include "fixtures/file_db_fixture.hpp" // #include "fixtures/file_db_fixture.hpp"
//
namespace { // namespace {
const auto get_stop_requested = []() -> bool { return false; }; // const auto get_stop_requested = []() -> bool { return false; };
} // namespace // } // namespace
//
namespace repertory { // namespace repertory {
TYPED_TEST_CASE(file_db_test, file_db_types); // TYPED_TEST_CASE(file_db_test, file_db_types);
//
TYPED_TEST(file_db_test, can_add_and_remove_directory) { // TYPED_TEST(file_db_test, can_add_and_remove_directory) {
this->file_db->clear(); // this->file_db->clear();
//
EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test")); // EXPECT_EQ(api_error::success, this->file_db->add_directory("/",
// "c:\\test"));
auto list = this->file_db->get_item_list(get_stop_requested); //
EXPECT_EQ(1U, list.size()); // auto list = this->file_db->get_item_list(get_stop_requested);
EXPECT_STREQ("/", list.at(0U).api_path.c_str()); // EXPECT_EQ(1U, list.size());
EXPECT_TRUE(list.at(0U).directory); // EXPECT_STREQ("/", list.at(0U).api_path.c_str());
EXPECT_STREQ("c:\\test", list.at(0U).source_path.c_str()); // EXPECT_TRUE(list.at(0U).directory);
// EXPECT_STREQ("c:\\test", list.at(0U).source_path.c_str());
EXPECT_EQ(api_error::success, this->file_db->remove_item("/")); //
// EXPECT_EQ(api_error::success, this->file_db->remove_item("/"));
list = this->file_db->get_item_list(get_stop_requested); //
EXPECT_EQ(0U, list.size()); // list = this->file_db->get_item_list(get_stop_requested);
} // EXPECT_EQ(0U, list.size());
// }
TYPED_TEST(file_db_test, can_add_and_remove_file) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_add_and_remove_file) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
0U, // "/file",
{}, // 0U,
"c:\\test\\file.txt", // {},
})); // "c:\\test\\file.txt",
// }));
auto list = this->file_db->get_item_list(get_stop_requested); //
EXPECT_EQ(1U, list.size()); // auto list = this->file_db->get_item_list(get_stop_requested);
EXPECT_STREQ("/file", list.at(0U).api_path.c_str()); // EXPECT_EQ(1U, list.size());
EXPECT_FALSE(list.at(0U).directory); // EXPECT_STREQ("/file", list.at(0U).api_path.c_str());
EXPECT_STREQ("c:\\test\\file.txt", list.at(0U).source_path.c_str()); // EXPECT_FALSE(list.at(0U).directory);
// EXPECT_STREQ("c:\\test\\file.txt", list.at(0U).source_path.c_str());
EXPECT_EQ(api_error::success, this->file_db->remove_item("/file")); //
// EXPECT_EQ(api_error::success, this->file_db->remove_item("/file"));
list = this->file_db->get_item_list(get_stop_requested); //
EXPECT_EQ(0U, list.size()); // list = this->file_db->get_item_list(get_stop_requested);
} // EXPECT_EQ(0U, list.size());
// }
TYPED_TEST(file_db_test, can_get_api_path_for_directory) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_get_api_path_for_directory) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test")); //
std::string api_path; // EXPECT_EQ(api_error::success, this->file_db->add_directory("/",
EXPECT_EQ(api_error::success, // "c:\\test")); std::string api_path; EXPECT_EQ(api_error::success,
this->file_db->get_api_path("c:\\test", api_path)); // this->file_db->get_api_path("c:\\test", api_path));
EXPECT_STREQ("/", api_path.c_str()); // EXPECT_STREQ("/", api_path.c_str());
} // }
//
TYPED_TEST(file_db_test, can_get_api_path_for_file) { // TYPED_TEST(file_db_test, can_get_api_path_for_file) {
this->file_db->clear(); // this->file_db->clear();
//
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
"/file", // "/file",
0U, // 0U,
{}, // {},
"c:\\test\\file.txt", // "c:\\test\\file.txt",
})); // }));
std::string api_path; // std::string api_path;
EXPECT_EQ(api_error::success, // EXPECT_EQ(api_error::success,
this->file_db->get_api_path("c:\\test\\file.txt", api_path)); // this->file_db->get_api_path("c:\\test\\file.txt", api_path));
EXPECT_STREQ("/file", api_path.c_str()); // EXPECT_STREQ("/file", api_path.c_str());
} // }
//
TYPED_TEST(file_db_test, // TYPED_TEST(file_db_test,
item_not_found_is_returned_for_non_existing_source_path) { // item_not_found_is_returned_for_non_existing_source_path) {
this->file_db->clear(); // this->file_db->clear();
//
std::string api_path; // std::string api_path;
EXPECT_EQ(api_error::item_not_found, // EXPECT_EQ(api_error::item_not_found,
this->file_db->get_api_path("c:\\test", api_path)); // this->file_db->get_api_path("c:\\test", api_path));
EXPECT_TRUE(api_path.empty()); // EXPECT_TRUE(api_path.empty());
} // }
//
TYPED_TEST(file_db_test, can_get_directory_api_path) { // TYPED_TEST(file_db_test, can_get_directory_api_path) {
this->file_db->clear(); // this->file_db->clear();
//
EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test")); // EXPECT_EQ(api_error::success, this->file_db->add_directory("/",
std::string api_path; // "c:\\test")); std::string api_path; EXPECT_EQ(api_error::success,
EXPECT_EQ(api_error::success, // this->file_db->get_directory_api_path("c:\\test", api_path));
this->file_db->get_directory_api_path("c:\\test", api_path)); // EXPECT_STREQ("/", api_path.c_str());
EXPECT_STREQ("/", api_path.c_str()); // }
} //
// TYPED_TEST(
TYPED_TEST( // file_db_test,
file_db_test, // directory_not_found_is_returned_for_non_existing_directory_source_path) {
directory_not_found_is_returned_for_non_existing_directory_source_path) { // this->file_db->clear();
this->file_db->clear(); //
// std::string api_path;
std::string api_path; // EXPECT_EQ(api_error::directory_not_found,
EXPECT_EQ(api_error::directory_not_found, // this->file_db->get_directory_api_path("c:\\test", api_path));
this->file_db->get_directory_api_path("c:\\test", api_path)); // EXPECT_TRUE(api_path.empty());
EXPECT_TRUE(api_path.empty()); // }
} //
// TYPED_TEST(file_db_test, can_get_file_api_path) {
TYPED_TEST(file_db_test, can_get_file_api_path) { // this->file_db->clear();
this->file_db->clear(); //
// EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ // "/file",
"/file", // 0U,
0U, // {},
{}, // "c:\\test\\file.txt",
"c:\\test\\file.txt", // }));
})); //
// std::string api_path;
std::string api_path; // EXPECT_EQ(api_error::success,
EXPECT_EQ(api_error::success, // this->file_db->get_file_api_path("c:\\test\\file.txt",
this->file_db->get_file_api_path("c:\\test\\file.txt", api_path)); // api_path));
EXPECT_STREQ("/file", api_path.c_str()); // EXPECT_STREQ("/file", api_path.c_str());
} // }
//
TYPED_TEST(file_db_test, // TYPED_TEST(file_db_test,
item_not_found_is_returned_for_non_existing_file_source_path) { // item_not_found_is_returned_for_non_existing_file_source_path) {
this->file_db->clear(); // this->file_db->clear();
//
std::string api_path; // std::string api_path;
EXPECT_EQ(api_error::item_not_found, // EXPECT_EQ(api_error::item_not_found,
this->file_db->get_file_api_path("c:\\test", api_path)); // this->file_db->get_file_api_path("c:\\test", api_path));
EXPECT_TRUE(api_path.empty()); // EXPECT_TRUE(api_path.empty());
} // }
//
TYPED_TEST(file_db_test, can_get_directory_source_path) { // TYPED_TEST(file_db_test, can_get_directory_source_path) {
this->file_db->clear(); // this->file_db->clear();
//
EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test")); // EXPECT_EQ(api_error::success, this->file_db->add_directory("/",
// "c:\\test"));
std::string source_path; //
EXPECT_EQ(api_error::success, // std::string source_path;
this->file_db->get_directory_source_path("/", source_path)); // EXPECT_EQ(api_error::success,
EXPECT_STREQ("c:\\test", source_path.c_str()); // this->file_db->get_directory_source_path("/", source_path));
} // EXPECT_STREQ("c:\\test", source_path.c_str());
// }
TYPED_TEST( //
file_db_test, // TYPED_TEST(
directory_not_found_is_returned_for_non_existing_directory_api_path) { // file_db_test,
this->file_db->clear(); // directory_not_found_is_returned_for_non_existing_directory_api_path) {
// this->file_db->clear();
std::string source_path; //
EXPECT_EQ(api_error::directory_not_found, // std::string source_path;
this->file_db->get_directory_source_path("/", source_path)); // EXPECT_EQ(api_error::directory_not_found,
EXPECT_TRUE(source_path.empty()); // this->file_db->get_directory_source_path("/", source_path));
} // EXPECT_TRUE(source_path.empty());
// }
TYPED_TEST(file_db_test, can_get_file_source_path) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_get_file_source_path) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
0U, // "/file",
{}, // 0U,
"c:\\test\\file.txt", // {},
})); // "c:\\test\\file.txt",
// }));
std::string source_path; //
EXPECT_EQ(api_error::success, // std::string source_path;
this->file_db->get_file_source_path("/file", source_path)); // EXPECT_EQ(api_error::success,
EXPECT_STREQ("c:\\test\\file.txt", source_path.c_str()); // this->file_db->get_file_source_path("/file", source_path));
} // EXPECT_STREQ("c:\\test\\file.txt", source_path.c_str());
// }
TYPED_TEST(file_db_test, //
item_not_found_is_returned_for_non_existing_file_api_path) { // TYPED_TEST(file_db_test,
this->file_db->clear(); // item_not_found_is_returned_for_non_existing_file_api_path) {
// this->file_db->clear();
std::string source_path; //
EXPECT_EQ(api_error::item_not_found, // std::string source_path;
this->file_db->get_file_source_path("/file.txt", source_path)); // EXPECT_EQ(api_error::item_not_found,
EXPECT_TRUE(source_path.empty()); // this->file_db->get_file_source_path("/file.txt", source_path));
} // EXPECT_TRUE(source_path.empty());
// }
TYPED_TEST(file_db_test, can_get_file_data) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_get_file_data) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
1U, // "/file",
{{}, {}}, // 1U,
"c:\\test\\file.txt", // {{}, {}},
})); // "c:\\test\\file.txt",
// }));
i_file_db::file_data data{}; //
EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data)); // i_file_db::file_data data{};
EXPECT_STREQ("/file", data.api_path.c_str()); // EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data));
EXPECT_EQ(1U, data.file_size); // EXPECT_STREQ("/file", data.api_path.c_str());
EXPECT_EQ(2U, data.iv_list.size()); // EXPECT_EQ(1U, data.file_size);
EXPECT_STREQ("c:\\test\\file.txt", data.source_path.c_str()); // EXPECT_EQ(2U, data.iv_list.size());
} // EXPECT_STREQ("c:\\test\\file.txt", data.source_path.c_str());
// }
TYPED_TEST(file_db_test, //
item_not_found_is_returned_for_non_existing_file_data_api_path) { // TYPED_TEST(file_db_test,
this->file_db->clear(); // item_not_found_is_returned_for_non_existing_file_data_api_path) {
// this->file_db->clear();
i_file_db::file_data data{}; //
EXPECT_EQ(api_error::item_not_found, // i_file_db::file_data data{};
this->file_db->get_file_data("/file", data)); // EXPECT_EQ(api_error::item_not_found,
} // this->file_db->get_file_data("/file", data));
// }
TYPED_TEST(file_db_test, can_update_existing_file_iv) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_update_existing_file_iv) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
1U, // "/file",
{{}, {}}, // 1U,
"c:\\test\\file.txt", // {{}, {}},
})); // "c:\\test\\file.txt",
// }));
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
1U, // "/file",
{{}, {}, {}}, // 1U,
"c:\\test\\file.txt", // {{}, {}, {}},
})); // "c:\\test\\file.txt",
// }));
i_file_db::file_data data{}; //
EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data)); // i_file_db::file_data data{};
EXPECT_STREQ("/file", data.api_path.c_str()); // EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data));
EXPECT_EQ(1U, data.file_size); // EXPECT_STREQ("/file", data.api_path.c_str());
EXPECT_EQ(3U, data.iv_list.size()); // EXPECT_EQ(1U, data.file_size);
EXPECT_STREQ("c:\\test\\file.txt", data.source_path.c_str()); // EXPECT_EQ(3U, data.iv_list.size());
// EXPECT_STREQ("c:\\test\\file.txt", data.source_path.c_str());
EXPECT_EQ(1U, this->file_db->count()); //
} // EXPECT_EQ(1U, this->file_db->count());
// }
TYPED_TEST(file_db_test, can_update_existing_file_size) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_update_existing_file_size) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
1U, // "/file",
{{}, {}}, // 1U,
"c:\\test\\file.txt", // {{}, {}},
})); // "c:\\test\\file.txt",
// }));
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
2U, // "/file",
{{}, {}}, // 2U,
"c:\\test\\file.txt", // {{}, {}},
})); // "c:\\test\\file.txt",
// }));
i_file_db::file_data data{}; //
EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data)); // i_file_db::file_data data{};
EXPECT_STREQ("/file", data.api_path.c_str()); // EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data));
EXPECT_EQ(2U, data.file_size); // EXPECT_STREQ("/file", data.api_path.c_str());
EXPECT_EQ(2U, data.iv_list.size()); // EXPECT_EQ(2U, data.file_size);
EXPECT_STREQ("c:\\test\\file.txt", data.source_path.c_str()); // EXPECT_EQ(2U, data.iv_list.size());
// EXPECT_STREQ("c:\\test\\file.txt", data.source_path.c_str());
EXPECT_EQ(1U, this->file_db->count()); //
} // EXPECT_EQ(1U, this->file_db->count());
// }
TYPED_TEST(file_db_test, can_update_existing_file_source_path) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_update_existing_file_source_path) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
1U, // "/file",
{{}, {}}, // 1U,
"c:\\test\\file.txt", // {{}, {}},
})); // "c:\\test\\file.txt",
// }));
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ //
"/file", // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
1U, // "/file",
{{}, {}}, // 1U,
"c:\\test\\file2.txt", // {{}, {}},
})); // "c:\\test\\file2.txt",
// }));
i_file_db::file_data data{}; //
EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data)); // i_file_db::file_data data{};
EXPECT_STREQ("/file", data.api_path.c_str()); // EXPECT_EQ(api_error::success, this->file_db->get_file_data("/file", data));
EXPECT_EQ(1U, data.file_size); // EXPECT_STREQ("/file", data.api_path.c_str());
EXPECT_EQ(2U, data.iv_list.size()); // EXPECT_EQ(1U, data.file_size);
EXPECT_STREQ("c:\\test\\file2.txt", data.source_path.c_str()); // EXPECT_EQ(2U, data.iv_list.size());
// EXPECT_STREQ("c:\\test\\file2.txt", data.source_path.c_str());
EXPECT_EQ(1U, this->file_db->count()); //
} // EXPECT_EQ(1U, this->file_db->count());
// }
TYPED_TEST(file_db_test, can_get_source_path_for_directory) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_get_source_path_for_directory) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test")); //
std::string source_path; // EXPECT_EQ(api_error::success, this->file_db->add_directory("/",
EXPECT_EQ(api_error::success, // "c:\\test")); std::string source_path; EXPECT_EQ(api_error::success,
this->file_db->get_source_path("/", source_path)); // this->file_db->get_source_path("/", source_path));
EXPECT_STREQ("c:\\test", source_path.c_str()); // EXPECT_STREQ("c:\\test", source_path.c_str());
} // }
//
TYPED_TEST(file_db_test, can_get_source_path_for_file) { // TYPED_TEST(file_db_test, can_get_source_path_for_file) {
this->file_db->clear(); // this->file_db->clear();
//
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
"/file", // "/file",
0U, // 0U,
{}, // {},
"c:\\test\\file.txt", // "c:\\test\\file.txt",
})); // }));
std::string source_path; // std::string source_path;
EXPECT_EQ(api_error::success, // EXPECT_EQ(api_error::success,
this->file_db->get_source_path("/file", source_path)); // this->file_db->get_source_path("/file", source_path));
EXPECT_STREQ("c:\\test\\file.txt", source_path.c_str()); // EXPECT_STREQ("c:\\test\\file.txt", source_path.c_str());
} // }
//
TYPED_TEST(file_db_test, item_not_found_is_returned_for_non_existing_api_path) { // TYPED_TEST(file_db_test,
this->file_db->clear(); // item_not_found_is_returned_for_non_existing_api_path) {
// this->file_db->clear();
std::string source_path; //
EXPECT_EQ(api_error::item_not_found, // std::string source_path;
this->file_db->get_source_path("/file", source_path)); // EXPECT_EQ(api_error::item_not_found,
EXPECT_TRUE(source_path.empty()); // this->file_db->get_source_path("/file", source_path));
} // EXPECT_TRUE(source_path.empty());
// }
TYPED_TEST(file_db_test, can_enumerate_item_list) { //
this->file_db->clear(); // TYPED_TEST(file_db_test, can_enumerate_item_list) {
// this->file_db->clear();
EXPECT_EQ(api_error::success, //
this->file_db->add_directory("/", std::filesystem::current_path().string())); // EXPECT_EQ(api_error::success,
EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({ // this->file_db->add_directory("/",
"/file", // std::filesystem::current_path().string()));
0U, // EXPECT_EQ(api_error::success, this->file_db->add_or_update_file({
{}, // "/file",
"c:\\test\\file.txt", // 0U,
})); // {},
// "c:\\test\\file.txt",
auto call_count{0U}; // }));
const auto get_stop_requested = []() -> bool { return false; }; //
// auto call_count{0U};
this->file_db->enumerate_item_list( // const auto get_stop_requested = []() -> bool { return false; };
[&call_count](auto &&list) { //
EXPECT_EQ(std::size_t(2U), list.size()); // this->file_db->enumerate_item_list(
++call_count; // [&call_count](auto &&list) {
}, // EXPECT_EQ(std::size_t(2U), list.size());
get_stop_requested); // ++call_count;
// },
EXPECT_EQ(std::size_t(1U), call_count); // get_stop_requested);
} //
// EXPECT_EQ(std::size_t(1U), call_count);
} // namespace repertory // }
//
// } // namespace repertory

View File

@@ -79,6 +79,13 @@ public:
std::optional<std::string> relative_parent_path, std::optional<std::string> relative_parent_path,
std::size_t error_return = 0U); std::size_t error_return = 0U);
encrypting_reader(std::string_view file_name, std::string_view source_path,
stop_type_callback stop_requested_cb,
const utils::hash::hash_256_t &master_key,
const std::pair<kdf_config, kdf_config> &configs,
std::optional<std::string> relative_parent_path,
std::size_t error_return = 0U);
encrypting_reader(stop_type_callback stop_requested_cb, encrypting_reader(stop_type_callback stop_requested_cb,
std::string_view encrypted_file_path, std::string_view encrypted_file_path,
std::string_view source_path, std::string_view source_path,
@@ -94,6 +101,16 @@ public:
iv_list, iv_list,
std::size_t error_return = 0U); std::size_t error_return = 0U);
encrypting_reader(
stop_type_callback stop_requested_cb,
std::string_view encrypted_file_path, std::string_view source_path,
const utils::hash::hash_256_t &master_key,
const std::pair<kdf_config, kdf_config> &configs,
std::vector<std::array<unsigned char,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list,
std::size_t error_return = 0U);
encrypting_reader(const encrypting_reader &reader); encrypting_reader(const encrypting_reader &reader);
encrypting_reader(encrypting_reader &&) = delete; encrypting_reader(encrypting_reader &&) = delete;

View File

@@ -173,8 +173,8 @@ struct kdf_config final {
return sub_key; return sub_key;
} }
[[nodiscard]] static auto from_header(data_cspan data, kdf_config &cfg) [[nodiscard]] static auto from_header(data_cspan data, kdf_config &cfg,
-> bool; bool ignore_checksum = false) -> bool;
[[nodiscard]] auto generate_checksum() const -> std::uint64_t; [[nodiscard]] auto generate_checksum() const -> std::uint64_t;

View File

@@ -285,6 +285,27 @@ encrypting_reader::encrypting_reader(
create_encrypted_paths(file_name, relative_parent_path); create_encrypted_paths(file_name, relative_parent_path);
} }
encrypting_reader::encrypting_reader(
std::string_view file_name, std::string_view source_path,
stop_type_callback stop_requested_cb,
const utils::hash::hash_256_t &master_key,
const std::pair<kdf_config, kdf_config> &configs,
std::optional<std::string> relative_parent_path, std::size_t error_return)
: stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)) {
keys_.first = configs.first.recreate_subkey(
utils::encryption::kdf_context::data, master_key);
keys_.second = configs.second.recreate_subkey(
utils::encryption::kdf_context::path, master_key);
kdf_headers_ = {
configs.first.to_header(),
configs.second.to_header(),
};
common_initialize(true);
create_encrypted_paths(file_name, relative_parent_path);
}
encrypting_reader::encrypting_reader(stop_type_callback stop_requested_cb, encrypting_reader::encrypting_reader(stop_type_callback stop_requested_cb,
std::string_view encrypted_file_path, std::string_view encrypted_file_path,
std::string_view source_path, std::string_view source_path,
@@ -322,6 +343,32 @@ encrypting_reader::encrypting_reader(
common_initialize(false); common_initialize(false);
} }
encrypting_reader::encrypting_reader(
stop_type_callback stop_requested_cb, std::string_view encrypted_file_path,
std::string_view source_path, const utils::hash::hash_256_t &master_key,
const std::pair<kdf_config, kdf_config> &configs,
std::vector<
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list,
std::size_t error_return)
: stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)),
encrypted_file_name_(
utils::path::strip_to_file_name(std::string{encrypted_file_path})),
encrypted_file_path_(encrypted_file_path),
iv_list_(std::move(iv_list)) {
keys_.first = configs.first.recreate_subkey(
utils::encryption::kdf_context::data, master_key);
keys_.second = configs.second.recreate_subkey(
utils::encryption::kdf_context::path, master_key);
kdf_headers_ = {
configs.first.to_header(),
configs.second.to_header(),
};
common_initialize(false);
}
encrypting_reader::encrypting_reader(const encrypting_reader &reader) encrypting_reader::encrypting_reader(const encrypting_reader &reader)
: keys_(reader.keys_), : keys_(reader.keys_),
stop_requested_cb_(reader.stop_requested_cb_), stop_requested_cb_(reader.stop_requested_cb_),

View File

@@ -63,7 +63,8 @@ auto kdf_config::generate_checksum() const -> std::uint64_t {
return *reinterpret_cast<std::uint64_t *>(hash.data()); return *reinterpret_cast<std::uint64_t *>(hash.data());
} }
auto kdf_config::from_header(data_cspan data, kdf_config &cfg) -> bool { auto kdf_config::from_header(data_cspan data, kdf_config &cfg,
bool ignore_checksum) -> bool {
if (data.size() < kdf_config::size()) { if (data.size() < kdf_config::size()) {
return false; return false;
} }
@@ -77,7 +78,7 @@ auto kdf_config::from_header(data_cspan data, kdf_config &cfg) -> bool {
cfg.memlimit <= memlimit_level::level4 && cfg.memlimit <= memlimit_level::level4 &&
cfg.opslimit >= opslimit_level::level1 && cfg.opslimit >= opslimit_level::level1 &&
cfg.opslimit <= opslimit_level::level3 && cfg.opslimit <= opslimit_level::level3 &&
cfg.checksum == cfg.generate_checksum(); (ignore_checksum || cfg.checksum == cfg.generate_checksum());
} }
void kdf_config::seal() { void kdf_config::seal() {