From 32ed611112f5e41de9f84b2e183aedf3c2c47fc5 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 25 Sep 2019 23:03:38 -0400 Subject: [PATCH] Authorized endpoints and updated README --- README.md | 10 +- include/callback/StreamCallback.h | 25 +- include/component/AppComponent.hpp | 39 ++- include/controller/AlbumController.hpp | 108 +++++---- include/controller/ArtistController.hpp | 104 ++++---- include/controller/CoverArtController.hpp | 142 +++++------ include/controller/GenreController.hpp | 104 ++++---- include/controller/SongController.hpp | 283 ++++++++++++---------- include/controller/YearController.hpp | 103 ++++---- include/manager/TokenManager.h | 33 ++- include/type/Scopes.h | 12 +- src/callback/StreamCallback.cpp | 8 +- src/manager/TokenManager.cpp | 51 ++-- 13 files changed, 563 insertions(+), 459 deletions(-) diff --git a/README.md b/README.md index 4b05dc3..6d584eb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Icarus -Icarus is a music streaming API Server that interacts with [Mear](https://github.com/amazing-username/mear). +Icarus is a music streaming API Server, allowing access to stream your personal music collection ### Interfacing With Icarus @@ -8,6 +8,7 @@ One can interface with Icarus the music server either by: * [Mear](https://github.com/amazing-username/mear) - Partially implemented (under development) * [IcarusDownloadManager](https://github.com/amazing-username/IcarusDownloadManager) +* Create your own client to interact with the API @@ -19,6 +20,9 @@ One can interface with Icarus the music server either by: * [json](https://www.github.com/nlohmann/json) * [cpr](https://www.github.com/whoshuu/cpr) * [TagLib](https://github.com/taglib/taglib) +* [jwt-cpp](https://github.com/Thalhammer/jwt-cpp) +* [libbcrypt](https://github.com/rg3/libbcrypt) +* [oatpp](https://github.com/oatpp/oatpp) ![image](https://user-images.githubusercontent.com/14333136/56252069-28532d00-6084-11e9-896d-1a3c378014ef.png) @@ -117,7 +121,7 @@ In order for Database functionality to be operable, there must be a valid connec ``` * server - The address or domain name of the MySQL server * database - The database name -* user - Username +* username - Username * password - Self-explanatory The only requirement of the User is that the user should have full permissions to the database as well as permissions to create a database. Other than that, that is all that is required. @@ -135,7 +139,7 @@ Prior to starting the API, the database must be created. The following tables ar There is a MySQL script to create these tables, it can be found in the [Scripts/MySQL/](https://github.com/amazing-username/Icarus/blob/master/Scripts/MySQL/create_database.sql) directory. Just merely execute: ```shell -mysql -u *dblikedecibel* -p < Scripts/MySQL/create_database.sql +mysql -u dblikedecibel -p < Scripts/MySQL/create_database.sql ``` From this point the database has been successfully created. Metadata and song filesystem locations can be saved. diff --git a/include/callback/StreamCallback.h b/include/callback/StreamCallback.h index c1d665a..3d9c651 100644 --- a/include/callback/StreamCallback.h +++ b/include/callback/StreamCallback.h @@ -6,22 +6,21 @@ #include "oatpp/core/data/stream/FileStream.hpp" #include "oatpp/web/protocol/http/outgoing/ChunkedBody.hpp" -namespace callback +namespace callback { +class StreamCallback : public oatpp::data::stream::ReadCallback { - class StreamCallback : public oatpp::data::stream::ReadCallback - { - public: - StreamCallback(); - StreamCallback(const std::string&); +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 91602c2..b26a0a2 100644 --- a/include/component/AppComponent.hpp +++ b/include/component/AppComponent.hpp @@ -8,31 +8,30 @@ #include "oatpp/parser/json/mapping/ObjectMapper.hpp" #include "oatpp/web/server/HttpConnectionHandler.hpp" -namespace component +namespace component { + +class AppComponent { +public: + OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { + return oatpp::network::server::SimpleTCPConnectionProvider::createShared(5002); + }()); - 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: +}; } #endif diff --git a/include/controller/AlbumController.hpp b/include/controller/AlbumController.hpp index a58460d..62dafe5 100644 --- a/include/controller/AlbumController.hpp +++ b/include/controller/AlbumController.hpp @@ -20,73 +20,83 @@ #include "database/AlbumRepository.h" #include "dto/AlbumDto.hpp" #include "manager/AlbumManager.h" +#include "manager/TokenManager.h" #include "model/Models.h" #include "type/Scopes.h" #include "type/AlbumFilter.h" namespace fs = std::filesystem; -namespace controller +namespace controller { +class AlbumController : public oatpp::web::server::api::ApiController { - 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) + { } + + 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) + + // endpoint for retrieving all album records in json format + ENDPOINT("GET", "/api/v1/album", albumRecords, + REQUEST(std::shared_ptr, request)) { - public: - AlbumController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + 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"); - AlbumController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + 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(); - #include OATPP_CODEGEN_BEGIN(ApiController) + for (auto& albDb : albsDb) { + auto alb = dto::AlbumDto::createShared(); + alb->id = albDb.id; + alb->title = albDb.title.c_str(); + alb->year = albDb.year; - // endpoint for retrieving all album records in json format - ENDPOINT("GET", "/api/v1/album", albumRecords, - REQUEST(std::shared_ptr, request)) - { - 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::AlbumDto::createShared(); - alb->id = albDb.id; - alb->title = albDb.title.c_str(); - alb->year = albDb.year; - - albums->pushBack(alb); - } - - return createDtoResponse(Status::CODE_200, albums); + albums->pushBack(alb); } - // endpoint for retrieving single album record by the album id in json format - ENDPOINT("GET", "/api/v1/album/{id}", albumRecord, - PATH(Int32, id)) { + return createDtoResponse(Status::CODE_200, albums); + } - database::AlbumRepository albRepo(m_bConf); - model::Album albDb(id); + // 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"); - OATPP_ASSERT_HTTP(albRepo.doesAlbumExists(albDb, type::AlbumFilter::id) , Status::CODE_403, "album does not exist"); + database::AlbumRepository albRepo(m_bConf); + model::Album albDb(id); - std::cout << "album exists" << std::endl; - albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id); + OATPP_ASSERT_HTTP(albRepo.doesAlbumExists(albDb, type::AlbumFilter::id) , Status::CODE_403, "album does not exist"); - auto album = dto::AlbumDto::createShared(); - album->id = albDb.id; - album->title = albDb.title.c_str(); - album->year = albDb.year; + std::cout << "album exists" << std::endl; + albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id); - return createDtoResponse(Status::CODE_200, album); - } + auto album = dto::AlbumDto::createShared(); + album->id = albDb.id; + album->title = albDb.title.c_str(); + album->year = albDb.year; - #include OATPP_CODEGEN_END(ApiController) - private: - std::string m_exe_path; - model::BinaryPath m_bConf; - const long m_dataSize = std::numeric_limits::max(); - }; + return createDtoResponse(Status::CODE_200, album); + } + + #include OATPP_CODEGEN_END(ApiController) +private: + std::string m_exe_path; + model::BinaryPath m_bConf; +}; } #endif diff --git a/include/controller/ArtistController.hpp b/include/controller/ArtistController.hpp index ad6982b..8c6ebc0 100644 --- a/include/controller/ArtistController.hpp +++ b/include/controller/ArtistController.hpp @@ -20,71 +20,81 @@ #include "database/ArtistRepository.h" #include "dto/ArtistDto.hpp" #include "manager/ArtistManager.h" +#include "manager/TokenManager.h" #include "model/Models.h" #include "type/Scopes.h" #include "type/ArtistFilter.h" namespace fs = std::filesystem; -namespace controller +namespace controller { +class ArtistController : public oatpp::web::server::api::ApiController { - 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) + { } + + 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) + + // endpoint for retrieving all artist records in json format + ENDPOINT("GET", "/api/v1/artist", artistRecords, + REQUEST(std::shared_ptr, request)) { - public: - ArtistController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + 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"); - ArtistController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + 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(); - #include OATPP_CODEGEN_BEGIN(ApiController) + for (auto& artDb : artsDb) { + auto art = dto::ArtistDto::createShared(); + art->id = artDb.id; + art->artist = artDb.artist.c_str(); - // endpoint for retrieving all artist records in json format - ENDPOINT("GET", "/api/v1/artist", artistRecords, - REQUEST(std::shared_ptr, request)) - { - 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(); - - artists->pushBack(art); - } - - return createDtoResponse(Status::CODE_200, artists); + artists->pushBack(art); } - // endpoint for retrieving single artist record by the artist id in json format - ENDPOINT("GET", "/api/v1/artist/{id}", artistRecord, - PATH(Int32, id)) { + return createDtoResponse(Status::CODE_200, artists); + } - database::ArtistRepository artRepo(m_bConf); - model::Artist artDb(id); + // 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"); - OATPP_ASSERT_HTTP(artRepo.doesArtistExist(artDb, type::ArtistFilter::id) , Status::CODE_403, "artist does not exist"); + database::ArtistRepository artRepo(m_bConf); + model::Artist artDb(id); - std::cout << "artist exist" << std::endl; - artDb = artRepo.retrieveRecord(artDb, type::ArtistFilter::id); + OATPP_ASSERT_HTTP(artRepo.doesArtistExist(artDb, type::ArtistFilter::id) , Status::CODE_403, "artist does not exist"); - auto artist = dto::ArtistDto::createShared(); - artist->id = artDb.id; - artist->artist = artDb.artist.c_str(); + std::cout << "artist exist" << std::endl; + artDb = artRepo.retrieveRecord(artDb, type::ArtistFilter::id); - return createDtoResponse(Status::CODE_200, artist); - } + auto artist = dto::ArtistDto::createShared(); + artist->id = artDb.id; + artist->artist = artDb.artist.c_str(); - #include OATPP_CODEGEN_END(ApiController) - private: - std::string m_exe_path; - model::BinaryPath m_bConf; - const long m_dataSize = std::numeric_limits::max(); - }; + return createDtoResponse(Status::CODE_200, artist); + } + + #include OATPP_CODEGEN_END(ApiController) +private: + std::string m_exe_path; + model::BinaryPath m_bConf; +}; } #endif diff --git a/include/controller/CoverArtController.hpp b/include/controller/CoverArtController.hpp index c33a4cd..ea41fd2 100644 --- a/include/controller/CoverArtController.hpp +++ b/include/controller/CoverArtController.hpp @@ -26,94 +26,96 @@ namespace fs = std::filesystem; -namespace controller +namespace controller { +class CoverArtController : public oatpp::web::server::api::ApiController { - 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) + { } + + 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) + + // endpoint for retrieving all cover art records in json format + ENDPOINT("GET", "/api/v1/coverart", coverArtRecords, + REQUEST(std::shared_ptr, request)) { - public: - CoverArtController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + 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"); - CoverArtController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + 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(); - #include OATPP_CODEGEN_BEGIN(ApiController) + for (auto& covDb : covsDb) { + auto cov = dto::CoverArtDto::createShared(); + cov->id = covDb.id; + cov->songTitle = covDb.songTitle.c_str(); - // endpoint for retrieving all cover art records in json format - ENDPOINT("GET", "/api/v1/coverart", coverArtRecords, - REQUEST(std::shared_ptr, request)) - { - 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(); - - coverArts->pushBack(cov); - } - - return createDtoResponse(Status::CODE_200, coverArts); + coverArts->pushBack(cov); } - // endpoint for retrieving single cover art record by the cover art id in json format - ENDPOINT("GET", "/api/v1/coverart/{id}", coverArtRecord, - PATH(Int32, id)) { + return createDtoResponse(Status::CODE_200, coverArts); + } - database::CoverArtRepository covRepo(m_bConf); - model::Cover covDb; - covDb.id = id; + // 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"); - OATPP_ASSERT_HTTP(covRepo.doesCoverArtExist(covDb, type::CoverFilter::id) , Status::CODE_403, "song does not exist"); + database::CoverArtRepository covRepo(m_bConf); + model::Cover covDb; + covDb.id = id; - std::cout << "cover art exists" << std::endl; - covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); + OATPP_ASSERT_HTTP(covRepo.doesCoverArtExist(covDb, type::CoverFilter::id) , Status::CODE_403, "song does not exist"); - auto coverArt = dto::CoverArtDto::createShared(); - coverArt->id = covDb.id; - coverArt->songTitle = covDb.songTitle.c_str(); + std::cout << "cover art exists" << std::endl; + covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); - return createDtoResponse(Status::CODE_200, coverArt); - } + auto coverArt = dto::CoverArtDto::createShared(); + coverArt->id = covDb.id; + coverArt->songTitle = covDb.songTitle.c_str(); - ENDPOINT("GET", "/api/v1/coverart/download/{id}", downloadCoverArt, - PATH(Int32, id)) { + return createDtoResponse(Status::CODE_200, coverArt); + } - database::CoverArtRepository covRepo(m_bConf); - model::Cover covDb; - covDb.id = id; - covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); + 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"); - /** - std::ifstream fl(covDb.imagePath.c_str(), std::ios::in | std::ios::binary | std::ios::ate); - fl.seekg(0); + database::CoverArtRepository covRepo(m_bConf); + model::Cover covDb; + covDb.id = id; + covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); - std::stringstream buf; - std::copy(std::istreambuf_iterator(fl), - std::istreambuf_iterator(), - std::ostreambuf_iterator(buf)); - fl.close(); - */ - - //auto rawCover = oatpp::String(buf.str().data(), (v_int32)buf.str().size(), true); - auto rawCover = oatpp::base::StrBuffer::loadFromFile(covDb.imagePath.c_str()); - auto response = createResponse(Status::CODE_200, rawCover); + auto rawCover = oatpp::base::StrBuffer::loadFromFile(covDb.imagePath.c_str()); + auto response = createResponse(Status::CODE_200, rawCover); - response->putHeader(Header::CONTENT_TYPE, "image/*"); + 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; - const long m_dataSize = std::numeric_limits::max(); - }; + #include OATPP_CODEGEN_END(ApiController) +private: + std::string m_exe_path; + model::BinaryPath m_bConf; +}; } #endif diff --git a/include/controller/GenreController.hpp b/include/controller/GenreController.hpp index 95fdfe4..efae772 100644 --- a/include/controller/GenreController.hpp +++ b/include/controller/GenreController.hpp @@ -20,71 +20,81 @@ #include "database/GenreRepository.h" #include "dto/GenreDto.hpp" #include "manager/GenreManager.h" +#include "manager/YearManager.h" #include "model/Models.h" #include "type/Scopes.h" #include "type/GenreFilter.h" namespace fs = std::filesystem; -namespace controller +namespace controller { +class GenreController : public oatpp::web::server::api::ApiController { - 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) + { } + + 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) + + // endpoint for retrieving all genre records in json format + ENDPOINT("GET", "/api/v1/genre", genreRecords, + REQUEST(std::shared_ptr, request)) { - public: - GenreController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + 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"); - GenreController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + 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(); - #include OATPP_CODEGEN_BEGIN(ApiController) + for (auto& gnrDb : gnrsDb) { + auto gnr = dto::GenreDto::createShared(); + gnr->id = gnrDb.id; + gnr->category = gnrDb.category.c_str(); - // endpoint for retrieving all genre records in json format - ENDPOINT("GET", "/api/v1/genre", genreRecords, - REQUEST(std::shared_ptr, request)) - { - 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(); - - genres->pushBack(gnr); - } - - return createDtoResponse(Status::CODE_200, genres); + genres->pushBack(gnr); } - // endpoint for retrieving single genre record by the genre id in json format - ENDPOINT("GET", "/api/v1/genre/{id}", genreRecord, - PATH(Int32, id)) { + return createDtoResponse(Status::CODE_200, genres); + } - database::GenreRepository gnrRepo(m_bConf); - model::Genre gnrDb(id); + // 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"); - OATPP_ASSERT_HTTP(gnrRepo.doesGenreExist(gnrDb, type::GenreFilter::id) , Status::CODE_403, "genre does not exist"); + database::GenreRepository gnrRepo(m_bConf); + model::Genre gnrDb(id); - std::cout << "genre exist" << std::endl; - gnrDb = gnrRepo.retrieveRecord(gnrDb, type::GenreFilter::id); + OATPP_ASSERT_HTTP(gnrRepo.doesGenreExist(gnrDb, type::GenreFilter::id) , Status::CODE_403, "genre does not exist"); - auto genre = dto::GenreDto::createShared(); - genre->id = gnrDb.id; - genre->category= gnrDb.category.c_str(); + std::cout << "genre exist" << std::endl; + gnrDb = gnrRepo.retrieveRecord(gnrDb, type::GenreFilter::id); - return createDtoResponse(Status::CODE_200, genre); - } + auto genre = dto::GenreDto::createShared(); + genre->id = gnrDb.id; + genre->category= gnrDb.category.c_str(); - #include OATPP_CODEGEN_END(ApiController) - private: - std::string m_exe_path; - model::BinaryPath m_bConf; - const long m_dataSize = std::numeric_limits::max(); - }; + return createDtoResponse(Status::CODE_200, genre); + } + + #include OATPP_CODEGEN_END(ApiController) +private: + std::string m_exe_path; + model::BinaryPath m_bConf; +}; } #endif diff --git a/include/controller/SongController.hpp b/include/controller/SongController.hpp index 110a146..07baa28 100644 --- a/include/controller/SongController.hpp +++ b/include/controller/SongController.hpp @@ -29,100 +29,73 @@ namespace fs = std::filesystem; -namespace controller +namespace controller { +class SongController : public oatpp::web::server::api::ApiController { - 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) + { } + + 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) + + // endpoint for uploading a song + ENDPOINT("POST", "/api/v1/song/data", songUpload, + REQUEST(std::shared_ptr, request)) { - public: - SongController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + 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"); - SongController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + auto mp = std::make_shared(request->getHeaders()); - #include OATPP_CODEGEN_BEGIN(ApiController) + oatpp::web::mime::multipart::Reader mp_reader(mp.get()); - // endpoint for uploading a song - ENDPOINT("POST", "/api/v1/song/data", songUpload, - REQUEST(std::shared_ptr, request)) - { - auto authHeader = request->getHeader("Authorization"); + mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize)); - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + request->transferBody(&mp_reader); - auto auth = authHeader->std_str(); - - manager::TokenManager tok; - OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::upload), Status::CODE_403, "Not allowed"); + auto file = mp->getNamedPart("file"); - auto mp = std::make_shared(request->getHeaders()); + OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); - oatpp::web::mime::multipart::Reader mp_reader(mp.get()); + auto buff = std::unique_ptr(new char[file->getKnownSize()]); + auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize()); - mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize)); + std::vector data(buff.get(), buff.get() + buffSize); - request->transferBody(&mp_reader); + model::Song sng; + sng.data = std::move(data); + + manager::SongManager songMgr(m_bConf); + songMgr.saveSong(sng); - auto file = mp->getNamedPart("file"); + return createResponse(Status::CODE_200, "OK"); + } - OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); + // 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"); - 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); - - model::Song sng; - sng.data = std::move(data); - - manager::SongManager songMgr(m_bConf); - songMgr.saveSong(sng); - - return createResponse(Status::CODE_200, "OK"); - } - - // endpoint for retrieving all song records in json format - ENDPOINT("GET", "/api/v1/song", songRecords, - REQUEST(std::shared_ptr, request)) - { - 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" << std::endl; - for (auto& songDb : songsDb) { - auto song = dto::SongDto::createShared(); - song->id = songDb.id; - song->title = songDb.title.c_str(); - song->artist = songDb.artist.c_str(); - song->album = songDb.album.c_str(); - song->genre = songDb.genre.c_str(); - song->year = songDb.year; - song->duration = songDb.duration; - song->track = songDb.track; - song->disc = songDb.disc; - - songs->pushBack(song); - } - - 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, - PATH(Int32, id)) { - - database::SongRepository songRepo(m_bConf); - model::Song songDb(id); - - OATPP_ASSERT_HTTP(songRepo.doesSongExist(songDb, type::SongFilter::id) , Status::CODE_403, "song does not exist"); - - std::cout << "song exists" << std::endl; - songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); + 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" << std::endl; + for (auto& songDb : songsDb) { auto song = dto::SongDto::createShared(); song->id = songDb.id; song->title = songDb.title.c_str(); @@ -134,72 +107,130 @@ namespace controller song->track = songDb.track; song->disc = songDb.disc; - return createDtoResponse(Status::CODE_200, song); + songs->pushBack(song); } - ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, - PATH(Int32, id)) { + return createDtoResponse(Status::CODE_200, songs); + } - database::SongRepository songRepo(m_bConf); - model::Song songDb(id); - songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); + // 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"); - auto rawSong = oatpp::base::StrBuffer::loadFromFile(songDb.songPath.c_str()); + database::SongRepository songRepo(m_bConf); + model::Song songDb(id); + + OATPP_ASSERT_HTTP(songRepo.doesSongExist(songDb, type::SongFilter::id) , Status::CODE_403, + "song does not exist"); + + std::cout << "song exists" << std::endl; + songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); + + auto song = dto::SongDto::createShared(); + song->id = songDb.id; + song->title = songDb.title.c_str(); + song->artist = songDb.artist.c_str(); + song->album = songDb.album.c_str(); + song->genre = songDb.genre.c_str(); + song->year = songDb.year; + song->duration = songDb.duration; + song->track = songDb.track; + song->disc = songDb.disc; + + 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"); + + database::SongRepository songRepo(m_bConf); + model::Song songDb(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 response = createResponse(Status::CODE_200, rawSong); + response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); - return response; - } + return response; + } - // TODO: create endpoint for updating songs - ENDPOINT("UPDATE", "/api/v1/song/{id}", songUpdate, - BODY_DTO(dto::SongDto::ObjectWrapper, songDto), PATH(Int32, id)) { - songDto->id = id; + 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 = manager::SongManager::songDtoConv(songDto); - manager::SongManager songMgr(m_bConf); - songMgr.updateSong(updatedSong); + auto updatedSong = manager::SongManager::songDtoConv(songDto); + manager::SongManager songMgr(m_bConf); + songMgr.updateSong(updatedSong); - 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, PATH(Int32, id)) { - model::Song song(id); + // 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"); - manager::SongManager sngMgr(m_bConf); - sngMgr.deleteSong(song); + model::Song song(id); - return createResponse(Status::CODE_200, "OK"); - } + manager::SongManager sngMgr(m_bConf); + sngMgr.deleteSong(song); - // endpoint for streaming a song - ENDPOINT("GET", "/api/v1/song/stream/{id}", streamSong, - PATH(Int32, id)) { - database::SongRepository songRepo(m_bConf); - model::Song songDb(id); - songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); + return createResponse(Status::CODE_200, "OK"); + } - oatpp::data::v_io_size dSize = 1024; + // 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"); - auto db = std::make_shared( - std::make_shared(songDb.songPath), nullptr, dSize); + database::SongRepository songRepo(m_bConf); + model::Song songDb(id); + songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); - auto response = OutgoingResponse::createShared(Status::CODE_200, db); - response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE); - response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); + oatpp::data::v_io_size dSize = 1024; - return response; - } + auto db = std::make_shared( + std::make_shared(songDb.songPath), nullptr, dSize); - #include OATPP_CODEGEN_END(ApiController) - private: - std::string m_exe_path; + auto response = OutgoingResponse::createShared(Status::CODE_200, db); + response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE); + response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); - model::BinaryPath m_bConf; + return response; + } - const long m_dataSize = std::numeric_limits::max(); - }; + #include OATPP_CODEGEN_END(ApiController) +private: + std::string m_exe_path; + + model::BinaryPath m_bConf; + + const long m_dataSize = std::numeric_limits::max(); +}; } #endif diff --git a/include/controller/YearController.hpp b/include/controller/YearController.hpp index 3cb8198..6e6b71e 100644 --- a/include/controller/YearController.hpp +++ b/include/controller/YearController.hpp @@ -26,65 +26,74 @@ namespace fs = std::filesystem; -namespace controller +namespace controller { +class YearController : public oatpp::web::server::api::ApiController { - 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) + { } + + 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) + + // endpoint for retrieving all year records in json format + ENDPOINT("GET", "/api/v1/year", yearRecords, + REQUEST(std::shared_ptr, request)) { - public: - YearController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } + 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"); - YearController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } + 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(); - #include OATPP_CODEGEN_BEGIN(ApiController) + for (auto& yrDb : yrsDb) { + auto yr = dto::YearDto::createShared(); + yr->id = yrDb.id; + yr->year = yrDb.year; - // endpoint for retrieving all year records in json format - ENDPOINT("GET", "/api/v1/year", yearRecords, - REQUEST(std::shared_ptr, request)) - { - 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; - - yearRecs->pushBack(yr); - } - - return createDtoResponse(Status::CODE_200, yearRecs); + yearRecs->pushBack(yr); } - // endpoint for retrieving single year record by the year id in json format - ENDPOINT("GET", "/api/v1/year/{id}", yearRecord, - PATH(Int32, id)) { + return createDtoResponse(Status::CODE_200, yearRecs); + } - database::YearRepository yrRepo(m_bConf); - model::Year yrDb(id); + // 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"); - OATPP_ASSERT_HTTP(yrRepo.doesYearExist(yrDb, type::YearFilter::id) , Status::CODE_403, "year does not exist"); + database::YearRepository yrRepo(m_bConf); + model::Year yrDb(id); - std::cout << "year exist" << std::endl; - yrDb = yrRepo.retrieveRecord(yrDb, type::YearFilter::id); + OATPP_ASSERT_HTTP(yrRepo.doesYearExist(yrDb, type::YearFilter::id) , Status::CODE_403, "year does not exist"); - auto year = dto::YearDto::createShared(); - year->id = yrDb.id; - year->year= yrDb.year; + std::cout << "year exist" << std::endl; + yrDb = yrRepo.retrieveRecord(yrDb, type::YearFilter::id); - return createDtoResponse(Status::CODE_200, year); - } + auto year = dto::YearDto::createShared(); + year->id = yrDb.id; + year->year= yrDb.year; - #include OATPP_CODEGEN_END(ApiController) - private: - std::string m_exe_path; - model::BinaryPath m_bConf; - const long m_dataSize = std::numeric_limits::max(); - }; + return createDtoResponse(Status::CODE_200, year); + } + + #include OATPP_CODEGEN_END(ApiController) +private: + std::string m_exe_path; + model::BinaryPath m_bConf; +}; } #endif diff --git a/include/manager/TokenManager.h b/include/manager/TokenManager.h index 319fc82..686b233 100644 --- a/include/manager/TokenManager.h +++ b/include/manager/TokenManager.h @@ -13,30 +13,29 @@ #include "model/Models.h" #include "type/Scopes.h" -namespace manager +namespace manager { +class TokenManager { - class TokenManager - { - public: - TokenManager(); +public: + TokenManager(); - model::LoginResult retrieveToken(const model::BinaryPath&); + model::LoginResult 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(std::string_view); - model::AuthCredentials parseAuthCredentials(const model::BinaryPath&); + model::AuthCredentials parseAuthCredentials(std::string_view); + 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/type/Scopes.h b/include/type/Scopes.h index 37ccf73..b5d1b25 100644 --- a/include/type/Scopes.h +++ b/include/type/Scopes.h @@ -6,7 +6,17 @@ namespace type enum class Scope { upload = 0, - download + download, + stream, + retrieveSong, + updateSong, + deleteSong, + retrieveAlbum, + retrieveArtist, + retrieveGenre, + retrieveYear, + downloadCoverArt + }; } diff --git a/src/callback/StreamCallback.cpp b/src/callback/StreamCallback.cpp index 44deb40..c1435f8 100644 --- a/src/callback/StreamCallback.cpp +++ b/src/callback/StreamCallback.cpp @@ -4,10 +4,11 @@ #include #include -callback::StreamCallback::StreamCallback() : +namespace callback { +StreamCallback::StreamCallback() : m_counter(0) { } -callback::StreamCallback::StreamCallback(const std::string& songPath) : +StreamCallback::StreamCallback(const std::string& songPath) : m_songPath(songPath), m_counter(0), m_bytesRead(0) @@ -19,7 +20,7 @@ callback::StreamCallback::StreamCallback(const std::string& songPath) : } -oatpp::data::v_io_size callback::StreamCallback::read(void *buff, oatpp::data::v_io_size 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" << std::endl; @@ -40,3 +41,4 @@ oatpp::data::v_io_size callback::StreamCallback::read(void *buff, oatpp::data::v return count; } +} diff --git a/src/manager/TokenManager.cpp b/src/manager/TokenManager.cpp index e7aa49d..ab9cf9a 100644 --- a/src/manager/TokenManager.cpp +++ b/src/manager/TokenManager.cpp @@ -13,13 +13,13 @@ namespace fs = std::filesystem; - -manager::TokenManager::TokenManager() +namespace manager { +TokenManager::TokenManager() { } -model::LoginResult manager::TokenManager::retrieveToken(const model::BinaryPath& bConf) +model::LoginResult TokenManager::retrieveToken(const model::BinaryPath& bConf) { auto cred = parseAuthCredentials(bConf); @@ -46,7 +46,7 @@ model::LoginResult manager::TokenManager::retrieveToken(const model::BinaryPath& } -bool manager::TokenManager::isTokenValid(std::string& auth, type::Scope scope) +bool TokenManager::isTokenValid(std::string& auth, type::Scope scope) { auto authPair = fetchAuthHeader(auth); @@ -65,9 +65,26 @@ bool manager::TokenManager::isTokenValid(std::string& auth, type::Scope scope) switch (scope) { case type::Scope::upload: return tokenSupportsScope(scopes, "upload:songs"); - break; 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; } @@ -75,7 +92,7 @@ bool manager::TokenManager::isTokenValid(std::string& auth, type::Scope scope) return false; } -bool manager::TokenManager::testAuth(const model::BinaryPath& bConf) +bool TokenManager::testAuth(const model::BinaryPath& bConf) { auto cred = parseAuthCredentials(bConf); auto reqObj = createTokenBody(cred); @@ -90,7 +107,7 @@ bool manager::TokenManager::testAuth(const model::BinaryPath& bConf) } -cpr::Response manager::TokenManager::sendRequest(std::string_view uri, nlohmann::json& obj) +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"}, @@ -100,7 +117,7 @@ cpr::Response manager::TokenManager::sendRequest(std::string_view uri, nlohmann: } -nlohmann::json manager::TokenManager::createTokenBody(const model::AuthCredentials& auth) +nlohmann::json TokenManager::createTokenBody(const model::AuthCredentials& auth) { nlohmann::json obj; obj["client_id"] = auth.clientId; @@ -112,12 +129,12 @@ nlohmann::json manager::TokenManager::createTokenBody(const model::AuthCredentia } -model::AuthCredentials manager::TokenManager::parseAuthCredentials(std::string_view path) +model::AuthCredentials TokenManager::parseAuthCredentials(std::string_view path) { - auto exe_path = manager::DirectoryManager::configPath(path); + auto exe_path = DirectoryManager::configPath(path); exe_path.append("/authcredentials.json"); - auto con = manager::DirectoryManager::credentialConfigContent(exe_path); + auto con = DirectoryManager::credentialConfigContent(exe_path); model::AuthCredentials auth; auth.uri = "https://"; @@ -129,9 +146,9 @@ model::AuthCredentials manager::TokenManager::parseAuthCredentials(std::string_v return auth; } -model::AuthCredentials manager::TokenManager::parseAuthCredentials(const model::BinaryPath& bConf) +model::AuthCredentials TokenManager::parseAuthCredentials(const model::BinaryPath& bConf) { - auto con = manager::DirectoryManager::credentialConfigContent(bConf); + auto con = DirectoryManager::credentialConfigContent(bConf); model::AuthCredentials auth; auth.uri = "https://"; @@ -144,7 +161,7 @@ model::AuthCredentials manager::TokenManager::parseAuthCredentials(const model:: return auth; } -std::vector manager::TokenManager::extractScopes(const jwt::decoded_jwt&& decoded) +std::vector TokenManager::extractScopes(const jwt::decoded_jwt&& decoded) { std::vector scopes; @@ -162,7 +179,7 @@ std::vector manager::TokenManager::extractScopes(const jwt::decoded return scopes; } -std::pair> manager::TokenManager::fetchAuthHeader(const std::string& auth) +std::pair> TokenManager::fetchAuthHeader(const std::string& auth) { std::istringstream iss(auth); std::vector authHeader{std::istream_iterator(iss), @@ -182,10 +199,12 @@ std::pair> manager::TokenManager::fetchAuthHeader } -bool manager::TokenManager::tokenSupportsScope(const std::vector scopes, const std::string&& scope) +bool TokenManager::tokenSupportsScope(const std::vector scopes, + const std::string&& scope) { return std::any_of(scopes.begin(), scopes.end(), [&](std::string foundScope) { return (foundScope.compare(scope) == 0); }); } +}