Multiple implementations of the same back-end application. The aim is to provide quick, side-by-side comparisons of different technologies (languages, frameworks, libraries) while preserving consistent business logic across all implementations.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

130 lines
3.0 KiB

#include "infrastructure/repositories/FileUserRepository.h"
#include "nlohmann/json.hpp"
#include <fstream>
#include <algorithm>
namespace nxl::autostore::infrastructure {
namespace {
// Helper functions for JSON serialization
inline void userToJson(nlohmann::json& j, const domain::User& u)
{
j = nlohmann::json{
{"id", u.id}, {"username", u.username}, {"passwordHash", u.passwordHash}};
}
inline void jsonToUser(const nlohmann::json& j, domain::User& u)
{
j.at("id").get_to(u.id);
j.at("username").get_to(u.username);
j.at("passwordHash").get_to(u.passwordHash);
}
// Helper functions for vector serialization
inline nlohmann::json usersToJson(const std::vector<domain::User>& users)
{
nlohmann::json j = nlohmann::json::array();
for (const auto& user : users) {
nlohmann::json userJson;
userToJson(userJson, user);
j.push_back(userJson);
}
return j;
}
inline std::vector<domain::User> jsonToUsers(const nlohmann::json& j)
{
std::vector<domain::User> users;
for (const auto& userJson : j) {
domain::User user;
jsonToUser(userJson, user);
users.push_back(user);
}
return users;
}
} // namespace
FileUserRepository::FileUserRepository(std::string_view dbPath) : dbPath(dbPath)
{
load();
}
void FileUserRepository::save(const domain::User& user)
{
std::lock_guard<std::mutex> lock(mtx);
auto it =
std::find_if(users.begin(), users.end(),
[&](const domain::User& u) { return u.id == user.id; });
if (it != users.end()) {
*it = user;
} else {
users.push_back(user);
}
persist();
}
std::optional<domain::User> FileUserRepository::findById(std::string_view id)
{
std::lock_guard<std::mutex> lock(mtx);
auto it = std::find_if(users.begin(), users.end(),
[&](const domain::User& u) { return u.id == id; });
if (it != users.end()) {
return *it;
}
return std::nullopt;
}
std::optional<domain::User>
FileUserRepository::findByUsername(std::string_view username)
{
std::lock_guard<std::mutex> lock(mtx);
auto it =
std::find_if(users.begin(), users.end(),
[&](const domain::User& u) { return u.username == username; });
if (it != users.end()) {
return *it;
}
return std::nullopt;
}
std::vector<domain::User> FileUserRepository::findAll()
{
std::lock_guard<std::mutex> lock(mtx);
return users;
}
void FileUserRepository::remove(std::string_view id)
{
std::lock_guard<std::mutex> lock(mtx);
users.erase(std::remove_if(users.begin(), users.end(),
[&](const domain::User& u) { return u.id == id; }),
users.end());
persist();
}
void FileUserRepository::load()
{
std::lock_guard<std::mutex> lock(mtx);
std::ifstream file(dbPath);
if (file.is_open()) {
nlohmann::json j;
file >> j;
users = jsonToUsers(j);
}
}
void FileUserRepository::persist()
{
std::ofstream file(dbPath);
if (file.is_open()) {
nlohmann::json j = usersToJson(users);
file << j.dump(4);
}
}
} // namespace nxl::autostore::infrastructure