From 107198d8e01ffa63c2129740d8385f81cf309ec1 Mon Sep 17 00:00:00 2001 From: Christoforos Sakellaris Date: Fri, 4 Apr 2025 17:38:43 +0200 Subject: [PATCH 1/2] TA-7 Add Drogon to Project Add Drogon Along with a quick test api --- .gitignore | 4 ++ CMakeLists.txt | 8 ++- docs/DB_schema.drawio | 122 +++++++++++++++++++++++++++++++++++++++ include/TAWAServer.hpp | 31 ++++++++++ include/data_service.hpp | 6 ++ sql_scripts/db_setup.sql | 58 +++++++++++++++++++ src/TAWAServer.cpp | 34 +++++++++++ src/data_service.cpp | 0 src/main.cpp | 26 ++++++--- vcpkg.json | 3 +- 10 files changed, 282 insertions(+), 10 deletions(-) create mode 100644 docs/DB_schema.drawio create mode 100644 include/TAWAServer.hpp create mode 100644 include/data_service.hpp create mode 100644 sql_scripts/db_setup.sql create mode 100644 src/TAWAServer.cpp create mode 100644 src/data_service.cpp diff --git a/.gitignore b/.gitignore index f2b235a..cfa208d 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,7 @@ vcpkg_installed/ out/ app.aps + +.idea/ + +external/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 1519ea6..7e6e947 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,8 @@ find_package(boost_program_options CONFIG REQUIRED) find_package(nlohmann_json CONFIG REQUIRED) find_package(unofficial-minizip CONFIG REQUIRED) find_package(indicators CONFIG REQUIRED) +find_package(Drogon CONFIG REQUIRED) + # Add source to this project's executable. add_executable (${PROJECT_NAME} @@ -23,9 +25,10 @@ add_executable (${PROJECT_NAME} "src/sim_object.cpp" "src/tac_file.cpp" "src/utils.cpp" - "src/tac_file_load.cpp" + "src/tac_file_load.cpp" + "src/TAWAServer.cpp" app.rc -) + "src/data_service.cpp") target_include_directories(${PROJECT_NAME} PRIVATE "include") @@ -33,6 +36,7 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Boost::program_options) target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(${PROJECT_NAME} PRIVATE unofficial::minizip::minizip) target_link_libraries(${PROJECT_NAME} PRIVATE indicators::indicators) +target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon) include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/package) diff --git a/docs/DB_schema.drawio b/docs/DB_schema.drawio new file mode 100644 index 0000000..3bbbb5b --- /dev/null +++ b/docs/DB_schema.drawio @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/TAWAServer.hpp b/include/TAWAServer.hpp new file mode 100644 index 0000000..1fd3276 --- /dev/null +++ b/include/TAWAServer.hpp @@ -0,0 +1,31 @@ +#pragma once +#include + +using namespace drogon; +namespace api { +namespace v1 { +class User : public drogon::HttpController { + public: + METHOD_LIST_BEGIN + // use METHOD_ADD to add your custom processing function here; + METHOD_ADD(User::getInfo, "/{id}", Get); // path is /api/v1/User/{arg1} + METHOD_ADD(User::getDetailInfo, "/{id}/detailinfo", + Get); // path is /api/v1/User/{arg1}/detailinfo + METHOD_ADD(User::newUser, "/{name}", Post); // path is /api/v1/User/{arg1} + METHOD_LIST_END + // your declaration of processing function maybe like this: + void getInfo(const HttpRequestPtr &req, + std::function &&callback, + int userId) const; + void getDetailInfo(const HttpRequestPtr &req, + std::function &&callback, + int userId) const; + void newUser(const HttpRequestPtr &req, + std::function &&callback, + std::string &&userName); + + public: + User() { LOG_DEBUG << "User constructor!"; } +}; +} // namespace v1 +} // namespace api \ No newline at end of file diff --git a/include/data_service.hpp b/include/data_service.hpp new file mode 100644 index 0000000..f38b1b6 --- /dev/null +++ b/include/data_service.hpp @@ -0,0 +1,6 @@ + + + +class DataService { + +} diff --git a/sql_scripts/db_setup.sql b/sql_scripts/db_setup.sql new file mode 100644 index 0000000..b6be465 --- /dev/null +++ b/sql_scripts/db_setup.sql @@ -0,0 +1,58 @@ +CREATE TABLE Pilot ( + Id SERIAL PRIMARY KEY, + Username VARCHAR(255) NOT NULL +); + +CREATE UNIQUE INDEX idx_pilot_username ON Pilot(Username); + +CREATE TABLE ServerFile ( + Id SERIAL PRIMARY KEY, + Filename VARCHAR(255) NOT NULL, + FilePath VARCHAR(255) NOT NULL +); + +CREATE TABLE TacFile ( + Id SERIAL PRIMARY KEY, + StartTime TIMESTAMP NOT NULL, + File INT NOT NULL, + FOREIGN KEY (File) REFERENCES ServerFile(Id) +); + + +CREATE TABLE PilotRun ( + Id SERIAL PRIMARY KEY, + Team VARCHAR(10) CHECK (Team IN ('Red', 'Blue')), + PilotId INT NOT NULL, + StartTime TIMESTAMP NOT NULL, + StartTimeRel INTERVAL NOT NULL, + EndTime TIMESTAMP NOT NULL, + EndTimeRel INTERVAL NOT NULL, + TacFileId INT NOT NULL, + PositionFile INT, + FOREIGN KEY (PilotId) REFERENCES Pilot(Id), + FOREIGN KEY (TacFileId) REFERENCES TacFile(Id), + FOREIGN KEY (PositionFile) REFERENCES ServerFile(Id) +); + +CREATE INDEX idx_pilotrun_pilotid ON PilotRun(PilotId); +CREATE INDEX idx_pilotrun_tacfile ON PilotRun(TacFileId); + +CREATE TABLE Missile ( + Id SERIAL PRIMARY KEY, + Type VARCHAR(255) NOT NULL, + Team VARCHAR(10) CHECK (Team IN ('Red', 'Blue')), + LauncherId INT, + TargetId INT, + StartTime TIMESTAMP NOT NULL, + StartTimeRel INTERVAL NOT NULL, + EndTime TIMESTAMP NOT NULL, + EndTimeRel INTERVAL NOT NULL, + TacFileId INT NOT NULL, + PositionFile INT, + FOREIGN KEY (LauncherId) REFERENCES PilotRun(Id), + FOREIGN KEY (TargetId) REFERENCES PilotRun(Id), + FOREIGN KEY (TacFileId) REFERENCES TacFile(Id), + FOREIGN KEY (PositionFile) REFERENCES ServerFile(Id) +); + +CREATE INDEX idx_missile_tacfile ON Missile(TacFileId); \ No newline at end of file diff --git a/src/TAWAServer.cpp b/src/TAWAServer.cpp new file mode 100644 index 0000000..3802850 --- /dev/null +++ b/src/TAWAServer.cpp @@ -0,0 +1,34 @@ +#include "TAWAServer.hpp" + +void api::v1::User::getInfo( + [[maybe_unused]] const HttpRequestPtr& req, + std::function&& callback, int userId) const { + Json::Value json; + json["result"] = "ok"; + json["message"] = "GetInfo: UserId[" + std::to_string(userId) + "]"; + auto resp = HttpResponse::newHttpJsonResponse(json); + callback(resp); +} + +void api::v1::User::getDetailInfo( + [[maybe_unused]] const HttpRequestPtr& req, + std::function&& callback, int userId) const { + Json::Value json; + json["result"] = "ok"; + json["message"] = "GetDetailInfo: UserId[" + std::to_string(userId) + "]"; + auto resp = HttpResponse::newHttpJsonResponse(json); + callback(resp); +} + +void api::v1::User::newUser( + [[maybe_unused]] const HttpRequestPtr& req, + std::function&& callback, + std::string&& userName) { + Json::Value json; + json["result"] = "ok"; + json["message"] = "NewUser"; + json["username"] = userName; + json["userId"] = rand() % 1000; + auto resp = HttpResponse::newHttpJsonResponse(json); + callback(resp); +} diff --git a/src/data_service.cpp b/src/data_service.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp index 6a93bed..8cc9afd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,20 +1,32 @@ -#include +#include "cache.hpp" +#include "global.hpp" +#include "tac_file.hpp" + +#include #include #include #include #include -#include "cache.hpp" -#include "global.hpp" -#include "tac_file.hpp" - +#include namespace po = boost::program_options; std::filesystem::path exe_path; std::filesystem::path exe_dir; int main(int argc, char** argv) { + drogon::app() + .setLogPath("./") + .setLogLevel(trantor::Logger::kWarn) + .addListener("0.0.0.0", 80) + .setThreadNum(16) + .run(); + + while (true) { + Sleep(1000); + } + exe_path = std::filesystem::path(argv[0]); exe_dir = exe_path.parent_path(); @@ -22,8 +34,8 @@ int main(int argc, char** argv) { cache.LoadCache();*/ po::options_description opts_desc("Allowed options"); - opts_desc.add_options()("help", "")( - "input-file", po::value(), "TacView file to analyse"); + opts_desc.add_options()("help", "")("input-file", po::value(), + "TacView file to analyse"); po::positional_options_description pos_opts_desc; pos_opts_desc.add("input-file", 1); diff --git a/vcpkg.json b/vcpkg.json index 09336ec..3caaca6 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -3,6 +3,7 @@ "boost-program-options", "indicators", "minizip", - "nlohmann-json" + "nlohmann-json", + "drogon" ] } From 96b41ad5e2b36538d1f5f14716b669a31225eddb Mon Sep 17 00:00:00 2001 From: Christoforos Sakellaris Date: Fri, 4 Apr 2025 23:01:28 +0200 Subject: [PATCH 2/2] TA-7 Add Basic API for Pilot fetching Database Connection Pool Pilots Api Add yaml configuration file --- CMakeLists.txt | 20 +++++-- include/TAWAServer.hpp | 20 ++----- include/data_service.hpp | 39 ++++++++++++- include/global.hpp | 8 +++ include/server_configuration.hpp | 32 +++++++++++ src/TAWAServer.cpp | 64 ++++++++++++---------- src/data_service.cpp | 94 ++++++++++++++++++++++++++++++++ src/main.cpp | 52 +++++++++++++----- src/server_configuration.cpp | 30 ++++++++++ vcpkg.json | 4 +- 10 files changed, 296 insertions(+), 67 deletions(-) create mode 100644 include/server_configuration.hpp create mode 100644 src/server_configuration.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e6e947..2b13ec5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,8 @@ find_package(nlohmann_json CONFIG REQUIRED) find_package(unofficial-minizip CONFIG REQUIRED) find_package(indicators CONFIG REQUIRED) find_package(Drogon CONFIG REQUIRED) +find_package(libpqxx CONFIG REQUIRED) +find_package(yaml-cpp CONFIG REQUIRED) # Add source to this project's executable. @@ -27,16 +29,22 @@ add_executable (${PROJECT_NAME} "src/utils.cpp" "src/tac_file_load.cpp" "src/TAWAServer.cpp" + "src/data_service.cpp" + "src/server_configuration.cpp" app.rc - "src/data_service.cpp") +) target_include_directories(${PROJECT_NAME} PRIVATE "include") -target_link_libraries(${PROJECT_NAME} PRIVATE Boost::program_options) -target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json) -target_link_libraries(${PROJECT_NAME} PRIVATE unofficial::minizip::minizip) -target_link_libraries(${PROJECT_NAME} PRIVATE indicators::indicators) -target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon) +target_link_libraries(${PROJECT_NAME} PRIVATE + Boost::program_options + nlohmann_json::nlohmann_json + unofficial::minizip::minizip + indicators::indicators + Drogon::Drogon + libpqxx::pqxx + yaml-cpp::yaml-cpp +) include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_DIRECTORY ${CMAKE_BINARY_DIR}/package) diff --git a/include/TAWAServer.hpp b/include/TAWAServer.hpp index 1fd3276..0998ea0 100644 --- a/include/TAWAServer.hpp +++ b/include/TAWAServer.hpp @@ -4,28 +4,18 @@ using namespace drogon; namespace api { namespace v1 { -class User : public drogon::HttpController { +class Pilot : public drogon::HttpController { public: METHOD_LIST_BEGIN // use METHOD_ADD to add your custom processing function here; - METHOD_ADD(User::getInfo, "/{id}", Get); // path is /api/v1/User/{arg1} - METHOD_ADD(User::getDetailInfo, "/{id}/detailinfo", - Get); // path is /api/v1/User/{arg1}/detailinfo - METHOD_ADD(User::newUser, "/{name}", Post); // path is /api/v1/User/{arg1} + METHOD_ADD(Pilot::getPilots, "/", Get); // path is /api/v1/Pilot/ METHOD_LIST_END // your declaration of processing function maybe like this: - void getInfo(const HttpRequestPtr &req, - std::function &&callback, - int userId) const; - void getDetailInfo(const HttpRequestPtr &req, - std::function &&callback, - int userId) const; - void newUser(const HttpRequestPtr &req, - std::function &&callback, - std::string &&userName); + void getPilots(const HttpRequestPtr &req, + std::function &&callback) const; public: - User() { LOG_DEBUG << "User constructor!"; } + Pilot() = default; }; } // namespace v1 } // namespace api \ No newline at end of file diff --git a/include/data_service.hpp b/include/data_service.hpp index f38b1b6..e5ad7f0 100644 --- a/include/data_service.hpp +++ b/include/data_service.hpp @@ -1,6 +1,39 @@ +#pragma once - +#include +#include +#include +#include +#include +#include +#include class DataService { - -} + private: + // Database connection parameters + std::string dbname; + std::string user; + std::string password; + std::string hostaddr; + uint16_t port; + std::vector> connection_pool; + std::queue connection_queue; + std::mutex connection_queue_lock; + + std::unique_ptr CreateConnection(); + + public: + DataService() = default; + DataService(std::string_view dbname, + std::string_view user, + std::string_view password, + std::string_view hostaddr, + uint16_t port); + ~DataService(); + + void Init(uint16_t count); + bool Test(); + void ReleaseConnection(pqxx::connection *conn); + pqxx::connection *GetConnection(); + std::unique_ptr ExecuteQuery(const std::string &query, const pqxx::params ¶ms = {}); +}; diff --git a/include/global.hpp b/include/global.hpp index 873aacb..28e7489 100644 --- a/include/global.hpp +++ b/include/global.hpp @@ -1,6 +1,14 @@ #pragma once + +#include "data_service.hpp" +#include "server_configuration.hpp" + #include #include +#include extern std::filesystem::path exe_path; extern std::filesystem::path exe_dir; + +extern std::unique_ptr data_service; +extern std::unique_ptr server_config; diff --git a/include/server_configuration.hpp b/include/server_configuration.hpp new file mode 100644 index 0000000..c0fa618 --- /dev/null +++ b/include/server_configuration.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +class ServerConfiguration { + public: + struct DatabaseConfig { + std::string host; + uint16_t port; + std::string username; + std::string password; + std::string database; + }; + + struct ServerConfig { + std::string host; + uint16_t port; + }; + + struct LogConfig { + std::filesystem::path log_directory; + int log_level; + }; + + ServerConfiguration() = default; + bool LoadYamlConfig(); + bool LoadYamlConfig(const std::filesystem::path &path); + DatabaseConfig database_config; + ServerConfig web_api_config; + LogConfig log_config; +}; diff --git a/src/TAWAServer.cpp b/src/TAWAServer.cpp index 3802850..94b495c 100644 --- a/src/TAWAServer.cpp +++ b/src/TAWAServer.cpp @@ -1,34 +1,42 @@ #include "TAWAServer.hpp" -void api::v1::User::getInfo( - [[maybe_unused]] const HttpRequestPtr& req, - std::function&& callback, int userId) const { - Json::Value json; - json["result"] = "ok"; - json["message"] = "GetInfo: UserId[" + std::to_string(userId) + "]"; - auto resp = HttpResponse::newHttpJsonResponse(json); - callback(resp); -} +#include "global.hpp" +#include "nlohmann/json.hpp" -void api::v1::User::getDetailInfo( - [[maybe_unused]] const HttpRequestPtr& req, - std::function&& callback, int userId) const { - Json::Value json; - json["result"] = "ok"; - json["message"] = "GetDetailInfo: UserId[" + std::to_string(userId) + "]"; - auto resp = HttpResponse::newHttpJsonResponse(json); - callback(resp); -} +using json = nlohmann::json; -void api::v1::User::newUser( +void api::v1::Pilot::getPilots( [[maybe_unused]] const HttpRequestPtr& req, - std::function&& callback, - std::string&& userName) { - Json::Value json; - json["result"] = "ok"; - json["message"] = "NewUser"; - json["username"] = userName; - json["userId"] = rand() % 1000; - auto resp = HttpResponse::newHttpJsonResponse(json); - callback(resp); + std::function&& callback) const { + auto qres = data_service->ExecuteQuery("SELECT t.* FROM main.pilot t LIMIT 501"); + if (!qres) { + auto resp = HttpResponse::newHttpResponse( + drogon::HttpStatusCode::k500InternalServerError, + drogon::CT_APPLICATION_JSON); + json res = { + {"result", "error"}, + {"message", "Internal Server Error"}, + }; + resp->setBody(res.dump()); + callback(resp); + return; + } else { + json pilotArray = {}; + for (auto row : *qres) { + json pilot = { + {"id", row["id"].as()}, + {"username", row["username"].as()} + }; + pilotArray.push_back(pilot); + } + json res = { + {"result", "ok"}, + {"pilots", pilotArray}, + }; + auto resp = HttpResponse::newHttpResponse(drogon::HttpStatusCode::k200OK, + drogon::CT_APPLICATION_JSON); + resp->setBody(res.dump()); + callback(resp); + return; + } } diff --git a/src/data_service.cpp b/src/data_service.cpp index e69de29..13ca085 100644 --- a/src/data_service.cpp +++ b/src/data_service.cpp @@ -0,0 +1,94 @@ +#include "data_service.hpp" + +#include "global.hpp" + +std::unique_ptr data_service; + +std::unique_ptr DataService::CreateConnection() { + std::string connectionStr = std::format( + "dbname={} user={} password={} " + "hostaddr={} port={}", + dbname, user, password, hostaddr, port); + std::unique_ptr cx = std::make_unique(connectionStr); + if (!cx->is_open()) { + return nullptr; + } + return cx; +} + +DataService::DataService(std::string_view dbname, + std::string_view user, + std::string_view password, + std::string_view hostaddr, + uint16_t port) + : dbname(dbname), user(user), password(password), hostaddr(hostaddr), port(port) {} + +DataService::~DataService() { + for (const auto &con : connection_pool) { + con->close(); + } +} + +void DataService::Init(uint16_t count) { + for (int i = 0; i < count; ++i) { + std::unique_ptr cx = CreateConnection(); + if (cx) { + connection_queue.push(cx.get()); + connection_pool.push_back(std::move(cx)); + } else { + std::cerr << "Failed to create connection." << std::endl; + return; + } + } +} + +bool DataService::Test() { + try { + std::unique_ptr cx(CreateConnection()); + if (cx) { + std::cout << "Connected to the database." << std::endl; + } else { + std::cerr << "Failed to connect to the database." << std::endl; + return false; + } + cx->close(); + return true; + } catch (const std::exception &e) { + std::cerr << "Exception: " << e.what() << std::endl; + return false; + } +} + +void DataService::ReleaseConnection(pqxx::connection *conn) { + std::scoped_lock lock(connection_queue_lock); + connection_queue.push(conn); +} + +pqxx::connection *DataService::GetConnection() { + std::scoped_lock lock(connection_queue_lock); + if (connection_queue.empty()) { + return nullptr; + } else { + pqxx::connection *conn = connection_queue.front(); + connection_queue.pop(); + return conn; + } +} + +std::unique_ptr DataService::ExecuteQuery(const std::string &query, const pqxx::params ¶ms) { + auto cx = GetConnection(); + if (!cx) { + std::cerr << "Failed to get a connection from the pool." << std::endl; + return nullptr; + } + std::unique_ptr res; + try { + pqxx::work tx{*cx}; + res = std::make_unique(tx.exec(query, params)); + tx.commit(); + } catch (const std::exception &e) { + std::cerr << "Query execution failed: " << e.what() << std::endl; + } + ReleaseConnection(cx); + return res; +} diff --git a/src/main.cpp b/src/main.cpp index 8cc9afd..7632dde 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,3 @@ -#include "cache.hpp" -#include "global.hpp" -#include "tac_file.hpp" - #include #include @@ -9,17 +5,48 @@ #include #include -#include +#include "cache.hpp" +#include "data_service.hpp" +#include "global.hpp" +#include "tac_file.hpp" + namespace po = boost::program_options; std::filesystem::path exe_path; std::filesystem::path exe_dir; -int main(int argc, char** argv) { +int main(int argc, char **argv) { + exe_path = std::filesystem::path(argv[0]); + exe_dir = exe_path.parent_path(); + + server_config = std::make_unique(); + if (!server_config->LoadYamlConfig()) { + std::cerr << "Error loading configuration. Exiting..." << std::endl; + return 1; + } + + data_service = std::make_unique( + server_config->database_config.database, + server_config->database_config.username, + server_config->database_config.password, + server_config->database_config.host, server_config->database_config.port); + if (!data_service->Test()) { + std::cerr << "Database Connection is required. Exiting..." << std::endl; + return 1; + } + data_service->Init(10); + + std::filesystem::create_directory(server_config->log_config.log_directory); + std::filesystem::create_directory(server_config->log_config.log_directory / + "web"); + std::filesystem::create_directory(server_config->log_config.log_directory / + "server"); drogon::app() - .setLogPath("./") - .setLogLevel(trantor::Logger::kWarn) - .addListener("0.0.0.0", 80) + .setLogPath((server_config->log_config.log_directory / "web").string()) + .setLogLevel(static_cast( + server_config->log_config.log_level)) + .addListener(server_config->web_api_config.host, + server_config->web_api_config.port) .setThreadNum(16) .run(); @@ -27,9 +54,6 @@ int main(int argc, char** argv) { Sleep(1000); } - exe_path = std::filesystem::path(argv[0]); - exe_dir = exe_path.parent_path(); - /*CacheObject cache; cache.LoadCache();*/ @@ -48,7 +72,7 @@ int main(int argc, char** argv) { .run(); po::store(parsed, vm); po::notify(vm); - } catch (const std::exception& e) { + } catch (const std::exception &e) { std::cerr << e.what() << "\n"; return 1; } @@ -72,7 +96,7 @@ int main(int argc, char** argv) { } try { tac_file->PrintPlayerRuns(std::cout, username); - } catch (const std::exception& e) { + } catch (const std::exception &e) { std::cerr << e.what() << "\n"; } } diff --git a/src/server_configuration.cpp b/src/server_configuration.cpp new file mode 100644 index 0000000..4e2c321 --- /dev/null +++ b/src/server_configuration.cpp @@ -0,0 +1,30 @@ +#include "server_configuration.hpp" + +#include "global.hpp" +#include "yaml-cpp/yaml.h" + +std::unique_ptr server_config; + +bool ServerConfiguration::LoadYamlConfig(const std::filesystem::path &path) { + try { + YAML::Node config = YAML::LoadFile(path.string()); + database_config.host = config["database"]["host"].as(); + database_config.port = config["database"]["port"].as(); + database_config.username = config["database"]["username"].as(); + database_config.password = config["database"]["password"].as(); + database_config.database = config["database"]["database"].as(); + web_api_config.host = config["server"]["host"].as(); + web_api_config.port = config["server"]["port"].as(); + log_config.log_directory = + exe_dir / config["logging"]["directory"].as(); + log_config.log_level = config["logging"]["level"].as(); + } catch (const YAML::Exception &e) { + std::cerr << "Error loading configuration: " << e.what() << std::endl; + return false; + } + return true; +} + +bool ServerConfiguration::LoadYamlConfig() { + return LoadYamlConfig(exe_dir / "config.yaml"); +} \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index 3caaca6..5b0ea17 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,9 +1,11 @@ { "dependencies": [ "boost-program-options", + "drogon", "indicators", + "libpqxx", "minizip", "nlohmann-json", - "drogon" + "yaml-cpp" ] }