From 69f5a37eb328d566038d5a7288ce7ed7dc309a11 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 17 Nov 2019 13:33:58 -0500 Subject: [PATCH] Code cleanup --- include/callback/StreamCallback.h | 23 +- include/component/AppComponent.hpp | 41 +- include/controller/AlbumController.hpp | 99 ++- include/controller/ArtistController.hpp | 107 ++- include/controller/CoverArtController.hpp | 144 ++-- include/controller/GenreController.hpp | 107 ++- include/controller/LoginController.hpp | 58 +- include/controller/RegisterController.hpp | 7 +- include/controller/SongController.hpp | 332 ++++---- include/controller/YearController.hpp | 108 ++- include/database/AlbumRepository.h | 6 +- include/database/ArtistRepository.h | 20 +- include/database/BaseRepository.h | 8 +- include/database/CoverArtRepository.h | 18 +- include/database/GenreRepository.h | 17 +- include/database/SongRepository.h | 10 +- include/database/UserRepository.h | 74 +- include/database/YearRepository.h | 23 +- include/dto/AlbumDto.hpp | 6 +- include/dto/ArtistDto.hpp | 6 +- include/dto/CoverArtDto.hpp | 6 +- include/dto/GenreDto.hpp | 6 +- include/dto/SongDto.hpp | 6 +- include/dto/YearDto.hpp | 6 +- include/manager/AlbumManager.h | 6 +- include/manager/ArtistManager.h | 6 +- include/manager/CoverArtManager.h | 8 +- include/manager/DirectoryManager.h | 9 +- include/manager/GenreManager.h | 6 +- include/manager/SongManager.h | 3 +- include/manager/TokenManager.h | 28 +- include/manager/UserManager.h | 20 +- include/manager/YearManager.h | 6 +- include/model/Models.h | 288 +++---- include/type/AlbumFilter.h | 6 +- include/type/ArtistFilter.h | 6 +- include/type/CoverFilter.h | 6 +- include/type/GenreFilter.h | 6 +- include/type/PathType.h | 6 +- include/type/SaltFilter.h | 3 +- include/type/Scopes.h | 6 +- include/type/SongChanged.h | 6 +- include/type/SongFilter.h | 6 +- include/type/SongUpload.h | 6 +- include/type/UserFilter.h | 3 +- include/type/YearFilter.h | 6 +- include/utility/ImageFile.h | 6 +- include/utility/MetadataRetriever.h | 21 +- include/utility/PasswordEncryption.h | 2 +- include/verify/Initialization.h | 6 +- src/Main.cpp | 8 +- src/callback/StreamCallback.cpp | 53 +- src/database/AlbumRepository.cpp | 684 ++++++++------- src/database/ArtistRepository.cpp | 683 +++++++-------- src/database/BaseRepository.cpp | 136 ++- src/database/CoverArtRepository.cpp | 556 ++++++------ src/database/GenreRepository.cpp | 643 +++++++------- src/database/SongRepository.cpp | 983 +++++++++++----------- src/database/UserRepository.cpp | 531 ++++++------ src/database/YearRepository.cpp | 541 ++++++------ src/dto/conversion/DtoConversions.cpp | 2 +- src/manager/AlbumManager.cpp | 98 +-- src/manager/ArtistManager.cpp | 107 ++- src/manager/CoverArtManager.cpp | 199 +++-- src/manager/DirectoryManager.cpp | 300 ++++--- src/manager/GenreManager.cpp | 105 ++- src/manager/SongManager.cpp | 749 ++++++++--------- src/manager/TokenManager.cpp | 266 +++--- src/manager/UserManager.cpp | 96 +-- src/manager/YearManager.cpp | 102 ++- src/utility/ImageFile.cpp | 11 +- src/utility/MetadataRetriever.cpp | 335 ++++---- src/utility/PasswordEncryption.cpp | 60 +- src/verify/Initialization.cpp | 147 ++-- 74 files changed, 4397 insertions(+), 4717 deletions(-) diff --git a/include/callback/StreamCallback.h b/include/callback/StreamCallback.h index 3d9c651..f0e56fc 100644 --- a/include/callback/StreamCallback.h +++ b/include/callback/StreamCallback.h @@ -7,20 +7,19 @@ #include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp" namespace callback { -class StreamCallback : public oatpp::data::stream::ReadCallback -{ -public: - StreamCallback(); - StreamCallback(const std::string&); + class StreamCallback : public oatpp::data::stream::ReadCallback { + public: + StreamCallback(); + StreamCallback(const std::string&); - oatpp::data::v_io_size read(void*, oatpp::data::v_io_size); -private: - std::string m_songPath; + oatpp::data::v_io_size read(void*, oatpp::data::v_io_size); + private: + std::string m_songPath; - long m_bytesRead; - long m_counter; - long m_fileSize; -}; + long m_bytesRead; + long m_counter; + long m_fileSize; + }; } #endif diff --git a/include/component/AppComponent.hpp b/include/component/AppComponent.hpp index b26a0a2..e24368a 100644 --- a/include/component/AppComponent.hpp +++ b/include/component/AppComponent.hpp @@ -9,29 +9,32 @@ #include "oatpp/web/server/HttpConnectionHandler.hpp" namespace component { + class AppComponent { + public: + OATPP_CREATE_COMPONENT(std::shared_ptr, + serverConnectionProvider)([&] { + return oatpp::network::server::SimpleTCPConnectionProvider:: + createShared(appPort()); + }()); -class AppComponent -{ -public: - OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { - return oatpp::network::server::SimpleTCPConnectionProvider::createShared(5002); - }()); + OATPP_CREATE_COMPONENT(std::shared_ptr, httpRouter)([] { + return oatpp::web::server::HttpRouter::createShared(); + }()); - OATPP_CREATE_COMPONENT(std::shared_ptr, httpRouter)([] { - return oatpp::web::server::HttpRouter::createShared(); - }()); + OATPP_CREATE_COMPONENT(std::shared_ptr, + serverConnectionHandler)([] { + OATPP_COMPONENT(std::shared_ptr, router); - OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionHandler)([] { - OATPP_COMPONENT(std::shared_ptr, router); + return oatpp::web::server::HttpConnectionHandler::createShared(router); + }()); - return oatpp::web::server::HttpConnectionHandler::createShared(router); - }()); - - OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { - return oatpp::parser::json::mapping::ObjectMapper::createShared(); - }()); -private: -}; + OATPP_CREATE_COMPONENT(std::shared_ptr, + apiObjectMapper)([] { + return oatpp::parser::json::mapping::ObjectMapper::createShared(); + }()); + private: + constexpr int appPort() noexcept { return 5002; } + }; } #endif diff --git a/include/controller/AlbumController.hpp b/include/controller/AlbumController.hpp index 60f08e5..2a5ca04 100644 --- a/include/controller/AlbumController.hpp +++ b/include/controller/AlbumController.hpp @@ -29,69 +29,66 @@ namespace fs = std::filesystem; namespace controller { -class AlbumController : public oatpp::web::server::api::ApiController -{ -public: - AlbumController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + class AlbumController : public oatpp::web::server::api::ApiController { + public: + AlbumController(const model::BinaryPath& bConf, + OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } - AlbumController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + #include OATPP_CODEGEN_BEGIN(ApiController) - #include OATPP_CODEGEN_BEGIN(ApiController) + // endpoint for retrieving all album records in json format + ENDPOINT("GET", "/api/v1/album", albumRecords, + REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveAlbum), Status::CODE_403, "Not allowed"); - // endpoint for retrieving all album records in json format - ENDPOINT("GET", "/api/v1/album", albumRecords, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveAlbum), Status::CODE_403, "Not allowed"); + std::cout << "starting process of retrieving album\n"; + database::AlbumRepository albRepo(m_bConf); + auto albsDb = albRepo.retrieveRecords(); + auto albums = oatpp::data::mapping::type:: + List::createShared(); - std::cout << "starting process of retrieving album" << std::endl; - database::AlbumRepository albRepo(m_bConf); - auto albsDb = albRepo.retrieveRecords(); - auto albums = oatpp::data::mapping::type::List::createShared(); + for (auto& albDb : albsDb) { + auto alb = dto::conversion::DtoConversions::toAlbumDto(albDb); - for (auto& albDb : albsDb) { - auto alb = dto::conversion::DtoConversions::toAlbumDto(albDb); + albums->pushBack(alb); + } - albums->pushBack(alb); - } + return createDtoResponse(Status::CODE_200, albums); + } - return createDtoResponse(Status::CODE_200, albums); - } + // endpoint for retrieving single album record by the album id in json format + ENDPOINT("GET", "/api/v1/album/{id}", albumRecord, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveAlbum), Status::CODE_403, "Not allowed"); - // endpoint for retrieving single album record by the album id in json format - ENDPOINT("GET", "/api/v1/album/{id}", albumRecord, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveAlbum), Status::CODE_403, "Not allowed"); + database::AlbumRepository albRepo(m_bConf); + model::Album albDb(id); - database::AlbumRepository albRepo(m_bConf); - model::Album albDb(id); + OATPP_ASSERT_HTTP(albRepo.doesAlbumExists(albDb, + type::AlbumFilter::id) , Status::CODE_403, "album does not exist"); - OATPP_ASSERT_HTTP(albRepo.doesAlbumExists(albDb, type::AlbumFilter::id) , Status::CODE_403, "album does not exist"); + std::cout << "album exists\n"; + albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id); - std::cout << "album exists" << std::endl; - albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id); + auto album = dto::conversion::DtoConversions::toAlbumDto(albDb); - auto album = dto::conversion::DtoConversions::toAlbumDto(albDb); + return createDtoResponse(Status::CODE_200, album); + } - return createDtoResponse(Status::CODE_200, album); - } - - #include OATPP_CODEGEN_END(ApiController) -private: - std::string m_exe_path; - model::BinaryPath m_bConf; -}; + #include OATPP_CODEGEN_END(ApiController) + private: + model::BinaryPath m_bConf; + }; } #endif diff --git a/include/controller/ArtistController.hpp b/include/controller/ArtistController.hpp index 8c6ebc0..4db305a 100644 --- a/include/controller/ArtistController.hpp +++ b/include/controller/ArtistController.hpp @@ -28,73 +28,70 @@ namespace fs = std::filesystem; namespace controller { -class ArtistController : public oatpp::web::server::api::ApiController -{ -public: - ArtistController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + class ArtistController : public oatpp::web::server::api::ApiController { + public: + ArtistController(const model::BinaryPath& bConf, + OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } - ArtistController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + #include OATPP_CODEGEN_BEGIN(ApiController) - #include OATPP_CODEGEN_BEGIN(ApiController) + // endpoint for retrieving all artist records in json format + ENDPOINT("GET", "/api/v1/artist", artistRecords, + REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveArtist), Status::CODE_403, "Not allowed"); - // endpoint for retrieving all artist records in json format - ENDPOINT("GET", "/api/v1/artist", artistRecords, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveArtist), Status::CODE_403, "Not allowed"); + std::cout << "starting process of retrieving artist\n"; + database::ArtistRepository artRepo(m_bConf); + auto artsDb = artRepo.retrieveRecords(); + auto artists = oatpp::data::mapping::type:: + List::createShared(); - std::cout << "starting process of retrieving artist" << std::endl; - database::ArtistRepository artRepo(m_bConf); - auto artsDb = artRepo.retrieveRecords(); - auto artists = oatpp::data::mapping::type::List::createShared(); + for (auto& artDb : artsDb) { + auto art = dto::ArtistDto::createShared(); + art->id = artDb.id; + art->artist = artDb.artist.c_str(); - for (auto& artDb : artsDb) { - auto art = dto::ArtistDto::createShared(); - art->id = artDb.id; - art->artist = artDb.artist.c_str(); + artists->pushBack(art); + } - artists->pushBack(art); - } + return createDtoResponse(Status::CODE_200, artists); + } - return createDtoResponse(Status::CODE_200, artists); - } + // endpoint for retrieving single artist record by the artist id in json format + ENDPOINT("GET", "/api/v1/artist/{id}", artistRecord, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveArtist), Status::CODE_403, "Not allowed"); - // endpoint for retrieving single artist record by the artist id in json format - ENDPOINT("GET", "/api/v1/artist/{id}", artistRecord, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveArtist), Status::CODE_403, "Not allowed"); + database::ArtistRepository artRepo(m_bConf); + model::Artist artDb(id); - database::ArtistRepository artRepo(m_bConf); - model::Artist artDb(id); + OATPP_ASSERT_HTTP(artRepo.doesArtistExist(artDb, + type::ArtistFilter::id) , Status::CODE_403, "artist does not exist"); - OATPP_ASSERT_HTTP(artRepo.doesArtistExist(artDb, type::ArtistFilter::id) , Status::CODE_403, "artist does not exist"); + std::cout << "artist exist\n"; + artDb = artRepo.retrieveRecord(artDb, type::ArtistFilter::id); - std::cout << "artist exist" << std::endl; - artDb = artRepo.retrieveRecord(artDb, type::ArtistFilter::id); + auto artist = dto::ArtistDto::createShared(); + artist->id = artDb.id; + artist->artist = artDb.artist.c_str(); - auto artist = dto::ArtistDto::createShared(); - artist->id = artDb.id; - artist->artist = artDb.artist.c_str(); + return createDtoResponse(Status::CODE_200, artist); + } - return createDtoResponse(Status::CODE_200, artist); - } - - #include OATPP_CODEGEN_END(ApiController) -private: - std::string m_exe_path; - model::BinaryPath m_bConf; -}; + #include OATPP_CODEGEN_END(ApiController) + private: + model::BinaryPath m_bConf; + }; } #endif diff --git a/include/controller/CoverArtController.hpp b/include/controller/CoverArtController.hpp index ea41fd2..10e2039 100644 --- a/include/controller/CoverArtController.hpp +++ b/include/controller/CoverArtController.hpp @@ -27,95 +27,93 @@ namespace fs = std::filesystem; namespace controller { -class CoverArtController : public oatpp::web::server::api::ApiController -{ -public: - CoverArtController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + class CoverArtController : public oatpp::web::server::api::ApiController { + public: + CoverArtController(const model::BinaryPath& bConf, + OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } - CoverArtController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + #include OATPP_CODEGEN_BEGIN(ApiController) - #include OATPP_CODEGEN_BEGIN(ApiController) + // endpoint for retrieving all cover art records in json format + ENDPOINT("GET", "/api/v1/coverart", coverArtRecords, + REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::downloadCoverArt), Status::CODE_403, "Not allowed"); - // endpoint for retrieving all cover art records in json format - ENDPOINT("GET", "/api/v1/coverart", coverArtRecords, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::downloadCoverArt), Status::CODE_403, "Not allowed"); + std::cout << "starting process of retrieving cover art\n"; + database::CoverArtRepository covRepo(m_bConf); + auto covsDb = covRepo.retrieveRecords(); + auto coverArts = oatpp::data::mapping::type:: + List::createShared(); - std::cout << "starting process of retrieving cover art" << std::endl; - database::CoverArtRepository covRepo(m_bConf); - auto covsDb = covRepo.retrieveRecords(); - auto coverArts = oatpp::data::mapping::type::List::createShared(); + for (auto& covDb : covsDb) { + auto cov = dto::CoverArtDto::createShared(); + cov->id = covDb.id; + cov->songTitle = covDb.songTitle.c_str(); - for (auto& covDb : covsDb) { - auto cov = dto::CoverArtDto::createShared(); - cov->id = covDb.id; - cov->songTitle = covDb.songTitle.c_str(); + coverArts->pushBack(cov); + } - coverArts->pushBack(cov); - } + return createDtoResponse(Status::CODE_200, coverArts); + } - return createDtoResponse(Status::CODE_200, coverArts); - } + // endpoint for retrieving single cover art record by the cover art id in json format + ENDPOINT("GET", "/api/v1/coverart/{id}", coverArtRecord, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::downloadCoverArt), Status::CODE_403, "Not allowed"); - // endpoint for retrieving single cover art record by the cover art id in json format - ENDPOINT("GET", "/api/v1/coverart/{id}", coverArtRecord, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::downloadCoverArt), Status::CODE_403, "Not allowed"); + database::CoverArtRepository covRepo(m_bConf); + model::Cover covDb; + covDb.id = id; - database::CoverArtRepository covRepo(m_bConf); - model::Cover covDb; - covDb.id = id; + OATPP_ASSERT_HTTP(covRepo.doesCoverArtExist(covDb, + type::CoverFilter::id) , Status::CODE_403, "song does not exist"); - OATPP_ASSERT_HTTP(covRepo.doesCoverArtExist(covDb, type::CoverFilter::id) , Status::CODE_403, "song does not exist"); + std::cout << "cover art exists\n"; + covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); - std::cout << "cover art exists" << std::endl; - covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); + auto coverArt = dto::CoverArtDto::createShared(); + coverArt->id = covDb.id; + coverArt->songTitle = covDb.songTitle.c_str(); - auto coverArt = dto::CoverArtDto::createShared(); - coverArt->id = covDb.id; - coverArt->songTitle = covDb.songTitle.c_str(); + return createDtoResponse(Status::CODE_200, coverArt); + } - return createDtoResponse(Status::CODE_200, coverArt); - } + ENDPOINT("GET", "/api/v1/coverart/download/{id}", downloadCoverArt, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::downloadCoverArt), Status::CODE_403, "Not allowed"); - ENDPOINT("GET", "/api/v1/coverart/download/{id}", downloadCoverArt, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::downloadCoverArt), Status::CODE_403, "Not allowed"); + database::CoverArtRepository covRepo(m_bConf); + model::Cover covDb; + covDb.id = id; + covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); - database::CoverArtRepository covRepo(m_bConf); - model::Cover covDb; - covDb.id = id; - covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); + auto rawCover = oatpp::base::StrBuffer::loadFromFile(covDb.imagePath.c_str()); + auto response = createResponse(Status::CODE_200, rawCover); + + response->putHeader(Header::CONTENT_TYPE, "image/*"); - auto rawCover = oatpp::base::StrBuffer::loadFromFile(covDb.imagePath.c_str()); - auto response = createResponse(Status::CODE_200, rawCover); - - response->putHeader(Header::CONTENT_TYPE, "image/*"); + return response; + } - return response; - } - - #include OATPP_CODEGEN_END(ApiController) -private: - std::string m_exe_path; - model::BinaryPath m_bConf; -}; + #include OATPP_CODEGEN_END(ApiController) + private: + model::BinaryPath m_bConf; + }; } #endif diff --git a/include/controller/GenreController.hpp b/include/controller/GenreController.hpp index efae772..327a26a 100644 --- a/include/controller/GenreController.hpp +++ b/include/controller/GenreController.hpp @@ -28,73 +28,70 @@ namespace fs = std::filesystem; namespace controller { -class GenreController : public oatpp::web::server::api::ApiController -{ -public: - GenreController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + class GenreController : public oatpp::web::server::api::ApiController { + public: + GenreController(const model::BinaryPath& bConf, + OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } - GenreController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + #include OATPP_CODEGEN_BEGIN(ApiController) - #include OATPP_CODEGEN_BEGIN(ApiController) + // endpoint for retrieving all genre records in json format + ENDPOINT("GET", "/api/v1/genre", genreRecords, + REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveGenre), Status::CODE_403, "Not allowed"); - // endpoint for retrieving all genre records in json format - ENDPOINT("GET", "/api/v1/genre", genreRecords, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveGenre), Status::CODE_403, "Not allowed"); + std::cout << "starting process of retrieving genre\n"; + database::GenreRepository gnrRepo(m_bConf); + auto gnrsDb = gnrRepo.retrieveRecords(); + auto genres = oatpp::data::mapping::type:: + List::createShared(); - std::cout << "starting process of retrieving genre" << std::endl; - database::GenreRepository gnrRepo(m_bConf); - auto gnrsDb = gnrRepo.retrieveRecords(); - auto genres = oatpp::data::mapping::type::List::createShared(); + for (auto& gnrDb : gnrsDb) { + auto gnr = dto::GenreDto::createShared(); + gnr->id = gnrDb.id; + gnr->category = gnrDb.category.c_str(); - for (auto& gnrDb : gnrsDb) { - auto gnr = dto::GenreDto::createShared(); - gnr->id = gnrDb.id; - gnr->category = gnrDb.category.c_str(); + genres->pushBack(gnr); + } - genres->pushBack(gnr); - } + return createDtoResponse(Status::CODE_200, genres); + } - return createDtoResponse(Status::CODE_200, genres); - } + // endpoint for retrieving single genre record by the genre id in json format + ENDPOINT("GET", "/api/v1/genre/{id}", genreRecord, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveGenre), Status::CODE_403, "Not allowed"); - // endpoint for retrieving single genre record by the genre id in json format - ENDPOINT("GET", "/api/v1/genre/{id}", genreRecord, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveGenre), Status::CODE_403, "Not allowed"); + database::GenreRepository gnrRepo(m_bConf); + model::Genre gnrDb(id); - database::GenreRepository gnrRepo(m_bConf); - model::Genre gnrDb(id); + OATPP_ASSERT_HTTP(gnrRepo.doesGenreExist(gnrDb, + type::GenreFilter::id) , Status::CODE_403, "genre does not exist"); - OATPP_ASSERT_HTTP(gnrRepo.doesGenreExist(gnrDb, type::GenreFilter::id) , Status::CODE_403, "genre does not exist"); + std::cout << "genre exist\n"; + gnrDb = gnrRepo.retrieveRecord(gnrDb, type::GenreFilter::id); - std::cout << "genre exist" << std::endl; - gnrDb = gnrRepo.retrieveRecord(gnrDb, type::GenreFilter::id); + auto genre = dto::GenreDto::createShared(); + genre->id = gnrDb.id; + genre->category= gnrDb.category.c_str(); - auto genre = dto::GenreDto::createShared(); - genre->id = gnrDb.id; - genre->category= gnrDb.category.c_str(); + return createDtoResponse(Status::CODE_200, genre); + } - return createDtoResponse(Status::CODE_200, genre); - } - - #include OATPP_CODEGEN_END(ApiController) -private: - std::string m_exe_path; - model::BinaryPath m_bConf; -}; + #include OATPP_CODEGEN_END(ApiController) + private: + model::BinaryPath m_bConf; + }; } #endif diff --git a/include/controller/LoginController.hpp b/include/controller/LoginController.hpp index 78bcbbf..359b2fe 100644 --- a/include/controller/LoginController.hpp +++ b/include/controller/LoginController.hpp @@ -16,46 +16,42 @@ #include "model/Models.h" namespace controller { -class LoginController : public oatpp::web::server::api::ApiController { -public: - LoginController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), exe_path(p) - { } - LoginController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - :oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + class LoginController : public oatpp::web::server::api::ApiController { + public: + LoginController(const model::BinaryPath& bConf, + OATPP_COMPONENT(std::shared_ptr, objectMapper)) + :oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } - #include OATPP_CODEGEN_BEGIN(ApiController) + #include OATPP_CODEGEN_BEGIN(ApiController) - ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(dto::UserDto::ObjectWrapper, usr)) { - OATPP_LOGI("icarus", "logging in"); + ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(dto::UserDto::ObjectWrapper, usr)) { + OATPP_LOGI("icarus", "logging in"); - manager::UserManager usrMgr(m_bConf); - auto user = dto::conversion::DtoConversions::toUser(usr); + manager::UserManager usrMgr(m_bConf); + auto user = dto::conversion::DtoConversions::toUser(usr); - if (!usrMgr.doesUserExist(user) || !usrMgr.validatePassword(user)) { - auto logRes = dto::LoginResultDto::createShared(); - logRes->message = "invalid credentials"; - std::cout << "user does not exist" << std::endl; - return createDtoResponse(Status::CODE_401, logRes); - } + if (!usrMgr.doesUserExist(user) || !usrMgr.validatePassword(user)) { + auto logRes = dto::LoginResultDto::createShared(); + logRes->message = "invalid credentials"; + std::cout << "user does not exist\n"; + return createDtoResponse(Status::CODE_401, logRes); + } - std::cout << "user exists" << std::endl; + std::cout << "user exists\n"; - manager::TokenManager tok; - auto token = tok.retrieveToken(m_bConf); + manager::TokenManager tok; + auto token = tok.retrieveToken(m_bConf); - auto logRes = dto::conversion::DtoConversions::toLoginResultDto(user, token); - logRes->message = "Successful"; + auto logRes = dto::conversion::DtoConversions::toLoginResultDto(user, token); + logRes->message = "Successful"; - return createDtoResponse(Status::CODE_200, logRes); - } + return createDtoResponse(Status::CODE_200, logRes); + } - #include OATPP_CODEGEN_END(ApiController) -private: - std::string exe_path; - model::BinaryPath m_bConf; -}; + #include OATPP_CODEGEN_END(ApiController) + private: + model::BinaryPath m_bConf; + }; } #endif diff --git a/include/controller/RegisterController.hpp b/include/controller/RegisterController.hpp index b1b3fc7..2e3d479 100644 --- a/include/controller/RegisterController.hpp +++ b/include/controller/RegisterController.hpp @@ -17,8 +17,8 @@ namespace controller { class RegisterController : public oatpp::web::server::api::ApiController { public: RegisterController(const model::BinaryPath& bConf, - OATPP_COMPONENT(std::shared_ptr, objectMapper)) : - oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } + OATPP_COMPONENT(std::shared_ptr, objectMapper)) : + oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } #include OATPP_CODEGEN_BEGIN(ApiController) @@ -26,6 +26,9 @@ namespace controller { BODY_DTO(dto::UserDto::ObjectWrapper, usr)) { manager::UserManager usrMgr(m_bConf); auto user = dto::conversion::DtoConversions::toUser(usr); + if (usrMgr.doesUserExist(user)) { + return createResponse(Status::CODE_401, "user already exists"); + } auto res = usrMgr.registerUser(user); auto registerResult = dto::conversion::DtoConversions::toRegisterResultDto(res); diff --git a/include/controller/SongController.hpp b/include/controller/SongController.hpp index 7c1b08b..e9209fa 100644 --- a/include/controller/SongController.hpp +++ b/include/controller/SongController.hpp @@ -32,219 +32,219 @@ namespace fs = std::filesystem; namespace controller { -class SongController : public oatpp::web::server::api::ApiController { -public: - SongController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + class SongController : public oatpp::web::server::api::ApiController { + public: + SongController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } - SongController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + #include OATPP_CODEGEN_BEGIN(ApiController) - #include OATPP_CODEGEN_BEGIN(ApiController) + // endpoint for uploading a song + ENDPOINT("POST", "/api/v1/song/data", songUpload, + REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::upload), Status::CODE_403, "Not allowed"); - // endpoint for uploading a song - ENDPOINT("POST", "/api/v1/song/data", songUpload, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::upload), Status::CODE_403, "Not allowed"); + auto mp = + std::make_shared + (request->getHeaders()); - auto mp = std::make_shared(request->getHeaders()); + oatpp::web::mime::multipart::Reader mp_reader(mp.get()); - oatpp::web::mime::multipart::Reader mp_reader(mp.get()); + mp_reader.setPartReader("file", + oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize)); - mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize)); + request->transferBody(&mp_reader); - request->transferBody(&mp_reader); + auto file = mp->getNamedPart("file"); - auto file = mp->getNamedPart("file"); + OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); - OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); + auto buff = std::unique_ptr(new char[file->getKnownSize()]); + auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize()); - auto buff = std::unique_ptr(new char[file->getKnownSize()]); - auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize()); + std::vector data(buff.get(), buff.get() + buffSize); - std::vector data(buff.get(), buff.get() + buffSize); + model::Song sng; + sng.data = std::move(data); + + manager::SongManager songMgr(m_bConf); + const auto result = songMgr.saveSong(sng); + if (!result.first) { + switch (result.second) { + case type::SongUpload::AlreadyExist: + return createResponse(Status::CODE_400, "Song already exists"); + default: + break; + } + } - model::Song sng; - sng.data = std::move(data); - - manager::SongManager songMgr(m_bConf); - const auto result = songMgr.saveSong(sng); - if (!result.first) { - switch (result.second) { - case type::SongUpload::AlreadyExist: - return createResponse(Status::CODE_400, "Song already exists"); - default: - break; - } - } + auto songDto = dto::conversion::DtoConversions::toSongDto(sng); - auto songDto = dto::conversion::DtoConversions::toSongDto(sng); + return createDtoResponse(Status::CODE_200, songDto); + } - return createDtoResponse(Status::CODE_200, songDto); - } + // endpoint for retrieving all song records in json format + ENDPOINT("GET", "/api/v1/song", songRecords, + REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveSong), Status::CODE_403, "Not allowed"); - // endpoint for retrieving all song records in json format - ENDPOINT("GET", "/api/v1/song", songRecords, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveSong), Status::CODE_403, "Not allowed"); + std::cout << "starting process of retrieving songs\n"; + database::SongRepository songRepo(m_bConf); + auto songsDb = songRepo.retrieveRecords(); + auto songs = oatpp::data::mapping::type::List::createShared(); - std::cout << "starting process of retrieving songs" << std::endl; - database::SongRepository songRepo(m_bConf); - auto songsDb = songRepo.retrieveRecords(); - auto songs = oatpp::data::mapping::type::List::createShared(); + std::cout << "creating object to send\n"; + for (auto& songDb : songsDb) { + auto song = dto::conversion::DtoConversions::toSongDto(songDb); - std::cout << "creating object to send" << std::endl; - for (auto& songDb : songsDb) { - auto song = dto::conversion::DtoConversions::toSongDto(songDb); + songs->pushBack(song); + } - songs->pushBack(song); - } - - return createDtoResponse(Status::CODE_200, songs); - } + return createDtoResponse(Status::CODE_200, songs); + } // endpoint for retrieving song record by the song id in json format - ENDPOINT("GET", "/api/v1/song/{id}", songRecord, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveSong), Status::CODE_403, "Not allowed"); + ENDPOINT("GET", "/api/v1/song/{id}", songRecord, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveSong), Status::CODE_403, "Not allowed"); - database::SongRepository songRepo(m_bConf); - model::Song songDb(id); + database::SongRepository songRepo(m_bConf); + model::Song songDb(id); - if (!songRepo.doesSongExist(songDb, type::SongFilter::id)) { - return songDoesNotExist(); - } + if (!songRepo.doesSongExist(songDb, type::SongFilter::id)) { + return songDoesNotExist(); + } - std::cout << "song exists" << std::endl; - songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); + std::cout << "song exists\n"; + songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); - auto song = dto::conversion::DtoConversions::toSongDto(songDb); + auto song = dto::conversion::DtoConversions::toSongDto(songDb); - return createDtoResponse(Status::CODE_200, song); - } + return createDtoResponse(Status::CODE_200, song); + } - ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::download), Status::CODE_403, "Not allowed"); + ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::download), Status::CODE_403, "Not allowed"); - database::SongRepository songRepo(m_bConf); - model::Song songDb(id); - if (!songRepo.doesSongExist(songDb, type::SongFilter::id)) { - return songDoesNotExist(); - } + database::SongRepository songRepo(m_bConf); + model::Song songDb(id); + if (!songRepo.doesSongExist(songDb, type::SongFilter::id)) { + return songDoesNotExist(); + } - songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); + songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); - auto rawSong = oatpp::base::StrBuffer::loadFromFile(songDb.songPath.c_str()); - - auto response = createResponse(Status::CODE_200, rawSong); - response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); + auto rawSong = oatpp::base::StrBuffer::loadFromFile(songDb.songPath.c_str()); + + auto response = createResponse(Status::CODE_200, rawSong); + response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); - return response; - } + return response; + } - ENDPOINT("UPDATE", "/api/v1/song/{id}", songUpdate, - REQUEST(std::shared_ptr, request), - BODY_DTO(dto::SongDto::ObjectWrapper, songDto), PATH(Int32, id)) { - songDto->id = id; - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::updateSong), Status::CODE_403, "Not allowed"); + ENDPOINT("UPDATE", "/api/v1/song/{id}", songUpdate, + REQUEST(std::shared_ptr, request), + BODY_DTO(dto::SongDto::ObjectWrapper, songDto), PATH(Int32, id)) { + songDto->id = id; + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::updateSong), Status::CODE_403, "Not allowed"); - auto updatedSong = dto::conversion::DtoConversions::toSong(songDto); - manager::SongManager songMgr(m_bConf); - auto result = songMgr.updateSong(updatedSong); - if (!result) { - return songDoesNotExist(); - } + auto updatedSong = dto::conversion::DtoConversions::toSong(songDto); + manager::SongManager songMgr(m_bConf); + auto result = songMgr.updateSong(updatedSong); + if (!result) { + return songDoesNotExist(); + } - return createResponse(Status::CODE_200, "OK"); - } + return createResponse(Status::CODE_200, "OK"); + } - // endpoint to delete a song - ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::deleteSong), Status::CODE_403, "Not allowed"); + // endpoint to delete a song + ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::deleteSong), Status::CODE_403, "Not allowed"); - model::Song song(id); + model::Song song(id); - manager::SongManager sngMgr(m_bConf); - auto result = sngMgr.deleteSong(song); - if (!result) { - return songDoesNotExist(); - } + manager::SongManager sngMgr(m_bConf); + auto result = sngMgr.deleteSong(song); + if (!result) { + return songDoesNotExist(); + } - return createResponse(Status::CODE_200, "OK"); - } + return createResponse(Status::CODE_200, "OK"); + } - // endpoint for streaming a song - ENDPOINT("GET", "/api/v1/song/stream/{id}", streamSong, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::stream), Status::CODE_403, "Not allowed"); + // endpoint for streaming a song + ENDPOINT("GET", "/api/v1/song/stream/{id}", streamSong, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::stream), Status::CODE_403, "Not allowed"); - database::SongRepository songRepo(m_bConf); - model::Song songDb(id); - if (!songRepo.doesSongExist(songDb, type::SongFilter::id)) { - return songDoesNotExist(); - } + database::SongRepository songRepo(m_bConf); + model::Song songDb(id); + if (!songRepo.doesSongExist(songDb, type::SongFilter::id)) { + return songDoesNotExist(); + } - songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); + songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); - oatpp::data::v_io_size dSize = 1024; + oatpp::data::v_io_size dSize = 1024; - auto db = std::make_shared( - std::make_shared(songDb.songPath), nullptr, dSize); + auto db = std::make_shared( + std::make_shared(songDb.songPath), + nullptr, dSize); - auto response = OutgoingResponse::createShared(Status::CODE_200, db); - response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE); - response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); + auto response = OutgoingResponse::createShared(Status::CODE_200, db); + response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE); + response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); - return response; - } + return response; + } - #include OATPP_CODEGEN_END(ApiController) -private: - std::shared_ptr - songDoesNotExist() { + #include OATPP_CODEGEN_END(ApiController) + private: + std::shared_ptr + songDoesNotExist() { - return createResponse(Status::CODE_404, "Song not found"); - } + return createResponse(Status::CODE_404, "Song not found"); + } - std::string m_exe_path; + model::BinaryPath m_bConf; - model::BinaryPath m_bConf; - - const long m_dataSize = std::numeric_limits::max(); -}; + const long m_dataSize = std::numeric_limits::max(); + }; } #endif diff --git a/include/controller/YearController.hpp b/include/controller/YearController.hpp index 6e6b71e..90c4892 100644 --- a/include/controller/YearController.hpp +++ b/include/controller/YearController.hpp @@ -27,73 +27,71 @@ namespace fs = std::filesystem; namespace controller { -class YearController : public oatpp::web::server::api::ApiController -{ -public: - YearController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + class YearController : public oatpp::web::server::api::ApiController { + public: + YearController(const model::BinaryPath& bConf, + OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } - YearController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + #include OATPP_CODEGEN_BEGIN(ApiController) - #include OATPP_CODEGEN_BEGIN(ApiController) + // endpoint for retrieving all year records in json format + ENDPOINT("GET", "/api/v1/year", yearRecords, + REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveYear), Status::CODE_403, "Not allowed"); - // endpoint for retrieving all year records in json format - ENDPOINT("GET", "/api/v1/year", yearRecords, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveYear), Status::CODE_403, "Not allowed"); + std::cout << "starting process of retrieving year\n"; + database::YearRepository yrRepo(m_bConf); + auto yrsDb = yrRepo.retrieveRecords(); + auto yearRecs = oatpp::data::mapping::type:: + List::createShared(); - std::cout << "starting process of retrieving year" << std::endl; - database::YearRepository yrRepo(m_bConf); - auto yrsDb = yrRepo.retrieveRecords(); - auto yearRecs = oatpp::data::mapping::type::List::createShared(); + for (auto& yrDb : yrsDb) { + auto yr = dto::YearDto::createShared(); + yr->id = yrDb.id; + yr->year = yrDb.year; - for (auto& yrDb : yrsDb) { - auto yr = dto::YearDto::createShared(); - yr->id = yrDb.id; - yr->year = yrDb.year; + yearRecs->pushBack(yr); + } - yearRecs->pushBack(yr); - } + return createDtoResponse(Status::CODE_200, yearRecs); + } - return createDtoResponse(Status::CODE_200, yearRecs); - } + // endpoint for retrieving single year record by the year id in json format + ENDPOINT("GET", "/api/v1/year/{id}", yearRecord, + REQUEST(std::shared_ptr, request), PATH(Int32, id)) { + auto authHeader = request->getHeader("Authorization"); + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + auto auth = authHeader->std_str(); + manager::TokenManager tok; + OATPP_ASSERT_HTTP(tok.isTokenValid(auth, + type::Scope::retrieveYear), Status::CODE_403, "Not allowed"); - // endpoint for retrieving single year record by the year id in json format - ENDPOINT("GET", "/api/v1/year/{id}", yearRecord, - REQUEST(std::shared_ptr, request), PATH(Int32, id)) { - auto authHeader = request->getHeader("Authorization"); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); - auto auth = authHeader->std_str(); - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::retrieveYear), Status::CODE_403, "Not allowed"); + database::YearRepository yrRepo(m_bConf); + model::Year yrDb(id); - database::YearRepository yrRepo(m_bConf); - model::Year yrDb(id); + OATPP_ASSERT_HTTP(yrRepo.doesYearExist(yrDb, + type::YearFilter::id) , Status::CODE_403, "year does not exist"); - OATPP_ASSERT_HTTP(yrRepo.doesYearExist(yrDb, type::YearFilter::id) , Status::CODE_403, "year does not exist"); + std::cout << "year exist\n"; + yrDb = yrRepo.retrieveRecord(yrDb, type::YearFilter::id); - std::cout << "year exist" << std::endl; - yrDb = yrRepo.retrieveRecord(yrDb, type::YearFilter::id); + auto year = dto::YearDto::createShared(); + year->id = yrDb.id; + year->year= yrDb.year; - auto year = dto::YearDto::createShared(); - year->id = yrDb.id; - year->year= yrDb.year; + return createDtoResponse(Status::CODE_200, year); + } - return createDtoResponse(Status::CODE_200, year); - } - - #include OATPP_CODEGEN_END(ApiController) -private: - std::string m_exe_path; - model::BinaryPath m_bConf; -}; + #include OATPP_CODEGEN_END(ApiController) + private: + model::BinaryPath m_bConf; + }; } + #endif diff --git a/include/database/AlbumRepository.h b/include/database/AlbumRepository.h index 45c9432..6e9ccda 100644 --- a/include/database/AlbumRepository.h +++ b/include/database/AlbumRepository.h @@ -9,10 +9,8 @@ #include "model/Models.h" #include "type/AlbumFilter.h" -namespace database -{ - class AlbumRepository : public BaseRepository - { +namespace database { + class AlbumRepository : public BaseRepository { public: AlbumRepository(const model::BinaryPath&); diff --git a/include/database/ArtistRepository.h b/include/database/ArtistRepository.h index 86f4395..8862369 100644 --- a/include/database/ArtistRepository.h +++ b/include/database/ArtistRepository.h @@ -1,6 +1,7 @@ #ifndef ARTISTREPOSITORY_H_ #define ARTISTREPOSITORY_H_ +#include #include #include @@ -8,16 +9,15 @@ #include "model/Models.h" #include "type/ArtistFilter.h" -namespace database -{ - class ArtistRepository : public BaseRepository - { +namespace database { + class ArtistRepository : public BaseRepository { public: ArtistRepository(const model::BinaryPath&); std::vector retrieveRecords(); - std::pair retrieveRecordWithSongCount(model::Artist&, type::ArtistFilter); + std::pair retrieveRecordWithSongCount( + model::Artist&, type::ArtistFilter); model::Artist retrieveRecord(model::Artist&, type::ArtistFilter); @@ -30,9 +30,13 @@ namespace database std::pair parseRecordWithSongCount(MYSQL_STMT*); - // TODO: After parseRecord(MYSQL_STMT*) is implemented - // remove parseRecord(MYSQL_RES*) - model::Artist parseRecord(MYSQL_RES*); + std::shared_ptr valueBind(model::Artist&, + std::tuple&); + std::shared_ptr valueBindWithSongCount(model::Artist&, + std::tuple&, int&); + + std::tuple metadataBuffer(); + model::Artist parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/BaseRepository.h b/include/database/BaseRepository.h index 8b05a84..d0dfd3d 100644 --- a/include/database/BaseRepository.h +++ b/include/database/BaseRepository.h @@ -7,12 +7,10 @@ #include "model/Models.h" -namespace database -{ - class BaseRepository - { +namespace database { + class BaseRepository { public: - BaseRepository(); + BaseRepository() = default; BaseRepository(const std::string&); BaseRepository(const model::BinaryPath&); diff --git a/include/database/CoverArtRepository.h b/include/database/CoverArtRepository.h index 3ec99d2..53dbe7d 100644 --- a/include/database/CoverArtRepository.h +++ b/include/database/CoverArtRepository.h @@ -1,6 +1,7 @@ #ifndef COVERARTREPOSITORY_H_ #define COVERARTREPOSITORY_H_ +#include #include #include @@ -9,12 +10,9 @@ #include "model/Models.h" #include "type/CoverFilter.h" -namespace database -{ - class CoverArtRepository : public BaseRepository - { +namespace database { + class CoverArtRepository : public BaseRepository { public: - CoverArtRepository(const std::string&); CoverArtRepository(const model::BinaryPath&); std::vector retrieveRecords(); @@ -23,15 +21,17 @@ namespace database bool doesCoverArtExist(const model::Cover&, type::CoverFilter); - void deleteRecord(const model::Cover&); + void deleteRecord(const model::Cover&, type::CoverFilter = type::CoverFilter::id); void saveRecord(const model::Cover&); void updateRecord(const model::Cover&); private: std::vector parseRecords(MYSQL_STMT*); - // TODO: After parseRecord(MYSQL_STMT*) is implemented - // remove parseRecord(MYSQL_RES*) - model::Cover parseRecord(MYSQL_RES*); + std::shared_ptr valueBind(model::Cover&, + std::tuple&); + + std::tuple metadataBuffer(); + model::Cover parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/GenreRepository.h b/include/database/GenreRepository.h index c7d9b08..43390cf 100644 --- a/include/database/GenreRepository.h +++ b/include/database/GenreRepository.h @@ -1,6 +1,7 @@ #ifndef GENREREPOSITORY_H_ #define GENREREPOSITORY_H_ +#include #include #include @@ -8,10 +9,8 @@ #include "model/Models.h" #include "type/GenreFilter.h" -namespace database -{ - class GenreRepository : public BaseRepository - { +namespace database { + class GenreRepository : public BaseRepository { public: GenreRepository(const model::BinaryPath&); @@ -30,9 +29,13 @@ namespace database std::pair parseRecordWithSongCount(MYSQL_STMT*); - // TODO: After parseRecord(MYSQL_STMT*) is implemented - // remove parseRecord(MYSQL_RES*) - model::Genre parseRecord(MYSQL_RES*); + std::shared_ptr valueBind(model::Genre&, + std::tuple&); + std::shared_ptr valueBindWithSongCount(model::Genre&, + std::tuple&, int&); + + std::tuple metadataBuffer(); + model::Genre parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/SongRepository.h b/include/database/SongRepository.h index 5e214d2..d3741e9 100644 --- a/include/database/SongRepository.h +++ b/include/database/SongRepository.h @@ -11,18 +11,16 @@ #include "model/Models.h" #include "type/SongFilter.h" -namespace database -{ - class SongRepository : public BaseRepository - { +namespace database { + class SongRepository : public BaseRepository { public: SongRepository(const model::BinaryPath&); std::vector retrieveRecords(); - model::Song retrieveRecord(const model::Song&, type::SongFilter); + model::Song retrieveRecord(const model::Song&, type::SongFilter = type::SongFilter::id); - bool doesSongExist(const model::Song&, type::SongFilter); + bool doesSongExist(const model::Song&, type::SongFilter = type::SongFilter::id); bool deleteRecord(const model::Song&); void saveRecord(const model::Song&); diff --git a/include/database/UserRepository.h b/include/database/UserRepository.h index 1de10a8..2eec79b 100644 --- a/include/database/UserRepository.h +++ b/include/database/UserRepository.h @@ -11,48 +11,48 @@ #include "type/UserFilter.h" namespace database { -class UserRepository : BaseRepository { -public: - UserRepository(const model::BinaryPath&); + class UserRepository : BaseRepository { + public: + UserRepository(const model::BinaryPath&); - model::User retrieveUserRecord(model::User&, type::UserFilter); - model::PassSec retrieverUserSaltRecord(model::PassSec&, type::SaltFilter); + model::User retrieveUserRecord(model::User&, type::UserFilter); + model::PassSec retrieverUserSaltRecord(model::PassSec&, type::SaltFilter); - bool doesUserRecordExist(const model::User&, type::UserFilter); + bool doesUserRecordExist(const model::User&, type::UserFilter); - void saveUserRecord(const model::User&); - void saveUserSalt(const model::PassSec&); -private: - struct UserLengths; - struct SaltLengths; + void saveUserRecord(const model::User&); + void saveUserSalt(const model::PassSec&); + private: + struct UserLengths; + struct SaltLengths; - struct UserLengths - { - unsigned long firstnameLength; - unsigned long lastnameLength; - unsigned long phoneLength; - unsigned long emailLength; - unsigned long usernameLength; - unsigned long passwordLength; + struct UserLengths { + unsigned long firstnameLength; + unsigned long lastnameLength; + unsigned long phoneLength; + unsigned long emailLength; + unsigned long usernameLength; + unsigned long passwordLength; + }; + struct SaltLengths { + unsigned long saltLength; + }; + + std::shared_ptr insertUserValues(const model::User&, + std::shared_ptr); + std::shared_ptr insertSaltValues(const model::PassSec&, + std::shared_ptr); + std::shared_ptr valueBind(model::User&, + std::tuple&); + std::shared_ptr saltValueBind(model::PassSec&, char*); + std::shared_ptr fetchUserLengths(const model::User&); + std::shared_ptr fetchSaltLengths(const model::PassSec&); + + std::tuple fetchUV(); + + model::User parseRecord(MYSQL_STMT*); + model::PassSec parseSaltRecord(MYSQL_STMT*); }; - struct SaltLengths - { - unsigned long saltLength; - }; - - std::shared_ptr insertUserValues(const model::User&, std::shared_ptr); - std::shared_ptr insertSaltValues(const model::PassSec&, std::shared_ptr); - std::shared_ptr valueBind(model::User&, std::tuple&); - std::shared_ptr saltValueBind(model::PassSec&, char*); - std::shared_ptr fetchUserLengths(const model::User&); - std::shared_ptr fetchSaltLengths(const model::PassSec&); - - std::tuple fetchUV(); - - model::User parseRecord(MYSQL_STMT*); - model::PassSec parseSaltRecord(MYSQL_STMT*); -}; } - #endif diff --git a/include/database/YearRepository.h b/include/database/YearRepository.h index a840017..bb92c0b 100644 --- a/include/database/YearRepository.h +++ b/include/database/YearRepository.h @@ -1,6 +1,7 @@ #ifndef YEARREPOSITORY_H_ #define YEARREPOSITORY_H_ +#include #include #include @@ -8,31 +9,31 @@ #include "model/Models.h" #include "type/YearFilter.h" -namespace database -{ - class YearRepository : public BaseRepository - { +namespace database { + class YearRepository : public BaseRepository { public: YearRepository(const model::BinaryPath&); std::vector retrieveRecords(); - std::pair retrieveRecordWithSongCount(model::Year&, type::YearFilter); + std::pair retrieveRecordWithSongCount(model::Year&, + type::YearFilter = type::YearFilter::id); - model::Year retrieveRecord(model::Year&, type::YearFilter); + model::Year retrieveRecord(model::Year&, type::YearFilter = type::YearFilter::id); - bool doesYearExist(const model::Year&, type::YearFilter); + bool doesYearExist(const model::Year&, type::YearFilter = type::YearFilter::id); void saveRecord(const model::Year&); - void deleteYear(const model::Year&, type::YearFilter); + void deleteYear(const model::Year&, type::YearFilter = type::YearFilter::id); private: std::vector parseRecords(MYSQL_STMT*); std::pair parseRecordWithSongCount(MYSQL_STMT*); - // TODO: After parseRecord(MYSQL_STMT*) is implemented - // remove parseRecord(MYSQL_RES*) - model::Year parseRecord(MYSQL_RES*); + std::shared_ptr valueBind(model::Year&); + std::shared_ptr valueBindWithSongCount(model::Year&, + int&); + model::Year parseRecord(MYSQL_STMT*); }; } diff --git a/include/dto/AlbumDto.hpp b/include/dto/AlbumDto.hpp index 93c6dba..8eff244 100644 --- a/include/dto/AlbumDto.hpp +++ b/include/dto/AlbumDto.hpp @@ -4,12 +4,10 @@ #include "oatpp/core/data/mapping/type/Object.hpp" #include "oatpp/core/macro/codegen.hpp" -namespace dto -{ +namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) - class AlbumDto : public oatpp::data::mapping::type::Object - { + class AlbumDto : public oatpp::data::mapping::type::Object { DTO_INIT(AlbumDto, Object) DTO_FIELD(Int32, id); diff --git a/include/dto/ArtistDto.hpp b/include/dto/ArtistDto.hpp index 08f9392..7d4c8ba 100644 --- a/include/dto/ArtistDto.hpp +++ b/include/dto/ArtistDto.hpp @@ -4,12 +4,10 @@ #include "oatpp/core/data/mapping/type/Object.hpp" #include "oatpp/core/macro/codegen.hpp" -namespace dto -{ +namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) - class ArtistDto : public oatpp::data::mapping::type::Object - { + class ArtistDto : public oatpp::data::mapping::type::Object { DTO_INIT(ArtistDto, Object) DTO_FIELD(Int32, id); diff --git a/include/dto/CoverArtDto.hpp b/include/dto/CoverArtDto.hpp index 1d8d706..22dca2c 100644 --- a/include/dto/CoverArtDto.hpp +++ b/include/dto/CoverArtDto.hpp @@ -4,12 +4,10 @@ #include "oatpp/core/data/mapping/type/Object.hpp" #include "oatpp/core/macro/codegen.hpp" -namespace dto -{ +namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) - class CoverArtDto : public oatpp::data::mapping::type::Object - { + class CoverArtDto : public oatpp::data::mapping::type::Object { DTO_INIT(CoverArtDto, Object) DTO_FIELD(Int32, id); diff --git a/include/dto/GenreDto.hpp b/include/dto/GenreDto.hpp index b7235a8..f1b6753 100644 --- a/include/dto/GenreDto.hpp +++ b/include/dto/GenreDto.hpp @@ -4,12 +4,10 @@ #include "oatpp/core/data/mapping/type/Object.hpp" #include "oatpp/core/macro/codegen.hpp" -namespace dto -{ +namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) - class GenreDto : public oatpp::data::mapping::type::Object - { + class GenreDto : public oatpp::data::mapping::type::Object { DTO_INIT(GenreDto, Object) DTO_FIELD(Int32, id); diff --git a/include/dto/SongDto.hpp b/include/dto/SongDto.hpp index 6ddd32f..050dee0 100644 --- a/include/dto/SongDto.hpp +++ b/include/dto/SongDto.hpp @@ -6,12 +6,10 @@ #include "model/Models.h" -namespace dto -{ +namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) - class SongDto : public oatpp::data::mapping::type::Object - { + class SongDto : public oatpp::data::mapping::type::Object { DTO_INIT(SongDto, Object) DTO_FIELD(Int32, id); diff --git a/include/dto/YearDto.hpp b/include/dto/YearDto.hpp index 1cb102a..915c270 100644 --- a/include/dto/YearDto.hpp +++ b/include/dto/YearDto.hpp @@ -4,12 +4,10 @@ #include "oatpp/core/data/mapping/type/Object.hpp" #include "oatpp/core/macro/codegen.hpp" -namespace dto -{ +namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) - class YearDto : public oatpp::data::mapping::type::Object - { + class YearDto : public oatpp::data::mapping::type::Object { DTO_INIT(YearDto, Object) DTO_FIELD(Int32, id); diff --git a/include/manager/AlbumManager.h b/include/manager/AlbumManager.h index 66fd2cf..a8c4ca6 100644 --- a/include/manager/AlbumManager.h +++ b/include/manager/AlbumManager.h @@ -3,10 +3,8 @@ #include "model/Models.h" -namespace manager -{ - class AlbumManager - { +namespace manager { + class AlbumManager { public: AlbumManager(const model::BinaryPath&); diff --git a/include/manager/ArtistManager.h b/include/manager/ArtistManager.h index e991032..001a49e 100644 --- a/include/manager/ArtistManager.h +++ b/include/manager/ArtistManager.h @@ -3,10 +3,8 @@ #include "model/Models.h" -namespace manager -{ - class ArtistManager - { +namespace manager { + class ArtistManager { public: ArtistManager(const model::BinaryPath&); diff --git a/include/manager/CoverArtManager.h b/include/manager/CoverArtManager.h index 4f5901b..3d30b26 100644 --- a/include/manager/CoverArtManager.h +++ b/include/manager/CoverArtManager.h @@ -6,12 +6,9 @@ #include "model/Models.h" -namespace manager -{ - class CoverArtManager - { +namespace manager { + class CoverArtManager { public: - CoverArtManager(const std::string&); CoverArtManager(const model::BinaryPath& bConf); model::Cover saveCover(const model::Song&); @@ -25,7 +22,6 @@ namespace manager std::string createImagePath(const model::Song&); model::BinaryPath m_bConf; - std::string path; }; } diff --git a/include/manager/DirectoryManager.h b/include/manager/DirectoryManager.h index 7ade859..f421f46 100644 --- a/include/manager/DirectoryManager.h +++ b/include/manager/DirectoryManager.h @@ -9,13 +9,12 @@ #include "model/Models.h" #include "type/PathType.h" -namespace manager -{ - class DirectoryManager - { +namespace manager { + class DirectoryManager { public: static std::string createDirectoryProcess(model::Song, const std::string&); - static std::string createDirectoryProcess(const model::Song&, const model::BinaryPath&, type::PathType); + static std::string createDirectoryProcess(const model::Song&, + const model::BinaryPath&, type::PathType); static std::string configPath(std::string_view); static std::string configPath(const model::BinaryPath&); static std::string contentOfPath(const std::string&); diff --git a/include/manager/GenreManager.h b/include/manager/GenreManager.h index 8e91b11..a0e4b07 100644 --- a/include/manager/GenreManager.h +++ b/include/manager/GenreManager.h @@ -3,10 +3,8 @@ #include "model/Models.h" -namespace manager -{ - class GenreManager - { +namespace manager { + class GenreManager { public: GenreManager(const model::BinaryPath&); diff --git a/include/manager/SongManager.h b/include/manager/SongManager.h index 74d7b21..a053819 100644 --- a/include/manager/SongManager.h +++ b/include/manager/SongManager.h @@ -14,8 +14,7 @@ #include "type/SongUpload.h" namespace manager { - class SongManager - { + class SongManager { public: SongManager(const model::BinaryPath&); diff --git a/include/manager/TokenManager.h b/include/manager/TokenManager.h index 27e6a58..46ee648 100644 --- a/include/manager/TokenManager.h +++ b/include/manager/TokenManager.h @@ -14,26 +14,26 @@ #include "type/Scopes.h" namespace manager { -class TokenManager { -public: - TokenManager() = default; + class TokenManager { + public: + TokenManager() = default; - model::Token retrieveToken(const model::BinaryPath&); + model::Token retrieveToken(const model::BinaryPath&); - bool isTokenValid(std::string&, type::Scope); - bool testAuth(const model::BinaryPath&); -private: - cpr::Response sendRequest(std::string_view, nlohmann::json&); + bool isTokenValid(std::string&, type::Scope); + bool testAuth(const model::BinaryPath&); + private: + cpr::Response sendRequest(std::string_view, nlohmann::json&); - nlohmann::json createTokenBody(const model::AuthCredentials&); + nlohmann::json createTokenBody(const model::AuthCredentials&); - model::AuthCredentials parseAuthCredentials(const model::BinaryPath&); + model::AuthCredentials parseAuthCredentials(const model::BinaryPath&); - std::vector extractScopes(const jwt::decoded_jwt&&); - std::pair> fetchAuthHeader(const std::string&); + std::vector extractScopes(const jwt::decoded_jwt&&); + std::pair> fetchAuthHeader(const std::string&); - bool tokenSupportsScope(const std::vector&, const std::string&&); -}; + bool tokenSupportsScope(const std::vector&, const std::string&&); + }; } #endif diff --git a/include/manager/UserManager.h b/include/manager/UserManager.h index 0734cef..3d55214 100644 --- a/include/manager/UserManager.h +++ b/include/manager/UserManager.h @@ -7,19 +7,19 @@ #include "model/Models.h" namespace manager { -class UserManager { -public: - UserManager(const model::BinaryPath&); + class UserManager { + public: + UserManager(const model::BinaryPath&); - model::RegisterResult registerUser(model::User&); + model::RegisterResult registerUser(model::User&); - bool doesUserExist(const model::User&); - bool validatePassword(const model::User&); + bool doesUserExist(const model::User&); + bool validatePassword(const model::User&); - void printUser(const model::User&); -private: - model::BinaryPath m_bConf; -}; + void printUser(const model::User&); + private: + model::BinaryPath m_bConf; + }; } #endif diff --git a/include/manager/YearManager.h b/include/manager/YearManager.h index f10c55f..1950bfd 100644 --- a/include/manager/YearManager.h +++ b/include/manager/YearManager.h @@ -3,10 +3,8 @@ #include "model/Models.h" -namespace manager -{ - class YearManager - { +namespace manager { + class YearManager { public: YearManager(const model::BinaryPath&); diff --git a/include/model/Models.h b/include/model/Models.h index 0fbdc98..85535d1 100644 --- a/include/model/Models.h +++ b/include/model/Models.h @@ -5,172 +5,172 @@ #include namespace model { -class Song { -public: - Song() = default; - Song(const int id) : id(id) { } - Song(const int id, const std::string& title, const std::string& artist, - const std::string& album, const std::string& albumArtist, - const std::string& genre, const int year, const int duration, - const int track, const int disc, const std::string songPath) : - id(id), title(title), artist(artist), album(album), - albumArtist(albumArtist), genre(genre), year(year), - duration(duration), track(track), disc(disc), - songPath(songPath) { } + class Song { + public: + Song() = default; + Song(const int id) : id(id) { } + Song(const int id, const std::string& title, const std::string& artist, + const std::string& album, const std::string& albumArtist, + const std::string& genre, const int year, const int duration, + const int track, const int disc, const std::string songPath) : + id(id), title(title), artist(artist), album(album), + albumArtist(albumArtist), genre(genre), year(year), + duration(duration), track(track), disc(disc), + songPath(songPath) { } - int id; - std::string title; - std::string artist; - std::string album; - std::string albumArtist; - std::string genre; - int year; - int duration; - int track; - int disc; - std::string songPath; - std::vector data; - int coverArtId; - int artistId; - int albumId; - int genreId; - int yearId; -}; + int id; + std::string title; + std::string artist; + std::string album; + std::string albumArtist; + std::string genre; + int year; + int duration; + int track; + int disc; + std::string songPath; + std::vector data; + int coverArtId; + int artistId; + int albumId; + int genreId; + int yearId; + }; -class Artist { -public: - Artist() = default; - Artist(const Song& song) : id(song.artistId), artist(song.artist) { } - Artist(const int id) : id(id) { } + class Artist { + public: + Artist() = default; + Artist(const Song& song) : id(song.artistId), artist(song.artist) { } + Artist(const int id) : id(id) { } - int id; - std::string artist; -}; + int id; + std::string artist; + }; -class Album { -public: - Album() = default; - Album(const Song& song) : - id(song.albumId), title(song.album),artist(song.artist), year(song.year) { } - Album(const int id) : id(id) { } + class Album { + public: + Album() = default; + Album(const Song& song) : + id(song.albumId), title(song.album),artist(song.artist), year(song.year) { } + Album(const int id) : id(id) { } - int id; - std::string title; - std::string artist; - int year; - std::vector songs; -}; + int id; + std::string title; + std::string artist; + int year; + std::vector songs; + }; -class Genre { -public: - Genre() = default; - Genre(const Song& song) : - id(song.genreId), category(song.genre) { } - Genre(const int id) : id(id) { } + class Genre { + public: + Genre() = default; + Genre(const Song& song) : + id(song.genreId), category(song.genre) { } + Genre(const int id) : id(id) { } - int id; - std::string category; + int id; + std::string category; -}; + }; -class Year { -public: - Year() = default; - Year(const Song& song) : - id(song.yearId), year(song.year) { } - Year(const int id) : id(id) { } + class Year { + public: + Year() = default; + Year(const Song& song) : + id(song.yearId), year(song.year) { } + Year(const int id) : id(id) { } - int id; - int year; -}; + int id; + int year; + }; -class Cover { -public: - Cover() = default; - Cover(const Song& song) : - id(song.coverArtId), songTitle(song.title) { } - Cover(const int id) : id(id) { } + class Cover { + public: + Cover() = default; + Cover(const Song& song) : + id(song.coverArtId), songTitle(song.title) { } + Cover(const int id) : id(id) { } - int id; - std::string songTitle; - std::string imagePath; - // Not being used but it should be - std::vector data; -}; + int id; + std::string songTitle; + std::string imagePath; + // Not being used but it should be + std::vector data; + }; -class Token { -public: - Token() = default; - Token(const std::string& accessToken) : - accessToken(accessToken) { } - Token(const std::string& accessToken, const std::string& tokenType, - const int expiration) : - accessToken(accessToken), tokenType(tokenType), - expiration(expiration) { } + class Token { + public: + Token() = default; + Token(const std::string& accessToken) : + accessToken(accessToken) { } + Token(const std::string& accessToken, const std::string& tokenType, + const int expiration) : + accessToken(accessToken), tokenType(tokenType), + expiration(expiration) { } - std::string accessToken; - int expiration; - std::string tokenType; -}; + std::string accessToken; + int expiration; + std::string tokenType; + }; -struct LoginResult { - int userId; - std::string username; - std::string accessToken; - std::string tokenType; - std::string message; - int expiration; -}; + struct LoginResult { + int userId; + std::string username; + std::string accessToken; + std::string tokenType; + std::string message; + int expiration; + }; -class RegisterResult { -public: - std::string username; - bool registered; - std::string message; -}; + class RegisterResult { + public: + std::string username; + bool registered; + std::string message; + }; -struct User { - int id; - std::string firstname; - std::string lastname; - std::string email; - std::string phone; - std::string username; - std::string password; -}; + struct User { + int id; + std::string firstname; + std::string lastname; + std::string email; + std::string phone; + std::string username; + std::string password; + }; -struct PassSec { - int id; - std::string hashPassword; - std::string salt; - int userId; -}; + struct PassSec { + int id; + std::string hashPassword; + std::string salt; + int userId; + }; -struct AuthCredentials { - std::string domain; - std::string apiIdentifier; - std::string clientId; - std::string clientSecret; - std::string uri; - std::string endpoint; -}; + struct AuthCredentials { + std::string domain; + std::string apiIdentifier; + std::string clientId; + std::string clientSecret; + std::string uri; + std::string endpoint; + }; -struct DatabaseConnection { - std::string server; - std::string username; - std::string password; - std::string database; -}; + struct DatabaseConnection { + std::string server; + std::string username; + std::string password; + std::string database; + }; -class BinaryPath { -public: - BinaryPath() = default; - BinaryPath(const char *p) : path(p) { } - BinaryPath(const std::string& p) : path(p) { } - BinaryPath(const std::string&& p) : path(p) { } + class BinaryPath { + public: + BinaryPath() = default; + BinaryPath(const char *p) : path(p) { } + BinaryPath(const std::string& p) : path(p) { } + BinaryPath(const std::string&& p) : path(p) { } - std::string path; -}; + std::string path; + }; } #endif diff --git a/include/type/AlbumFilter.h b/include/type/AlbumFilter.h index bc382a4..727ec25 100644 --- a/include/type/AlbumFilter.h +++ b/include/type/AlbumFilter.h @@ -1,10 +1,8 @@ #ifndef ALBUMFILTER_H_ #define ALBUMFILTER_H_ -namespace type -{ - enum class AlbumFilter - { +namespace type { + enum class AlbumFilter { id = 0, title, year diff --git a/include/type/ArtistFilter.h b/include/type/ArtistFilter.h index 9ddc9e5..9ed74a8 100644 --- a/include/type/ArtistFilter.h +++ b/include/type/ArtistFilter.h @@ -1,10 +1,8 @@ #ifndef ARTISTFILTER_H_ #define ARTISTFILTER_H_ -namespace type -{ - enum class ArtistFilter - { +namespace type { + enum class ArtistFilter { id = 0, artist }; diff --git a/include/type/CoverFilter.h b/include/type/CoverFilter.h index b0b8f7e..8ff593b 100644 --- a/include/type/CoverFilter.h +++ b/include/type/CoverFilter.h @@ -1,10 +1,8 @@ #ifndef COVERFILTER_H_ #define COVERFILTER_H_ -namespace type -{ - enum class CoverFilter - { +namespace type { + enum class CoverFilter { id = 0, songTitle, imagePath diff --git a/include/type/GenreFilter.h b/include/type/GenreFilter.h index 297ab7b..1bd7ebc 100644 --- a/include/type/GenreFilter.h +++ b/include/type/GenreFilter.h @@ -1,10 +1,8 @@ #ifndef GENREFILTER_H_ #define GENREFILTER_H_ -namespace type -{ - enum class GenreFilter - { +namespace type { + enum class GenreFilter { id = 0, category }; diff --git a/include/type/PathType.h b/include/type/PathType.h index 798f2f2..35e23ed 100644 --- a/include/type/PathType.h +++ b/include/type/PathType.h @@ -1,10 +1,8 @@ #ifndef PATHTYPE_H_ #define PATHTYPE_H_ -namespace type -{ - enum PathType - { +namespace type { + enum PathType { music = 0, archive, temp, diff --git a/include/type/SaltFilter.h b/include/type/SaltFilter.h index b2e6ab5..0c413b5 100644 --- a/include/type/SaltFilter.h +++ b/include/type/SaltFilter.h @@ -2,8 +2,7 @@ #define SALTFILTER_H_ namespace type { - enum class SaltFilter - { + enum class SaltFilter { id = 0, salt, userId diff --git a/include/type/Scopes.h b/include/type/Scopes.h index b5d1b25..cabd102 100644 --- a/include/type/Scopes.h +++ b/include/type/Scopes.h @@ -1,10 +1,8 @@ #ifndef SCOPES_H_ #define SCOPES_H_ -namespace type -{ - enum class Scope - { +namespace type { + enum class Scope { upload = 0, download, stream, diff --git a/include/type/SongChanged.h b/include/type/SongChanged.h index e5b063c..f701cf3 100644 --- a/include/type/SongChanged.h +++ b/include/type/SongChanged.h @@ -1,10 +1,8 @@ #ifndef SONGCHANGED_H_ #define SONGCHANGED_H_ -namespace type -{ - enum SongChanged - { +namespace type { + enum SongChanged { title = 0, artist, album, diff --git a/include/type/SongFilter.h b/include/type/SongFilter.h index 18fe58f..5508c58 100644 --- a/include/type/SongFilter.h +++ b/include/type/SongFilter.h @@ -1,10 +1,8 @@ #ifndef SONGFILTER_H_ #define SONGFILTER_H_ -namespace type -{ - enum class SongFilter - { +namespace type { + enum class SongFilter { id = 0, title, album, diff --git a/include/type/SongUpload.h b/include/type/SongUpload.h index 9307a0a..449f287 100644 --- a/include/type/SongUpload.h +++ b/include/type/SongUpload.h @@ -1,10 +1,8 @@ #ifndef SONGUPLOAD_H_ #define SONGUPLOAD_H_ -namespace type -{ - enum class SongUpload - { +namespace type { + enum class SongUpload { Successful = 0, AlreadyExist = 1, Failed = 2 diff --git a/include/type/UserFilter.h b/include/type/UserFilter.h index 0d5c2ac..ec52928 100644 --- a/include/type/UserFilter.h +++ b/include/type/UserFilter.h @@ -2,8 +2,7 @@ #define USERFILTER_H_ namespace type { - enum class UserFilter - { + enum class UserFilter { id = 0, username }; diff --git a/include/type/YearFilter.h b/include/type/YearFilter.h index 343ea31..47da439 100644 --- a/include/type/YearFilter.h +++ b/include/type/YearFilter.h @@ -1,10 +1,8 @@ #ifndef YEARFILTER_H_ #define YEARFILTER_H_ -namespace type -{ - enum class YearFilter - { +namespace type { + enum class YearFilter { id = 0, year }; diff --git a/include/utility/ImageFile.h b/include/utility/ImageFile.h index df9ac18..8d890a9 100644 --- a/include/utility/ImageFile.h +++ b/include/utility/ImageFile.h @@ -13,10 +13,8 @@ #include #include -namespace utility -{ - class ImageFile : public TagLib::File - { +namespace utility { + class ImageFile : public TagLib::File { public: ImageFile(const char *file); diff --git a/include/utility/MetadataRetriever.h b/include/utility/MetadataRetriever.h index 42093ea..83d53ed 100644 --- a/include/utility/MetadataRetriever.h +++ b/include/utility/MetadataRetriever.h @@ -7,20 +7,19 @@ #include "model/Models.h" namespace utility { -class MetadataRetriever -{ -public: - model::Song retrieveMetadata(model::Song&); + class MetadataRetriever { + public: + model::Song retrieveMetadata(model::Song&); - model::Cover updateCoverArt(const model::Song&, model::Cover&, const std::string&); - model::Cover applyStockCoverArt(const model::Song&, model::Cover&, const std::string&); - model::Cover applyCoverArt(const model::Song&, model::Cover&); + model::Cover updateCoverArt(const model::Song&, model::Cover&, const std::string&); + model::Cover applyStockCoverArt(const model::Song&, model::Cover&, const std::string&); + model::Cover applyCoverArt(const model::Song&, model::Cover&); - bool songContainsCoverArt(const model::Song&); + bool songContainsCoverArt(const model::Song&); - void updateMetadata(model::Song&, const model::Song&); -private: -}; + void updateMetadata(model::Song&, const model::Song&); + private: + }; } #endif diff --git a/include/utility/PasswordEncryption.h b/include/utility/PasswordEncryption.h index 186ad37..69e4f44 100644 --- a/include/utility/PasswordEncryption.h +++ b/include/utility/PasswordEncryption.h @@ -12,7 +12,7 @@ public: bool isPasswordValid(const model::User&, const model::PassSec&); private: - int saltSize(); + constexpr int saltSize() noexcept; }; } diff --git a/include/verify/Initialization.h b/include/verify/Initialization.h index c5e0145..25d6a5b 100644 --- a/include/verify/Initialization.h +++ b/include/verify/Initialization.h @@ -5,10 +5,8 @@ #include "model/Models.h" -namespace verify -{ - class Initialization - { +namespace verify { + class Initialization { public: static bool skipVerification(const std::string&); diff --git a/src/Main.cpp b/src/Main.cpp index 345a2bd..f502e80 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -23,8 +23,7 @@ namespace fs = std::filesystem; -void run(const model::BinaryPath& bConf) -{ +void run(const model::BinaryPath& bConf) { component::AppComponent component; OATPP_COMPONENT(std::shared_ptr, router); @@ -58,8 +57,7 @@ void run(const model::BinaryPath& bConf) server.run(); } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { oatpp::base::Environment::init(); model::BinaryPath bConf(std::move(argv[0])); @@ -68,7 +66,7 @@ int main(int argc, char **argv) if (!verify::Initialization::skipVerification(argv[1])) { verify::Initialization::checkIcarus(bConf); } else { - std::cout << "skiping verifyication" << std::endl; + std::cout << "skiping verifyication\n"; } } else { verify::Initialization::checkIcarus(bConf); diff --git a/src/callback/StreamCallback.cpp b/src/callback/StreamCallback.cpp index c1435f8..0e0cca6 100644 --- a/src/callback/StreamCallback.cpp +++ b/src/callback/StreamCallback.cpp @@ -5,40 +5,37 @@ #include namespace callback { -StreamCallback::StreamCallback() : - m_counter(0) { } + StreamCallback::StreamCallback() : m_counter(0) { } -StreamCallback::StreamCallback(const std::string& songPath) : - m_songPath(songPath), - m_counter(0), - m_bytesRead(0) -{ - // getting file size - std::ifstream song(m_songPath.c_str(), std::ios::binary | std::ios::in | std::ios::ate); - m_fileSize = song.tellg(); - std::cout << "file size is " << m_fileSize << " bytes" << std::endl; -} - - -oatpp::data::v_io_size StreamCallback::read(void *buff, oatpp::data::v_io_size count) -{ - if (m_counter >= m_fileSize) { - std::cout << "done streaming song" << std::endl; - return 0; + StreamCallback::StreamCallback(const std::string& songPath) : + m_songPath(songPath), + m_counter(0), + m_bytesRead(0) { + // getting file size + std::ifstream song(m_songPath.c_str(), std::ios::binary | std::ios::in | std::ios::ate); + m_fileSize = song.tellg(); + std::cout << "file size is " << m_fileSize << " bytes\n"; } - std::fstream song(m_songPath.c_str(), std::ios::binary | std::ios::in); - song.seekg(m_counter); - std::unique_ptr data(new char[count]); + oatpp::data::v_io_size StreamCallback::read(void *buff, oatpp::data::v_io_size count) { + if (m_counter >= m_fileSize) { + std::cout << "done streaming song\n"; + return 0; + } - song.read(data.get(), count); - std::memcpy(buff, data.get(), count); + std::fstream song(m_songPath.c_str(), std::ios::binary | std::ios::in); + song.seekg(m_counter); - m_counter += count; + std::unique_ptr data(new char[count]); - song.close(); + song.read(data.get(), count); + std::memcpy(buff, data.get(), count); - return count; -} + m_counter += count; + + song.close(); + + return count; + } } diff --git a/src/database/AlbumRepository.cpp b/src/database/AlbumRepository.cpp index a5ea1cb..2d025bc 100644 --- a/src/database/AlbumRepository.cpp +++ b/src/database/AlbumRepository.cpp @@ -8,396 +8,384 @@ #include namespace database { -AlbumRepository::AlbumRepository(const model::BinaryPath& bConf) - : BaseRepository(bConf) -{ } + AlbumRepository::AlbumRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { } -std::vector AlbumRepository::retrieveRecords() -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + std::vector AlbumRepository::retrieveRecords() { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - const std::string query = "SELECT * FROM Album"; - mysql_stmt_prepare(stmt, query.c_str(), query.size()); - mysql_stmt_execute(stmt); + const std::string query = "SELECT * FROM Album"; + mysql_stmt_prepare(stmt, query.c_str(), query.size()); + mysql_stmt_execute(stmt); - auto albums = parseRecords(stmt); + auto albums = parseRecords(stmt); - mysql_stmt_close(stmt); - mysql_close(conn); + mysql_stmt_close(stmt); + mysql_close(conn); - return albums; -} - - -std::pair AlbumRepository::retrieveRecordWithSongCount(model::Album& album, type::AlbumFilter filter = type::AlbumFilter::id) -{ - std::cout << "retrieving album with song count" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - qry << "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb LEFT JOIN "; - qry << "Song sng ON alb.AlbumId=sng.AlbumId WHERE "; - - switch (filter) { - case type::AlbumFilter::id: - qry << "sng.AlbumId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&album.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; - } - qry << " GROUP BY alb.AlbumId LIMIT 1"; - - const auto query = qry.str(); - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - auto albWSC = parseRecordWithSongCount(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - return albWSC; -} - -model::Album AlbumRepository::retrieveRecord(model::Album& album, type::AlbumFilter filter) -{ - std::cout << "retrieving album record" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - qry << "SELECT alb.* FROM Album alb WHERE "; - - auto titleLength = album.title.size(); - switch (filter) { - case type::AlbumFilter::id: - qry << "alb.AlbumId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&album.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::AlbumFilter::title: - qry << "alb.Title = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)album.title.c_str(); - params[0].length = &titleLength; - params[0].is_null = 0; - break; - default: - break; + return albums; } - qry << " LIMIT 1"; - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + std::pair AlbumRepository::retrieveRecordWithSongCount(model::Album& album, + type::AlbumFilter filter = type::AlbumFilter::id) { + std::cout << "retrieving album with song count\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - album = parseRecord(stmt); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - mysql_stmt_close(stmt); - mysql_close(conn); + qry << "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb LEFT JOIN "; + qry << "Song sng ON alb.AlbumId=sng.AlbumId WHERE "; - std::cout << "done" << std::endl; + switch (filter) { + case type::AlbumFilter::id: + qry << "sng.AlbumId = ?"; - return album; -} - -bool AlbumRepository::doesAlbumExists(const model::Album& album, type::AlbumFilter filter) -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - std::stringstream qry; - qry << "SELECT * FROM Album WHERE "; - - auto titleLength = album.title.size(); - switch (filter) { - case type::AlbumFilter::id: - qry << "AlbumId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&album.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::AlbumFilter::title: - qry << "Title = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)album.title.c_str(); - params[0].length = &titleLength; - params[0].is_null = 0; - break; - default: - break; - } - - qry << " LIMIT 1"; - - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - std::cout << "the query has been performed" << std::endl; - - ::mysql_stmt_store_result(stmt); - auto rowCount = ::mysql_stmt_num_rows(stmt); - - ::mysql_stmt_close(stmt); - ::mysql_close(conn); - - return (rowCount > 0) ? true : false; -} - -void AlbumRepository::saveAlbum(const model::Album& album) -{ - std::cout << "beginning to insert album record" << std::endl; - - auto conn = setupMysqlConnection(); - MYSQL_STMT *stmt = mysql_stmt_init(conn); - - const std::string query = "INSERT INTO Album(Title, Artist, Year) VALUES(?, ?, ?)"; - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - - MYSQL_BIND params[3]; - memset(params, 0, sizeof(params)); - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)album.title.c_str(); - auto titleLength = album.title.size(); - params[0].length= &titleLength; - params[0].is_null = 0; - - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)album.artist.c_str(); - auto artistLength = album.artist.size(); - params[1].length = &artistLength; - params[1].is_null = 0; - - params[2].buffer_type = MYSQL_TYPE_LONG; - params[2].buffer = (char*)&album.year; - params[2].length = 0; - params[2].is_null = 0; - - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "done inserting album record" << std::endl; -} - -void AlbumRepository::deleteAlbum(const model::Album& album, type::AlbumFilter filter = type::AlbumFilter::id) -{ - std::cout << "deleting album record" << std::endl; - - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - qry << "DELETE FROM Album WHERE "; - - switch (filter) { - case type::AlbumFilter::id: - qry << "AlbumId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&album.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; - } - - const auto query = qry.str(); - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - std::cout << "execute delete query" << std::endl; -} - - -std::vector AlbumRepository::parseRecords(MYSQL_STMT* stmt) -{ - std::cout << "parsing album record" << std::endl; - mysql_stmt_store_result(stmt); - - std::vector albums; - albums.reserve(mysql_stmt_num_rows(stmt)); - - const auto valAmt = 3; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; - - for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) { - if (mysql_stmt_field_count(stmt) > 0) { - model::Album alb; - auto metaBuff = metadataBuffer(); - auto bindedValues = valueBind(alb, metaBuff); - status = mysql_stmt_bind_result(stmt, bindedValues.get()); - - while (true) { - std::cout << "fetching statement result" << std::endl; - status = mysql_stmt_fetch(stmt); - - if (status == 1 || status == MYSQL_NO_DATA) { - break; - } - - alb.title = std::get<0>(metaBuff); - alb.artist = std::get<1>(metaBuff); - albums.push_back(std::move(alb)); - } + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&album.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; } - std::cout << "fetching next result" << std::endl; + qry << " GROUP BY alb.AlbumId LIMIT 1"; + + const auto query = qry.str(); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + auto albWSC = parseRecordWithSongCount(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + return albWSC; } - return albums; -} + model::Album AlbumRepository::retrieveRecord(model::Album& album, type::AlbumFilter filter) { + std::cout << "retrieving album record\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); -std::pair AlbumRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) -{ - std::cout << "parsing album record with song count" << std::endl; - mysql_stmt_store_result(stmt); - auto rowCount = mysql_stmt_num_rows(stmt); + qry << "SELECT alb.* FROM Album alb WHERE "; - model::Album album; - auto metaBuff = metadataBuffer(); - int songCount = 0; - auto val = valueBindWithSongCount(album, metaBuff, songCount); + auto titleLength = album.title.size(); + switch (filter) { + case type::AlbumFilter::id: + qry << "alb.AlbumId = ?"; - if (rowCount == 0) { - std::cout << "no results" << std::endl; - return std::make_pair(album, songCount); + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&album.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::AlbumFilter::title: + qry << "alb.Title = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)album.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + album = parseRecord(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done\n"; + + return album; } - auto status = mysql_stmt_bind_result(stmt, val.get()); - status = mysql_stmt_fetch(stmt); + bool AlbumRepository::doesAlbumExists(const model::Album& album, type::AlbumFilter filter) { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - album.title = std::get<0>(metaBuff); - album.artist = std::get<1>(metaBuff); + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); - std::cout << "done parsing album record with song count" << std::endl; + std::stringstream qry; + qry << "SELECT * FROM Album WHERE "; - auto albWSC = std::make_pair(album, songCount); + auto titleLength = album.title.size(); + switch (filter) { + case type::AlbumFilter::id: + qry << "AlbumId = ?"; - return albWSC; -} + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&album.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::AlbumFilter::title: + qry << "Title = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)album.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed\n"; + + mysql_stmt_store_result(stmt); + auto rowCount = mysql_stmt_num_rows(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + return (rowCount > 0) ? true : false; + } + + void AlbumRepository::saveAlbum(const model::Album& album) { + std::cout << "beginning to insert album record\n"; + + auto conn = setupMysqlConnection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + const std::string query = "INSERT INTO Album(Title, Artist, Year) VALUES(?, ?, ?)"; + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[3]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)album.title.c_str(); + auto titleLength = album.title.size(); + params[0].length= &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)album.artist.c_str(); + auto artistLength = album.artist.size(); + params[1].length = &artistLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_LONG; + params[2].buffer = (char*)&album.year; + params[2].length = 0; + params[2].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done inserting album record\n"; + } + + void AlbumRepository::deleteAlbum(const model::Album& album, + type::AlbumFilter filter = type::AlbumFilter::id) { + std::cout << "deleting album record\n"; + + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); + + qry << "DELETE FROM Album WHERE "; + + switch (filter) { + case type::AlbumFilter::id: + qry << "AlbumId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&album.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } + + const auto query = qry.str(); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "execute delete query\n"; + } -std::shared_ptr AlbumRepository::valueBind(model::Album& album, - std::tuple& metadata) -{ - constexpr auto wordLen = 1024; - constexpr auto valueCount = 4; - std::shared_ptr values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND))); + std::vector AlbumRepository::parseRecords(MYSQL_STMT* stmt) { + std::cout << "parsing album record\n"; + mysql_stmt_store_result(stmt); - values.get()[0].buffer_type = MYSQL_TYPE_LONG; - values.get()[0].buffer = (char*)&album.id; + std::vector albums; + albums.reserve(mysql_stmt_num_rows(stmt)); - values.get()[1].buffer_type = MYSQL_TYPE_STRING; - values.get()[1].buffer = (char*)std::get<0>(metadata); - values.get()[1].buffer_length = wordLen; + const auto valAmt = 3; + unsigned long len[valAmt]; + my_bool nullRes[valAmt]; - values.get()[2].buffer_type = MYSQL_TYPE_STRING; - values.get()[2].buffer = (char*)std::get<1>(metadata); - values.get()[2].buffer_length = wordLen; + for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) { + if (mysql_stmt_field_count(stmt) > 0) { + model::Album alb; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(alb, metaBuff); + status = mysql_stmt_bind_result(stmt, bindedValues.get()); - values.get()[3].buffer_type = MYSQL_TYPE_LONG; - values.get()[3].buffer = (char*)&album.year; + while (true) { + std::cout << "fetching statement result\n"; + status = mysql_stmt_fetch(stmt); - return values; -} + if (status == 1 || status == MYSQL_NO_DATA) break; -std::shared_ptr AlbumRepository::valueBindWithSongCount(model::Album& album, - std::tuple& metadata, int& songCount) -{ - constexpr auto wordLen = 1024; - constexpr auto valueCount = 5; - std::shared_ptr values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND))); + alb.title = std::get<0>(metaBuff); + alb.artist = std::get<1>(metaBuff); + albums.push_back(std::move(alb)); + } + } + std::cout << "fetching next result\n"; + } - values.get()[0].buffer_type = MYSQL_TYPE_LONG; - values.get()[0].buffer = (char*)&album.id; - - values.get()[1].buffer_type = MYSQL_TYPE_STRING; - values.get()[1].buffer = (char*)std::get<0>(metadata); - values.get()[1].buffer_length = wordLen; - - values.get()[2].buffer_type = MYSQL_TYPE_STRING; - values.get()[2].buffer = (char*)std::get<1>(metadata); - values.get()[2].buffer_length = wordLen; - - values.get()[3].buffer_type = MYSQL_TYPE_LONG; - values.get()[3].buffer = (char*)&album.year; - - values.get()[4].buffer_type = MYSQL_TYPE_LONG; - values.get()[4].buffer = (char*)&songCount; - - return values; -} + return albums; + } -std::tuple AlbumRepository::metadataBuffer() -{ - constexpr auto wordLen = 1024; - char title[wordLen]; - char artist[wordLen]; + std::pair AlbumRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) { + std::cout << "parsing album record with song count\n"; + mysql_stmt_store_result(stmt); + auto rowCount = mysql_stmt_num_rows(stmt); - return std::make_tuple(title, artist); -} + model::Album album; + auto metaBuff = metadataBuffer(); + int songCount = 0; + auto val = valueBindWithSongCount(album, metaBuff, songCount); + + if (rowCount == 0) { + std::cout << "no results\n"; + return std::make_pair(album, songCount); + } + + auto status = mysql_stmt_bind_result(stmt, val.get()); + status = mysql_stmt_fetch(stmt); + + album.title = std::get<0>(metaBuff); + album.artist = std::get<1>(metaBuff); + + std::cout << "done parsing album record with song count\n"; + + auto albWSC = std::make_pair(album, songCount); + + return albWSC; + } -model::Album AlbumRepository::parseRecord(MYSQL_STMT *stmt) -{ - std::cout << "parsing album record" << std::endl; - mysql_stmt_store_result(stmt); - auto rows = mysql_stmt_num_rows(stmt); + std::shared_ptr AlbumRepository::valueBind(model::Album& album, + std::tuple& metadata) { + constexpr auto wordLen = 1024; + constexpr auto valueCount = 4; + std::shared_ptr values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND))); - model::Album album; - auto metaBuff = metadataBuffer(); - auto bindedValues = valueBind(album, metaBuff); - auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); - status = mysql_stmt_fetch(stmt); + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = (char*)&album.id; + + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = (char*)std::get<0>(metadata); + values.get()[1].buffer_length = wordLen; + + values.get()[2].buffer_type = MYSQL_TYPE_STRING; + values.get()[2].buffer = (char*)std::get<1>(metadata); + values.get()[2].buffer_length = wordLen; + + values.get()[3].buffer_type = MYSQL_TYPE_LONG; + values.get()[3].buffer = (char*)&album.year; + + return values; + } + + std::shared_ptr AlbumRepository::valueBindWithSongCount(model::Album& album, + std::tuple& metadata, int& songCount) { + constexpr auto wordLen = 1024; + constexpr auto valueCount = 5; + std::shared_ptr values( + (MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND))); + + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = (char*)&album.id; + + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = (char*)std::get<0>(metadata); + values.get()[1].buffer_length = wordLen; + + values.get()[2].buffer_type = MYSQL_TYPE_STRING; + values.get()[2].buffer = (char*)std::get<1>(metadata); + values.get()[2].buffer_length = wordLen; + + values.get()[3].buffer_type = MYSQL_TYPE_LONG; + values.get()[3].buffer = (char*)&album.year; + + values.get()[4].buffer_type = MYSQL_TYPE_LONG; + values.get()[4].buffer = (char*)&songCount; + + return values; + } + + + std::tuple AlbumRepository::metadataBuffer() { + constexpr auto wordLen = 1024; + char title[wordLen]; + char artist[wordLen]; + + return std::make_tuple(title, artist); + } + + + model::Album AlbumRepository::parseRecord(MYSQL_STMT *stmt) + { + std::cout << "parsing album record\n"; + mysql_stmt_store_result(stmt); + auto rows = mysql_stmt_num_rows(stmt); + + model::Album album; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(album, metaBuff); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); + status = mysql_stmt_fetch(stmt); - album.title = std::get<0>(metaBuff); - album.artist = std::get<1>(metaBuff); + album.title = std::get<0>(metaBuff); + album.artist = std::get<1>(metaBuff); - std::cout << "done parsing album record" << std::endl; + std::cout << "done parsing album record\n"; - return album; -} + return album; + } } diff --git a/src/database/ArtistRepository.cpp b/src/database/ArtistRepository.cpp index 5585a0d..62b99f3 100644 --- a/src/database/ArtistRepository.cpp +++ b/src/database/ArtistRepository.cpp @@ -7,410 +7,355 @@ #include namespace database { -ArtistRepository::ArtistRepository(const model::BinaryPath& binConf) - : BaseRepository(binConf) -{ -} + ArtistRepository::ArtistRepository(const model::BinaryPath& binConf) : + BaseRepository(binConf) { } -std::vector ArtistRepository::retrieveRecords() -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - const std::string query = "SELECT * FROM Artist"; + std::vector ArtistRepository::retrieveRecords() { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + const std::string query = "SELECT * FROM Artist"; - mysql_stmt_prepare(stmt, query.c_str(), query.size()); - mysql_stmt_execute(stmt); + mysql_stmt_prepare(stmt, query.c_str(), query.size()); + mysql_stmt_execute(stmt); - auto artists = parseRecords(stmt); + auto artists = parseRecords(stmt); - mysql_stmt_close(stmt); - mysql_close(conn); + mysql_stmt_close(stmt); + mysql_close(conn); - return artists; -} - -std::pair ArtistRepository::retrieveRecordWithSongCount(model::Artist& artist, type::ArtistFilter filter = type::ArtistFilter::id) -{ - std::cout << "retrieving artist record with song count" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - qry << "SELECT art.*, COUNT(*) AS SongCount FROM Artist art LEFT JOIN "; - qry << "Song sng ON art.ArtistId=sng.ArtistId WHERE "; - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - switch (filter) { - case type::ArtistFilter::id: - qry << "sng.ArtistId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&artist.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; - } - - qry << " GROUP BY art.ArtistId LIMIT 1"; - - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - std::cout << "Artist record with song count query "; - std::cout << "has been performed" << std::endl; - - auto artWSC = parseRecordWithSongCount(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - return artWSC; -} - -model::Artist ArtistRepository::retrieveRecord(model::Artist& artist, type::ArtistFilter filter) -{ - std::cout << "retrieving artist record" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - qry << "SELECT art.* FROM Artist art WHERE "; - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - auto artistLength = artist.artist.size(); - switch (filter) { - case type::ArtistFilter::id: - qry << "art.ArtistId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&artist.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::ArtistFilter::artist: - qry << "art.Artist = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)artist.artist.c_str(); - params[0].length = &artistLength; - params[0].is_null = 0; - break; - default: - break; - } - - qry << " LIMIT 1"; - - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - artist = parseRecord(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "retrieved record" << std::endl; - - return artist; -} - -bool ArtistRepository::doesArtistExist(const model::Artist& artist, type::ArtistFilter filter) -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - std::stringstream qry; - qry << "SELECT * FROM Artist WHERE "; - - auto artistLength = artist.artist.size(); - switch (filter) { - case type::ArtistFilter::id: - qry << "ArtistId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&artist.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::ArtistFilter::artist: - qry << "Artist = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)artist.artist.c_str(); - params[0].length = &artistLength; - params[0].is_null = 0; - break; - default: - break; - } - - qry << " LIMIT 1"; - - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - std::cout << "the query has been performed" << std::endl; - - mysql_stmt_store_result(stmt); - auto rowCount = mysql_stmt_num_rows(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - return (rowCount > 0) ? true : false; -} - -void ArtistRepository::saveRecord(const model::Artist& artist) -{ - std::cout << "inserting artist record" << std::endl; - - auto conn = setupMysqlConnection(); - MYSQL_STMT *stmt = mysql_stmt_init(conn); - - const std::string query = "INSERT INTO Artist(Artist) VALUES(?)"; - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)artist.artist.c_str(); - auto artistLength = artist.artist.size(); - params[0].length = &artistLength; - params[0].is_null = 0; - - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout<< "inserted artist record" << std::endl; -} - -void ArtistRepository::deleteArtist(const model::Artist& artist, type::ArtistFilter filter = type::ArtistFilter::id) { - std::cout << "delete Artist record" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - qry << "DELETE FROM Artist WHERE "; - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - switch (filter) { - case type::ArtistFilter::id: - qry << "ArtistId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&artist.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; - } - - const auto query = qry.str(); - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "deleted artist record" << std::endl; -} - -std::vector ArtistRepository::parseRecords(MYSQL_STMT *stmt) -{ - mysql_stmt_store_result(stmt); - - std::vector artists; - artists.reserve(mysql_stmt_num_rows(stmt)); - - if (mysql_stmt_field_count(stmt) == 0) { - std::cout << "field count is 0" << std::endl; return artists; } - model::Artist art; - const auto valAmt = 2; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; + std::pair ArtistRepository::retrieveRecordWithSongCount( + model::Artist& artist, type::ArtistFilter filter = type::ArtistFilter::id) { + std::cout << "retrieving artist record with song count\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - auto res = mysql_stmt_result_metadata(stmt); - auto fields = mysql_fetch_fields(res); - const auto strLen = 1024; + qry << "SELECT art.*, COUNT(*) AS SongCount FROM Artist art LEFT JOIN "; + qry << "Song sng ON art.ArtistId=sng.ArtistId WHERE "; - char artist[strLen]; + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); + + switch (filter) { + case type::ArtistFilter::id: + qry << "sng.ArtistId = ?"; - MYSQL_BIND val[valAmt]; - memset(val, 0, sizeof(val)); + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&artist.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&art.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; + qry << " GROUP BY art.ArtistId LIMIT 1"; - val[1].buffer_type = MYSQL_TYPE_STRING; - val[1].buffer = (char*)artist; - val[1].buffer_length = strLen; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - for (auto status = mysql_stmt_bind_result(stmt, val); status == 0; ) { - std::cout << "fetching statement result" << std::endl; + std::cout << "Artist record with song count query "; + std::cout << "has been performed\n"; + + auto artWSC = parseRecordWithSongCount(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + return artWSC; + } + + model::Artist ArtistRepository::retrieveRecord(model::Artist& artist, + type::ArtistFilter filter) { + std::cout << "retrieving artist record\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + qry << "SELECT art.* FROM Artist art WHERE "; + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + auto artistLength = artist.artist.size(); + switch (filter) { + case type::ArtistFilter::id: + qry << "art.ArtistId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&artist.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::ArtistFilter::artist: + qry << "art.Artist = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)artist.artist.c_str(); + params[0].length = &artistLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + artist = parseRecord(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "retrieved record\n"; + + return artist; + } + + bool ArtistRepository::doesArtistExist(const model::Artist& artist, type::ArtistFilter filter) { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + std::stringstream qry; + qry << "SELECT * FROM Artist WHERE "; + + auto artistLength = artist.artist.size(); + switch (filter) { + case type::ArtistFilter::id: + qry << "ArtistId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&artist.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::ArtistFilter::artist: + qry << "Artist = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)artist.artist.c_str(); + params[0].length = &artistLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed\n"; + + mysql_stmt_store_result(stmt); + auto rowCount = mysql_stmt_num_rows(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + return (rowCount > 0) ? true : false; + } + + void ArtistRepository::saveRecord(const model::Artist& artist) { + std::cout << "inserting artist record\n"; + + auto conn = setupMysqlConnection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + const std::string query = "INSERT INTO Artist(Artist) VALUES(?)"; + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)artist.artist.c_str(); + auto artistLength = artist.artist.size(); + params[0].length = &artistLength; + params[0].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout<< "inserted artist record\n"; + } + + void ArtistRepository::deleteArtist(const model::Artist& artist, + type::ArtistFilter filter = type::ArtistFilter::id) { + std::cout << "delete Artist record\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + + qry << "DELETE FROM Artist WHERE "; + + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); + + switch (filter) { + case type::ArtistFilter::id: + qry << "ArtistId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&artist.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } + + const auto query = qry.str(); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "deleted artist record\n"; + } + + std::vector ArtistRepository::parseRecords(MYSQL_STMT *stmt) { + mysql_stmt_store_result(stmt); + + std::vector artists; + artists.reserve(mysql_stmt_num_rows(stmt)); + + constexpr auto valAmt = 2; + unsigned long len[valAmt]; + my_bool nullRes[valAmt]; + + for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) { + if (mysql_stmt_field_count(stmt) > 0) { + model::Artist art; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(art, metaBuff); + status = mysql_stmt_bind_result(stmt, bindedValues.get()); + + std::cout << "fetching statement result\n"; + status = mysql_stmt_fetch(stmt); + + if (status == 1 || status == MYSQL_NO_DATA) break; + + art.artist = std::get<0>(metaBuff); + artists.push_back(art); + } + std::cout << "fetching next result\n"; + } + + return artists; + } + + + std::pair ArtistRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) { + std::cout << "parsing artist record with song count\n"; + mysql_stmt_store_result(stmt); + const auto rowCount = mysql_stmt_num_rows(stmt); + + model::Artist artist; + + auto metaBuff = metadataBuffer(); + auto songCount = 0; + auto val = valueBindWithSongCount(artist, metaBuff, songCount); + + if (rowCount == 0) { + std::cout << "no results\n"; + return std::make_pair(artist, songCount); + } + + auto status = mysql_stmt_bind_result(stmt, val.get()); status = mysql_stmt_fetch(stmt); - if (status == 0) { - art.artist = artist; - artists.push_back(std::move(art)); - } + artist.artist = std::get<0>(metaBuff); + + std::cout << "done parsing album record with song count\n"; + + return std::make_pair(artist, songCount); } - return artists; -} + std::shared_ptr ArtistRepository::valueBind(model::Artist& artist, + std::tuple& metadata) { + constexpr auto valueCount = 2; + constexpr auto wordLen = 1024; + std::shared_ptr values((MYSQL_BIND*) + std::calloc(valueCount, sizeof(MYSQL_BIND))); -model::Artist ArtistRepository::parseRecord(MYSQL_RES* results) -{ - std::cout << "parsing artist record" << std::endl; - model::Artist artist; + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = (char*)&artist.id; - auto fieldNum = mysql_num_fields(results); - auto row = mysql_fetch_row(results); + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = (char*)std::get<0>(metadata); + values.get()[1].buffer_length = wordLen; - for (auto i = 0; i != fieldNum; ++i) { - const std::string field(mysql_fetch_field(results)->name); - - if (field.compare("ArtistId") == 0) { - artist.id = std::stoi(row[i]); - } - if (field.compare("Artist") == 0) { - artist.artist = row[i]; - } + return values; } - std::cout << "parsed artist record" << std::endl; + std::shared_ptr ArtistRepository::valueBindWithSongCount(model::Artist& artist, + std::tuple& metadata, int& songCount) { + constexpr auto valueCount = 3; + constexpr auto wordLen = 1024; + std::shared_ptr values((MYSQL_BIND*) + std::calloc(valueCount, sizeof(MYSQL_BIND))); - return artist; -} + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = reinterpret_cast(&artist.id); -std::pair ArtistRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) -{ - std::cout << "parsing artist record with song count" << std::endl; - mysql_stmt_store_result(stmt); + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = reinterpret_cast(std::get<0>(metadata)); + values.get()[1].buffer_length = wordLen; - const auto strLen = 1024; - const auto valAmt = 3; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; + values.get()[2].buffer_type = MYSQL_TYPE_LONG; + values.get()[2].buffer = reinterpret_cast(&songCount); - model::Artist artist; - int songCount = 0; - if (mysql_stmt_num_rows(stmt) == 0) { - std::cout << "no results" << std::endl; - return std::make_pair(artist, songCount); + return values; } - MYSQL_BIND params[valAmt]; - std::memset(params, 0, sizeof(params)); - char art[strLen]; + std::tuple ArtistRepository::metadataBuffer() { + constexpr auto wordLen = 1024; + char artist[wordLen]; - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&artist.id; - params[0].length = &len[0]; - params[0].is_null = &nullRes[0]; - - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)art; - params[1].buffer_length = strLen; - params[1].length = &len[1]; - params[1].is_null = &nullRes[1]; - - params[2].buffer_type = MYSQL_TYPE_LONG; - params[2].buffer = (char*)&songCount; - params[2].length = &len[2]; - params[2].is_null = &nullRes[2]; - - mysql_stmt_bind_result(stmt, params); - mysql_stmt_fetch(stmt); - - artist.artist = std::move(art); - - std::cout << "parsed artist record with song count" << std::endl; - - return std::make_pair(artist, songCount); -} - -model::Artist ArtistRepository::parseRecord(MYSQL_STMT *stmt) -{ - std::cout << "parsing artist record" << std::endl; - mysql_stmt_store_result(stmt); - - model::Artist art; - auto status = 0; - auto time = 0; - auto valAmt = 2; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; - - while (status == 0) { - if (mysql_stmt_field_count(stmt) > 0) { - auto res = mysql_stmt_result_metadata(stmt); - auto fields = mysql_fetch_fields(res); - auto strLen = 1024; - - MYSQL_BIND val[valAmt]; - memset(val, 0, sizeof(val)); - - char artist[strLen]; - - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&art.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; - - val[1].buffer_type = MYSQL_TYPE_STRING; - val[1].buffer = (char*)&artist; - val[1].buffer_length = strLen; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; - - status = mysql_stmt_bind_result(stmt, val); - mysql_stmt_store_result(stmt); - - status = mysql_stmt_fetch(stmt); - - art.artist = artist; - } - - status = mysql_stmt_next_result(stmt); + return std::make_tuple(artist); } - std::cout << "done parsing artist record" << std::endl; - return art; -} + model::Artist ArtistRepository::parseRecord(MYSQL_STMT *stmt) { + std::cout << "parsing artist record\n"; + mysql_stmt_store_result(stmt); + + model::Artist art; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(art, metaBuff); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); + status = mysql_stmt_fetch(stmt); + + art.artist = std::get<0>(metaBuff); + + std::cout << "done parsing artist record\n"; + + return art; + } } diff --git a/src/database/BaseRepository.cpp b/src/database/BaseRepository.cpp index 37cb3bc..22b92f0 100644 --- a/src/database/BaseRepository.cpp +++ b/src/database/BaseRepository.cpp @@ -7,92 +7,82 @@ #include "manager/DirectoryManager.h" namespace database { -BaseRepository::BaseRepository() -{ } - -BaseRepository::BaseRepository(const std::string& path) : path(path) -{ - intitalizeDetails(); -} - -BaseRepository::BaseRepository(const model::BinaryPath& bConf) -{ - initializeDetails(bConf); -} - - -bool BaseRepository::testConnection() -{ - auto conn = mysql_init(nullptr); - if (!mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), - details.password.c_str(), details.database.c_str(), 0, - nullptr, 0)) { - std::cout << "failed to connect to the database" << std::endl; - return false; + BaseRepository::BaseRepository(const std::string& path) : path(path) { + intitalizeDetails(); } - mysql_close(conn); - - return true; -} - - -MYSQL* BaseRepository::setupMysqlConnection() -{ - MYSQL *conn = mysql_init(nullptr); - - if (!mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), - details.password.c_str(), details.database.c_str(), 0, nullptr, 0)) { - std::cout << "connection error" << std::endl; + BaseRepository::BaseRepository(const model::BinaryPath& bConf) { + initializeDetails(bConf); } - return conn; -} -MYSQL* BaseRepository::setupMysqlConnection(model::DatabaseConnection details) -{ - MYSQL *connection = mysql_init(NULL); + bool BaseRepository::testConnection() { + auto conn = mysql_init(nullptr); + if (!mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), + details.password.c_str(), details.database.c_str(), 0, nullptr, 0)) { + std::cout << "failed to connect to the database\n"; + return false; + } - // connect to the database with the details attached. - if (!mysql_real_connect(connection,details.server.c_str(), details.username.c_str(), details.password.c_str(), details.database.c_str(), 0, NULL, 0)) { - printf("Conection error : %s\n", mysql_error(connection)); - exit(1); + mysql_close(conn); + + return true; } - return connection; -} -MYSQL_RES* BaseRepository::performMysqlQuery(MYSQL *conn, const std::string& query) -{ - // send the query to the database - if (mysql_query(conn, query.c_str())) - { - printf("MySQL query error : %s\n", mysql_error(conn)); - exit(1); - } + MYSQL* BaseRepository::setupMysqlConnection() { + MYSQL *conn = mysql_init(nullptr); - return mysql_use_result(conn); -} + if (!mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), + details.password.c_str(), details.database.c_str(), 0, nullptr, 0)) { + std::cout << "connection error\n"; + } + + return conn; + } + + MYSQL* BaseRepository::setupMysqlConnection(model::DatabaseConnection details) { + MYSQL *connection = mysql_init(NULL); + + // connect to the database with the details attached. + if (!mysql_real_connect(connection,details.server.c_str(), details.username.c_str(), + details.password.c_str(), details.database.c_str(), 0, NULL, 0)) { + std::cout << "Connection error: " << mysql_error(connection) << "\n"; + std::exit(-1); + } + return connection; + } -void BaseRepository::intitalizeDetails() -{ - auto databaseConfig = manager::DirectoryManager::databaseConfigContent(path); + MYSQL_RES* BaseRepository::performMysqlQuery(MYSQL *conn, const std::string& query) { + // send the query to the database + if (mysql_query(conn, query.c_str())) { + printf("MySQL query error : %s\n", mysql_error(conn)); + std::cout << "MySQL query error : " << mysql_error(conn) << "\n"; + std::exit(1); + } + + return mysql_use_result(conn); + } + + + void BaseRepository::intitalizeDetails() { + auto databaseConfig = manager::DirectoryManager::databaseConfigContent(path); - details.database = databaseConfig["database"].get(); - details.password = databaseConfig["password"].get(); - details.server = databaseConfig["server"].get(); - details.username = databaseConfig["username"].get(); -} -void BaseRepository::initializeDetails(const model::BinaryPath& bConf) -{ - auto databaseConfig = manager::DirectoryManager::databaseConfigContent(bConf); + details.database = databaseConfig["database"].get(); + details.password = databaseConfig["password"].get(); + details.server = databaseConfig["server"].get(); + details.username = databaseConfig["username"].get(); + } + void BaseRepository::initializeDetails(const model::BinaryPath& bConf) + { + auto databaseConfig = manager::DirectoryManager::databaseConfigContent(bConf); - details.database = databaseConfig["database"].get(); - details.server = databaseConfig["server"].get(); - details.username = databaseConfig["username"].get(); - details.password = databaseConfig["password"].get(); + details.database = databaseConfig["database"].get(); + details.server = databaseConfig["server"].get(); + details.username = databaseConfig["username"].get(); + details.password = databaseConfig["password"].get(); - std::cout << "retrieved database details" << std::endl; -} + std::cout << "retrieved database details\n"; + } } diff --git a/src/database/CoverArtRepository.cpp b/src/database/CoverArtRepository.cpp index a36c623..e55848f 100644 --- a/src/database/CoverArtRepository.cpp +++ b/src/database/CoverArtRepository.cpp @@ -7,370 +7,320 @@ #include namespace database { -CoverArtRepository::CoverArtRepository(const std::string& path) : BaseRepository(path) -{ } - -CoverArtRepository::CoverArtRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) -{ } + CoverArtRepository::CoverArtRepository(const model::BinaryPath& bConf) : + BaseRepository(bConf) { } -std::vector CoverArtRepository::retrieveRecords() -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - const std::string query = "SELECT * FROM CoverArt"; + std::vector CoverArtRepository::retrieveRecords() { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + const std::string query = "SELECT * FROM CoverArt"; - mysql_stmt_prepare(stmt, query.c_str(), query.size()); - mysql_stmt_execute(stmt); + mysql_stmt_prepare(stmt, query.c_str(), query.size()); + mysql_stmt_execute(stmt); - auto coverArts = parseRecords(stmt); + auto coverArts = parseRecords(stmt); - mysql_stmt_close(stmt); - mysql_close(conn); + mysql_stmt_close(stmt); + mysql_close(conn); - return coverArts; -} - -model::Cover CoverArtRepository::retrieveRecord(model::Cover& cov, type::CoverFilter filter = type::CoverFilter::id) -{ - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - qry << "SELECT * FROM CoverArt WHERE "; - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - auto songTitleLength = cov.songTitle.size(); - switch (filter) { - case type::CoverFilter::id: - qry << "CoverArtId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&cov.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::CoverFilter::songTitle: - qry << "SongTitle = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)cov.songTitle.c_str(); - params[0].length = &songTitleLength; - params[0].is_null = 0; - break; - default: - break; + return coverArts; } - qry << " LIMIT 1"; + model::Cover CoverArtRepository::retrieveRecord(model::Cover& cov, + type::CoverFilter filter = type::CoverFilter::id) { + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - const std::string query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + qry << "SELECT * FROM CoverArt WHERE "; - auto covDb = parseRecord(stmt); + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); - mysql_stmt_close(stmt); - mysql_close(conn); - std::cout << "retrieved cover art record" << std::endl; + auto songTitleLength = cov.songTitle.size(); + switch (filter) { + case type::CoverFilter::id: + qry << "CoverArtId = ?"; - return covDb; -} + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&cov.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::CoverFilter::songTitle: + qry << "SongTitle = ?"; + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)cov.songTitle.c_str(); + params[0].length = &songTitleLength; + params[0].is_null = 0; + break; + default: + break; + } -bool CoverArtRepository::doesCoverArtExist(const model::Cover& cover, type::CoverFilter filter) -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + qry << " LIMIT 1"; - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); + const std::string query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - std::stringstream qry; - qry << "SELECT * FROM CoverArt WHERE "; + auto covDb = parseRecord(stmt); - auto titleLength = cover.songTitle.size(); - switch (filter) { - case type::CoverFilter::id: - qry << "CoverArtId = ?"; + mysql_stmt_close(stmt); + mysql_close(conn); + std::cout << "retrieved cover art record\n"; - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&cover.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::CoverFilter::songTitle: - qry << "SongTitle = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)cover.songTitle.c_str(); - params[0].length = &titleLength; - params[0].is_null = 0; - break; - default: - break; + return covDb; } - qry << " LIMIT 1"; - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + bool CoverArtRepository::doesCoverArtExist(const model::Cover& cover, + type::CoverFilter filter) { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - std::cout << "the query has been performed" << std::endl; + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); - mysql_stmt_store_result(stmt); - auto rowCount = mysql_stmt_num_rows(stmt); + std::stringstream qry; + qry << "SELECT * FROM CoverArt WHERE "; - mysql_stmt_close(stmt); - mysql_close(conn); + auto titleLength = cover.songTitle.size(); + switch (filter) { + case type::CoverFilter::id: + qry << "CoverArtId = ?"; - return (rowCount > 0) ? true : false; -} + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&cover.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::CoverFilter::songTitle: + qry << "SongTitle = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)cover.songTitle.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed\n"; + + mysql_stmt_store_result(stmt); + auto rowCount = mysql_stmt_num_rows(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + return (rowCount > 0) ? true : false; + } -// TODO: change to prepared statement -void CoverArtRepository::deleteRecord(const model::Cover& cov) -{ - auto conn = setupMysqlConnection(); - const std::string query("DELETE FROM CoverArt WHERE CoverArtId = " + std::to_string(cov.id)); + void CoverArtRepository::deleteRecord(const model::Cover& cov, + type::CoverFilter filter) { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + std::cout << "delete CoverArt record\n"; + std::stringstream qry; + qry << "DELETE FROM CoverArt WHERE "; - auto result = performMysqlQuery(conn, query); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - mysql_close(conn); -} + switch (filter) { + case type::CoverFilter::id: + qry << "CoverArtId = ?"; -void CoverArtRepository::saveRecord(const model::Cover& cov) -{ - std::cout << "saving cover art record"; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&cov.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } - MYSQL_BIND params[2]; - memset(params, 0, sizeof(params)); - my_bool isNull; + const auto query = qry.str(); - const std::string query = "INSERT INTO CoverArt(SongTitle, ImagePath) VALUES(?, ?)"; + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + mysql_stmt_close(stmt); + mysql_close(conn); - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)cov.songTitle.c_str(); - auto songTitleLength = cov.songTitle.size(); - params[0].length = &songTitleLength; - params[0].is_null = 0; + std::cout << "deleted CoverArt record\n"; + } - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)cov.imagePath.c_str(); - auto imagePathLength = cov.imagePath.size(); - params[1].length = &imagePathLength; - params[1].is_null = 0; + void CoverArtRepository::saveRecord(const model::Cover& cov) { + std::cout << "saving cover art record"; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + MYSQL_BIND params[2]; + memset(params, 0, sizeof(params)); + my_bool isNull; - mysql_stmt_close(stmt); - mysql_close(conn); + const std::string query = "INSERT INTO CoverArt(SongTitle, ImagePath) VALUES(?, ?)"; - std::cout << "saved cover art record" << std::endl; -} + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); -void CoverArtRepository::updateRecord(const model::Cover& cover) -{ - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)cov.songTitle.c_str(); + auto songTitleLength = cov.songTitle.size(); + params[0].length = &songTitleLength; + params[0].is_null = 0; - qry << "UPDATE CoverArt SET "; - qry << "SongTitle = ?, "; - qry << "ImagePath = ? "; - qry << "WHERE CoverArtId = ?"; + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)cov.imagePath.c_str(); + auto imagePathLength = cov.imagePath.size(); + params[1].length = &imagePathLength; + params[1].is_null = 0; - MYSQL_BIND params[3]; - memset(params, 0, sizeof(params)); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - auto songTitleLength = cover.songTitle.size(); - auto imagePathLength = cover.imagePath.size(); + mysql_stmt_close(stmt); + mysql_close(conn); - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)cover.songTitle.c_str(); - params[0].length = &songTitleLength; - params[0].is_null = 0; + std::cout << "saved cover art record\n"; + } - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)cover.imagePath.c_str(); - params[1].length = &imagePathLength; - params[1].is_null = 0; + void CoverArtRepository::updateRecord(const model::Cover& cover) { + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - params[2].buffer_type = MYSQL_TYPE_LONG; - params[2].buffer = (char*)&cover.id; - params[2].length = 0; - params[2].is_null = 0; + qry << "UPDATE CoverArt SET "; + qry << "SongTitle = ?, "; + qry << "ImagePath = ? "; + qry << "WHERE CoverArtId = ?"; - const std::string query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + MYSQL_BIND params[3]; + memset(params, 0, sizeof(params)); - mysql_stmt_close(stmt); - mysql_close(conn); + auto songTitleLength = cover.songTitle.size(); + auto imagePathLength = cover.imagePath.size(); - std::cout << "updated cover art record" << std::endl; -} + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)cover.songTitle.c_str(); + params[0].length = &songTitleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)cover.imagePath.c_str(); + params[1].length = &imagePathLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_LONG; + params[2].buffer = (char*)&cover.id; + params[2].length = 0; + params[2].is_null = 0; + + const std::string query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "updated cover art record\n"; + } -std::vector CoverArtRepository::parseRecords(MYSQL_STMT *stmt) -{ - mysql_stmt_store_result(stmt); - auto rowCount = mysql_stmt_num_rows(stmt); - std::cout << "number of results " << rowCount << std::endl; + std::vector CoverArtRepository::parseRecords(MYSQL_STMT *stmt) { + mysql_stmt_store_result(stmt); + const auto rowCount = mysql_stmt_num_rows(stmt); + std::cout << "number of results " << rowCount << "\n"; - std::vector coverArts; - coverArts.reserve(rowCount); + std::vector coverArts; + coverArts.reserve(rowCount); - const auto valAmt = 3; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; + constexpr auto valAmt = 3; - for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) { - if (mysql_stmt_field_count(stmt) > 0) { - model::Cover coverArt; - auto res = mysql_stmt_result_metadata(stmt); - auto fields = mysql_fetch_fields(res); - auto strLen = 1024; + for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) { + if (mysql_stmt_field_count(stmt) > 0) { + model::Cover cover; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(cover, metaBuff); + status = mysql_stmt_bind_result(stmt, bindedValues.get()); - MYSQL_BIND val[valAmt]; - memset(val, 0, sizeof(val)); - - char songTitle[strLen]; - char imagePath[strLen]; - - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&coverArt.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; - - val[1].buffer_type = MYSQL_TYPE_STRING; - val[1].buffer = (char*)songTitle; - val[1].buffer_length = strLen; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; - - val[2].buffer_type = MYSQL_TYPE_STRING; - val[2].buffer = (char*)imagePath; - val[2].buffer_length = strLen; - val[2].length = &len[2]; - val[2].is_null = &nullRes[2]; - - status = mysql_stmt_bind_result(stmt, val); - - while (true) { - std::cout << "fetching statement result" << std::endl; + std::cout << "fetching statement result\n"; status = mysql_stmt_fetch(stmt); - if (status == 1 || status == MYSQL_NO_DATA) { - break; - } + if (status == 1 || status == MYSQL_NO_DATA) break; - coverArt.songTitle = songTitle; - coverArt.imagePath = imagePath; - - coverArts.push_back(std::move(coverArt)); + cover.songTitle = std::get<0>(metaBuff); + cover.imagePath = std::get<1>(metaBuff); + coverArts.push_back(cover); } - } - std::cout << "fetching next result" << std::endl; - } - - return coverArts; -} - - -model::Cover CoverArtRepository::parseRecord(MYSQL_RES *results) -{ - std::cout << "parsing record" << std::endl; - model::Cover cov; - auto fieldNum = mysql_num_fields(results); - - MYSQL_ROW row = mysql_fetch_row(results); - - for (auto i = 0; i != fieldNum; ++i) { - switch (i) { - case 0: - cov.id = std::stoi(row[i]); - break; - case 1: - cov.songTitle = row[i]; - break; - case 2: - cov.imagePath = row[i]; - break; - } - } - std::cout << "done parsing record" << std::endl; - - return cov; -} - -model::Cover CoverArtRepository::parseRecord(MYSQL_STMT *stmt) -{ - std::cout << "parsing cover art record" << std::endl; - - mysql_stmt_store_result(stmt); - model::Cover cover; - - auto status = 0; - auto time = 0; - auto valAmt = 3; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; - - while (status == 0) { - if (mysql_stmt_field_count(stmt) > 0) { - auto res = mysql_stmt_result_metadata(stmt); - auto fields = mysql_fetch_fields(res); - auto strLen = 1024; - - MYSQL_BIND val[valAmt]; - memset(val, 0, sizeof(val)); - - char songTitle[strLen]; - char imagePath[strLen]; - - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&cover.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; - - val[1].buffer_type = MYSQL_TYPE_STRING; - val[1].buffer = (char*)&songTitle; - val[1].buffer_length = strLen; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; - - val[2].buffer_type = MYSQL_TYPE_STRING; - val[2].buffer = (char*)&imagePath; - val[2].buffer_length = strLen; - val[2].length = &len[2]; - val[2].is_null = &nullRes[2]; - - status = mysql_stmt_bind_result(stmt, val); - mysql_stmt_store_result(stmt); - - status = mysql_stmt_fetch(stmt); - - cover.songTitle = songTitle; - cover.imagePath = imagePath; + std::cout << "fetching next result\n"; } - status = mysql_stmt_next_result(stmt); + return coverArts; } - std::cout << "done parsing cover art record" << std::endl; - return cover; -} + std::shared_ptr CoverArtRepository::valueBind(model::Cover& cover, + std::tuple& metadata) { + constexpr auto valueCount = 3; + constexpr auto wordLen = 1024; + std::shared_ptr values((MYSQL_BIND*) + std::calloc(valueCount, sizeof(MYSQL_BIND))); + + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = reinterpret_cast(&cover.id); + + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = reinterpret_cast(std::get<0>(metadata)); + values.get()[1].buffer_length = wordLen; + + values.get()[2].buffer_type = MYSQL_TYPE_STRING; + values.get()[2].buffer = reinterpret_cast(std::get<1>(metadata)); + values.get()[2].buffer_length = wordLen; + + return values; + } + + + std::tuple CoverArtRepository::metadataBuffer() { + constexpr auto wordLen = 1024; + char songTitle[wordLen]; + char imagePath[wordLen]; + + return std::make_pair(songTitle, imagePath); + } + + + model::Cover CoverArtRepository::parseRecord(MYSQL_STMT *stmt) { + std::cout << "parsing cover art record\n"; + mysql_stmt_store_result(stmt); + model::Cover cover; + + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(cover, metaBuff); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); + status = mysql_stmt_fetch(stmt); + + cover.songTitle = std::get<0>(metaBuff); + cover.imagePath = std::get<1>(metaBuff); + + std::cout << "done parsing cover art record\n"; + + return cover; + } } diff --git a/src/database/GenreRepository.cpp b/src/database/GenreRepository.cpp index 8b86306..ca47aa1 100644 --- a/src/database/GenreRepository.cpp +++ b/src/database/GenreRepository.cpp @@ -6,357 +6,350 @@ #include namespace database { - -GenreRepository::GenreRepository(const model::BinaryPath& bConf) - : BaseRepository(bConf) -{ } + GenreRepository::GenreRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { } -std::vector GenreRepository::retrieveRecords() -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - const std::string query = "SELECT * FROM Genre"; + std::vector GenreRepository::retrieveRecords() { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + const std::string query = "SELECT * FROM Genre"; - mysql_stmt_prepare(stmt, query.c_str(), query.size()); - mysql_stmt_execute(stmt); + mysql_stmt_prepare(stmt, query.c_str(), query.size()); + mysql_stmt_execute(stmt); - auto genres = parseRecords(stmt); + auto genres = parseRecords(stmt); - mysql_stmt_close(stmt); - mysql_close(conn); + mysql_stmt_close(stmt); + mysql_close(conn); - return genres; -} - -std::pair GenreRepository::retrieveRecordWithSongCount(model::Genre& genre, type::GenreFilter filter = type::GenreFilter::id) -{ - std::cout << "retrieving genre record with song count" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - qry << "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre gnr LEFT JOIN "; - qry << "Song sng ON gnr.GenreId=sng.GenreId WHERE "; - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - switch (filter) { - case type::GenreFilter::id: - qry << "sng.GenreId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&genre.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; + return genres; } - qry << " GROUP BY gnr.GenreId LIMIT 1"; + std::pair GenreRepository::retrieveRecordWithSongCount( + model::Genre& genre, type::GenreFilter filter = type::GenreFilter::id) { + std::cout << "retrieving genre record with song count\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - const auto query = qry.str(); + qry << "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre gnr LEFT JOIN "; + qry << "Song sng ON gnr.GenreId=sng.GenreId WHERE "; - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - auto gnrWSC = parseRecordWithSongCount(stmt); + switch (filter) { + case type::GenreFilter::id: + qry << "sng.GenreId = ?"; - mysql_stmt_close(stmt); - mysql_close(conn); + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&genre.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } - std::cout << "retrieved genre record with song count" << std::endl; + qry << " GROUP BY gnr.GenreId LIMIT 1"; - return gnrWSC; -} + const auto query = qry.str(); -model::Genre GenreRepository::retrieveRecord(model::Genre& genre, type::GenreFilter filter) -{ - // TODO: change to prepared statement + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + auto gnrWSC = parseRecordWithSongCount(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "retrieved genre record with song count\n"; + + return gnrWSC; + } + + model::Genre GenreRepository::retrieveRecord(model::Genre& genre, type::GenreFilter filter) { + std::cout << "retrieving genre record\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + qry << "SELECT gnr.* FROM Genre gnr WHERE "; + + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); + auto categoryLength = genre.category.size(); + + switch (filter) { + case type::GenreFilter::id: + qry << "gnr.GenreId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = reinterpret_cast(&genre.id); + params[0].length = 0; + params[0].is_null = 0; + break; + case type::GenreFilter::category: + qry << "gnr.Category = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = const_cast(genre.category.c_str()); + params[0].length = &categoryLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " ORDER BY GenreId DESC LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + genre = parseRecord(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "retrieved record\n"; + + return genre; + } + + bool GenreRepository::doesGenreExist(const model::Genre& genre, type::GenreFilter filter) { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + + std::stringstream qry; + qry << "SELECT * FROM Genre WHERE "; + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + auto categoryLength = genre.category.size(); + switch (filter) { + case type::GenreFilter::id: + qry << "GenreId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&genre.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::GenreFilter::category: + qry << "Category = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)genre.category.c_str(); + params[0].length = &categoryLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed\n"; + + mysql_stmt_store_result(stmt); + auto rowCount = mysql_stmt_num_rows(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + return (rowCount > 0) ? true : false; + } + + void GenreRepository::saveRecord(const model::Genre& genre) { + std::cout << "inserting genre record\n"; + + auto conn = setupMysqlConnection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + const std::string query("INSERT INTO Genre(Category) VALUES(?)"); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)genre.category.c_str(); + auto categoryLength = genre.category.size(); + params[0].length = &categoryLength; + params[0].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "inserted record\n"; + } + + void GenreRepository::deleteRecord(const model::Genre& genre, + type::GenreFilter filter = type::GenreFilter::id) { + std::cout << "deleting genre record\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + + qry << "DELETE FROM Genre WHERE "; + + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); + + switch (filter) { + case type::GenreFilter::id: + qry << "GenreId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&genre.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } + + const auto query = qry.str(); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "deleted genre record\n"; + } + + + std::vector GenreRepository::parseRecords(MYSQL_STMT *stmt) { + mysql_stmt_store_result(stmt); + + std::vector genres; + genres.reserve(mysql_stmt_num_rows(stmt)); + + constexpr auto valAmt = 2; + + for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) { + if (mysql_stmt_field_count(stmt) > 0) { + model::Genre genre; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(genre, metaBuff); + status = mysql_stmt_bind_result(stmt, bindedValues.get()); + + std::cout << "fetching statement result\n"; + status = mysql_stmt_fetch(stmt); + + if (status == 1 || status == MYSQL_NO_DATA) break; + + genre.category = std::get<0>(metaBuff); + genres.push_back(genre); + } + std::cout << "fetching statement result\n"; + } + + return genres; + } + + std::pair GenreRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) { + std::cout << "parsing genre record with song count\n"; + mysql_stmt_store_result(stmt); + const auto rowCount = mysql_stmt_num_rows(stmt); + + model::Genre genre; + int songCount = 0; + + auto metaBuff = metadataBuffer(); + auto val = valueBindWithSongCount(genre, metaBuff, songCount); + + if (rowCount == 0) { + std::cout << "no results\n"; + return std::make_pair(genre, songCount); + } + + auto status = mysql_stmt_bind_result(stmt, val.get()); + status = mysql_stmt_fetch(stmt); + + genre.category = std::get<0>(metaBuff); + + std::cout << "parsed genre record with song count\n"; + + return std::make_pair(genre, songCount); + } + + + std::shared_ptr GenreRepository::valueBind(model::Genre& genre, + std::tuple& metadata) { + constexpr auto valueCount = 2; + constexpr auto wordLen = 1024; + std::shared_ptr values((MYSQL_BIND*) + std::calloc(valueCount, sizeof(MYSQL_BIND))); + + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = reinterpret_cast(&genre.id); + + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = reinterpret_cast(std::get<0>(metadata)); + values.get()[1].buffer_length = wordLen; + + return values; + } - std::cout << "retrieving genre record" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - qry << "SELECT gnr.* FROM Genre gnr WHERE "; + std::shared_ptr GenreRepository::valueBindWithSongCount(model::Genre& genre, + std::tuple& metadata, int& songCount) { + constexpr auto valueCount = 3; + constexpr auto wordLen = 1024; + std::shared_ptr values((MYSQL_BIND*) + std::calloc(valueCount, sizeof(MYSQL_BIND))); - std::unique_ptr param; - switch (filter) { - case type::GenreFilter::id: - qry << "gnr.GenreId = " << genre.id; - break; - case type::GenreFilter::category: - param = std::make_unique(new char[genre.category.size()]); - mysql_real_escape_string(conn, *param, genre.category.c_str(), genre.category.size()); - qry << "gnr.Category ='" << *param << "'"; - break; - default: - break; + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = reinterpret_cast(&genre.id); + + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = reinterpret_cast(std::get<0>(metadata)); + values.get()[1].buffer_length = wordLen; + + values.get()[2].buffer_type = MYSQL_TYPE_LONG; + values.get()[2].buffer = reinterpret_cast(&songCount); + + return values; } - qry << " ORDER BY GenreId DESC LIMIT 1"; - const auto query = qry.str(); - auto results = performMysqlQuery(conn, query); + std::tuple GenreRepository::metadataBuffer() { + constexpr auto wordLen = 1024; + char category[wordLen]; - genre = parseRecord(results); - - mysql_close(conn); - - std::cout << "retrieved record" << std::endl; - - return genre; -} - -bool GenreRepository::doesGenreExist(const model::Genre& genre, type::GenreFilter filter) -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - std::stringstream qry; - qry << "SELECT * FROM Genre WHERE "; - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - auto categoryLength = genre.category.size(); - switch (filter) { - case type::GenreFilter::id: - qry << "GenreId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&genre.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::GenreFilter::category: - qry << "Category = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)genre.category.c_str(); - params[0].length = &categoryLength; - params[0].is_null = 0; - break; - default: - break; + return std::make_tuple(category); } - qry << " LIMIT 1"; - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + model::Genre GenreRepository::parseRecord(MYSQL_STMT *stmt) { + std::cout << "parsing genre record\n"; + mysql_stmt_store_result(stmt); - std::cout << "the query has been performed" << std::endl; - - mysql_stmt_store_result(stmt); - auto rowCount = mysql_stmt_num_rows(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - return (rowCount > 0) ? true : false; -} - -void GenreRepository::saveRecord(const model::Genre& genre) -{ - std::cout << "inserting genre record" << std::endl; - - auto conn = setupMysqlConnection(); - MYSQL_STMT *stmt = mysql_stmt_init(conn); - - const std::string query("INSERT INTO Genre(Category) VALUES(?)"); - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)genre.category.c_str(); - auto categoryLength = genre.category.size(); - params[0].length = &categoryLength; - params[0].is_null = 0; - - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "inserted record" << std::endl; -} - -void GenreRepository::deleteRecord(const model::Genre& genre, type::GenreFilter filter = type::GenreFilter::id) -{ - // TODO: implement this - std::cout << "deleting genre record" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - qry << "DELETE FROM Genre WHERE "; - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - switch (filter) { - case type::GenreFilter::id: - qry << "GenreId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&genre.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; - } - - const auto query = qry.str(); - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "deleted genre record" << std::endl; -} - - -std::vector GenreRepository::parseRecords(MYSQL_STMT *stmt) -{ - mysql_stmt_store_result(stmt); - - std::vector genres; - genres.reserve(mysql_stmt_num_rows(stmt)); - - if (mysql_stmt_field_count(stmt) == 0) { - std::cout << "field count is 0" << std::endl; - return genres; - } - - model::Genre gnr; - const auto valAmt = 2; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; - - auto res = mysql_stmt_result_metadata(stmt); - auto fields = mysql_fetch_fields(res); - const auto strLen = 1024; - - char category[strLen]; - - MYSQL_BIND val[valAmt]; - memset(val, 0, sizeof(val)); - - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&gnr.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; - - val[1].buffer_type = MYSQL_TYPE_STRING; - val[1].buffer = (char*)category; - val[1].buffer_length = strLen; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; - - for (auto status = mysql_stmt_bind_result(stmt, val); status == 0;) { - std::cout << "fetching statement result" << std::endl; + model::Genre genre; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(genre, metaBuff); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); status = mysql_stmt_fetch(stmt); - if (status == 0) { - gnr.category = category; - genres.push_back(std::move(gnr)); - } + genre.category = std::get<0>(metaBuff); + + std::cout << "done parsing genre record\n"; + + return genre; } - - return genres; -} - -std::pair GenreRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) -{ - std::cout << "parsing genre record with song count" << std::endl; - mysql_stmt_store_result(stmt); - - const auto strLen = 1024; - const auto valAmt = 3; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; - - model::Genre genre; - int songCount = 0; - - if (mysql_stmt_num_rows(stmt) == 0) { - std::cout << "no results" << std::endl; - return std::make_pair(genre, songCount); - } - - MYSQL_BIND val[valAmt]; - std::memset(val, 0, sizeof(val)); - - char category[strLen] ; - - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&genre.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; - - val[1].buffer_type = MYSQL_TYPE_STRING; - val[1].buffer = (char*)category; - val[1].buffer_length = strLen; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; - - val[2].buffer_type = MYSQL_TYPE_LONG; - val[2].buffer = (char*)&songCount; - val[2].length = &len[2]; - val[2].is_null = &nullRes[2]; - - mysql_stmt_bind_result(stmt, val); - mysql_stmt_fetch(stmt); - - genre.category = std::move(category); - - std::cout << "parsed genre record with song count" << std::endl; - - return std::make_pair(genre, songCount); -} - -model::Genre GenreRepository::parseRecord(MYSQL_RES* results) -{ - std::cout << "parsing genre record" << std::endl; - model::Genre genre; - - auto fieldNum = mysql_num_fields(results); - auto row = mysql_fetch_row(results); - - for (auto i =0; i != fieldNum; ++i) { - const std::string field(mysql_fetch_field(results)->name); - - if (field.compare("GenreId") == 0) { - genre.id = std::stoi(row[i]); - } - if (field.compare("Category") == 0) { - genre.category = row[i]; - } - } - - std::cout << "parsed genre record" << std::endl; - - return genre; -} -model::Genre GenreRepository::parseRecord(MYSQL_STMT *stmt) -{ - // TODO: implement this - - model::Genre genre; - - return genre; -} } diff --git a/src/database/SongRepository.cpp b/src/database/SongRepository.cpp index ce7ca5b..743579c 100644 --- a/src/database/SongRepository.cpp +++ b/src/database/SongRepository.cpp @@ -8,541 +8,528 @@ #include "type/SongFilter.h" namespace database { - -SongRepository::SongRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) -{ } + SongRepository::SongRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { } -std::vector SongRepository::retrieveRecords() -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - std::stringstream qry; - qry << "SELECT sng.*, alb.Artist AS AlbumArtist FROM Song sng "; - qry << "LEFT JOIN Album alb ON sng.AlbumId=alb.AlbumId"; - const auto query = qry.str(); + std::vector SongRepository::retrieveRecords() { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + std::stringstream qry; + qry << "SELECT sng.*, alb.Artist AS AlbumArtist FROM Song sng "; + qry << "LEFT JOIN Album alb ON sng.AlbumId=alb.AlbumId"; + const auto query = qry.str(); - ::mysql_stmt_prepare(stmt, query.c_str(), query.size()); - ::mysql_stmt_execute(stmt); + ::mysql_stmt_prepare(stmt, query.c_str(), query.size()); + ::mysql_stmt_execute(stmt); - auto songs = parseRecords(stmt); + auto songs = parseRecords(stmt); - mysql_stmt_close(stmt); - mysql_close(conn); + mysql_stmt_close(stmt); + mysql_close(conn); - return songs; -} - - -model::Song SongRepository::retrieveRecord(const model::Song& song, type::SongFilter filter) -{ - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - auto valueFilterCount = 1; - switch (filter) { - case type::SongFilter::titleAndArtist: - valueFilterCount = 2; - break; - default: - break; - } - - MYSQL_BIND params[valueFilterCount]; - memset(params, 0, sizeof(params)); - - qry << "SELECT sng.*, alb.Artist AS AlbumArtist FROM Song sng "; - qry << "LEFT JOIN Album alb ON sng.AlbumId=alb.AlbumId WHERE "; - - auto titleLength = song.title.size(); - auto artistLength = song.artist.size(); - switch (filter) { - case type::SongFilter::id: - qry << "sng.SongId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&song.id; - params[0].length = 0; - params[0].is_null = 0;; - break; - case type::SongFilter::title: - qry << "sng.Title = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)song.title.c_str(); - params[0].length = &titleLength; - params[0].is_null = 0; - break; - case type::SongFilter::titleAndArtist: - qry << "sng.Title = ? AND sng.Artist = ?"; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)song.title.c_str(); - params[0].length = &titleLength; - params[0].is_null = 0; - - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)song.artist.c_str(); - params[1].length = &artistLength; - params[1].is_null = 0; - - std::cout << "title: " << song.title.c_str() << " artist: " << - song.artist.c_str() << "\n"; - break; - default: - break; - } - - qry << " LIMIT 1"; - - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - std::cout << "the query has been performed" << std::endl; - - //song = parseRecord(stmt); - auto retrievedSong = parseRecord(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - std::cout << "done" << std::endl; - - return retrievedSong; -} - - -bool SongRepository::doesSongExist(const model::Song& song, type::SongFilter filter) -{ - std::cout << "checking to see if song exists" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - auto valueFilterCount = 1; - switch (filter) { - case type::SongFilter::titleAndArtist: - valueFilterCount = 2; - break; - default: - break; + return songs; } - MYSQL_BIND params[valueFilterCount]; - memset(params, 0, sizeof(params)); + model::Song SongRepository::retrieveRecord(const model::Song& song, type::SongFilter filter) { + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - qry << "SELECT * FROM Song WHERE "; + auto valueFilterCount = 1; + switch (filter) { + case type::SongFilter::titleAndArtist: + valueFilterCount = 2; + break; + default: + break; + } - auto titleLength = song.title.size(); - auto artistLength = song.artist.size(); - switch (filter) { - case type::SongFilter::id: - qry << "SongId = ?"; + MYSQL_BIND params[valueFilterCount]; + memset(params, 0, sizeof(params)); - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&song.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::SongFilter::title: - qry << "Title = ?"; + qry << "SELECT sng.*, alb.Artist AS AlbumArtist FROM Song sng "; + qry << "LEFT JOIN Album alb ON sng.AlbumId=alb.AlbumId WHERE "; - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)song.title.c_str(); - params[0].length = &titleLength; - params[0].is_null = 0; - break; - case type::SongFilter::titleAndArtist: - qry << "Title = ? AND Artist = ?"; + auto titleLength = song.title.size(); + auto artistLength = song.artist.size(); + switch (filter) { + case type::SongFilter::id: + qry << "sng.SongId = ?"; - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)song.title.c_str(); - params[0].length = &titleLength; - params[0].is_null = 0; + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&song.id; + params[0].length = 0; + params[0].is_null = 0;; + break; + case type::SongFilter::title: + qry << "sng.Title = ?"; - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)song.artist.c_str(); - params[1].length = &artistLength; - params[1].is_null = 0; - break; - default: - break; + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + break; + case type::SongFilter::titleAndArtist: + qry << "sng.Title = ? AND sng.Artist = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.artist.c_str(); + params[1].length = &artistLength; + params[1].is_null = 0; + + std::cout << "title: " << song.title.c_str() << " artist: " << + song.artist.c_str() << "\n"; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed\n"; + + auto retrievedSong = parseRecord(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + std::cout << "done\n"; + + return retrievedSong; } - qry << " LIMIT 1"; - const std::string query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + bool SongRepository::doesSongExist(const model::Song& song, type::SongFilter filter) { + std::cout << "checking to see if song exists\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + auto valueFilterCount = 1; + switch (filter) { + case type::SongFilter::titleAndArtist: + valueFilterCount = 2; + break; + default: + break; + } + + + MYSQL_BIND params[valueFilterCount]; + memset(params, 0, sizeof(params)); + + qry << "SELECT * FROM Song WHERE "; + + auto titleLength = song.title.size(); + auto artistLength = song.artist.size(); + switch (filter) { + case type::SongFilter::id: + qry << "SongId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&song.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::SongFilter::title: + qry << "Title = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + break; + case type::SongFilter::titleAndArtist: + qry << "Title = ? AND Artist = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.artist.c_str(); + params[1].length = &artistLength; + params[1].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const std::string query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed\n"; + + ::mysql_stmt_store_result(stmt); + auto rowCount = ::mysql_stmt_num_rows(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + std::cout << "done\n"; + + return (rowCount > 0) ? true : false; + } + + bool SongRepository::deleteRecord(const model::Song& song) { + auto conn = setupMysqlConnection(); + auto status = 0; + + const std::string query("DELETE FROM Song WHERE SongId = " + std::to_string(song.id)); + + auto result = performMysqlQuery(conn, query); + + mysql_close(conn); + + return (result == 0) ? true : false; + } + + void SongRepository::saveRecord(const model::Song& song) { + std::cout << "beginning to insert song record\n"; + auto conn = setupMysqlConnection(); + auto status = 0; + + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; + query.append("Year, Duration, Track, Disc, SongPath, CoverArtId, ArtistId, "); + query.append("AlbumId, GenreId, YearId) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + + status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[14]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + auto titleLength = song.title.size(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.artist.c_str(); + auto artistLength = song.artist.size(); + params[1].length = &artistLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.album.c_str(); + auto albumLength = song.album.size(); + params[2].length = &albumLength; + params[2].is_null = 0; + + params[3].buffer_type = MYSQL_TYPE_STRING; + params[3].buffer = (char*)song.genre.c_str(); + auto genreLength = song.genre.size(); + params[3].length = &genreLength; + params[3].is_null = 0; + + params[4].buffer_type = MYSQL_TYPE_LONG; + params[4].buffer = (char*)&song.year; + params[4].length = 0; + params[4].is_null = 0; + + params[5].buffer_type = MYSQL_TYPE_LONG; + params[5].buffer = (char*)&song.duration; + params[5].length = 0; + params[5].is_null = 0; + + params[6].buffer_type = MYSQL_TYPE_LONG; + params[6].buffer = (char*)&song.track; + params[6].length = 0; + params[6].is_null = 0; + + params[7].buffer_type = MYSQL_TYPE_LONG; + params[7].buffer = (char*)&song.disc; + params[7].length = 0; + params[7].is_null = 0; + + params[8].buffer_type = MYSQL_TYPE_STRING; + params[8].buffer = (char*)song.songPath.c_str(); + auto pathLength = song.songPath.size(); + params[8].length = &pathLength; + params[8].is_null = 0; + + params[9].buffer_type = MYSQL_TYPE_LONG; + params[9].buffer = (char*)&song.coverArtId; + params[9].length = 0; + params[9].is_null = 0; + + params[10].buffer_type = MYSQL_TYPE_LONG; + params[10].buffer = (char*)&song.artistId; + params[10].length = 0; + params[10].is_null = 0; + + params[11].buffer_type = MYSQL_TYPE_LONG; + params[11].buffer = (char*)&song.albumId; + params[11].length = 0; + params[11].is_null = 0; + + params[12].buffer_type = MYSQL_TYPE_LONG; + params[12].buffer = (char*)&song.genreId; + params[12].length = 0; + params[12].is_null = 0; + + params[13].buffer_type = MYSQL_TYPE_LONG; + params[13].buffer = (char*)&song.yearId; + params[13].length = 0; + params[13].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done inserting song record\n"; + } + + void SongRepository::updateRecord(const model::Song& song) { + std::cout << "executing query to update record\n"; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + + std::stringstream qry; + qry << "UPDATE Song SET Title = ?, Artist = ?, Album = ?, Genre = ?, "; + qry << "Year = ?, SongPath = ?, CoverArtId = ?, ArtistId = ?, "; + qry << "AlbumId = ?, GenreId = ?, YearId = ? WHERE SongId = ?"; + const auto query = qry.str(); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[12]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + auto titleLength = song.title.size(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.artist.c_str(); + auto artistLength = song.artist.size(); + params[1].length = &artistLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.album.c_str(); + auto albumLength = song.album.size(); + params[2].length = &albumLength; + params[2].is_null = 0; + + params[3].buffer_type = MYSQL_TYPE_STRING; + params[3].buffer = (char*)song.genre.c_str(); + auto genreLength = song.genre.size(); + params[3].length = &genreLength; + params[3].is_null = 0; + + params[4].buffer_type = MYSQL_TYPE_LONG; + params[4].buffer = (char*)&song.year; + params[4].length = 0; + params[4].is_null = 0; + + params[5].buffer_type = MYSQL_TYPE_STRING; + params[5].buffer = (char*)song.songPath.c_str(); + auto pathLength = song.songPath.size(); + params[5].length = &pathLength; + params[5].is_null = 0; + + params[6].buffer_type = MYSQL_TYPE_LONG; + params[6].buffer = (char*)&song.coverArtId; + params[6].length = 0; + params[6].is_null = 0; + + params[7].buffer_type = MYSQL_TYPE_LONG; + params[7].buffer = (char*)&song.artistId; + params[7].length = 0; + params[7].is_null = 0; + + params[8].buffer_type = MYSQL_TYPE_LONG; + params[8].buffer = (char*)&song.albumId; + params[8].length = 0; + params[8].is_null = 0; + + params[9].buffer_type = MYSQL_TYPE_LONG; + params[9].buffer = (char*)&song.genreId; + params[9].length = 0; + params[9].is_null = 0; + + params[10].buffer_type = MYSQL_TYPE_LONG; + params[10].buffer = (char*)&song.yearId; + params[10].length = 0; + params[10].is_null = 0; + + params[11].buffer_type = MYSQL_TYPE_LONG; + params[11].buffer = (char*)&song.id; + params[11].length = 0; + params[11].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "updated song record\n"; + } - std::cout << "the query has been performed" << std::endl; - - ::mysql_stmt_store_result(stmt); - auto rowCount = ::mysql_stmt_num_rows(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - std::cout << "done" << std::endl; - - return (rowCount > 0) ? true : false; -} - -bool SongRepository::deleteRecord(const model::Song& song) -{ - auto conn = setupMysqlConnection(); - auto status = 0; - - const std::string query("DELETE FROM Song WHERE SongId = " + std::to_string(song.id)); - - auto result = performMysqlQuery(conn, query); - - mysql_close(conn); - - return (result == 0) ? true : false; -} - -void SongRepository::saveRecord(const model::Song& song) -{ - std::cout << "beginning to insert song record" << std::endl; - auto conn = setupMysqlConnection(); - auto status = 0; - - MYSQL_STMT *stmt = mysql_stmt_init(conn); - - std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; - query.append("Year, Duration, Track, Disc, SongPath, CoverArtId, ArtistId, "); - query.append("AlbumId, GenreId, YearId) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - - status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - - MYSQL_BIND params[14]; - memset(params, 0, sizeof(params)); - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)song.title.c_str(); - auto titleLength = song.title.size(); - params[0].length = &titleLength; - params[0].is_null = 0; - - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)song.artist.c_str(); - auto artistLength = song.artist.size(); - params[1].length = &artistLength; - params[1].is_null = 0; - - params[2].buffer_type = MYSQL_TYPE_STRING; - params[2].buffer = (char*)song.album.c_str(); - auto albumLength = song.album.size(); - params[2].length = &albumLength; - params[2].is_null = 0; - - params[3].buffer_type = MYSQL_TYPE_STRING; - params[3].buffer = (char*)song.genre.c_str(); - auto genreLength = song.genre.size(); - params[3].length = &genreLength; - params[3].is_null = 0; - - params[4].buffer_type = MYSQL_TYPE_LONG; - params[4].buffer = (char*)&song.year; - params[4].length = 0; - params[4].is_null = 0; - - params[5].buffer_type = MYSQL_TYPE_LONG; - params[5].buffer = (char*)&song.duration; - params[5].length = 0; - params[5].is_null = 0; - - params[6].buffer_type = MYSQL_TYPE_LONG; - params[6].buffer = (char*)&song.track; - params[6].length = 0; - params[6].is_null = 0; - - params[7].buffer_type = MYSQL_TYPE_LONG; - params[7].buffer = (char*)&song.disc; - params[7].length = 0; - params[7].is_null = 0; - - params[8].buffer_type = MYSQL_TYPE_STRING; - params[8].buffer = (char*)song.songPath.c_str(); - auto pathLength = song.songPath.size(); - params[8].length = &pathLength; - params[8].is_null = 0; - - params[9].buffer_type = MYSQL_TYPE_LONG; - params[9].buffer = (char*)&song.coverArtId; - params[9].length = 0; - params[9].is_null = 0; - - params[10].buffer_type = MYSQL_TYPE_LONG; - params[10].buffer = (char*)&song.artistId; - params[10].length = 0; - params[10].is_null = 0; - - params[11].buffer_type = MYSQL_TYPE_LONG; - params[11].buffer = (char*)&song.albumId; - params[11].length = 0; - params[11].is_null = 0; - - params[12].buffer_type = MYSQL_TYPE_LONG; - params[12].buffer = (char*)&song.genreId; - params[12].length = 0; - params[12].is_null = 0; - - params[13].buffer_type = MYSQL_TYPE_LONG; - params[13].buffer = (char*)&song.yearId; - params[13].length = 0; - params[13].is_null = 0; - - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "done inserting song record" << std::endl; -} - -void SongRepository::updateRecord(const model::Song& song) -{ - std::cout << "executing query to update record" << std::endl; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - std::stringstream qry; - qry << "UPDATE Song SET Title = ?, Artist = ?, Album = ?, Genre = ?, "; - qry << "Year = ?, SongPath = ?, CoverArtId = ?, ArtistId = ?, "; - qry << "AlbumId = ?, GenreId = ?, YearId = ? WHERE SongId = ?"; - const auto query = qry.str(); - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - - MYSQL_BIND params[12]; - memset(params, 0, sizeof(params)); - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)song.title.c_str(); - auto titleLength = song.title.size(); - params[0].length = &titleLength; - params[0].is_null = 0; - - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)song.artist.c_str(); - auto artistLength = song.artist.size(); - params[1].length = &artistLength; - params[1].is_null = 0; - - params[2].buffer_type = MYSQL_TYPE_STRING; - params[2].buffer = (char*)song.album.c_str(); - auto albumLength = song.album.size(); - params[2].length = &albumLength; - params[2].is_null = 0; - - params[3].buffer_type = MYSQL_TYPE_STRING; - params[3].buffer = (char*)song.genre.c_str(); - auto genreLength = song.genre.size(); - params[3].length = &genreLength; - params[3].is_null = 0; - - params[4].buffer_type = MYSQL_TYPE_LONG; - params[4].buffer = (char*)&song.year; - params[4].length = 0; - params[4].is_null = 0; - - params[5].buffer_type = MYSQL_TYPE_STRING; - params[5].buffer = (char*)song.songPath.c_str(); - auto pathLength = song.songPath.size(); - params[5].length = &pathLength; - params[5].is_null = 0; - - params[6].buffer_type = MYSQL_TYPE_LONG; - params[6].buffer = (char*)&song.coverArtId; - params[6].length = 0; - params[6].is_null = 0; - - params[7].buffer_type = MYSQL_TYPE_LONG; - params[7].buffer = (char*)&song.artistId; - params[7].length = 0; - params[7].is_null = 0; - - params[8].buffer_type = MYSQL_TYPE_LONG; - params[8].buffer = (char*)&song.albumId; - params[8].length = 0; - params[8].is_null = 0; - - params[9].buffer_type = MYSQL_TYPE_LONG; - params[9].buffer = (char*)&song.genreId; - params[9].length = 0; - params[9].is_null = 0; - - params[10].buffer_type = MYSQL_TYPE_LONG; - params[10].buffer = (char*)&song.yearId; - params[10].length = 0; - params[10].is_null = 0; - - params[11].buffer_type = MYSQL_TYPE_LONG; - params[11].buffer = (char*)&song.id; - params[11].length = 0; - params[11].is_null = 0; - - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "updated song record" << std::endl; -} - - -std::shared_ptr SongRepository::valueBind(model::Song& song, - std::tuple& metadata) -{ - constexpr auto strLen = 1024; - constexpr auto valueCount = 16; - std::shared_ptr values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND))); - unsigned long len[valueCount]; - my_bool nullRes[valueCount]; - - - values.get()[0].buffer_type = MYSQL_TYPE_LONG; - values.get()[0].buffer = (char*)&song.id; - - values.get()[1].buffer_type = MYSQL_TYPE_STRING; - values.get()[1].buffer = (char*)std::get<0>(metadata); - values.get()[1].buffer_length = strLen; - - values.get()[2].buffer_type = MYSQL_TYPE_STRING; - values.get()[2].buffer = (char*)std::get<1>(metadata); - values.get()[2].buffer_length = strLen; - - values.get()[3].buffer_type = MYSQL_TYPE_STRING; - values.get()[3].buffer = (char*)std::get<2>(metadata); - values.get()[3].buffer_length = strLen; - - values.get()[4].buffer_type = MYSQL_TYPE_STRING; - values.get()[4].buffer = (char*)std::get<3>(metadata); - values.get()[4].buffer_length = strLen; - - values.get()[5].buffer_type = MYSQL_TYPE_LONG; - values.get()[5].buffer = (char*)&song.year; - - values.get()[6].buffer_type = MYSQL_TYPE_LONG; - values.get()[6].buffer = (char*)&song.duration; - - values.get()[7].buffer_type = MYSQL_TYPE_LONG; - values.get()[7].buffer = (char*)&song.track; - - values.get()[8].buffer_type = MYSQL_TYPE_LONG; - values.get()[8].buffer = (char*)&song.disc; - - values.get()[9].buffer_type = MYSQL_TYPE_STRING; - values.get()[9].buffer = (char*)std::get<4>(metadata); - values.get()[9].buffer_length = strLen; - - values.get()[10].buffer_type = MYSQL_TYPE_LONG; - values.get()[10].buffer = (char*)&song.coverArtId; - values.get()[11].buffer_type = MYSQL_TYPE_LONG; - values.get()[11].buffer = (char*)&song.artistId; + std::shared_ptr SongRepository::valueBind(model::Song& song, + std::tuple& metadata) { + constexpr auto strLen = 1024; + constexpr auto valueCount = 16; + std::shared_ptr values((MYSQL_BIND*) std::calloc(valueCount, sizeof(MYSQL_BIND))); + unsigned long len[valueCount]; + my_bool nullRes[valueCount]; + + + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = (char*)&song.id; + + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = (char*)std::get<0>(metadata); + values.get()[1].buffer_length = strLen; + + values.get()[2].buffer_type = MYSQL_TYPE_STRING; + values.get()[2].buffer = (char*)std::get<1>(metadata); + values.get()[2].buffer_length = strLen; - values.get()[12].buffer_type = MYSQL_TYPE_LONG; - values.get()[12].buffer = (char*)&song.albumId;; + values.get()[3].buffer_type = MYSQL_TYPE_STRING; + values.get()[3].buffer = (char*)std::get<2>(metadata); + values.get()[3].buffer_length = strLen; + + values.get()[4].buffer_type = MYSQL_TYPE_STRING; + values.get()[4].buffer = (char*)std::get<3>(metadata); + values.get()[4].buffer_length = strLen; + + values.get()[5].buffer_type = MYSQL_TYPE_LONG; + values.get()[5].buffer = (char*)&song.year; - values.get()[13].buffer_type = MYSQL_TYPE_LONG; - values.get()[13].buffer = (char*)&song.genreId; + values.get()[6].buffer_type = MYSQL_TYPE_LONG; + values.get()[6].buffer = (char*)&song.duration; + + values.get()[7].buffer_type = MYSQL_TYPE_LONG; + values.get()[7].buffer = (char*)&song.track; - values.get()[14].buffer_type = MYSQL_TYPE_LONG; - values.get()[14].buffer = (char*)&song.yearId; + values.get()[8].buffer_type = MYSQL_TYPE_LONG; + values.get()[8].buffer = (char*)&song.disc; - values.get()[15].buffer_type = MYSQL_TYPE_STRING; - values.get()[15].buffer = (char*)std::get<5>(metadata); - values.get()[15].buffer_length = strLen; + values.get()[9].buffer_type = MYSQL_TYPE_STRING; + values.get()[9].buffer = (char*)std::get<4>(metadata); + values.get()[9].buffer_length = strLen; - return values; -} + values.get()[10].buffer_type = MYSQL_TYPE_LONG; + values.get()[10].buffer = (char*)&song.coverArtId; + values.get()[11].buffer_type = MYSQL_TYPE_LONG; + values.get()[11].buffer = (char*)&song.artistId; -std::tuple SongRepository::metadataBuffer() -{ - constexpr auto length = 1024; - char title[length]; - char artist[length]; - char album[length]; - char genre[length]; - char path[length]; - char albumArtist[length]; + values.get()[12].buffer_type = MYSQL_TYPE_LONG; + values.get()[12].buffer = (char*)&song.albumId;; - return std::make_tuple(title, artist, album, genre, path, albumArtist); -} + values.get()[13].buffer_type = MYSQL_TYPE_LONG; + values.get()[13].buffer = (char*)&song.genreId; + values.get()[14].buffer_type = MYSQL_TYPE_LONG; + values.get()[14].buffer = (char*)&song.yearId; -std::vector SongRepository::parseRecords(MYSQL_STMT *stmt) -{ - ::mysql_stmt_store_result(stmt); - auto c = ::mysql_stmt_num_rows(stmt); - std::cout << "number of results " << c << std::endl; - std::vector songs; - songs.reserve(c); + values.get()[15].buffer_type = MYSQL_TYPE_STRING; + values.get()[15].buffer = (char*)std::get<5>(metadata); + values.get()[15].buffer_length = strLen; - auto status = 0; - auto time = 0; + return values; + } - while (status == 0) { - if (::mysql_stmt_field_count(stmt) > 0) { - model::Song song; - auto metaBuff = metadataBuffer(); - auto val = valueBind(song, metaBuff); - status = ::mysql_stmt_bind_result(stmt, val.get()); + std::tuple SongRepository::metadataBuffer() { + constexpr auto length = 1024; + char title[length]; + char artist[length]; + char album[length]; + char genre[length]; + char path[length]; + char albumArtist[length]; - while (1) { - std::cout << "fetching statement result" << std::endl; - status = ::mysql_stmt_fetch(stmt); + return std::make_tuple(title, artist, album, genre, path, albumArtist); + } - if (status == 1 || status == MYSQL_NO_DATA) { - break; - } + + std::vector SongRepository::parseRecords(MYSQL_STMT *stmt) { + ::mysql_stmt_store_result(stmt); + auto c = ::mysql_stmt_num_rows(stmt); + std::cout << "number of results " << c << "\n"; + std::vector songs; + songs.reserve(c); + + auto status = 0; + auto time = 0; + + while (status == 0) { + if (::mysql_stmt_field_count(stmt) > 0) { + model::Song song; + auto metaBuff = metadataBuffer(); + auto val = valueBind(song, metaBuff); + + status = ::mysql_stmt_bind_result(stmt, val.get()); + + while (1) { + std::cout << "fetching statement result\n"; + status = ::mysql_stmt_fetch(stmt); + + if (status == 1 || status == MYSQL_NO_DATA) { + break; + } - song.title = std::get<0>(metaBuff); - song.artist = std::get<1>(metaBuff); - song.album = std::get<2>(metaBuff); - song.genre = std::get<3>(metaBuff); - song.songPath = std::get<4>(metaBuff); - song.albumArtist = std::get<5>(metaBuff); + song.title = std::get<0>(metaBuff); + song.artist = std::get<1>(metaBuff); + song.album = std::get<2>(metaBuff); + song.genre = std::get<3>(metaBuff); + song.songPath = std::get<4>(metaBuff); + song.albumArtist = std::get<5>(metaBuff); - songs.push_back(song); - } - } - std::cout << "fetching next result" << std::endl; - status = ::mysql_stmt_next_result(stmt); + songs.push_back(song); + } + } + std::cout << "fetching next result\n"; + status = ::mysql_stmt_next_result(stmt); + } + + return songs; } - return songs; -} - - -model::Song SongRepository::parseRecord(MYSQL_STMT *stmt) -{ - mysql_stmt_store_result(stmt); - std::cout << "amount of rows: " << mysql_stmt_num_rows(stmt) << std::endl; - model::Song song; - auto metaBuff = metadataBuffer(); - auto bindedValues = valueBind(song, metaBuff); - auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); - status = mysql_stmt_fetch(stmt); - - song.title = std::get<0>(metaBuff); - song.artist = std::get<1>(metaBuff); - song.album = std::get<2>(metaBuff); - song.genre = std::get<3>(metaBuff); - song.songPath = std::get<4>(metaBuff); - song.albumArtist = std::get<5>(metaBuff); - - std::cout << "done parsing record" << std::endl; - - return song; -} + + model::Song SongRepository::parseRecord(MYSQL_STMT *stmt) { + mysql_stmt_store_result(stmt); + std::cout << "amount of rows: " << mysql_stmt_num_rows(stmt) << "\n"; + model::Song song; + auto metaBuff = metadataBuffer(); + auto bindedValues = valueBind(song, metaBuff); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); + status = mysql_stmt_fetch(stmt); + + song.title = std::get<0>(metaBuff); + song.artist = std::get<1>(metaBuff); + song.album = std::get<2>(metaBuff); + song.genre = std::get<3>(metaBuff); + song.songPath = std::get<4>(metaBuff); + song.albumArtist = std::get<5>(metaBuff); + + std::cout << "done parsing record\n"; + + return song; + } } diff --git a/src/database/UserRepository.cpp b/src/database/UserRepository.cpp index ae5dc92..b0cc6e0 100644 --- a/src/database/UserRepository.cpp +++ b/src/database/UserRepository.cpp @@ -7,358 +7,349 @@ namespace database { -UserRepository::UserRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { } + UserRepository::UserRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { } -model::User UserRepository::retrieveUserRecord(model::User& user, - type::UserFilter filter = type::UserFilter::username) -{ - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + model::User UserRepository::retrieveUserRecord(model::User& user, + type::UserFilter filter = type::UserFilter::username) { + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - qry << "SELECT * FROM User WHERE "; + qry << "SELECT * FROM User WHERE "; - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - auto userLength = user.username.size(); - switch (filter) { - case type::UserFilter::id: - qry << "UserId = ?"; + auto userLength = user.username.size(); + switch (filter) { + case type::UserFilter::id: + qry << "UserId = ?"; - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&user.id; - params[0].length = nullptr; - params[0].is_null = 0; + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&user.id; + params[0].length = nullptr; + params[0].is_null = 0; - break; - case type::UserFilter::username: - qry << "Username = ?"; + break; + case type::UserFilter::username: + qry << "Username = ?"; - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)user.username.c_str(); - params[0].length = &userLength; - params[0].is_null = 0; - break; - default: - break; + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)user.username.c_str(); + params[0].length = &userLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + user = parseRecord(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + return user; } - qry << " LIMIT 1"; + model::PassSec UserRepository::retrieverUserSaltRecord(model::PassSec& userSec, + type::SaltFilter filter) { + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + qry << "SELECT * FROM Salt WHERE "; - user = parseRecord(stmt); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - mysql_stmt_close(stmt); - mysql_close(conn); + switch (filter) { + case type::SaltFilter::userId: + qry << "UserId = ?"; - return user; -} + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&userSec.userId; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } -model::PassSec UserRepository::retrieverUserSaltRecord(model::PassSec& userSec, type::SaltFilter filter) -{ - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + qry << " LIMIT 1"; - qry << "SELECT * FROM Salt WHERE "; + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); + userSec = parseSaltRecord(stmt); - switch (filter) { - case type::SaltFilter::userId: - qry << "UserId = ?"; + mysql_stmt_close(stmt); + mysql_close(conn); - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&userSec.userId; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; + return userSec; } - qry << " LIMIT 1"; - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + bool UserRepository::doesUserRecordExist(const model::User& user, type::UserFilter filter) { + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - userSec = parseSaltRecord(stmt); + qry << "SELECT * FROM User WHERE "; - mysql_stmt_close(stmt); - mysql_close(conn); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - return userSec; -} + auto userLength = user.username.size(); + switch (filter) { + case type::UserFilter::username: + qry << "Username = ?"; + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)user.username.c_str(); + params[0].length = &userLength; + params[0].is_null = 0; + break; + default: + break; + } -bool UserRepository::doesUserRecordExist(const model::User& user, type::UserFilter filter) -{ - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + qry << " LIMIT 1"; - qry << "SELECT * FROM User WHERE "; + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); + mysql_stmt_store_result(stmt); + const auto rowCount = mysql_stmt_num_rows(stmt); - auto userLength = user.username.size(); - switch (filter) { - case type::UserFilter::username: - qry << "Username = ?"; + mysql_stmt_close(stmt); + mysql_close(conn); - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)user.username.c_str(); - params[0].length = &userLength; - params[0].is_null = 0; - break; - default: - break; + return (rowCount > 0) ? true : false; } - qry << " LIMIT 1"; - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + void UserRepository::saveUserRecord(const model::User& user) { + std::cout << "inserting user record\n"; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - mysql_stmt_store_result(stmt); - const auto rowCount = mysql_stmt_num_rows(stmt); + std::stringstream qry; + qry << "INSERT INTO User(Firstname, Lastname, Phone, Email, Username, Password) "; + qry << "VALUES(?, ?, ?, ?, ?, ?)"; - mysql_stmt_close(stmt); - mysql_close(conn); + const auto query = qry.str(); + auto sizes = fetchUserLengths(user); + auto params = insertUserValues(user, sizes); - return (rowCount > 0) ? true : false; -} -void UserRepository::saveUserRecord(const model::User& user) -{ - std::cout << "inserting user record" << std::endl; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params.get()); + status = mysql_stmt_execute(stmt); - std::stringstream qry; - qry << "INSERT INTO User(Firstname, Lastname, Phone, Email, Username, Password) "; - qry << "VALUES(?, ?, ?, ?, ?, ?)"; + mysql_stmt_close(stmt); + mysql_close(conn); + } - const auto query = qry.str(); + void UserRepository::saveUserSalt(const model::PassSec& userSec) { + std::cout << "inserting user salt record\n"; - auto sizes = fetchUserLengths(user); - auto params = insertUserValues(user, sizes); + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params.get()); - status = mysql_stmt_execute(stmt); + std::stringstream qry; + qry << "INSERT INTO Salt(Salt, UserId) VALUES(?,?)"; - mysql_stmt_close(stmt); - mysql_close(conn); -} + const auto query = qry.str(); -void UserRepository::saveUserSalt(const model::PassSec& userSec) -{ - std::cout << "inserting user salt record" << std::endl; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + auto sizes = fetchSaltLengths(userSec); + auto values = insertSaltValues(userSec, sizes); - std::stringstream qry; - qry << "INSERT INTO Salt(Salt, UserId) VALUES(?,?)"; + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, values.get()); + status = mysql_stmt_execute(stmt); - const auto query = qry.str(); - - auto sizes = fetchSaltLengths(userSec); - auto values = insertSaltValues(userSec, sizes); - - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, values.get()); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); -} + mysql_stmt_close(stmt); + mysql_close(conn); + } -std::shared_ptr UserRepository::insertUserValues(const model::User& user, - std::shared_ptr lengths) -{ - std::shared_ptr values((MYSQL_BIND*) std::calloc(6, sizeof(MYSQL_BIND))); + std::shared_ptr UserRepository::insertUserValues(const model::User& user, + std::shared_ptr lengths) { + std::shared_ptr values((MYSQL_BIND*) std::calloc(6, sizeof(MYSQL_BIND))); - values.get()[0].buffer_type = MYSQL_TYPE_STRING; - values.get()[0].buffer = (char*)user.firstname.c_str(); - values.get()[0].length = &(lengths->firstnameLength); - values.get()[0].is_null = 0; + values.get()[0].buffer_type = MYSQL_TYPE_STRING; + values.get()[0].buffer = (char*)user.firstname.c_str(); + values.get()[0].length = &(lengths->firstnameLength); + values.get()[0].is_null = 0; - values.get()[1].buffer_type = MYSQL_TYPE_STRING; - values.get()[1].buffer = (char*)user.lastname.c_str(); - values.get()[1].length = &(lengths->lastnameLength); - values.get()[1].is_null = 0; + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = (char*)user.lastname.c_str(); + values.get()[1].length = &(lengths->lastnameLength); + values.get()[1].is_null = 0; - values.get()[2].buffer_type = MYSQL_TYPE_STRING; - values.get()[2].buffer = (char*)user.phone.c_str(); - values.get()[2].length = &(lengths->phoneLength); - values.get()[2].is_null = 0; + values.get()[2].buffer_type = MYSQL_TYPE_STRING; + values.get()[2].buffer = (char*)user.phone.c_str(); + values.get()[2].length = &(lengths->phoneLength); + values.get()[2].is_null = 0; - values.get()[3].buffer_type = MYSQL_TYPE_STRING; - values.get()[3].buffer = (char*)user.email.c_str(); - values.get()[3].length = &(lengths->emailLength); - values.get()[3].is_null = 0; + values.get()[3].buffer_type = MYSQL_TYPE_STRING; + values.get()[3].buffer = (char*)user.email.c_str(); + values.get()[3].length = &(lengths->emailLength); + values.get()[3].is_null = 0; - values.get()[4].buffer_type = MYSQL_TYPE_STRING; - values.get()[4].buffer = (char*)user.username.c_str(); - values.get()[4].length = &(lengths->usernameLength); - values.get()[4].is_null = 0; + values.get()[4].buffer_type = MYSQL_TYPE_STRING; + values.get()[4].buffer = (char*)user.username.c_str(); + values.get()[4].length = &(lengths->usernameLength); + values.get()[4].is_null = 0; - values.get()[5].buffer_type = MYSQL_TYPE_STRING; - values.get()[5].buffer = (char*)user.password.c_str(); - values.get()[5].length = &(lengths->passwordLength); - values.get()[5].is_null = 0; + values.get()[5].buffer_type = MYSQL_TYPE_STRING; + values.get()[5].buffer = (char*)user.password.c_str(); + values.get()[5].length = &(lengths->passwordLength); + values.get()[5].is_null = 0; - return values; -} + return values; + } -std::shared_ptr UserRepository::insertSaltValues(const model::PassSec& passSec, - std::shared_ptr lengths) -{ - std::shared_ptr values((MYSQL_BIND*) std::calloc(6, sizeof(MYSQL_BIND))); + std::shared_ptr UserRepository::insertSaltValues(const model::PassSec& passSec, + std::shared_ptr lengths) { + std::shared_ptr values((MYSQL_BIND*) std::calloc(6, sizeof(MYSQL_BIND))); - values.get()[0].buffer_type = MYSQL_TYPE_STRING; - values.get()[0].buffer = (char*)passSec.hashPassword.c_str(); - values.get()[0].length = &(lengths->saltLength); + values.get()[0].buffer_type = MYSQL_TYPE_STRING; + values.get()[0].buffer = (char*)passSec.hashPassword.c_str(); + values.get()[0].length = &(lengths->saltLength); - values.get()[1].buffer_type = MYSQL_TYPE_LONG; - values.get()[1].buffer = (char*)&passSec.userId; + values.get()[1].buffer_type = MYSQL_TYPE_LONG; + values.get()[1].buffer = (char*)&passSec.userId; + return values; + } - return values; -} + std::shared_ptr UserRepository::valueBind(model::User& user, + std::tuple& us) { + std::shared_ptr values((MYSQL_BIND*) std::calloc(7, sizeof(MYSQL_BIND))); + constexpr auto strLen = 1024; -std::shared_ptr UserRepository::valueBind(model::User& user, - std::tuple& us) -{ - std::shared_ptr values((MYSQL_BIND*) std::calloc(7, sizeof(MYSQL_BIND))); - constexpr auto strLen = 1024; + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = (char*)&user.id; - values.get()[0].buffer_type = MYSQL_TYPE_LONG; - values.get()[0].buffer = (char*)&user.id; + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = (char*)std::get<0>(us); + values.get()[1].buffer_length = strLen; - values.get()[1].buffer_type = MYSQL_TYPE_STRING; - values.get()[1].buffer = (char*)std::get<0>(us); - values.get()[1].buffer_length = strLen; + values.get()[2].buffer_type = MYSQL_TYPE_STRING; + values.get()[2].buffer = (char*)std::get<1>(us); + values.get()[2].buffer_length = strLen; - values.get()[2].buffer_type = MYSQL_TYPE_STRING; - values.get()[2].buffer = (char*)std::get<1>(us); - values.get()[2].buffer_length = strLen; - - values.get()[3].buffer_type = MYSQL_TYPE_STRING; - values.get()[3].buffer = (char*)std::get<2>(us); - values.get()[3].buffer_length = strLen; + values.get()[3].buffer_type = MYSQL_TYPE_STRING; + values.get()[3].buffer = (char*)std::get<2>(us); + values.get()[3].buffer_length = strLen; - values.get()[4].buffer_type = MYSQL_TYPE_STRING; - values.get()[4].buffer = (char*)std::get<3>(us); - values.get()[4].buffer_length = strLen; + values.get()[4].buffer_type = MYSQL_TYPE_STRING; + values.get()[4].buffer = (char*)std::get<3>(us); + values.get()[4].buffer_length = strLen; - values.get()[5].buffer_type = MYSQL_TYPE_STRING; - values.get()[5].buffer = (char*)std::get<4>(us); - values.get()[5].buffer_length = strLen; + values.get()[5].buffer_type = MYSQL_TYPE_STRING; + values.get()[5].buffer = (char*)std::get<4>(us); + values.get()[5].buffer_length = strLen; - values.get()[6].buffer_type = MYSQL_TYPE_STRING; - values.get()[6].buffer = (char*)std::get<5>(us); - values.get()[6].buffer_length = strLen; + values.get()[6].buffer_type = MYSQL_TYPE_STRING; + values.get()[6].buffer = (char*)std::get<5>(us); + values.get()[6].buffer_length = strLen; - return values; -} + return values; + } -std::shared_ptr UserRepository::saltValueBind(model::PassSec& userSalt, char *salt) -{ - std::shared_ptr values((MYSQL_BIND*) std::calloc(3, sizeof(MYSQL_BIND))); - constexpr auto strLen = 1024; + std::shared_ptr UserRepository::saltValueBind(model::PassSec& userSalt, + char *salt) { + std::shared_ptr values((MYSQL_BIND*) std::calloc(3, sizeof(MYSQL_BIND))); + constexpr auto strLen = 1024; - values.get()[0].buffer_type = MYSQL_TYPE_LONG; - values.get()[0].buffer = (char*)&userSalt.id; + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = (char*)&userSalt.id; - values.get()[1].buffer_type = MYSQL_TYPE_STRING; - values.get()[1].buffer = (char*)salt; - values.get()[1].buffer_length = strLen; + values.get()[1].buffer_type = MYSQL_TYPE_STRING; + values.get()[1].buffer = (char*)salt; + values.get()[1].buffer_length = strLen; - values.get()[2].buffer_type = MYSQL_TYPE_LONG; - values.get()[2].buffer = (char*)&userSalt.userId; + values.get()[2].buffer_type = MYSQL_TYPE_LONG; + values.get()[2].buffer = (char*)&userSalt.userId; - return values; -} + return values; + } -std::shared_ptr UserRepository::fetchUserLengths(const model::User& user) -{ - auto userLen = std::make_shared(); - userLen->firstnameLength = user.firstname.size(); - userLen->lastnameLength = user.lastname.size(); - userLen->phoneLength = user.phone.size(); - userLen->emailLength = user.email.size(); - userLen->usernameLength = user.username.size(); - userLen->passwordLength = user.password.size(); + std::shared_ptr UserRepository::fetchUserLengths( + const model::User& user) { + auto userLen = std::make_shared(); + userLen->firstnameLength = user.firstname.size(); + userLen->lastnameLength = user.lastname.size(); + userLen->phoneLength = user.phone.size(); + userLen->emailLength = user.email.size(); + userLen->usernameLength = user.username.size(); + userLen->passwordLength = user.password.size(); - return userLen; -} + return userLen; + } -std::shared_ptr UserRepository::fetchSaltLengths(const model::PassSec& passSec) -{ - auto saltLen = std::make_shared(); - saltLen->saltLength = passSec.salt.size(); + std::shared_ptr UserRepository::fetchSaltLengths( + const model::PassSec& passSec) { + auto saltLen = std::make_shared(); + saltLen->saltLength = passSec.salt.size(); - return saltLen; -} + return saltLen; + } -std::tuple UserRepository::fetchUV() -{ - char firstname[1024]; - char lastname[1024]; - char phone[1024]; - char email[1024]; - char username[1024]; - char password[1024]; + std::tuple UserRepository::fetchUV() { + char firstname[1024]; + char lastname[1024]; + char phone[1024]; + char email[1024]; + char username[1024]; + char password[1024]; - return std::make_tuple(firstname, lastname, phone, email, username, password); -} + return std::make_tuple(firstname, lastname, phone, email, username, password); + } -model::User UserRepository::parseRecord(MYSQL_STMT *stmt) -{ - model::User user; - auto usv = fetchUV(); + model::User UserRepository::parseRecord(MYSQL_STMT *stmt) { + model::User user; + auto usv = fetchUV(); - auto bindedValues = valueBind(user, usv); - auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); - status = mysql_stmt_fetch(stmt); + auto bindedValues = valueBind(user, usv); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); + status = mysql_stmt_fetch(stmt); - user.firstname = std::get<0>(usv); - user.lastname = std::get<1>(usv); - user.email = std::get<2>(usv); - user.phone = std::get<3>(usv); - user.username = std::get<4>(usv); - user.password = std::get<5>(usv); + user.firstname = std::get<0>(usv); + user.lastname = std::get<1>(usv); + user.email = std::get<2>(usv); + user.phone = std::get<3>(usv); + user.username = std::get<4>(usv); + user.password = std::get<5>(usv); - return user; -} - -model::PassSec UserRepository::parseSaltRecord(MYSQL_STMT* stmt) -{ - model::PassSec userSalt; - char saltKey[1024]; - - auto bindedValues = saltValueBind(userSalt, saltKey); - auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); - status = mysql_stmt_fetch(stmt); - - userSalt.salt = saltKey; - - return userSalt; -} + return user; + } + + model::PassSec UserRepository::parseSaltRecord(MYSQL_STMT* stmt) { + model::PassSec userSalt; + char saltKey[1024]; + + auto bindedValues = saltValueBind(userSalt, saltKey); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); + status = mysql_stmt_fetch(stmt); + + userSalt.salt = saltKey; + + return userSalt; + } } diff --git a/src/database/YearRepository.cpp b/src/database/YearRepository.cpp index 5a49ea3..20824d3 100644 --- a/src/database/YearRepository.cpp +++ b/src/database/YearRepository.cpp @@ -7,335 +7,336 @@ #include namespace database { -YearRepository::YearRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { } + YearRepository::YearRepository(const model::BinaryPath& bConf) : BaseRepository(bConf) { } -std::vector YearRepository::retrieveRecords() -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - const std::string query = "SELECT * FROM Year"; + std::vector YearRepository::retrieveRecords() { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + const std::string query = "SELECT * FROM Year"; - mysql_stmt_prepare(stmt, query.c_str(), query.size()); - mysql_stmt_execute(stmt); + mysql_stmt_prepare(stmt, query.c_str(), query.size()); + mysql_stmt_execute(stmt); - auto yearRecs = parseRecords(stmt); + auto yearRecs = parseRecords(stmt); - mysql_stmt_close(stmt); - mysql_close(conn); + mysql_stmt_close(stmt); + mysql_close(conn); - return yearRecs; -} - -std::pair YearRepository::retrieveRecordWithSongCount(model::Year& year, type::YearFilter filter = type::YearFilter::id) -{ - std::cout << "retrieving year record with song count" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - qry << "SELECT yr.*, COUNT(*) AS SongCount FROM Year yr LEFT JOIN "; - qry << "Song sng ON yr.YearId=sng.YearId WHERE "; - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - switch (filter) { - case type::YearFilter::id: - qry << "sng.YearId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&year.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; + return yearRecs; } - qry << " GROUP BY yr.YearId LIMIT 1"; + std::pair YearRepository::retrieveRecordWithSongCount(model::Year& year, + type::YearFilter filter) { + std::cout << "retrieving year record with song count\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - const auto query = qry.str(); + qry << "SELECT yr.*, COUNT(*) AS SongCount FROM Year yr LEFT JOIN "; + qry << "Song sng ON yr.YearId=sng.YearId WHERE "; - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - auto yearWSC = parseRecordWithSongCount(stmt); + switch (filter) { + case type::YearFilter::id: + qry << "sng.YearId = ?"; - mysql_stmt_close(stmt); - mysql_close(conn); + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&year.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } - std::cout << "retrieved year record with song count" << std::endl; + qry << " GROUP BY yr.YearId LIMIT 1"; - return yearWSC; -} + const auto query = qry.str(); -model::Year YearRepository::retrieveRecord(model::Year& year, type::YearFilter filter) -{ - // TODO: switch to prepared statements - std::cout << "retrieving year record" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - qry << "SELECT yr.* FROM Year yr WHERE "; + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - switch (filter) { - case type::YearFilter::id: - qry << "yr.YearId = " << year.id; - break; - case type::YearFilter::year: - qry << "yr.Year = " << year.year; - break; - default: - break; + auto yearWSC = parseRecordWithSongCount(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "retrieved year record with song count\n"; + + return yearWSC; } - qry << " ORDER BY yr.YearId DESC LIMIT 1"; + model::Year YearRepository::retrieveRecord(model::Year& year, type::YearFilter filter) { + std::cout << "retrieving year record\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); + qry << "SELECT yr.* FROM Year yr WHERE "; - const auto query = qry.str(); - auto results = performMysqlQuery(conn, query); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(0)); - year = parseRecord(results); + switch (filter) { + case type::YearFilter::id: + qry << "yr.YearId = ?"; - mysql_close(conn); + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = reinterpret_cast(&year.id); + params[0].length = 0; + params[0].is_null = 0; + break; + case type::YearFilter::year: + qry << "yr.Year = ?"; - std::cout << "retrieved record" << std::endl; + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = reinterpret_cast(&year.year); + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } - return year; -} + qry << " ORDER BY yr.YearId DESC LIMIT 1"; -bool YearRepository::doesYearExist(const model::Year& year, type::YearFilter filter) -{ - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); + const auto query = qry.str(); - std::stringstream qry; - qry << "SELECT * FROM Year WHERE "; + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - MYSQL_BIND params[1]; - memset(params, 0, sizeof(params)); + year = parseRecord(stmt); - switch (filter) { - case type::YearFilter::id: - qry << "YearId = ?"; + mysql_stmt_close(stmt); + mysql_close(conn); - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&year.id; - params[0].length = 0; - params[0].is_null = 0; - break; - case type::YearFilter::year: - qry << "Year = ?"; + std::cout << "retrieved record\n"; - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&year.year; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; + return year; } - qry << " LIMIT 1"; - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + bool YearRepository::doesYearExist(const model::Year& year, type::YearFilter filter) { + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - std::cout << "the query has been performed" << std::endl; + std::stringstream qry; + qry << "SELECT * FROM Year WHERE "; - mysql_stmt_store_result(stmt); - auto rowCount = mysql_stmt_num_rows(stmt); + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); - mysql_stmt_close(stmt); - mysql_close(conn); + switch (filter) { + case type::YearFilter::id: + qry << "YearId = ?"; - return (rowCount > 0) ? true : false; -} + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&year.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case type::YearFilter::year: + qry << "Year = ?"; -void YearRepository::saveRecord(const model::Year& year) -{ - std::cout << "saving year record" << std::endl; + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&year.year; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } - auto conn = setupMysqlConnection(); - MYSQL_STMT *stmt = mysql_stmt_init(conn); + qry << " LIMIT 1"; - const std::string query("INSERT INTO Year(Year) VALUES(?)"); + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + std::cout << "the query has been performed\n"; - MYSQL_BIND params[1]; - memset(params, 0 , sizeof(params)); + mysql_stmt_store_result(stmt); + auto rowCount = mysql_stmt_num_rows(stmt); - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&year.year; - params[0].length = 0; - params[0].is_null = 0; + mysql_stmt_close(stmt); + mysql_close(conn); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); - - mysql_stmt_close(stmt); - mysql_close(conn); - - std::cout << "saved record" << std::endl; -} - -void YearRepository::deleteYear(const model::Year& year, type::YearFilter filter = type::YearFilter::id) -{ - std::cout << "deleting year record" << std::endl; - std::stringstream qry; - auto conn = setupMysqlConnection(); - auto stmt = mysql_stmt_init(conn); - - qry << "DELETE FROM Year WHERE "; - - MYSQL_BIND params[1]; - std::memset(params, 0, sizeof(params)); - - switch (filter) { - case type::YearFilter::id: - qry << "YearId = ?"; - - params[0].buffer_type = MYSQL_TYPE_LONG; - params[0].buffer = (char*)&year.id; - params[0].length = 0; - params[0].is_null = 0; - break; - default: - break; + return (rowCount > 0) ? true : false; } - const auto query = qry.str(); - auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - status = mysql_stmt_bind_param(stmt, params); - status = mysql_stmt_execute(stmt); + void YearRepository::saveRecord(const model::Year& year) { + std::cout << "saving year record\n"; - mysql_stmt_close(stmt); - mysql_close(conn); + auto conn = setupMysqlConnection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); - std::cout << "deleted year record" << std::endl; -} + const std::string query("INSERT INTO Year(Year) VALUES(?)"); -std::vector YearRepository::parseRecords(MYSQL_STMT *stmt) -{ - mysql_stmt_store_result(stmt); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - std::vector yearRecs; - yearRecs.reserve(mysql_stmt_num_rows(stmt)); + MYSQL_BIND params[1]; + memset(params, 0 , sizeof(params)); - if (mysql_stmt_field_count(stmt) == 0) { - std::cout << "field count is 0" << std::endl; - return yearRecs; + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&year.year; + params[0].length = 0; + params[0].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "saved record\n"; } - model::Year yearRec; - const auto valAmt = 2; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; + void YearRepository::deleteYear(const model::Year& year, + type::YearFilter filter) { + std::cout << "deleting year record\n"; + std::stringstream qry; + auto conn = setupMysqlConnection(); + auto stmt = mysql_stmt_init(conn); - auto res = mysql_stmt_result_metadata(stmt); + qry << "DELETE FROM Year WHERE "; - MYSQL_BIND val[valAmt]; - memset(val, 0, sizeof(val)); + MYSQL_BIND params[1]; + std::memset(params, 0, sizeof(params)); - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&yearRec.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; + switch (filter) { + case type::YearFilter::id: + qry << "YearId = ?"; - val[1].buffer_type = MYSQL_TYPE_LONG; - val[1].buffer = (char*)&yearRec.year; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&year.id; + params[0].length = 0; + params[0].is_null = 0; + break; + default: + break; + } - for (auto status = mysql_stmt_bind_result(stmt, val); status == 0;) { - std::cout << "fetching statement result" << std::endl; + const auto query = qry.str(); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "deleted year record\n"; + } + + + std::vector YearRepository::parseRecords(MYSQL_STMT *stmt) { + mysql_stmt_store_result(stmt); + const auto rowCount = mysql_stmt_num_rows(stmt); + + std::vector yearRecs; + yearRecs.reserve(rowCount); + + if (mysql_stmt_field_count(stmt) == 0) { + std::cout << "field count is 0\n"; + return yearRecs; + } + + const auto valAmt = 2; + unsigned long len[valAmt]; + my_bool nullRes[valAmt]; + + for (auto status = 0; status == 0; status = mysql_stmt_next_result(stmt)) { + if (mysql_stmt_field_count(stmt) > 0) { + model::Year yearRec; + + std::cout << "fetching statement result\n"; + auto bindedValues = valueBind(yearRec); + status = mysql_stmt_bind_result(stmt, bindedValues.get()); + status = mysql_stmt_fetch(stmt); + + if (status == 1 || status == MYSQL_NO_DATA) break; + + yearRecs.push_back(yearRec); + } + std::cout << "fetching next result\n"; + } + + return yearRecs; + } + + std::pair YearRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) { + std::cout << "parsing year record\n"; + mysql_stmt_store_result(stmt); + + model::Year year; + int songCount = 0; + + if (mysql_stmt_num_rows(stmt) == 0) { + std::cout << "no results\n"; + return std::make_pair(year, songCount); + } + + auto val = valueBindWithSongCount(year, songCount); + + auto status = mysql_stmt_bind_result(stmt, val.get()); + status = mysql_stmt_fetch(stmt); + + std::cout << "parsed year record from the database\n"; + + return std::make_pair(year, songCount); + } + + + std::shared_ptr YearRepository::valueBind(model::Year& year) { + constexpr auto valueCount = 2; + std::shared_ptr values((MYSQL_BIND*) + std::calloc(valueCount, sizeof(MYSQL_BIND))); + + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = reinterpret_cast(&year.id); + + values.get()[1].buffer_type = MYSQL_TYPE_LONG; + values.get()[1].buffer = reinterpret_cast(&year.year); + + return values; + } + + std::shared_ptr YearRepository::valueBindWithSongCount(model::Year& year, + int& songCount) { + constexpr auto valueCount = 3; + std::shared_ptr values((MYSQL_BIND*) + std::calloc(valueCount, sizeof(MYSQL_BIND))); + + values.get()[0].buffer_type = MYSQL_TYPE_LONG; + values.get()[0].buffer = reinterpret_cast(&year.id); + + values.get()[1].buffer_type = MYSQL_TYPE_LONG; + values.get()[1].buffer = reinterpret_cast(&year.year); + + values.get()[2].buffer_type = MYSQL_TYPE_LONG; + values.get()[2].buffer = reinterpret_cast(&songCount); + + return values; + } + + + model::Year YearRepository::parseRecord(MYSQL_STMT *stmt) { + std::cout << "parsing year record\n"; + mysql_stmt_store_result(stmt); + + model::Year year; + auto bindedValues = valueBind(year); + auto status = mysql_stmt_bind_result(stmt, bindedValues.get()); status = mysql_stmt_fetch(stmt); - if (status == 0) { - yearRecs.push_back(std::move(yearRec)); - } + std::cout << "done parsing year record\n"; + + return year; } - - return yearRecs; -} - -std::pair YearRepository::parseRecordWithSongCount(MYSQL_STMT *stmt) -{ - std::cout << "parsing year record" << std::endl; - mysql_stmt_store_result(stmt); - - constexpr auto valAmt = 3; - unsigned long len[valAmt]; - my_bool nullRes[valAmt]; - - model::Year year; - int songCount = 0; - - if (mysql_stmt_num_rows(stmt) == 0) { - std::cout << "no results" << std::endl; - return std::make_pair(year, songCount); - } - - MYSQL_BIND val[valAmt]; - std::memset(val, 0, sizeof(val)); - - val[0].buffer_type = MYSQL_TYPE_LONG; - val[0].buffer = (char*)&year.id; - val[0].length = &len[0]; - val[0].is_null = &nullRes[0]; - - val[1].buffer_type = MYSQL_TYPE_LONG; - val[1].buffer = (char*)&year.year; - val[1].length = &len[1]; - val[1].is_null = &nullRes[1]; - - val[2].buffer_type = MYSQL_TYPE_LONG; - val[2].buffer = (char*)&songCount; - val[2].length = &len[2]; - val[2].is_null = &nullRes[2]; - - mysql_stmt_bind_result(stmt, val); - mysql_stmt_fetch(stmt); - - std::cout << "parsed year record from the database" << std::endl; - - return std::make_pair(year, songCount); -} - -model::Year YearRepository::parseRecord(MYSQL_RES *results) -{ - std::cout << "parsing year record" << std::endl; - model::Year year; - - auto fieldNum = mysql_num_fields(results); - auto row = mysql_fetch_row(results); - - for (auto i = 0; i != fieldNum; ++i) { - const std::string field(mysql_fetch_field(results)->name); - - if (field.compare("YearId") == 0) { - year.id= std::stoi(row[i]); - } - if (field.compare("Year") == 0) { - year.year = std::stoi(row[i]); - } - } - - std::cout << "parse year record" << std::endl; - - return year; -} -model::Year YearRepository::parseRecord(MYSQL_STMT *stmt) -{ - // TODO: imeplement this - // I really thought that I had already done this - - model::Year year; - - return year; -} } diff --git a/src/dto/conversion/DtoConversions.cpp b/src/dto/conversion/DtoConversions.cpp index cac2230..8c57822 100644 --- a/src/dto/conversion/DtoConversions.cpp +++ b/src/dto/conversion/DtoConversions.cpp @@ -2,7 +2,7 @@ namespace dto { namespace conversion { LoginResultDto::ObjectWrapper DtoConversions::toLoginResultDto(const model::User& user, - const model::Token& token) { + const model::Token& token) { auto logRes = dto::LoginResultDto::createShared(); logRes->username = user.username.c_str(); logRes->token = token.accessToken.c_str(); diff --git a/src/manager/AlbumManager.cpp b/src/manager/AlbumManager.cpp index 2ea1951..12627a3 100644 --- a/src/manager/AlbumManager.cpp +++ b/src/manager/AlbumManager.cpp @@ -7,72 +7,66 @@ #include "type/AlbumFilter.h" namespace manager { -AlbumManager::AlbumManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } + AlbumManager::AlbumManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -model::Album AlbumManager::retrieveAlbum(model::Album& album) -{ - database::AlbumRepository albRepo(m_bConf); - album = std::move(albRepo.retrieveRecord(album, type::AlbumFilter::title)); + model::Album AlbumManager::retrieveAlbum(model::Album& album) { + database::AlbumRepository albRepo(m_bConf); + album = std::move(albRepo.retrieveRecord(album, type::AlbumFilter::title)); - return album; -} + return album; + } -model::Album AlbumManager::saveAlbum(const model::Song& song) -{ - model::Album album(song); + model::Album AlbumManager::saveAlbum(const model::Song& song) { + model::Album album(song); - database::AlbumRepository albRepo(m_bConf); - // TODO: check for existence with the title and the artist - if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) { - albRepo.saveAlbum(album); - } else { - std::cout << "album record already exists in the database" << std::endl; + database::AlbumRepository albRepo(m_bConf); + // TODO: check for existence with the title and the artist + if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) { + albRepo.saveAlbum(album); + } else { + std::cout << "album record already exists in the database\n"; + } + + return album; } - return album; -} + void AlbumManager::deleteAlbum(const model::Song& song) { + model::Album album(song); - -void AlbumManager::deleteAlbum(const model::Song& song) -{ - model::Album album(song); - - database::AlbumRepository albRepo(m_bConf); - auto albWSC = albRepo.retrieveRecordWithSongCount(album, type::AlbumFilter::id); + database::AlbumRepository albRepo(m_bConf); + auto albWSC = albRepo.retrieveRecordWithSongCount(album, type::AlbumFilter::id); - if (albWSC.second > 1) { - std::cout << "album still contain songs related to it, will not delete" << std::endl; - return; + if (albWSC.second > 1) { + std::cout << "album still contain songs related to it, will not delete\n"; + return; + } + + std::cout << "safe to delete the album record\n"; + albRepo.deleteAlbum(album, type::AlbumFilter::id); } - std::cout << "safe to delete the album record" << std::endl; - albRepo.deleteAlbum(album, type::AlbumFilter::id); -} + void AlbumManager::updateAlbum(model::Song& updatedSong, + const model::Song& currSong) { + model::Album album(updatedSong); -void AlbumManager::updateAlbum(model::Song& updatedSong, - const model::Song& currSong) -{ - model::Album album(updatedSong); + database::AlbumRepository albRepo(m_bConf); + if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) { + std::cout << "album record does not exist\n"; + albRepo.saveAlbum(album); + } else { + std::cout << "album record already exists\n"; + } - database::AlbumRepository albRepo(m_bConf); - if (!albRepo.doesAlbumExists(album, type::AlbumFilter::title)) { - std::cout << "album record does not exist" << std::endl; - albRepo.saveAlbum(album); - } else { - std::cout << "album record already exists" << std::endl; + album = albRepo.retrieveRecord(album, type::AlbumFilter::title); + updatedSong.albumId = album.id; } - album = albRepo.retrieveRecord(album, type::AlbumFilter::title); - updatedSong.albumId = album.id; -} - -void AlbumManager::printAlbum(const model::Album& album) -{ - std::cout << "\nalbum record" << std::endl; - std::cout << "id: " << album.id << std::endl; - std::cout << "title: " << album.title << std::endl; - std::cout << "year: " << album.year << std::endl; -} + void AlbumManager::printAlbum(const model::Album& album) { + std::cout << "\nalbum record\n"; + std::cout << "id: " << album.id << "\n"; + std::cout << "title: " << album.title << "\n"; + std::cout << "year: " << album.year << "\n"; + } } diff --git a/src/manager/ArtistManager.cpp b/src/manager/ArtistManager.cpp index c5aa6d0..d5c7354 100644 --- a/src/manager/ArtistManager.cpp +++ b/src/manager/ArtistManager.cpp @@ -7,75 +7,70 @@ namespace manager { -ArtistManager::ArtistManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } + ArtistManager::ArtistManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -model::Artist ArtistManager::retrieveArtist(model::Artist& artist) -{ - std::cout << "retrieving artist record" << std::endl; - database::ArtistRepository artRepo(m_bConf); - std::cout << "initialized artist repo" << std::endl; - std::cout << artist.artist << std::endl; - artist = artRepo.retrieveRecord(artist, type::ArtistFilter::artist); + model::Artist ArtistManager::retrieveArtist(model::Artist& artist) { + std::cout << "retrieving artist record\n"; + database::ArtistRepository artRepo(m_bConf); + std::cout << "initialized artist repo\n"; + std::cout << artist.artist << "\n"; + artist = artRepo.retrieveRecord(artist, type::ArtistFilter::artist); - return artist; -} - -model::Artist ArtistManager::saveArtist(const model::Song& song) -{ - model::Artist artist; - artist.artist = song.artist; - - database::ArtistRepository artRepo(m_bConf); - if (!artRepo.doesArtistExist(artist, type::ArtistFilter::artist)) { - artRepo.saveRecord(artist); - } else { - std::cout << "artist already exists" << std::endl; + return artist; } - return artist; -} + model::Artist ArtistManager::saveArtist(const model::Song& song) { + model::Artist artist; + artist.artist = song.artist; + + database::ArtistRepository artRepo(m_bConf); + if (!artRepo.doesArtistExist(artist, type::ArtistFilter::artist)) { + artRepo.saveRecord(artist); + } else { + std::cout << "artist already exists\n"; + } + + return artist; + } -void ArtistManager::deleteArtist(const model::Song& song) -{ - model::Artist artist(song); + void ArtistManager::deleteArtist(const model::Song& song) { + model::Artist artist(song); - database::ArtistRepository artRepo(m_bConf); - auto artWSC = artRepo.retrieveRecordWithSongCount(artist, type::ArtistFilter::id); + database::ArtistRepository artRepo(m_bConf); + auto artWSC = artRepo.retrieveRecordWithSongCount(artist, type::ArtistFilter::id); - if (artWSC.second > 1) { - std::cout << "artist still contain songs related to it"; - std::cout << ", not delete" << std::endl; - return; + if (artWSC.second > 1) { + std::cout << "artist still contain songs related to it"; + std::cout << ", not delete\n"; + return; + } + + std::cout << "safe to delete the artist record\n"; + artRepo.deleteArtist(artist, type::ArtistFilter::id); } - std::cout << "safe to delete the artist record" << std::endl; - artRepo.deleteArtist(artist, type::ArtistFilter::id); -} + void ArtistManager::updateArtist(model::Song& updatedSong, + const model::Song& currSong) { + model::Artist artist; + artist.artist = updatedSong.artist; -void ArtistManager::updateArtist(model::Song& updatedSong, - const model::Song& currSong) -{ - model::Artist artist; - artist.artist = updatedSong.artist; + database::ArtistRepository artRepo(m_bConf); + if (!artRepo.doesArtistExist(artist, type::ArtistFilter::artist)) { + std::cout << "artist record does not exist\n"; + artRepo.saveRecord(artist); + } else { + std::cout << "artist record already exists\n"; + } - database::ArtistRepository artRepo(m_bConf); - if (!artRepo.doesArtistExist(artist, type::ArtistFilter::artist)) { - std::cout << "artist record does not exist" << std::endl; - artRepo.saveRecord(artist); - } else { - std::cout << "artist record already exists" << std::endl; + artist = artRepo.retrieveRecord(artist, type::ArtistFilter::artist); + updatedSong.artistId = artist.id; } - artist = artRepo.retrieveRecord(artist, type::ArtistFilter::artist); - updatedSong.artistId = artist.id; -} - -void ArtistManager::printArtist(const model::Artist& artist) -{ - std::cout << "\nartist record" << std::endl; - std::cout << "id: " << artist.id << std::endl; - std::cout << "artist: " << artist.artist << std::endl; -} + void ArtistManager::printArtist(const model::Artist& artist) { + std::cout << "\nartist record" << "\n"; + std::cout << "id: " << artist.id << "\n"; + std::cout << "artist: " << artist.artist << "\n"; + } } diff --git a/src/manager/CoverArtManager.cpp b/src/manager/CoverArtManager.cpp index 5a96cb7..c3386ba 100644 --- a/src/manager/CoverArtManager.cpp +++ b/src/manager/CoverArtManager.cpp @@ -12,129 +12,124 @@ namespace fs = std::filesystem; namespace manager { -CoverArtManager::CoverArtManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } + CoverArtManager::CoverArtManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -model::Cover CoverArtManager::saveCover(const model::Song& song) -{ - auto pathConfigContent = DirectoryManager::pathConfigContent(m_bConf); - auto stockCoverPath = DirectoryManager::configPath(m_bConf); - stockCoverPath.append("/CoverArt.png"); + model::Cover CoverArtManager::saveCover(const model::Song& song) { + auto pathConfigContent = DirectoryManager::pathConfigContent(m_bConf); + auto stockCoverPath = DirectoryManager::configPath(m_bConf); + stockCoverPath.append("/CoverArt.png"); - utility::MetadataRetriever meta; - model::Cover cov; - cov.songTitle = song.title; + utility::MetadataRetriever meta; + model::Cover cov; + cov.songTitle = song.title; - if (meta.songContainsCoverArt(song)) { - cov.imagePath = createImagePath(song); - cov = meta.applyCoverArt(song, cov); - } else { - cov.imagePath = pathConfigContent["cover_root_path"].get(); - cov = meta.applyStockCoverArt(song, cov, stockCoverPath); + if (meta.songContainsCoverArt(song)) { + cov.imagePath = createImagePath(song); + cov = meta.applyCoverArt(song, cov); + } else { + cov.imagePath = pathConfigContent["cover_root_path"].get(); + cov = meta.applyStockCoverArt(song, cov, stockCoverPath); + } + + database::CoverArtRepository covRepo(m_bConf); + if (!covRepo.doesCoverArtExist(cov, type::CoverFilter::songTitle)) { + std::cout << "saving image record to the database\n"; + covRepo.saveRecord(cov); + } else { + std::cout << "cover art record already exists\n"; + } + + std::cout << "retrieving image record from database\n"; + cov = covRepo.retrieveRecord(cov, type::CoverFilter::songTitle); + + return cov; } - database::CoverArtRepository covRepo(m_bConf); - if (!covRepo.doesCoverArtExist(cov, type::CoverFilter::songTitle)) { - std::cout << "saving image record to the database" << std::endl; - covRepo.saveRecord(cov); - } else { - std::cout << "cover art record already exists" << std::endl; + + std::pair CoverArtManager::defaultCover( + const model::Cover& cover) { + + auto paths = DirectoryManager::pathConfigContent(m_bConf); + const auto coverArtPath = + paths[DirectoryManager::retrievePathType( + type::PathType::coverArt)].get(); + + auto stockCoverArtPath = coverArtPath; + stockCoverArtPath.append("CoverArt.png"); + + if (stockCoverArtPath.compare(cover.imagePath) == 0) { + return std::make_pair(true, coverArtPath); + } else { + return std::make_pair(false, coverArtPath); + } } - std::cout << "retrieving image record from database" << std::endl; - cov = covRepo.retrieveRecord(cov, type::CoverFilter::songTitle); - return cov; -} + void CoverArtManager::deleteCover(const model::Song& song) { + database::CoverArtRepository covRepo(m_bConf); + model::Cover cov(song.coverArtId); -std::pair CoverArtManager::defaultCover( - const model::Cover& cover) { + cov = covRepo.retrieveRecord(cov, type::CoverFilter::id); + covRepo.deleteRecord(cov); - auto paths = DirectoryManager::pathConfigContent(m_bConf); - const auto coverArtPath = - paths[DirectoryManager::retrievePathType( - type::PathType::coverArt)].get(); + auto result = defaultCover(cov); + if (!result.first) { + fs::remove(cov.imagePath); + std::cout << "deleting cover art\n"; + const auto coverArtPath = result.second; + } else { + std::cout << "song contains the stock cover art, will not delete\n"; + return; + } - auto stockCoverArtPath = coverArtPath; - stockCoverArtPath.append("CoverArt.png"); - - if (stockCoverArtPath.compare(cover.imagePath) == 0) { - return std::make_pair(true, coverArtPath); - } else { - return std::make_pair(false, coverArtPath); - } -} - - -void CoverArtManager::deleteCover(const model::Song& song) -{ - database::CoverArtRepository covRepo(m_bConf); - - model::Cover cov(song.coverArtId); - - cov = covRepo.retrieveRecord(cov, type::CoverFilter::id); - covRepo.deleteRecord(cov); - - auto result = defaultCover(cov); - if (!result.first) { - fs::remove(cov.imagePath); - std::cout << "deleting cover art" << std::endl; - const auto coverArtPath = result.second; - } else { - std::cout << "song contains the stock cover art, will not delete" << std::endl; - return; + DirectoryManager::deleteDirectories(song, result.second); } - DirectoryManager::deleteDirectories(song, result.second); -} + void CoverArtManager::updateCover(const model::Song& updatedSong, + const model::Song& currSong) { + database::CoverArtRepository covRepo(m_bConf); + model::Cover cover(updatedSong.coverArtId); + cover = covRepo.retrieveRecord(cover, type::CoverFilter::id); -void CoverArtManager::updateCover(const model::Song& updatedSong, - const model::Song& currSong) -{ - database::CoverArtRepository covRepo(m_bConf); - model::Cover cover(updatedSong.coverArtId); - cover = covRepo.retrieveRecord(cover, type::CoverFilter::id); + auto result = defaultCover(cover); - auto result = defaultCover(cover); + if (result.first) { + return; + } - if (result.first) { - return; + auto imagePath = createImagePath(updatedSong); + + fs::copy(cover.imagePath, imagePath); + fs::remove(cover.imagePath); + + DirectoryManager::deleteDirectories(currSong, result.second); } - auto imagePath = createImagePath(updatedSong); + void CoverArtManager::updateCoverRecord(const model::Song& updatedSong) { + model::Cover updatedCover(updatedSong); + auto updatedImagePath = createImagePath(updatedSong); - fs::copy(cover.imagePath, imagePath); - fs::remove(cover.imagePath); - - DirectoryManager::deleteDirectories(currSong, result.second); -} - -void CoverArtManager::updateCoverRecord(const model::Song& updatedSong) -{ - model::Cover updatedCover(updatedSong); - auto updatedImagePath = createImagePath(updatedSong); - - database::CoverArtRepository covRepo(m_bConf); - covRepo.updateRecord(updatedCover); -} - - -std::string CoverArtManager::createImagePath(const model::Song& song) -{ - auto imagePath = DirectoryManager::createDirectoryProcess( - song, m_bConf, type::PathType::coverArt); - - if (song.track != 0) { - imagePath.append("track"); - auto trackNum = (song.track > 9) ? - std::to_string(song.track) : "0" + std::to_string(song.track); - imagePath.append(trackNum); - } else { - imagePath.append(song.title); + database::CoverArtRepository covRepo(m_bConf); + covRepo.updateRecord(updatedCover); } - imagePath.append(".png"); - return imagePath; -} + + std::string CoverArtManager::createImagePath(const model::Song& song) { + auto imagePath = DirectoryManager::createDirectoryProcess( + song, m_bConf, type::PathType::coverArt); + + if (song.track != 0) { + imagePath.append("track"); + auto trackNum = (song.track > 9) ? + std::to_string(song.track) : "0" + std::to_string(song.track); + imagePath.append(trackNum); + } else { + imagePath.append(song.title); + } + imagePath.append(".png"); + + return imagePath; + } } diff --git a/src/manager/DirectoryManager.cpp b/src/manager/DirectoryManager.cpp index f7f89b3..f34282b 100644 --- a/src/manager/DirectoryManager.cpp +++ b/src/manager/DirectoryManager.cpp @@ -8,188 +8,176 @@ namespace fs = std::filesystem; namespace manager { -std::string DirectoryManager::createDirectoryProcess(model::Song song, const std::string& rootPath) -{ - auto currPath = fs::path(rootPath); + std::string DirectoryManager::createDirectoryProcess(model::Song song, + const std::string& rootPath) { + auto currPath = fs::path(rootPath); - if (fs::exists(currPath)) { - std::cout << "path exists" << std::endl; - } else { - std::cout << "creating path" << std::endl; - fs::create_directory(currPath); + if (fs::exists(currPath)) { + std::cout << "path exists\n"; + } else { + std::cout << "creating path\n"; + fs::create_directory(currPath); + } + + auto artPath = fs::path(currPath.string() + song.artist); + if (fs::exists(artPath)) { + std::cout << "artist path exists\n"; + } else { + std::cout << "creating artist path\n"; + fs::create_directory(artPath); + } + + auto albPath = fs::path(artPath.string() + "/" + song.album); + if (fs::exists(albPath)) { + std::cout << "album path exists\n"; + } else { + std::cout << "creating album path\n"; + fs::create_directory(albPath); + } + + return albPath.string() + "/"; } - auto artPath = fs::path(currPath.string() + song.artist); - if (fs::exists(artPath)) { - std::cout << "artist path exists" << std::endl; - } else { - std::cout << "creating artist path" << std::endl; - fs::create_directory(artPath); + std::string DirectoryManager::createDirectoryProcess(const model::Song& song, + const model::BinaryPath& bConf, type::PathType pType) { + auto path = pathConfigContent(bConf)[retrievePathType(pType)]; + auto rootPath = path.get(); + auto currPath = fs::path(rootPath); + + if (fs::exists(currPath)) { + std::cout << "path exists\n"; + } else { + std::cout << "creating root music path\n"; + fs::create_directory(currPath); + } + + auto artPath = fs::path(currPath.string() + song.albumArtist); + if (fs::exists(artPath)) { + std::cout << "artist path exists\n"; + } else { + std::cout << "creating artist path\n"; + fs::create_directory(artPath); + } + + auto albPath = fs::path(artPath.string() + "/" + song.album); + if (fs::exists(albPath)) { + std::cout << "album path exists\n"; + } else { + std::cout << "creating album path\n"; + fs::create_directory(albPath); + } + + return albPath.string() + "/"; } - auto albPath = fs::path(artPath.string() + "/" + song.album); - if (fs::exists(albPath)) { - std::cout << "album path exists" << std::endl; - } else { - std::cout << "creating album path" << std::endl; - fs::create_directory(albPath); + std::string DirectoryManager::configPath(std::string_view path) { + return fs::canonical(path).parent_path().string(); } - return albPath.string() + "/"; -} - -std::string DirectoryManager::createDirectoryProcess(const model::Song& song, - const model::BinaryPath& bConf, type::PathType pType) -{ - auto path = pathConfigContent(bConf)[retrievePathType(pType)]; - auto rootPath = path.get(); - auto currPath = fs::path(rootPath); - - if (fs::exists(currPath)) { - std::cout << "path exists" << std::endl; - } else { - std::cout << "creating root music path" << std::endl; - fs::create_directory(currPath); + std::string DirectoryManager::configPath(const model::BinaryPath& bConf) { + return fs::canonical(bConf.path).parent_path().string(); } - auto artPath = fs::path(currPath.string() + song.albumArtist); - if (fs::exists(artPath)) { - std::cout << "artist path exists" << std::endl; - } else { - std::cout << "creating artist path" << std::endl; - fs::create_directory(artPath); + std::string DirectoryManager::contentOfPath(const std::string& path) { + std::fstream a(path, std::ios::in); + std::stringstream s; + s << a.rdbuf(); + a.close(); + + return s.str(); } - auto albPath = fs::path(artPath.string() + "/" + song.album); - if (fs::exists(albPath)) { - std::cout << "album path exists" << std::endl; - } else { - std::cout << "creating album path" << std::endl; - fs::create_directory(albPath); + std::string DirectoryManager::retrievePathType(type::PathType pType) { + std::string path; + switch (pType) { + case type::PathType::music: + path = "root_music_path"; + break; + case type::PathType::archive: + path = "archive_root_path"; + break; + case type::PathType::temp: + path = "temp_root_path"; + break; + case type::PathType::coverArt: + path = "cover_root_path"; + break; + default: + break; + } + + return path; } - return albPath.string() + "/"; -} -std::string DirectoryManager::configPath(std::string_view path) -{ - return fs::canonical(path).parent_path().string(); -} + nlohmann::json DirectoryManager::credentialConfigContent(const model::BinaryPath& bConf) { + auto path = configPath(bConf); + path.append("/authcredentials.json"); -std::string DirectoryManager::configPath(const model::BinaryPath& bConf) -{ - return fs::canonical(bConf.path).parent_path().string(); -} - -std::string DirectoryManager::contentOfPath(const std::string& path) -{ - std::fstream a(path, std::ios::in); - std::stringstream s; - s << a.rdbuf(); - a.close(); - - return s.str(); -} - -std::string DirectoryManager::retrievePathType(type::PathType pType) -{ - std::string path; - switch (pType) { - case type::PathType::music: - path = "root_music_path"; - break; - case type::PathType::archive: - path = "archive_root_path"; - break; - case type::PathType::temp: - path = "temp_root_path"; - break; - case type::PathType::coverArt: - path = "cover_root_path"; - break; - default: - break; + return nlohmann::json::parse(contentOfPath(path)); } - return path; -} + nlohmann::json DirectoryManager::databaseConfigContent(const model::BinaryPath& bConf) { + auto path = configPath(bConf); + path.append("/database.json"); + + return nlohmann::json::parse(contentOfPath(path)); + } + + nlohmann::json DirectoryManager::pathConfigContent(const model::BinaryPath& bConf) { + auto path = configPath(bConf); + path.append("/paths.json"); + + return nlohmann::json::parse(contentOfPath(path)); + } -nlohmann::json DirectoryManager::credentialConfigContent(const model::BinaryPath& bConf) -{ - auto path = configPath(bConf); - path.append("/authcredentials.json"); + void DirectoryManager::deleteDirectories(model::Song song, const std::string& rootPath) { + std::cout << "checking for empty directories to delete\n"; + const std::string art(rootPath + std::string("/") + song.albumArtist); + const std::string alb(art + "/" + song.album); - return nlohmann::json::parse(contentOfPath(path)); -} - -nlohmann::json DirectoryManager::databaseConfigContent(const model::BinaryPath& bConf) -{ - auto path = configPath(bConf); - path.append("/database.json"); - - return nlohmann::json::parse(contentOfPath(path)); -} - -nlohmann::json DirectoryManager::pathConfigContent(const model::BinaryPath& bConf) -{ - auto path = configPath(bConf); - path.append("/paths.json"); - - return nlohmann::json::parse(contentOfPath(path)); -} - - -void DirectoryManager::deleteDirectories(model::Song song, const std::string& rootPath) -{ - std::cout << "checking for empty directories to delete" << std::endl; - const std::string art(rootPath + std::string("/") + song.albumArtist); - const std::string alb(art + "/" + song.album); - - auto albPath = fs::path(alb); + auto albPath = fs::path(alb); - if (!fs::exists(albPath)) { - std::cout << "directory does not exists" << std::endl; - } else if (fs::is_empty(albPath)) { - fs::remove(albPath); - } + if (!fs::exists(albPath)) { + std::cout << "directory does not exists\n"; + } else if (fs::is_empty(albPath)) { + fs::remove(albPath); + } - auto artPath = fs::path(art); + auto artPath = fs::path(art); - if (!fs::exists(artPath)) { - std::cout << "directory does not exists" << std::endl; - return; - } else if (fs::is_empty(artPath)) { - fs::remove(artPath); + if (!fs::exists(artPath)) { + std::cout << "directory does not exists\n"; + return; + } else if (fs::is_empty(artPath)) { + fs::remove(artPath); + } + + std::cout << "deleted empty directory or directories\n"; } - std::cout << "deleted empty directory or directories" << std::endl; -} - -void DirectoryManager::deleteCoverArtFile(const std::string& covPath, - const std::string& stockCoverPath) -{ - if (covPath.compare(stockCoverPath) == 0) { - std::cout << "cover has stock cover art, will not deleted" << std::endl; - } else { - std::cout << "deleting song path" << std::endl; - auto cov = fs::path(covPath); - fs::remove(cov); - } -} - -void DirectoryManager::deleteSong(const model::Song song) -{ - std::cout << "deleting song" << std::endl; - auto songPath = fs::path(song.songPath); - - if (!fs::exists(songPath)) { - std::cout << "song does not exists" << std::endl; - return; + void DirectoryManager::deleteCoverArtFile(const std::string& covPath, + const std::string& stockCoverPath) { + if (covPath.compare(stockCoverPath) == 0) { + std::cout << "cover has stock cover art, will not deleted\n"; + } else { + std::cout << "deleting song path\n"; + auto cov = fs::path(covPath); + fs::remove(cov); + } } - fs::remove(songPath); - std::cout << "deleted song" << std::endl; -} + void DirectoryManager::deleteSong(const model::Song song) { + std::cout << "deleting song\n"; + auto songPath = fs::path(song.songPath); + if (!fs::exists(songPath)) { + std::cout << "song does not exists\n"; + return; + } + + fs::remove(songPath); + std::cout << "deleted song" << "\n"; + } } diff --git a/src/manager/GenreManager.cpp b/src/manager/GenreManager.cpp index e322c57..af98b6e 100644 --- a/src/manager/GenreManager.cpp +++ b/src/manager/GenreManager.cpp @@ -6,72 +6,67 @@ #include "type/GenreFilter.h" namespace manager { -GenreManager::GenreManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } + GenreManager::GenreManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -model::Genre GenreManager::retrieveGenre(model::Genre& genre) -{ - database::GenreRepository gnrRepo(m_bConf); - genre = gnrRepo.retrieveRecord(genre, type::GenreFilter::category); + model::Genre GenreManager::retrieveGenre(model::Genre& genre) { + database::GenreRepository gnrRepo(m_bConf); + genre = gnrRepo.retrieveRecord(genre, type::GenreFilter::category); - return genre; -} - -model::Genre GenreManager::saveGenre(const model::Song& song) -{ - model::Genre genre; - genre.category = song.genre; - - database::GenreRepository gnrRepo(m_bConf); - if (!gnrRepo.doesGenreExist(genre, type::GenreFilter::category)) { - gnrRepo.saveRecord(genre); - } else { - std::cout << "genre record already exists" << std::endl; + return genre; } - return genre; -} + model::Genre GenreManager::saveGenre(const model::Song& song) { + model::Genre genre; + genre.category = song.genre; + + database::GenreRepository gnrRepo(m_bConf); + if (!gnrRepo.doesGenreExist(genre, type::GenreFilter::category)) { + gnrRepo.saveRecord(genre); + } else { + std::cout << "genre record already exists\n"; + } - -void GenreManager::deleteGenre(const model::Song& song) -{ - model::Genre genre(song); - - database::GenreRepository gnrRepo(m_bConf); - auto gnrWSC = gnrRepo.retrieveRecordWithSongCount(genre, type::GenreFilter::id); - - if (gnrWSC.second > 1) { - std::cout << "genre still contain songs related to it"; - std::cout << ", will not delete" << std::endl; - return; + return genre; } - std::cout << "safe to delete the genre record" << std::endl; - gnrRepo.deleteRecord(genre, type::GenreFilter::id); -} -void GenreManager::updateGenre(model::Song& updatedSong, - const model::Song& currSong) -{ - model::Genre genre; - genre.category = updatedSong.genre; + void GenreManager::deleteGenre(const model::Song& song) { + model::Genre genre(song); - database::GenreRepository gnrRepo(m_bConf); - if (!gnrRepo.doesGenreExist(genre, type::GenreFilter::category)) { - std::cout << "genre record does not exist" << std::endl; - gnrRepo.saveRecord(genre); - } else { - std::cout << "genre record already exists" << std::endl; + database::GenreRepository gnrRepo(m_bConf); + auto gnrWSC = gnrRepo.retrieveRecordWithSongCount(genre, type::GenreFilter::id); + + if (gnrWSC.second > 1) { + std::cout << "genre still contain songs related to it"; + std::cout << ", will not delete\n"; + return; + } + + std::cout << "safe to delete the genre record\n"; + gnrRepo.deleteRecord(genre, type::GenreFilter::id); } - genre = gnrRepo.retrieveRecord(genre, type::GenreFilter::category); - updatedSong.genreId = genre.id; -} + void GenreManager::updateGenre(model::Song& updatedSong, + const model::Song& currSong) { + model::Genre genre; + genre.category = updatedSong.genre; -void GenreManager::printGenre(const model::Genre& genre) -{ - std::cout << "genre record" << std::endl; - std::cout << "id: " << genre.id << std::endl; - std::cout << "category: " << genre.category << std::endl; -} + database::GenreRepository gnrRepo(m_bConf); + if (!gnrRepo.doesGenreExist(genre, type::GenreFilter::category)) { + std::cout << "genre record does not exist\n"; + gnrRepo.saveRecord(genre); + } else { + std::cout << "genre record already exists\n"; + } + + genre = gnrRepo.retrieveRecord(genre, type::GenreFilter::category); + updatedSong.genreId = genre.id; + } + + void GenreManager::printGenre(const model::Genre& genre) { + std::cout << "genre record\n"; + std::cout << "id: " << genre.id << "\n"; + std::cout << "category: " << genre.category << "\n"; + } } diff --git a/src/manager/SongManager.cpp b/src/manager/SongManager.cpp index 27182c0..5ea7ac7 100644 --- a/src/manager/SongManager.cpp +++ b/src/manager/SongManager.cpp @@ -22,418 +22,401 @@ namespace fs = std::filesystem; namespace manager { -SongManager::SongManager(const model::BinaryPath& bConf) - : m_bConf(bConf) { } + SongManager::SongManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -std::pair SongManager::saveSong(model::Song& song) -{ - saveSongTemp(song); - utility::MetadataRetriever meta; - auto data = std::move(song.data); - song = meta.retrieveMetadata(song); - song.data = std::move(data); + std::pair SongManager::saveSong(model::Song& song) { + saveSongTemp(song); + utility::MetadataRetriever meta; + auto data = std::move(song.data); + song = meta.retrieveMetadata(song); + song.data = std::move(data); - database::SongRepository songRepo(m_bConf); - if (songRepo.doesSongExist(song, type::SongFilter::titleAndArtist)) { - std::cout << "\ntitle: " << song.title << "\nartist: " << song.artist << "\n"; - std::cout << "does not exist\n"; - return std::make_pair(false, type::SongUpload::AlreadyExist); + database::SongRepository songRepo(m_bConf); + if (songRepo.doesSongExist(song, type::SongFilter::titleAndArtist)) { + std::cout << "\ntitle: " << song.title << "\nartist: " << song.artist << "\n"; + std::cout << "does not exist\n"; + return std::make_pair(false, type::SongUpload::AlreadyExist); + } + + saveMisc(song); + + printSong(song); + + songRepo.saveRecord(song); + song = songRepo.retrieveRecord(song, type::SongFilter::titleAndArtist); + + return std::make_pair(true, type::SongUpload::Successful); } - saveMisc(song); - printSong(song); + bool SongManager::didSongChange(const model::Song& updatedSong, + const model::Song& currSong) { + if (!updatedSong.title.empty()) { + return true; + } + if (!updatedSong.artist.empty()) { + return true; + } + if (!updatedSong.album.empty()) { + return true; + } + if (updatedSong.genre.empty()) { + return true; + } + if (updatedSong.year != 0) { + return true; + } - songRepo.saveRecord(song); - song = songRepo.retrieveRecord(song, type::SongFilter::titleAndArtist); + return false; + } - return std::make_pair(true, type::SongUpload::Successful); + bool SongManager::requiresFilesystemChange(const model::Song& updatedSong, + const model::Song& currSong) { + if (updatedSong.title.compare(currSong.title) != 0) { + return true; + } + if (updatedSong.artist.compare(currSong.album) != 0) { + return true; + } + if (updatedSong.album.compare(currSong.genre) != 0) { + return true; + } + + return false; + } + + bool SongManager::deleteSong(model::Song& song) { + database::SongRepository songRepo(m_bConf); + + if (!songRepo.doesSongExist(song, type::SongFilter::id)) { + std::cout << "song does not exist\n"; + return false; + } + + song = songRepo.retrieveRecord(song, type::SongFilter::id); + + auto paths = DirectoryManager::pathConfigContent(m_bConf); + + auto deleted = songRepo.deleteRecord(song); + + if (!deleted) { + std::cout << "song not deleted from databases\n"; + return deleted; + } + deleteMisc(song); + + fs::remove(song.songPath); + DirectoryManager::deleteDirectories(song, paths["root_music_path"].get()); + return deleted; + } + + bool SongManager::updateSong(model::Song& updatedSong) { + database::SongRepository songRepo(m_bConf); + model::Song currSong(updatedSong.id); + + currSong = songRepo.retrieveRecord(currSong, type::SongFilter::id); + if (!didSongChange(updatedSong, currSong)) { + std::cout << "no change to the song\n"; + return false; + } + + assignMiscId(updatedSong, currSong); + + auto changes = changesInSong(updatedSong, currSong); + + utility::MetadataRetriever meta; + meta.updateMetadata(updatedSong, currSong); + assignMiscFields(changes, updatedSong, currSong); + + if (requiresFilesystemChange(updatedSong, currSong)) { + modifySongOnFilesystem(updatedSong, currSong); + } + + printSong(updatedSong); + printSong(currSong); + + updateMisc(changes, updatedSong, currSong); + + return true; + } + + + void SongManager::printSong(const model::Song& song) { + std::cout << "\nsong" << "\n"; + std::cout << "title: " << song.title << "\n"; + std::cout << "artist: " << song.artist << "\n"; + std::cout << "album artist: " << song.albumArtist << "\n"; + std::cout << "album: " << song.album << "\n"; + std::cout << "genre: " << song.genre << "\n"; + std::cout << "duration: " << song.duration << "\n"; + std::cout << "year: " << song.year << "\n"; + std::cout << "track: " << song.track << "\n"; + std::cout << "disc: " << song.disc << "\n"; + std::cout << "song path: " << song.songPath << "\n"; + std::cout << "cover art id: " << song.coverArtId << "\n"; + std::cout << "album id: " << song.albumId << "\n"; + std::cout << "artist id: " << song.artistId << "\n"; + std::cout << "genre id: " << song.genreId << "\n"; + std::cout << "year id: " << song.yearId << "\n"; + } + + + std::map SongManager::changesInSong( + const model::Song& updatedSong, const model::Song& currSong) { + std::map songChanges; + + std::string_view updatedTitle = updatedSong.title; + std::string_view updatedArtist = updatedSong.artist; + std::string_view updatedAlbum = updatedSong.album; + std::string_view updatedGenre = updatedSong.genre; + + songChanges[type::SongChanged::title] = + (currSong.title.compare(updatedTitle) != 0 && + updatedTitle.size() > 0) ? true : false; + + songChanges[type::SongChanged::artist] = + (currSong.artist.compare(updatedArtist) != 0 && + updatedArtist.size() > 0) ? true : false; + + songChanges[type::SongChanged::album] = + (currSong.album.compare(updatedAlbum) != 0 && + updatedAlbum.size() > 0) ? true : false; + + songChanges[type::SongChanged::genre] = + (currSong.genre.compare(updatedGenre) != 0 && + updatedGenre.size() > 0) ? true : false; + + songChanges[type::SongChanged::year] = + (updatedSong.year != 0) ? true : false; + + return songChanges; } -bool SongManager::didSongChange(const model::Song& updatedSong, - const model::Song& currSong) -{ - if (!updatedSong.title.empty()) { - return true; - } - if (!updatedSong.artist.empty()) { - return true; - } - if (!updatedSong.album.empty()) { - return true; - } - if (updatedSong.genre.empty()) { - return true; - } - if (updatedSong.year != 0) { - return true; + std::string SongManager::createSongPath(const model::Song& song) { + auto songPath = DirectoryManager::createDirectoryProcess( + song, m_bConf, type::PathType::music); + + if (song.track != 0) { + songPath.append("track"); + auto trackNum = (song.track > 9) ? + std::to_string(song.track) : "0" + std::to_string(song.track); + songPath.append(trackNum); + } else { + songPath.append(song.title); + } + songPath.append(".mp3"); + + return songPath; } - return false; -} -bool SongManager::requiresFilesystemChange(const model::Song& updatedSong, - const model::Song& currSong) -{ - if (updatedSong.title.compare(currSong.title) != 0) { - return true; - } - if (updatedSong.artist.compare(currSong.album) != 0) { - return true; - } - if (updatedSong.album.compare(currSong.genre) != 0) { - return true; - } + // used to prevent empty values to appear in the updated song + void SongManager::assignMiscFields( + std::map& songChanges, model::Song& updatedSong, + const model::Song& currSong) { + std::cout << "assigning miscellanes fields to updated song\n"; + updatedSong.track = currSong.track; + for (auto scIter = songChanges.begin(); scIter != songChanges.end(); ++scIter) { + type::SongChanged key = scIter->first; + bool changed = songChanges.at(key); - return false; -} - -bool SongManager::deleteSong(model::Song& song) -{ - database::SongRepository songRepo(m_bConf); - - if (!songRepo.doesSongExist(song, type::SongFilter::id)) { - std::cout << "song does not exist" << std::endl; - return false; - } - - song = songRepo.retrieveRecord(song, type::SongFilter::id); - - auto paths = DirectoryManager::pathConfigContent(m_bConf); - - auto deleted = songRepo.deleteRecord(song); - - if (!deleted) { - std::cout << "song not deleted from databases" << std::endl; - return deleted; - } - deleteMisc(song); - - fs::remove(song.songPath); - DirectoryManager::deleteDirectories(song, paths["root_music_path"].get()); - return deleted; -} - -bool SongManager::updateSong(model::Song& updatedSong) -{ - database::SongRepository songRepo(m_bConf); - model::Song currSong(updatedSong.id); - - currSong = songRepo.retrieveRecord(currSong, type::SongFilter::id); - if (!didSongChange(updatedSong, currSong)) { - std::cout << "no change to the song" << std::endl; - return false; - } - - assignMiscId(updatedSong, currSong); - - auto changes = changesInSong(updatedSong, currSong); - - utility::MetadataRetriever meta; - meta.updateMetadata(updatedSong, currSong); - assignMiscFields(changes, updatedSong, currSong); - - if (requiresFilesystemChange(updatedSong, currSong)) { - modifySongOnFilesystem(updatedSong, currSong); - } - - printSong(updatedSong); - printSong(currSong); - - updateMisc(changes, updatedSong, currSong); - - return true; -} - - -void SongManager::printSong(const model::Song& song) -{ - std::cout << "\nsong" << std::endl; - std::cout << "title: " << song.title << std::endl; - std::cout << "artist: " << song.artist << std::endl; - std::cout << "album artist: " << song.albumArtist << std::endl; - std::cout << "album: " << song.album << std::endl; - std::cout << "genre: " << song.genre << std::endl; - std::cout << "duration: " << song.duration << std::endl; - std::cout << "year: " << song.year << std::endl; - std::cout << "track: " << song.track << std::endl; - std::cout << "disc: " << song.disc << std::endl; - std::cout << "song path: " << song.songPath << std::endl; - std::cout << "cover art id: " << song.coverArtId << std::endl; - std::cout << "album id: " << song.albumId << std::endl; - std::cout << "artist id: " << song.artistId << std::endl; - std::cout << "genre id: " << song.genreId << std::endl; - std::cout << "year id: " << song.yearId << std::endl; -} - - -std::map SongManager::changesInSong( - const model::Song& updatedSong, const model::Song& currSong) -{ - std::map songChanges; - - std::string_view updatedTitle = updatedSong.title; - std::string_view updatedArtist = updatedSong.artist; - std::string_view updatedAlbum = updatedSong.album; - std::string_view updatedGenre = updatedSong.genre; - - songChanges[type::SongChanged::title] = - (currSong.title.compare(updatedTitle) != 0 && - updatedTitle.size() > 0) ? true : false; - - songChanges[type::SongChanged::artist] = - (currSong.artist.compare(updatedArtist) != 0 && - updatedArtist.size() > 0) ? true : false; - - songChanges[type::SongChanged::album] = - (currSong.album.compare(updatedAlbum) != 0 && - updatedAlbum.size() > 0) ? true : false; - - songChanges[type::SongChanged::genre] = - (currSong.genre.compare(updatedGenre) != 0 && - updatedGenre.size() > 0) ? true : false; - - songChanges[type::SongChanged::year] = - (updatedSong.year != 0) ? true : false; - - return songChanges; -} - - -std::string SongManager::createSongPath(const model::Song& song) -{ - auto songPath = DirectoryManager::createDirectoryProcess( - song, m_bConf, type::PathType::music); - - if (song.track != 0) { - songPath.append("track"); - auto trackNum = (song.track > 9) ? - std::to_string(song.track) : "0" + std::to_string(song.track); - songPath.append(trackNum); - } else { - songPath.append(song.title); - } - songPath.append(".mp3"); - - return songPath; -} - - -// used to prevent empty values to appear in the updated song -void SongManager::assignMiscFields( - std::map& songChanges, model::Song& updatedSong, - const model::Song& currSong) -{ - std::cout << "assigning miscellanes fields to updated song" << std::endl; - updatedSong.track = currSong.track; - for (auto scIter = songChanges.begin(); scIter != songChanges.end(); ++scIter) { - type::SongChanged key = scIter->first; - bool changed = songChanges.at(key); - - if (!changed) { - switch (key) { - case type::SongChanged::title: - updatedSong.title = currSong.title; - std::cout << "title has not been changed" << std::endl; - break; - case type::SongChanged::artist: - updatedSong.artist = currSong.artist; - std::cout << "artist has not been changed" << std::endl; - break; - case type::SongChanged::album: - updatedSong.album = currSong.album; - std::cout << "album has not been changed" << std::endl; - break; - case type::SongChanged::genre: - updatedSong.genre = currSong.genre; - std::cout << "genre has not been changed" << std::endl; - break; - case::type::SongChanged::year: - updatedSong.year = currSong.year; - std::cout << "year has not been changed" << std::endl; - default: - break; + if (!changed) { + switch (key) { + case type::SongChanged::title: + updatedSong.title = currSong.title; + std::cout << "title has not been changed\n"; + break; + case type::SongChanged::artist: + updatedSong.artist = currSong.artist; + std::cout << "artist has not been changed\n"; + break; + case type::SongChanged::album: + updatedSong.album = currSong.album; + std::cout << "album has not been changed\n"; + break; + case type::SongChanged::genre: + updatedSong.genre = currSong.genre; + std::cout << "genre has not been changed\n"; + break; + case::type::SongChanged::year: + updatedSong.year = currSong.year; + std::cout << "year has not been changed\n"; + default: + break; + } } } } -} -// used to dump miscellaneous id to the updated song -void SongManager::assignMiscId(model::Song& updatedSong, - const model::Song& currSong) -{ - std::cout << "assigning miscellaneous Id's to updated song" << std::endl; - updatedSong.artistId = currSong.artistId; - updatedSong.albumId = currSong.albumId; - updatedSong.genreId = currSong.genreId; - updatedSong.yearId = currSong.yearId; - updatedSong.coverArtId = currSong.coverArtId; -} - -// saves song to a temporary path -void SongManager::saveSongTemp(model::Song& song) -{ - auto config = DirectoryManager::pathConfigContent(m_bConf); - - auto tmpSongPath = config["temp_root_path"].get(); - std::random_device dev; - std::mt19937 rng(dev()); - std::uniform_int_distribution dist(1,1000); - - tmpSongPath.append(std::to_string(dist(rng))); - tmpSongPath.append(".mp3"); - - std::fstream s(tmpSongPath, std::fstream::binary | std::fstream::out); - s.write((char*)&song.data[0], song.data.size()); - s.close(); - - song.songPath = tmpSongPath; -} - -void SongManager::saveMisc(model::Song& song) -{ - CoverArtManager covMgr(m_bConf); - auto pathConfigContent = DirectoryManager::pathConfigContent(m_bConf); - auto musicRootPath = pathConfigContent["root_music_path"].get(); - - auto cov = covMgr.saveCover(song); - const auto songPath = createSongPath(song); - - if (fs::exists(songPath)) { - std::cout << "deleting old song with the same metadata" << std::endl; - fs::remove(songPath); - } - std::cout << "copying song to the appropriate directory" << std::endl; - std::cout << song.songPath << std::endl; - std::cout << songPath << std::endl; - fs::copy(song.songPath, songPath); - fs::remove(song.songPath); - song.songPath = std::move(songPath); - std::cout << "copied song to the appropriate directory" << std::endl; - - AlbumManager albMgr(m_bConf); - auto album = albMgr.saveAlbum(song); - album = albMgr.retrieveAlbum(album); - AlbumManager::printAlbum(album); - - ArtistManager artMgr(m_bConf); - auto artist = artMgr.saveArtist(song); - artist = artMgr.retrieveArtist(artist); - ArtistManager::printArtist(artist); - - GenreManager gnrMgr(m_bConf); - auto genre = gnrMgr.saveGenre(song); - genre = gnrMgr.retrieveGenre(genre); - GenreManager::printGenre(genre); - - YearManager yrMgr(m_bConf); - auto year = yrMgr.saveYear(song); - year = yrMgr.retrieveYear(year); - YearManager::printYear(year); - - song.coverArtId = cov.id; - song.albumId = album.id; - song.artistId = artist.id; - song.genreId = genre.id; - song.yearId = year.id; - - std::cout << "done with miscellaneous database records" << std::endl; -} - -void SongManager::deleteMisc(const model::Song& song) -{ - CoverArtManager covMgr(m_bConf); - covMgr.deleteCover(song); - - AlbumManager albMgr(m_bConf); - albMgr.deleteAlbum(song); - - ArtistManager artMgr(m_bConf); - artMgr.deleteArtist(song); - - GenreManager gnrMgr(m_bConf); - gnrMgr.deleteGenre(song); - - YearManager yrMgr(m_bConf); - yrMgr.deleteYear(song); -} - -// deletes miscellanes records -void SongManager::deleteMiscExceptCoverArt(const model::Song& song) -{ - AlbumManager albMgr(m_bConf); - albMgr.deleteAlbum(song); - - ArtistManager artMgr(m_bConf); - artMgr.deleteArtist(song); - - GenreManager gnrMgr(m_bConf); - gnrMgr.deleteGenre(song); - - YearManager yrMgr(m_bConf); - yrMgr.deleteYear(song); -} - -void SongManager::updateMisc( - const std::map& songChanges, - model::Song& updatedSong, const model::Song& currSong) -{ - auto titleChange = songChanges.at(type::SongChanged::title); - auto artistChange = songChanges.at(type::SongChanged::artist); - auto albumChange = songChanges.at(type::SongChanged::album); - auto genreChange = songChanges.at(type::SongChanged::genre); - auto yearChange = songChanges.at(type::SongChanged::year); - - if (artistChange) { - ArtistManager artMgr(m_bConf); - artMgr.updateArtist(updatedSong, currSong); - } - if (albumChange) { - AlbumManager albMgr(m_bConf); - albMgr.updateAlbum(updatedSong, currSong); - } - if (genreChange) { - GenreManager gnrMgr(m_bConf); - gnrMgr.updateGenre(updatedSong, currSong); - } - if (yearChange) { - YearManager yrMgr(m_bConf); - yrMgr.updateYear(updatedSong, currSong); + // used to dump miscellaneous id to the updated song + void SongManager::assignMiscId(model::Song& updatedSong, + const model::Song& currSong) { + std::cout << "assigning miscellaneous Id's to updated song\n"; + updatedSong.artistId = currSong.artistId; + updatedSong.albumId = currSong.albumId; + updatedSong.genreId = currSong.genreId; + updatedSong.yearId = currSong.yearId; + updatedSong.coverArtId = currSong.coverArtId; } - // determins to update the cover art record - if (titleChange || artistChange || albumChange) { + // saves song to a temporary path + void SongManager::saveSongTemp(model::Song& song) { + auto config = DirectoryManager::pathConfigContent(m_bConf); + + auto tmpSongPath = config["temp_root_path"].get(); + std::random_device dev; + std::mt19937 rng(dev()); + std::uniform_int_distribution dist(1,1000); + + tmpSongPath.append(std::to_string(dist(rng))); + tmpSongPath.append(".mp3"); + + std::fstream s(tmpSongPath, std::fstream::binary | std::fstream::out); + s.write((char*)&song.data[0], song.data.size()); + s.close(); + + song.songPath = tmpSongPath; + } + + void SongManager::saveMisc(model::Song& song) { CoverArtManager covMgr(m_bConf); - covMgr.updateCoverRecord(updatedSong); + auto pathConfigContent = DirectoryManager::pathConfigContent(m_bConf); + auto musicRootPath = pathConfigContent["root_music_path"].get(); + + auto cov = covMgr.saveCover(song); + const auto songPath = createSongPath(song); + + if (fs::exists(songPath)) { + std::cout << "deleting old song with the same metadata\n"; + fs::remove(songPath); + } + std::cout << "copying song to the appropriate directory\n"; + std::cout << song.songPath << std::endl; + std::cout << songPath << std::endl; + fs::copy(song.songPath, songPath); + fs::remove(song.songPath); + song.songPath = std::move(songPath); + std::cout << "copied song to the appropriate directory\n"; + + AlbumManager albMgr(m_bConf); + auto album = albMgr.saveAlbum(song); + album = albMgr.retrieveAlbum(album); + AlbumManager::printAlbum(album); + + ArtistManager artMgr(m_bConf); + auto artist = artMgr.saveArtist(song); + artist = artMgr.retrieveArtist(artist); + ArtistManager::printArtist(artist); + + GenreManager gnrMgr(m_bConf); + auto genre = gnrMgr.saveGenre(song); + genre = gnrMgr.retrieveGenre(genre); + GenreManager::printGenre(genre); + + YearManager yrMgr(m_bConf); + auto year = yrMgr.saveYear(song); + year = yrMgr.retrieveYear(year); + YearManager::printYear(year); + + song.coverArtId = cov.id; + song.albumId = album.id; + song.artistId = artist.id; + song.genreId = genre.id; + song.yearId = year.id; + + std::cout << "done with miscellaneous database records\n"; } - database::SongRepository songRepo(m_bConf); - songRepo.updateRecord(updatedSong); + void SongManager::deleteMisc(const model::Song& song) { + CoverArtManager covMgr(m_bConf); + covMgr.deleteCover(song); - deleteMiscExceptCoverArt(currSong); -} + AlbumManager albMgr(m_bConf); + albMgr.deleteAlbum(song); -void SongManager::modifySongOnFilesystem(model::Song& updatedSong, - const model::Song& currSong) -{ - std::cout << "preparing to modify song" << std::endl; - auto songPath = createSongPath(updatedSong); - updatedSong.songPath = std::move(songPath); + ArtistManager artMgr(m_bConf); + artMgr.deleteArtist(song); - std::cout << "new path " << updatedSong.songPath << std::endl; + GenreManager gnrMgr(m_bConf); + gnrMgr.deleteGenre(song); - fs::copy(currSong.songPath, updatedSong.songPath); - fs::remove(currSong.songPath); + YearManager yrMgr(m_bConf); + yrMgr.deleteYear(song); + } - auto paths = DirectoryManager::pathConfigContent(m_bConf); - const auto musicRootPath = - paths[DirectoryManager::retrievePathType( + // deletes miscellanes records + void SongManager::deleteMiscExceptCoverArt(const model::Song& song) { + AlbumManager albMgr(m_bConf); + albMgr.deleteAlbum(song); + + ArtistManager artMgr(m_bConf); + artMgr.deleteArtist(song); + + GenreManager gnrMgr(m_bConf); + gnrMgr.deleteGenre(song); + + YearManager yrMgr(m_bConf); + yrMgr.deleteYear(song); + } + + void SongManager::updateMisc( + const std::map& songChanges, + model::Song& updatedSong, const model::Song& currSong) { + auto titleChange = songChanges.at(type::SongChanged::title); + auto artistChange = songChanges.at(type::SongChanged::artist); + auto albumChange = songChanges.at(type::SongChanged::album); + auto genreChange = songChanges.at(type::SongChanged::genre); + auto yearChange = songChanges.at(type::SongChanged::year); + + if (artistChange) { + ArtistManager artMgr(m_bConf); + artMgr.updateArtist(updatedSong, currSong); + } + if (albumChange) { + AlbumManager albMgr(m_bConf); + albMgr.updateAlbum(updatedSong, currSong); + } + if (genreChange) { + GenreManager gnrMgr(m_bConf); + gnrMgr.updateGenre(updatedSong, currSong); + } + if (yearChange) { + YearManager yrMgr(m_bConf); + yrMgr.updateYear(updatedSong, currSong); + } + + // determins to update the cover art record + if (titleChange || artistChange || albumChange) { + CoverArtManager covMgr(m_bConf); + covMgr.updateCoverRecord(updatedSong); + } + + database::SongRepository songRepo(m_bConf); + songRepo.updateRecord(updatedSong); + + deleteMiscExceptCoverArt(currSong); + } + + void SongManager::modifySongOnFilesystem(model::Song& updatedSong, + const model::Song& currSong) { + std::cout << "preparing to modify song\n"; + auto songPath = createSongPath(updatedSong); + updatedSong.songPath = std::move(songPath); + + std::cout << "new path " << updatedSong.songPath << "\n"; + + fs::copy(currSong.songPath, updatedSong.songPath); + fs::remove(currSong.songPath); + + auto paths = DirectoryManager::pathConfigContent(m_bConf); + const auto musicRootPath = + paths[DirectoryManager::retrievePathType( type::PathType::music)].get(); - DirectoryManager::deleteDirectories(currSong, musicRootPath); + DirectoryManager::deleteDirectories(currSong, musicRootPath); - CoverArtManager covMgr(m_bConf); - covMgr.updateCover(updatedSong, currSong); -} + CoverArtManager covMgr(m_bConf); + covMgr.updateCover(updatedSong, currSong); + } } diff --git a/src/manager/TokenManager.cpp b/src/manager/TokenManager.cpp index a914964..bff3121 100644 --- a/src/manager/TokenManager.cpp +++ b/src/manager/TokenManager.cpp @@ -14,169 +14,159 @@ namespace fs = std::filesystem; namespace manager { -model::Token TokenManager::retrieveToken(const model::BinaryPath& bConf) -{ - auto cred = parseAuthCredentials(bConf); - auto reqObj = createTokenBody(cred); + model::Token TokenManager::retrieveToken(const model::BinaryPath& bConf) { + auto cred = parseAuthCredentials(bConf); + auto reqObj = createTokenBody(cred); - std::string uri{cred.uri}; - uri.append("/"); - uri.append(cred.endpoint); + std::string uri{cred.uri}; + uri.append("/"); + uri.append(cred.endpoint); - auto r = sendRequest(uri, reqObj); - auto postRes = nlohmann::json::parse(r.text); + auto r = sendRequest(uri, reqObj); + auto postRes = nlohmann::json::parse(r.text); - model::Token lr(std::move(postRes["access_token"].get()), - std::move(postRes["token_type"].get()), - postRes["expires_in"].get()); + model::Token lr(std::move(postRes["access_token"].get()), + std::move(postRes["token_type"].get()), + postRes["expires_in"].get()); - return lr; -} - - -bool TokenManager::isTokenValid(std::string& auth, type::Scope scope) -{ - auto authPair = fetchAuthHeader(auth); - - if (!std::get<0>(authPair)) { - std::cout << "no Bearer found" << std::endl; - - return std::get<0>(authPair); + return lr; } - auto authHeader = std::get<1>(authPair); - auto token = authHeader.at(authHeader.size()-1); + bool TokenManager::isTokenValid(std::string& auth, type::Scope scope) { + auto authPair = fetchAuthHeader(auth); - auto scopes = extractScopes(jwt::decode(token)); + if (!std::get<0>(authPair)) { + std::cout << "no Bearer found\n"; - switch (scope) { - case type::Scope::upload: - return tokenSupportsScope(scopes, "upload:songs"); - case type::Scope::download: - return tokenSupportsScope(scopes, "download:songs"); - case type::Scope::stream: - return tokenSupportsScope(scopes, "stream:songs"); - case type::Scope::deleteSong: - return tokenSupportsScope(scopes, "delete:songs"); - case type::Scope::updateSong: - return tokenSupportsScope(scopes, "update:songs"); - case type::Scope::retrieveSong: - return tokenSupportsScope(scopes, "read:song_details"); - case type::Scope::retrieveAlbum: - return tokenSupportsScope(scopes, "read:albums"); - case type::Scope::retrieveArtist: - return tokenSupportsScope(scopes, "read:artists"); - case type::Scope::retrieveGenre: - return tokenSupportsScope(scopes, "read:genre"); - case type::Scope::retrieveYear: - return tokenSupportsScope(scopes, "read:year"); - case type::Scope::downloadCoverArt: - return tokenSupportsScope(scopes, "download:cover_art"); - default: - break; + return std::get<0>(authPair); + } + + auto authHeader = std::get<1>(authPair); + + auto token = authHeader.at(authHeader.size()-1); + + auto scopes = extractScopes(jwt::decode(token)); + + switch (scope) { + case type::Scope::upload: + return tokenSupportsScope(scopes, "upload:songs"); + case type::Scope::download: + return tokenSupportsScope(scopes, "download:songs"); + case type::Scope::stream: + return tokenSupportsScope(scopes, "stream:songs"); + case type::Scope::deleteSong: + return tokenSupportsScope(scopes, "delete:songs"); + case type::Scope::updateSong: + return tokenSupportsScope(scopes, "update:songs"); + case type::Scope::retrieveSong: + return tokenSupportsScope(scopes, "read:song_details"); + case type::Scope::retrieveAlbum: + return tokenSupportsScope(scopes, "read:albums"); + case type::Scope::retrieveArtist: + return tokenSupportsScope(scopes, "read:artists"); + case type::Scope::retrieveGenre: + return tokenSupportsScope(scopes, "read:genre"); + case type::Scope::retrieveYear: + return tokenSupportsScope(scopes, "read:year"); + case type::Scope::downloadCoverArt: + return tokenSupportsScope(scopes, "download:cover_art"); + default: + break; + } + + return false; } - return false; -} + bool TokenManager::testAuth(const model::BinaryPath& bConf) { + auto cred = parseAuthCredentials(bConf); + auto reqObj = createTokenBody(cred); -bool TokenManager::testAuth(const model::BinaryPath& bConf) -{ - auto cred = parseAuthCredentials(bConf); - auto reqObj = createTokenBody(cred); + std::string uri(cred.uri); + uri.append("/"); + uri.append(cred.endpoint); - std::string uri(cred.uri); - uri.append("/"); - uri.append(cred.endpoint); + auto response = sendRequest(uri, reqObj); - auto response = sendRequest(uri, reqObj); - - return (response.status_code == 200) ? true : false; -} + return (response.status_code == 200) ? true : false; + } -cpr::Response TokenManager::sendRequest(std::string_view uri, nlohmann::json& obj) -{ - auto resp = cpr::Post(cpr::Url{uri}, cpr::Body{obj.dump()}, + cpr::Response TokenManager::sendRequest(std::string_view uri, nlohmann::json& obj) { + auto resp = cpr::Post(cpr::Url{uri}, cpr::Body{obj.dump()}, cpr::Header{{"Content-type", "application/json"}, {"Connection", "keep-alive"}}); - return resp; -} - - -nlohmann::json TokenManager::createTokenBody(const model::AuthCredentials& auth) -{ - nlohmann::json obj; - obj["client_id"] = auth.clientId; - obj["client_secret"] = auth.clientSecret; - obj["audience"] = auth.apiIdentifier; - obj["grant_type"] = "client_credentials"; - - return obj; -} - - -model::AuthCredentials TokenManager::parseAuthCredentials(const model::BinaryPath& bConf) -{ - auto con = DirectoryManager::credentialConfigContent(bConf); - - model::AuthCredentials auth; - auth.uri = "https://"; - auth.uri.append(con["domain"]); - auth.apiIdentifier = con["api_identifier"]; - auth.clientId = con["client_id"]; - auth.clientSecret = con["client_secret"]; - auth.endpoint = "oauth/token"; - - return auth; -} - - -std::vector TokenManager::extractScopes(const jwt::decoded_jwt&& decoded) -{ - std::vector scopes; - - for (auto& d : decoded.get_payload_claims()) { - if (d.first.compare("scope") == 0) { - std::cout << "found scope" << std::endl; - std::string allScopes(d.second.to_json().get()); - std::istringstream iss(allScopes); - - scopes.assign(std::istream_iterator(iss), - std::istream_iterator()); - } + return resp; } - return scopes; -} -std::pair> TokenManager::fetchAuthHeader(const std::string& auth) -{ - std::istringstream iss(auth); - std::vector authHeader{std::istream_iterator(iss), - std::istream_iterator() - }; + nlohmann::json TokenManager::createTokenBody(const model::AuthCredentials& auth) { + nlohmann::json obj; + obj["client_id"] = auth.clientId; + obj["client_secret"] = auth.clientSecret; + obj["audience"] = auth.apiIdentifier; + obj["grant_type"] = "client_credentials"; - bool foundBearer = false; - if (std::any_of(authHeader.begin(), authHeader.end(), - [&](std::string_view word) { - return (word.compare("Bearer") == 0); - })) { - std::cout << "Bearer found" << std::endl; - foundBearer = true; + return obj; } - return std::make_pair(foundBearer, authHeader); -} + + model::AuthCredentials TokenManager::parseAuthCredentials(const model::BinaryPath& bConf) { + auto con = DirectoryManager::credentialConfigContent(bConf); + + model::AuthCredentials auth; + auth.uri = "https://"; + auth.uri.append(con["domain"]); + auth.apiIdentifier = con["api_identifier"]; + auth.clientId = con["client_id"]; + auth.clientSecret = con["client_secret"]; + auth.endpoint = "oauth/token"; + + return auth; + } -bool TokenManager::tokenSupportsScope(const std::vector& scopes, - const std::string&& scope) -{ - return std::any_of(scopes.begin(), scopes.end(), - [&](std::string_view foundScope) { - return (foundScope.compare(scope) == 0); - }); -} + std::vector TokenManager::extractScopes(const jwt::decoded_jwt&& decoded) { + std::vector scopes; + + for (auto& d : decoded.get_payload_claims()) { + if (d.first.compare("scope") == 0) { + std::cout << "found scope\n"; + std::string allScopes(d.second.to_json().get()); + std::istringstream iss(allScopes); + + scopes.assign(std::istream_iterator(iss), + std::istream_iterator()); + } + } + + return scopes; + } + + std::pair> TokenManager::fetchAuthHeader(const std::string& auth) { + std::istringstream iss(auth); + std::vector authHeader{std::istream_iterator(iss), + std::istream_iterator() + }; + + bool foundBearer = false; + if (std::any_of(authHeader.begin(), authHeader.end(), + [&](std::string_view word) { + return (word.compare("Bearer") == 0); })) { + std::cout << "Bearer found\n"; + foundBearer = true; + } + + return std::make_pair(foundBearer, authHeader); + } + + + bool TokenManager::tokenSupportsScope(const std::vector& scopes, + const std::string&& scope) { + return std::any_of(scopes.begin(), scopes.end(), + [&](std::string_view foundScope) { + return (foundScope.compare(scope) == 0); + }); + } } diff --git a/src/manager/UserManager.cpp b/src/manager/UserManager.cpp index e5f8d8a..fda0a0e 100644 --- a/src/manager/UserManager.cpp +++ b/src/manager/UserManager.cpp @@ -7,70 +7,70 @@ #include "utility/PasswordEncryption.h" namespace manager { -UserManager::UserManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } + UserManager::UserManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -model::RegisterResult UserManager::registerUser(model::User& user) { - model::RegisterResult result; - result.username = user.username; - printUser(user); + model::RegisterResult UserManager::registerUser(model::User& user) { + model::RegisterResult result; + result.username = user.username; + printUser(user); - utility::PasswordEncryption passEnc; - auto hashed = passEnc.hashPassword(user); - user.password = hashed.hashPassword; + utility::PasswordEncryption passEnc; + auto hashed = passEnc.hashPassword(user); + user.password = hashed.hashPassword; - database::UserRepository usrRepo(m_bConf); - usrRepo.saveUserRecord(user); + database::UserRepository usrRepo(m_bConf); + usrRepo.saveUserRecord(user); - model::User usr; - usr.username = user.username; + model::User usr; + usr.username = user.username; - std::cout << usr.username << std::endl; - usr = usrRepo.retrieveUserRecord(usr, type::UserFilter::username); - hashed.hashPassword = usr.password; - hashed.userId = usr.id; + std::cout << usr.username << "\n"; + usr = usrRepo.retrieveUserRecord(usr, type::UserFilter::username); + hashed.hashPassword = usr.password; + hashed.userId = usr.id; - usrRepo.saveUserSalt(hashed); - result.registered = true; - result.message = "successfully registered"; - printUser(usr); + usrRepo.saveUserSalt(hashed); + result.registered = true; + result.message = "successfully registered"; + printUser(usr); - return result; -} + return result; + } -bool UserManager::doesUserExist(const model::User& user) { - database::UserRepository userRepo(m_bConf); + bool UserManager::doesUserExist(const model::User& user) { + database::UserRepository userRepo(m_bConf); - return userRepo.doesUserRecordExist(user, type::UserFilter::username); -} + return userRepo.doesUserRecordExist(user, type::UserFilter::username); + } -bool UserManager::validatePassword(const model::User& user) { - database::UserRepository userRepo(m_bConf); - model::User usr; - usr.username = user.username; - usr = userRepo.retrieveUserRecord(usr, type::UserFilter::username); + bool UserManager::validatePassword(const model::User& user) { + database::UserRepository userRepo(m_bConf); + model::User usr; + usr.username = user.username; + usr = userRepo.retrieveUserRecord(usr, type::UserFilter::username); - model::PassSec userSec; - userSec.userId = usr.id; - userSec = userRepo.retrieverUserSaltRecord(userSec, type::SaltFilter::userId); - userSec.hashPassword = usr.password; + model::PassSec userSec; + userSec.userId = usr.id; + userSec = userRepo.retrieverUserSaltRecord(userSec, type::SaltFilter::userId); + userSec.hashPassword = usr.password; - utility::PasswordEncryption passEnc; + utility::PasswordEncryption passEnc; - return passEnc.isPasswordValid(user, userSec); -} + return passEnc.isPasswordValid(user, userSec); + } -void UserManager::printUser(const model::User& user) { - std::cout << "\nuser info" << std::endl; - std::cout << "id: " << user.id << std::endl; - std::cout << "firstname: " << user.firstname << std::endl; - std::cout << "lastname: " << user.lastname << std::endl; - std::cout << "phone: " << user.phone << std::endl; - std::cout << "email: " << user.email << std::endl; - std::cout << "username: " << user.username << std::endl; - std::cout << "password: " << user.password<< std::endl; -} + void UserManager::printUser(const model::User& user) { + std::cout << "\nuser info\n"; + std::cout << "id: " << user.id << "\n"; + std::cout << "firstname: " << user.firstname << "\n"; + std::cout << "lastname: " << user.lastname << "\n"; + std::cout << "phone: " << user.phone << "\n"; + std::cout << "email: " << user.email << "\n"; + std::cout << "username: " << user.username << "\n"; + std::cout << "password: " << user.password<< "\n"; + } } diff --git a/src/manager/YearManager.cpp b/src/manager/YearManager.cpp index 3400d14..d92d26b 100644 --- a/src/manager/YearManager.cpp +++ b/src/manager/YearManager.cpp @@ -6,72 +6,66 @@ #include "type/YearFilter.h" namespace manager { -YearManager::YearManager(const model::BinaryPath& bConf) - : m_bConf(bConf) { } + YearManager::YearManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -model::Year YearManager::retrieveYear(model::Year& year) -{ - database::YearRepository yearRepo(m_bConf); - year = yearRepo.retrieveRecord(year, type::YearFilter::year); + model::Year YearManager::retrieveYear(model::Year& year) { + database::YearRepository yearRepo(m_bConf); + year = yearRepo.retrieveRecord(year, type::YearFilter::year); - return year; -} - -model::Year YearManager::saveYear(const model::Song& song) -{ - model::Year year; - year.year = song.year; - - database::YearRepository yearRepo(m_bConf); - if (!yearRepo.doesYearExist(year, type::YearFilter::year)) { - yearRepo.saveRecord(year); - } else { - std::cout << "year record already exists in the database" << std::endl; + return year; } - return year; -} + model::Year YearManager::saveYear(const model::Song& song) { + model::Year year; + year.year = song.year; -void YearManager::deleteYear(const model::Song& song) -{ - model::Year year(song); + database::YearRepository yearRepo(m_bConf); + if (!yearRepo.doesYearExist(year, type::YearFilter::year)) { + yearRepo.saveRecord(year); + } else { + std::cout << "year record already exists in the database\n"; + } - database::YearRepository yrRepo(m_bConf); - auto yrWSC = yrRepo.retrieveRecordWithSongCount(year, type::YearFilter::id); - - if (yrWSC.second > 1) { - std::cout << "year still contain songs related to it"; - std::cout << ", will not delete" << std::endl; - return; + return year; } - std::cout << "safe to delete the year record" << std::endl; - yrRepo.deleteYear(year, type::YearFilter::id); -} + void YearManager::deleteYear(const model::Song& song) { + model::Year year(song); -void YearManager::updateYear(model::Song& updatedSong, - const model::Song& currSong) -{ - model::Year year; - year.year = updatedSong.year; + database::YearRepository yrRepo(m_bConf); + auto yrWSC = yrRepo.retrieveRecordWithSongCount(year, type::YearFilter::id); - database::YearRepository albRepo(m_bConf); - if (!albRepo.doesYearExist(year, type::YearFilter::year)) { - std::cout << "year record does not exist" << std::endl; - albRepo.saveRecord(year); - } else { - std::cout << "year record already exists" << std::endl; + if (yrWSC.second > 1) { + std::cout << "year still contain songs related to it"; + std::cout << ", will not delete\n"; + return; + } + + std::cout << "safe to delete the year record\n"; + yrRepo.deleteYear(year, type::YearFilter::id); } - year = albRepo.retrieveRecord(year, type::YearFilter::year); - updatedSong.yearId = year.id; -} + void YearManager::updateYear(model::Song& updatedSong, + const model::Song& currSong) { + model::Year year; + year.year = updatedSong.year; -void YearManager::printYear(const model::Year& year) -{ - std::cout << "\nyear record" << std::endl; - std::cout << "id: " << year.id << std::endl; - std::cout << "year: " << year.year << std::endl; -} + database::YearRepository albRepo(m_bConf); + if (!albRepo.doesYearExist(year, type::YearFilter::year)) { + std::cout << "year record does not exist\n"; + albRepo.saveRecord(year); + } else { + std::cout << "year record already exists\n"; + } + + year = albRepo.retrieveRecord(year, type::YearFilter::year); + updatedSong.yearId = year.id; + } + + void YearManager::printYear(const model::Year& year) { + std::cout << "\nyear record\n"; + std::cout << "id: " << year.id << "\n"; + std::cout << "year: " << year.year << "\n"; + } } diff --git a/src/utility/ImageFile.cpp b/src/utility/ImageFile.cpp index d2fdfc4..bcdc282 100644 --- a/src/utility/ImageFile.cpp +++ b/src/utility/ImageFile.cpp @@ -1,12 +1,9 @@ #include "utility/ImageFile.h" namespace utility { -ImageFile::ImageFile(const char *file) : TagLib::File(file) -{ -} + ImageFile::ImageFile(const char *file) : TagLib::File(file) { } -TagLib::ByteVector ImageFile::data() -{ - return readBlock(length()); -} + TagLib::ByteVector ImageFile::data() { + return readBlock(length()); + } } diff --git a/src/utility/MetadataRetriever.cpp b/src/utility/MetadataRetriever.cpp index 7ccd679..132eb07 100644 --- a/src/utility/MetadataRetriever.cpp +++ b/src/utility/MetadataRetriever.cpp @@ -19,190 +19,183 @@ namespace fs = std::filesystem; namespace utility { -model::Song MetadataRetriever::retrieveMetadata(model::Song& song) -{ - TagLib::MPEG::File sameFile(song.songPath.c_str()); - auto tag = sameFile.ID3v2Tag(); - song.title = tag->title().toCString(); - song.artist = tag->artist().toCString(); - song.album = tag->album().toCString(); - song.genre = tag->genre().toCString(); - song.year = tag->year(); - song.track = tag->track(); - song.duration = sameFile.audioProperties()->lengthInSeconds(); + model::Song MetadataRetriever::retrieveMetadata(model::Song& song) { + TagLib::MPEG::File sameFile(song.songPath.c_str()); + auto tag = sameFile.ID3v2Tag(); + song.title = tag->title().toCString(); + song.artist = tag->artist().toCString(); + song.album = tag->album().toCString(); + song.genre = tag->genre().toCString(); + song.year = tag->year(); + song.track = tag->track(); + song.duration = sameFile.audioProperties()->lengthInSeconds(); - constexpr auto id3DiscName = "TPOS"; - constexpr auto id3AlbumArtistName = "TPE2"; + constexpr auto id3DiscName = "TPOS"; + constexpr auto id3AlbumArtistName = "TPE2"; - auto discFrame = tag->frameList(id3DiscName); - auto albumArtistFrame = tag->frameList(id3AlbumArtistName); - if (discFrame.isEmpty()) { - constexpr auto discDefaultVal = "1"; - TagLib::ID3v2::TextIdentificationFrame *emptyFrame = - new TagLib::ID3v2::TextIdentificationFrame(id3DiscName); - tag->addFrame(emptyFrame); - emptyFrame->setText(discDefaultVal); - song.disc = std::atoi(discDefaultVal); - sameFile.save(); - } else { - song.disc = std::stoi(discFrame.front()->toString().toCString()); + auto discFrame = tag->frameList(id3DiscName); + auto albumArtistFrame = tag->frameList(id3AlbumArtistName); + if (discFrame.isEmpty()) { + constexpr auto discDefaultVal = "1"; + TagLib::ID3v2::TextIdentificationFrame *emptyFrame = + new TagLib::ID3v2::TextIdentificationFrame(id3DiscName); + tag->addFrame(emptyFrame); + emptyFrame->setText(discDefaultVal); + song.disc = std::atoi(discDefaultVal); + sameFile.save(); + } else { + song.disc = std::stoi(discFrame.front()->toString().toCString()); + } + + if (albumArtistFrame.isEmpty()) { + TagLib::ID3v2::TextIdentificationFrame *emptyFrame = + new TagLib::ID3v2::TextIdentificationFrame(id3DiscName); + tag->addFrame(emptyFrame); + emptyFrame->setText(song.artist.c_str()); + sameFile.save(); + } else { + song.albumArtist = albumArtistFrame.front()->toString().toCString(); + } + + return song; } - if (albumArtistFrame.isEmpty()) { - TagLib::ID3v2::TextIdentificationFrame *emptyFrame = - new TagLib::ID3v2::TextIdentificationFrame(id3DiscName); - tag->addFrame(emptyFrame); - emptyFrame->setText(song.artist.c_str()); - sameFile.save(); - } else { - song.albumArtist = albumArtistFrame.front()->toString().toCString(); + model::Cover MetadataRetriever::updateCoverArt(const model::Song& song, model::Cover& cov, + const std::string& stockCoverPath) { + TagLib::MPEG::File sngF(song.songPath.c_str()); + auto tag = sngF.ID3v2Tag(); + auto frameList = tag->frameListMap()["APIC"]; + + if (frameList.isEmpty()) { + cov.imagePath.append("CoverArt.png"); + + if (!fs::exists(cov.imagePath)) { + std::cout << "copying stock cover path\n"; + fs::copy(stockCoverPath, cov.imagePath); + } + + ImageFile stockImg(cov.imagePath.c_str()); + + TagLib::ID3v2::AttachedPictureFrame *pic = + new TagLib::ID3v2::AttachedPictureFrame; + pic->setPicture(stockImg.data()); + pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover); + + tag->addFrame(pic); + + sngF.save(); + std::cout << "applied stock cover art" << std::endl; + } else { + auto frame = dynamic_cast( + frameList.front()); + + auto imgPath = manager::DirectoryManager::createDirectoryProcess(song, cov.imagePath); + imgPath.append(song.title); + imgPath.append(".png"); + cov.imagePath = imgPath; + + std::fstream imgSave(cov.imagePath, std::ios::out | + std::ios::binary); + imgSave.write(frame->picture().data(), frame->picture().size()); + imgSave.close(); + std::cout << "saved to " << cov.imagePath << "\n"; + } + + return cov; + } + + // tags song with the stock cover art + model::Cover MetadataRetriever::applyStockCoverArt( + const model::Song& song, model::Cover& cov, + const std::string& stockCoverPath) { + TagLib::MPEG::File songFile(song.songPath.c_str()); + auto tag = songFile.ID3v2Tag(); + + ImageFile stockImg(cov.imagePath.c_str()); + TagLib::ID3v2::AttachedPictureFrame *pic = + new TagLib::ID3v2::AttachedPictureFrame; + + pic->setPicture(stockImg.data()); + pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover); + + tag->addFrame(pic); + + songFile.save(); + std::cout << "applied stock cover art\n"; + + delete pic; + + return cov; + } + + // extracts cover art from the song and save it to the + // appropriate directory + model::Cover MetadataRetriever::applyCoverArt(const model::Song& song, + model::Cover& cov) { + TagLib::MPEG::File songFile(song.songPath.c_str()); + auto tag = songFile.ID3v2Tag(); + auto frameList = tag->frameListMap()["APIC"]; + + auto frame = dynamic_cast( + frameList.front()); + + std::fstream imgSave(cov.imagePath, std::ios::out | + std::ios::binary); + imgSave.write(frame->picture().data(), frame->picture().size()); + imgSave.close(); + + std::cout << "saved to " << cov.imagePath << "\n"; + + return cov; } - return song; -} + bool MetadataRetriever::songContainsCoverArt(const model::Song& song) { + TagLib::MPEG::File songFile(song.songPath.c_str()); + auto tag = songFile.ID3v2Tag(); + auto frameList = tag->frameListMap()["APIC"]; -model::Cover MetadataRetriever::updateCoverArt(const model::Song& song, model::Cover& cov, - const std::string& stockCoverPath) -{ - TagLib::MPEG::File sngF(song.songPath.c_str()); - auto tag = sngF.ID3v2Tag(); - auto frameList = tag->frameListMap()["APIC"]; - - if (frameList.isEmpty()) { - cov.imagePath.append("CoverArt.png"); - - if (!fs::exists(cov.imagePath)) { - std::cout << "copying stock cover path" << std::endl; - fs::copy(stockCoverPath, cov.imagePath); - } - - ImageFile stockImg(cov.imagePath.c_str()); - - TagLib::ID3v2::AttachedPictureFrame *pic = - new TagLib::ID3v2::AttachedPictureFrame; - pic->setPicture(stockImg.data()); - pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover); - - tag->addFrame(pic); - - sngF.save(); - std::cout << "applied stock cover art" << std::endl; - } else { - auto frame = dynamic_cast( - frameList.front()); - - auto imgPath = manager::DirectoryManager::createDirectoryProcess(song, cov.imagePath); - imgPath.append(song.title); - imgPath.append(".png"); - cov.imagePath = imgPath; - - std::fstream imgSave(cov.imagePath, std::ios::out | - std::ios::binary); - imgSave.write(frame->picture().data(), frame->picture().size()); - imgSave.close(); - std::cout << "saved to " << cov.imagePath << std::endl; + return !frameList.isEmpty(); } - return cov; -} -// tags song with the stock cover art -model::Cover MetadataRetriever::applyStockCoverArt( - const model::Song& song, model::Cover& cov, - const std::string& stockCoverPath) -{ - TagLib::MPEG::File songFile(song.songPath.c_str()); - auto tag = songFile.ID3v2Tag(); - - ImageFile stockImg(cov.imagePath.c_str()); - TagLib::ID3v2::AttachedPictureFrame *pic = - new TagLib::ID3v2::AttachedPictureFrame; - - pic->setPicture(stockImg.data()); - pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover); - - tag->addFrame(pic); - - songFile.save(); - std::cout << "applied stock cover art" << std::endl; - - delete pic; - - return cov; -} - -// extracts cover art from the song and save it to the -// appropriate directory -model::Cover MetadataRetriever::applyCoverArt(const model::Song& song, - model::Cover& cov) -{ - TagLib::MPEG::File songFile(song.songPath.c_str()); - auto tag = songFile.ID3v2Tag(); - auto frameList = tag->frameListMap()["APIC"]; - - auto frame = dynamic_cast( - frameList.front()); - - std::fstream imgSave(cov.imagePath, std::ios::out | - std::ios::binary); - imgSave.write(frame->picture().data(), frame->picture().size()); - imgSave.close(); - - std::cout << "saved to " << cov.imagePath << std::endl; - - return cov; -} - - -bool MetadataRetriever::songContainsCoverArt(const model::Song& song) -{ - TagLib::MPEG::File songFile(song.songPath.c_str()); - auto tag = songFile.ID3v2Tag(); - auto frameList = tag->frameListMap()["APIC"]; - - return !frameList.isEmpty(); -} - - -void MetadataRetriever::updateMetadata(model::Song& sngUpdated, const model::Song& sngOld) -{ - std::cout<<"updating metadata"< 0) { - file.tag()->setTitle(sngUpdated.title); - } - if (sngUpdated.artist.size() > 0) { - file.tag()->setArtist(sngUpdated.artist); - } - if (sngUpdated.albumArtist.size() > 0) { - constexpr auto frameId = "TPE2"; - auto albumArtistFrame = tag->frameList(frameId); - if (albumArtistFrame.isEmpty()) { - TagLib::ID3v2::TextIdentificationFrame *frame = - new TagLib::ID3v2::TextIdentificationFrame(frameId); - frame->setText(sngUpdated.albumArtist.c_str()); - tag->addFrame(frame); - } else { - albumArtistFrame.front()->setText(sngUpdated.albumArtist.c_str()); - } + if (sngUpdated.title.size() > 0) { + file.tag()->setTitle(sngUpdated.title); + } + if (sngUpdated.artist.size() > 0) { + file.tag()->setArtist(sngUpdated.artist); + } + if (sngUpdated.albumArtist.size() > 0) { + constexpr auto frameId = "TPE2"; + auto albumArtistFrame = tag->frameList(frameId); + if (albumArtistFrame.isEmpty()) { + TagLib::ID3v2::TextIdentificationFrame *frame = + new TagLib::ID3v2::TextIdentificationFrame(frameId); + frame->setText(sngUpdated.albumArtist.c_str()); + tag->addFrame(frame); + } else { + albumArtistFrame.front()->setText(sngUpdated.albumArtist.c_str()); + } - file.save(); - } - if (sngUpdated.album.size() > 0) { - file.tag()->setAlbum(sngUpdated.album); - } - if (sngUpdated.genre.size() > 0) { - file.tag()->setGenre(sngUpdated.genre); - } - if (sngUpdated.year > 0) { - file.tag()->setYear(sngUpdated.year); - } + file.save(); + } + if (sngUpdated.album.size() > 0) { + file.tag()->setAlbum(sngUpdated.album); + } + if (sngUpdated.genre.size() > 0) { + file.tag()->setGenre(sngUpdated.genre); + } + if (sngUpdated.year > 0) { + file.tag()->setYear(sngUpdated.year); + } - // TODO: functionality to update the track number and disc number + // TODO: functionality to update the track number and disc number - file.save(); -} + file.save(); + } } diff --git a/src/utility/PasswordEncryption.cpp b/src/utility/PasswordEncryption.cpp index a905fa3..742ec8d 100644 --- a/src/utility/PasswordEncryption.cpp +++ b/src/utility/PasswordEncryption.cpp @@ -7,42 +7,36 @@ namespace utility { -model::PassSec PasswordEncryption::hashPassword(const model::User& user) -{ - model::PassSec passSec; + model::PassSec PasswordEncryption::hashPassword(const model::User& user) { + model::PassSec passSec; - std::unique_ptr salt(new char[BCRYPT_HASHSIZE]); - std::unique_ptr hash(new char[BCRYPT_HASHSIZE]); + std::unique_ptr salt(new char[BCRYPT_HASHSIZE]); + std::unique_ptr hash(new char[BCRYPT_HASHSIZE]); - std::cout << "generating salt" << std::endl; - bcrypt_gensalt(saltSize(), salt.get()); - std::cout << "hashing password" << std::endl; - bcrypt_hashpw(user.password.c_str(), salt.get(), hash.get()); + std::cout << "generating salt" << std::endl; + bcrypt_gensalt(saltSize(), salt.get()); + std::cout << "hashing password" << std::endl; + bcrypt_hashpw(user.password.c_str(), salt.get(), hash.get()); - passSec.salt = salt.get(); - passSec.hashPassword = hash.get(); + passSec.salt = salt.get(); + passSec.hashPassword = hash.get(); - std::cout << "hash: " << passSec.hashPassword << std::endl; - std::cout << "salt: " << passSec.salt << std::endl; + std::cout << "hash: " << passSec.hashPassword << std::endl; + std::cout << "salt: " << passSec.salt << std::endl; - return passSec; -} - - -bool PasswordEncryption::isPasswordValid(const model::User& user, const model::PassSec& userSalt) -{ - std::unique_ptr passwordHashed(new char[BCRYPT_HASHSIZE]); - - bcrypt_hashpw(user.password.c_str(), userSalt.salt.c_str(), passwordHashed.get()); - - return (userSalt.hashPassword.compare(passwordHashed.get()) == 0) ? true : false; -} - - -int PasswordEncryption::saltSize() -{ - constexpr auto size = 10000; - - return size; -} + return passSec; + } + + + bool PasswordEncryption::isPasswordValid(const model::User& user, + const model::PassSec& userSalt) { + std::unique_ptr passwordHashed(new char[BCRYPT_HASHSIZE]); + + bcrypt_hashpw(user.password.c_str(), userSalt.salt.c_str(), passwordHashed.get()); + + return (userSalt.hashPassword.compare(passwordHashed.get()) == 0) ? true : false; + } + + + constexpr int PasswordEncryption::saltSize() noexcept { return 10000; } } diff --git a/src/verify/Initialization.cpp b/src/verify/Initialization.cpp index b0c26f7..4750de3 100644 --- a/src/verify/Initialization.cpp +++ b/src/verify/Initialization.cpp @@ -11,103 +11,88 @@ namespace fs = std::filesystem; namespace verify { - -bool Initialization::skipVerification(const std::string& argument) -{ - return argument.compare("--noverify") == 0; -} - - -// verifies if the configuration settings are valid -void Initialization::checkIcarus(const model::BinaryPath& bConf) -{ - auto auth = confirmConfigAuth(bConf); - auto database = confirmConfigDatabase(bConf); - auto path = confirmConfigPaths(bConf); - - if ((auth && database && path) == false) { - failedConfirmation(); + bool Initialization::skipVerification(const std::string& argument) { + return argument.compare("--noverify") == 0; } - std::cout << "icarus check passed" << std::endl; -} + + // verifies if the configuration settings are valid + void Initialization::checkIcarus(const model::BinaryPath& bConf) { + auto auth = confirmConfigAuth(bConf); + auto database = confirmConfigDatabase(bConf); + auto path = confirmConfigPaths(bConf); + + if ((auth && database && path) == false) { + failedConfirmation(); + } + + std::cout << "icarus check passed\n"; + } -// verifies that the authorization settings are not the default values -bool Initialization::confirmConfigAuth(const model::BinaryPath& bConf) -{ - manager::TokenManager tokMgr; + // verifies that the authorization settings are not the default values + bool Initialization::confirmConfigAuth(const model::BinaryPath& bConf) { + manager::TokenManager tokMgr; - return tokMgr.testAuth(bConf); -} + return tokMgr.testAuth(bConf); + } -// verifies if database connectivity can be established -bool Initialization::confirmConfigDatabase(const model::BinaryPath& bConf) -{ - database::BaseRepository baseRepo(bConf); + // verifies if database connectivity can be established + bool Initialization::confirmConfigDatabase(const model::BinaryPath& bConf) { + database::BaseRepository baseRepo(bConf); - return baseRepo.testConnection(); -} + return baseRepo.testConnection(); + } -// verifies if the paths found in the config files exists -bool Initialization::confirmConfigPaths(const model::BinaryPath& bConf) -{ - auto pathConfig = manager::DirectoryManager::pathConfigContent(bConf); + // verifies if the paths found in the config files exists + bool Initialization::confirmConfigPaths(const model::BinaryPath& bConf) { + using manager::DirectoryManager; + auto pathConfig = DirectoryManager::pathConfigContent(bConf); - const auto rootMusicPath = - pathConfig - [manager:: - DirectoryManager:: - retrievePathType + const auto rootMusicPath = + pathConfig + [DirectoryManager::retrievePathType (type::PathType::music)].get(); - const auto archiveRootPath = - pathConfig - [manager:: - DirectoryManager:: - retrievePathType + const auto archiveRootPath = + pathConfig + [DirectoryManager::retrievePathType (type::PathType::archive)].get(); - const auto tempRootPath = - pathConfig - [manager:: - DirectoryManager:: - retrievePathType + const auto tempRootPath = + pathConfig + [DirectoryManager::retrievePathType (type::PathType::temp)].get(); - const auto coverRootPath = - pathConfig - [manager:: - DirectoryManager:: - retrievePathType + const auto coverRootPath = + pathConfig + [DirectoryManager::retrievePathType (type::PathType::coverArt)].get(); - if (!fs::exists(rootMusicPath)) { - std::cout << "root music path is not properly configured" << std::endl; - return false; + if (!fs::exists(rootMusicPath)) { + std::cout << "root music path is not properly configured\n"; + return false; + } + + if (!fs::exists(archiveRootPath)) { + std::cout << "archive root path is not properly configured\n"; + return false; + } + + if (!fs::exists(tempRootPath)) { + std::cout << "temp root path is not properly configured\n"; + return false; + } + + if (!fs::exists(coverRootPath)) { + std::cout << "cover art root path is not properly configured\n"; + return false; + } + + return true; } - if (!fs::exists(archiveRootPath)) { - std::cout << "archive root path is not properly configured" << std::endl; - return false; - } - if (!fs::exists(tempRootPath)) { - std::cout << "temp root path is not properly configured" << std::endl; - return false; + // confirmation failed + void Initialization::failedConfirmation() { + std::cout << "configuration confirmation failed. check your settings\n"; + std::exit(-1); } - - if (!fs::exists(coverRootPath)) { - std::cout << "cover art root path is not properly configured" << std::endl; - return false; - } - - return true; -} - - -// confirmation failed -void Initialization::failedConfirmation() -{ - std::cout << "configuration confirmation failed. check your settings" << std::endl; - std::exit(-1); -} - }