Authorized endpoints and updated README

This commit is contained in:
kdeng00
2019-09-25 23:03:38 -04:00
parent 698ccf9099
commit 32ed611112
13 changed files with 563 additions and 459 deletions
+7 -3
View File
@@ -1,6 +1,6 @@
# Icarus # 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 ### 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) * [Mear](https://github.com/amazing-username/mear) - Partially implemented (under development)
* [IcarusDownloadManager](https://github.com/amazing-username/IcarusDownloadManager) * [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) * [json](https://www.github.com/nlohmann/json)
* [cpr](https://www.github.com/whoshuu/cpr) * [cpr](https://www.github.com/whoshuu/cpr)
* [TagLib](https://github.com/taglib/taglib) * [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) ![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 * server - The address or domain name of the MySQL server
* database - The database name * database - The database name
* user - Username * username - Username
* password - Self-explanatory * 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. 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: 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 ```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. From this point the database has been successfully created. Metadata and song filesystem locations can be saved.
+12 -13
View File
@@ -6,22 +6,21 @@
#include "oatpp/core/data/stream/FileStream.hpp" #include "oatpp/core/data/stream/FileStream.hpp"
#include "oatpp/web/protocol/http/outgoing/ChunkedBody.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();
public: StreamCallback(const std::string&);
StreamCallback();
StreamCallback(const std::string&);
oatpp::data::v_io_size read(void*, oatpp::data::v_io_size); oatpp::data::v_io_size read(void*, oatpp::data::v_io_size);
private: private:
std::string m_songPath; std::string m_songPath;
long m_bytesRead; long m_bytesRead;
long m_counter; long m_counter;
long m_fileSize; long m_fileSize;
}; };
} }
#endif #endif
+19 -20
View File
@@ -8,31 +8,30 @@
#include "oatpp/parser/json/mapping/ObjectMapper.hpp" #include "oatpp/parser/json/mapping/ObjectMapper.hpp"
#include "oatpp/web/server/HttpConnectionHandler.hpp" #include "oatpp/web/server/HttpConnectionHandler.hpp"
namespace component namespace component {
class AppComponent
{ {
public:
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([] {
return oatpp::network::server::SimpleTCPConnectionProvider::createShared(5002);
}());
class AppComponent OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
{ return oatpp::web::server::HttpRouter::createShared();
public: }());
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([] {
return oatpp::network::server::SimpleTCPConnectionProvider::createShared(5002);
}());
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] { OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::server::ConnectionHandler>, serverConnectionHandler)([] {
return oatpp::web::server::HttpRouter::createShared(); OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
}());
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::server::ConnectionHandler>, serverConnectionHandler)([] { return oatpp::web::server::HttpConnectionHandler::createShared(router);
OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router); }());
return oatpp::web::server::HttpConnectionHandler::createShared(router); OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, apiObjectMapper)([] {
}()); return oatpp::parser::json::mapping::ObjectMapper::createShared();
}());
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, apiObjectMapper)([] { private:
return oatpp::parser::json::mapping::ObjectMapper::createShared(); };
}());
private:
};
} }
#endif #endif
+59 -49
View File
@@ -20,73 +20,83 @@
#include "database/AlbumRepository.h" #include "database/AlbumRepository.h"
#include "dto/AlbumDto.hpp" #include "dto/AlbumDto.hpp"
#include "manager/AlbumManager.h" #include "manager/AlbumManager.h"
#include "manager/TokenManager.h"
#include "model/Models.h" #include "model/Models.h"
#include "type/Scopes.h" #include "type/Scopes.h"
#include "type/AlbumFilter.h" #include "type/AlbumFilter.h"
namespace fs = std::filesystem; 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>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p)
{ }
AlbumController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, 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<IncomingRequest>, request))
{ {
public: auto authHeader = request->getHeader("Authorization");
AlbumController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)) OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope");
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) 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>, objectMapper)) std::cout << "starting process of retrieving album" << std::endl;
: oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) database::AlbumRepository albRepo(m_bConf);
{ } auto albsDb = albRepo.retrieveRecords();
auto albums = oatpp::data::mapping::type::List<dto::AlbumDto::ObjectWrapper>::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 albums->pushBack(alb);
ENDPOINT("GET", "/api/v1/album", albumRecords,
REQUEST(std::shared_ptr<IncomingRequest>, 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<dto::AlbumDto::ObjectWrapper>::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);
} }
// endpoint for retrieving single album record by the album id in json format return createDtoResponse(Status::CODE_200, albums);
ENDPOINT("GET", "/api/v1/album/{id}", albumRecord, }
PATH(Int32, id)) {
database::AlbumRepository albRepo(m_bConf); // endpoint for retrieving single album record by the album id in json format
model::Album albDb(id); ENDPOINT("GET", "/api/v1/album/{id}", albumRecord,
REQUEST(std::shared_ptr<IncomingRequest>, 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; OATPP_ASSERT_HTTP(albRepo.doesAlbumExists(albDb, type::AlbumFilter::id) , Status::CODE_403, "album does not exist");
albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id);
auto album = dto::AlbumDto::createShared(); std::cout << "album exists" << std::endl;
album->id = albDb.id; albDb = albRepo.retrieveRecord(albDb, type::AlbumFilter::id);
album->title = albDb.title.c_str();
album->year = albDb.year;
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) return createDtoResponse(Status::CODE_200, album);
private: }
std::string m_exe_path;
model::BinaryPath m_bConf; #include OATPP_CODEGEN_END(ApiController)
const long m_dataSize = std::numeric_limits<long long int>::max(); private:
}; std::string m_exe_path;
model::BinaryPath m_bConf;
};
} }
#endif #endif
+57 -47
View File
@@ -20,71 +20,81 @@
#include "database/ArtistRepository.h" #include "database/ArtistRepository.h"
#include "dto/ArtistDto.hpp" #include "dto/ArtistDto.hpp"
#include "manager/ArtistManager.h" #include "manager/ArtistManager.h"
#include "manager/TokenManager.h"
#include "model/Models.h" #include "model/Models.h"
#include "type/Scopes.h" #include "type/Scopes.h"
#include "type/ArtistFilter.h" #include "type/ArtistFilter.h"
namespace fs = std::filesystem; 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>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p)
{ }
ArtistController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, 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<IncomingRequest>, request))
{ {
public: auto authHeader = request->getHeader("Authorization");
ArtistController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)) OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope");
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) 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>, objectMapper)) std::cout << "starting process of retrieving artist" << std::endl;
: oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) database::ArtistRepository artRepo(m_bConf);
{ } auto artsDb = artRepo.retrieveRecords();
auto artists = oatpp::data::mapping::type::List<dto::ArtistDto::ObjectWrapper>::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 artists->pushBack(art);
ENDPOINT("GET", "/api/v1/artist", artistRecords,
REQUEST(std::shared_ptr<IncomingRequest>, 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<dto::ArtistDto::ObjectWrapper>::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);
} }
// endpoint for retrieving single artist record by the artist id in json format return createDtoResponse(Status::CODE_200, artists);
ENDPOINT("GET", "/api/v1/artist/{id}", artistRecord, }
PATH(Int32, id)) {
database::ArtistRepository artRepo(m_bConf); // endpoint for retrieving single artist record by the artist id in json format
model::Artist artDb(id); ENDPOINT("GET", "/api/v1/artist/{id}", artistRecord,
REQUEST(std::shared_ptr<IncomingRequest>, 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; OATPP_ASSERT_HTTP(artRepo.doesArtistExist(artDb, type::ArtistFilter::id) , Status::CODE_403, "artist does not exist");
artDb = artRepo.retrieveRecord(artDb, type::ArtistFilter::id);
auto artist = dto::ArtistDto::createShared(); std::cout << "artist exist" << std::endl;
artist->id = artDb.id; artDb = artRepo.retrieveRecord(artDb, type::ArtistFilter::id);
artist->artist = artDb.artist.c_str();
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) return createDtoResponse(Status::CODE_200, artist);
private: }
std::string m_exe_path;
model::BinaryPath m_bConf; #include OATPP_CODEGEN_END(ApiController)
const long m_dataSize = std::numeric_limits<long long int>::max(); private:
}; std::string m_exe_path;
model::BinaryPath m_bConf;
};
} }
#endif #endif
+72 -70
View File
@@ -26,94 +26,96 @@
namespace fs = std::filesystem; 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>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p)
{ }
CoverArtController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, 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<IncomingRequest>, request))
{ {
public: auto authHeader = request->getHeader("Authorization");
CoverArtController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)) OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope");
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) 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>, objectMapper)) std::cout << "starting process of retrieving cover art" << std::endl;
: oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) database::CoverArtRepository covRepo(m_bConf);
{ } auto covsDb = covRepo.retrieveRecords();
auto coverArts = oatpp::data::mapping::type::List<dto::CoverArtDto::ObjectWrapper>::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 coverArts->pushBack(cov);
ENDPOINT("GET", "/api/v1/coverart", coverArtRecords,
REQUEST(std::shared_ptr<IncomingRequest>, 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<dto::CoverArtDto::ObjectWrapper>::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);
} }
// endpoint for retrieving single cover art record by the cover art id in json format return createDtoResponse(Status::CODE_200, coverArts);
ENDPOINT("GET", "/api/v1/coverart/{id}", coverArtRecord, }
PATH(Int32, id)) {
database::CoverArtRepository covRepo(m_bConf); // endpoint for retrieving single cover art record by the cover art id in json format
model::Cover covDb; ENDPOINT("GET", "/api/v1/coverart/{id}", coverArtRecord,
covDb.id = id; REQUEST(std::shared_ptr<IncomingRequest>, 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; OATPP_ASSERT_HTTP(covRepo.doesCoverArtExist(covDb, type::CoverFilter::id) , Status::CODE_403, "song does not exist");
covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id);
auto coverArt = dto::CoverArtDto::createShared(); std::cout << "cover art exists" << std::endl;
coverArt->id = covDb.id; covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id);
coverArt->songTitle = covDb.songTitle.c_str();
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, return createDtoResponse(Status::CODE_200, coverArt);
PATH(Int32, id)) { }
database::CoverArtRepository covRepo(m_bConf); ENDPOINT("GET", "/api/v1/coverart/download/{id}", downloadCoverArt,
model::Cover covDb; REQUEST(std::shared_ptr<IncomingRequest>, request), PATH(Int32, id)) {
covDb.id = id; auto authHeader = request->getHeader("Authorization");
covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id); 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);
std::ifstream fl(covDb.imagePath.c_str(), std::ios::in | std::ios::binary | std::ios::ate); model::Cover covDb;
fl.seekg(0); covDb.id = id;
covDb = covRepo.retrieveRecord(covDb, type::CoverFilter::id);
std::stringstream buf; auto rawCover = oatpp::base::StrBuffer::loadFromFile(covDb.imagePath.c_str());
std::copy(std::istreambuf_iterator<char>(fl), auto response = createResponse(Status::CODE_200, rawCover);
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(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);
response->putHeader(Header::CONTENT_TYPE, "image/*"); response->putHeader(Header::CONTENT_TYPE, "image/*");
return response; return response;
} }
#include OATPP_CODEGEN_END(ApiController) #include OATPP_CODEGEN_END(ApiController)
private: private:
std::string m_exe_path; std::string m_exe_path;
model::BinaryPath m_bConf; model::BinaryPath m_bConf;
const long m_dataSize = std::numeric_limits<long long int>::max(); };
};
} }
#endif #endif
+57 -47
View File
@@ -20,71 +20,81 @@
#include "database/GenreRepository.h" #include "database/GenreRepository.h"
#include "dto/GenreDto.hpp" #include "dto/GenreDto.hpp"
#include "manager/GenreManager.h" #include "manager/GenreManager.h"
#include "manager/YearManager.h"
#include "model/Models.h" #include "model/Models.h"
#include "type/Scopes.h" #include "type/Scopes.h"
#include "type/GenreFilter.h" #include "type/GenreFilter.h"
namespace fs = std::filesystem; 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>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p)
{ }
GenreController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, 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<IncomingRequest>, request))
{ {
public: auto authHeader = request->getHeader("Authorization");
GenreController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)) OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope");
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) 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>, objectMapper)) std::cout << "starting process of retrieving genre" << std::endl;
: oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) database::GenreRepository gnrRepo(m_bConf);
{ } auto gnrsDb = gnrRepo.retrieveRecords();
auto genres = oatpp::data::mapping::type::List<dto::GenreDto::ObjectWrapper>::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 genres->pushBack(gnr);
ENDPOINT("GET", "/api/v1/genre", genreRecords,
REQUEST(std::shared_ptr<IncomingRequest>, 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<dto::GenreDto::ObjectWrapper>::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);
} }
// endpoint for retrieving single genre record by the genre id in json format return createDtoResponse(Status::CODE_200, genres);
ENDPOINT("GET", "/api/v1/genre/{id}", genreRecord, }
PATH(Int32, id)) {
database::GenreRepository gnrRepo(m_bConf); // endpoint for retrieving single genre record by the genre id in json format
model::Genre gnrDb(id); ENDPOINT("GET", "/api/v1/genre/{id}", genreRecord,
REQUEST(std::shared_ptr<IncomingRequest>, 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; OATPP_ASSERT_HTTP(gnrRepo.doesGenreExist(gnrDb, type::GenreFilter::id) , Status::CODE_403, "genre does not exist");
gnrDb = gnrRepo.retrieveRecord(gnrDb, type::GenreFilter::id);
auto genre = dto::GenreDto::createShared(); std::cout << "genre exist" << std::endl;
genre->id = gnrDb.id; gnrDb = gnrRepo.retrieveRecord(gnrDb, type::GenreFilter::id);
genre->category= gnrDb.category.c_str();
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) return createDtoResponse(Status::CODE_200, genre);
private: }
std::string m_exe_path;
model::BinaryPath m_bConf; #include OATPP_CODEGEN_END(ApiController)
const long m_dataSize = std::numeric_limits<long long int>::max(); private:
}; std::string m_exe_path;
model::BinaryPath m_bConf;
};
} }
#endif #endif
+157 -126
View File
@@ -29,100 +29,73 @@
namespace fs = std::filesystem; 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>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p)
{ }
SongController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, 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<IncomingRequest>, request))
{ {
public: auto authHeader = request->getHeader("Authorization");
SongController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)) OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope");
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) 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>, objectMapper)) auto mp = std::make_shared<oatpp::web::mime::multipart::Multipart>(request->getHeaders());
: oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf)
{ }
#include OATPP_CODEGEN_BEGIN(ApiController) oatpp::web::mime::multipart::Reader mp_reader(mp.get());
// endpoint for uploading a song mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize));
ENDPOINT("POST", "/api/v1/song/data", songUpload,
REQUEST(std::shared_ptr<IncomingRequest>, request))
{
auto authHeader = request->getHeader("Authorization");
OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); request->transferBody(&mp_reader);
auto auth = authHeader->std_str(); auto file = mp->getNamedPart("file");
manager::TokenManager tok;
OATPP_ASSERT_HTTP(tok.isTokenValid(auth, type::Scope::upload), Status::CODE_403, "Not allowed");
auto mp = std::make_shared<oatpp::web::mime::multipart::Multipart>(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<char>(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<unsigned char> 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<IncomingRequest>, 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<char>(new char[file->getKnownSize()]); std::cout << "starting process of retrieving songs" << std::endl;
auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize()); database::SongRepository songRepo(m_bConf);
auto songsDb = songRepo.retrieveRecords();
std::vector<unsigned char> data(buff.get(), buff.get() + buffSize); auto songs = oatpp::data::mapping::type::List<dto::SongDto::ObjectWrapper>::createShared();
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<IncomingRequest>, 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<dto::SongDto::ObjectWrapper>::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 << "creating object to send" << std::endl;
for (auto& songDb : songsDb) {
auto song = dto::SongDto::createShared(); auto song = dto::SongDto::createShared();
song->id = songDb.id; song->id = songDb.id;
song->title = songDb.title.c_str(); song->title = songDb.title.c_str();
@@ -134,72 +107,130 @@ namespace controller
song->track = songDb.track; song->track = songDb.track;
song->disc = songDb.disc; song->disc = songDb.disc;
return createDtoResponse(Status::CODE_200, song); songs->pushBack(song);
} }
ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, return createDtoResponse(Status::CODE_200, songs);
PATH(Int32, id)) { }
database::SongRepository songRepo(m_bConf); // endpoint for retrieving song record by the song id in json format
model::Song songDb(id); ENDPOINT("GET", "/api/v1/song/{id}", songRecord,
songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id); REQUEST(std::shared_ptr<IncomingRequest>, 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<IncomingRequest>, 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); auto response = createResponse(Status::CODE_200, rawSong);
response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); response->putHeader(Header::CONTENT_TYPE, "audio/mpeg");
return response; return response;
} }
// TODO: create endpoint for updating songs ENDPOINT("UPDATE", "/api/v1/song/{id}", songUpdate,
ENDPOINT("UPDATE", "/api/v1/song/{id}", songUpdate, REQUEST(std::shared_ptr<IncomingRequest>, request),
BODY_DTO(dto::SongDto::ObjectWrapper, songDto), PATH(Int32, id)) { BODY_DTO(dto::SongDto::ObjectWrapper, songDto), PATH(Int32, id)) {
songDto->id = 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); auto updatedSong = manager::SongManager::songDtoConv(songDto);
manager::SongManager songMgr(m_bConf); manager::SongManager songMgr(m_bConf);
songMgr.updateSong(updatedSong); songMgr.updateSong(updatedSong);
return createResponse(Status::CODE_200, "OK"); return createResponse(Status::CODE_200, "OK");
} }
// endpoint to delete a song // endpoint to delete a song
ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete,
model::Song song(id); REQUEST(std::shared_ptr<IncomingRequest>, 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); model::Song song(id);
sngMgr.deleteSong(song);
return createResponse(Status::CODE_200, "OK"); manager::SongManager sngMgr(m_bConf);
} sngMgr.deleteSong(song);
// endpoint for streaming a song return createResponse(Status::CODE_200, "OK");
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);
oatpp::data::v_io_size dSize = 1024; // endpoint for streaming a song
ENDPOINT("GET", "/api/v1/song/stream/{id}", streamSong,
REQUEST(std::shared_ptr<IncomingRequest>, 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<oatpp::web::protocol::http::outgoing::ChunkedBody>( database::SongRepository songRepo(m_bConf);
std::make_shared<callback::StreamCallback>(songDb.songPath), nullptr, dSize); model::Song songDb(id);
songDb = songRepo.retrieveRecord(songDb, type::SongFilter::id);
auto response = OutgoingResponse::createShared(Status::CODE_200, db); oatpp::data::v_io_size dSize = 1024;
response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE);
response->putHeader(Header::CONTENT_TYPE, "audio/mpeg");
return response; auto db = std::make_shared<oatpp::web::protocol::http::outgoing::ChunkedBody>(
} std::make_shared<callback::StreamCallback>(songDb.songPath), nullptr, dSize);
#include OATPP_CODEGEN_END(ApiController) auto response = OutgoingResponse::createShared(Status::CODE_200, db);
private: response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE);
std::string m_exe_path; response->putHeader(Header::CONTENT_TYPE, "audio/mpeg");
model::BinaryPath m_bConf; return response;
}
const long m_dataSize = std::numeric_limits<long long int>::max(); #include OATPP_CODEGEN_END(ApiController)
}; private:
std::string m_exe_path;
model::BinaryPath m_bConf;
const long m_dataSize = std::numeric_limits<long long int>::max();
};
} }
#endif #endif
+56 -47
View File
@@ -26,65 +26,74 @@
namespace fs = std::filesystem; 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>, objectMapper))
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p)
{ }
YearController(const model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, 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<IncomingRequest>, request))
{ {
public: auto authHeader = request->getHeader("Authorization");
YearController(std::string p, OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)) OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope");
: oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) 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>, objectMapper)) std::cout << "starting process of retrieving year" << std::endl;
: oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) database::YearRepository yrRepo(m_bConf);
{ } auto yrsDb = yrRepo.retrieveRecords();
auto yearRecs = oatpp::data::mapping::type::List<dto::YearDto::ObjectWrapper>::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 yearRecs->pushBack(yr);
ENDPOINT("GET", "/api/v1/year", yearRecords,
REQUEST(std::shared_ptr<IncomingRequest>, 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<dto::YearDto::ObjectWrapper>::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);
} }
// endpoint for retrieving single year record by the year id in json format return createDtoResponse(Status::CODE_200, yearRecs);
ENDPOINT("GET", "/api/v1/year/{id}", yearRecord, }
PATH(Int32, id)) {
database::YearRepository yrRepo(m_bConf); // endpoint for retrieving single year record by the year id in json format
model::Year yrDb(id); ENDPOINT("GET", "/api/v1/year/{id}", yearRecord,
REQUEST(std::shared_ptr<IncomingRequest>, 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; OATPP_ASSERT_HTTP(yrRepo.doesYearExist(yrDb, type::YearFilter::id) , Status::CODE_403, "year does not exist");
yrDb = yrRepo.retrieveRecord(yrDb, type::YearFilter::id);
auto year = dto::YearDto::createShared(); std::cout << "year exist" << std::endl;
year->id = yrDb.id; yrDb = yrRepo.retrieveRecord(yrDb, type::YearFilter::id);
year->year= yrDb.year;
return createDtoResponse(Status::CODE_200, year); auto year = dto::YearDto::createShared();
} year->id = yrDb.id;
year->year= yrDb.year;
#include OATPP_CODEGEN_END(ApiController) return createDtoResponse(Status::CODE_200, year);
private: }
std::string m_exe_path;
model::BinaryPath m_bConf; #include OATPP_CODEGEN_END(ApiController)
const long m_dataSize = std::numeric_limits<long long int>::max(); private:
}; std::string m_exe_path;
model::BinaryPath m_bConf;
};
} }
#endif #endif
+16 -17
View File
@@ -13,30 +13,29 @@
#include "model/Models.h" #include "model/Models.h"
#include "type/Scopes.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 isTokenValid(std::string&, type::Scope);
bool testAuth(const model::BinaryPath&); bool testAuth(const model::BinaryPath&);
private: private:
cpr::Response sendRequest(std::string_view, nlohmann::json&); 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(std::string_view);
model::AuthCredentials parseAuthCredentials(const model::BinaryPath&); model::AuthCredentials parseAuthCredentials(const model::BinaryPath&);
std::vector<std::string> extractScopes(const jwt::decoded_jwt&&); std::vector<std::string> extractScopes(const jwt::decoded_jwt&&);
std::pair<bool, std::vector<std::string>> fetchAuthHeader(const std::string&); std::pair<bool, std::vector<std::string>> fetchAuthHeader(const std::string&);
bool tokenSupportsScope(const std::vector<std::string>, const std::string&&); bool tokenSupportsScope(const std::vector<std::string>, const std::string&&);
}; };
} }
#endif #endif
+11 -1
View File
@@ -6,7 +6,17 @@ namespace type
enum class Scope enum class Scope
{ {
upload = 0, upload = 0,
download download,
stream,
retrieveSong,
updateSong,
deleteSong,
retrieveAlbum,
retrieveArtist,
retrieveGenre,
retrieveYear,
downloadCoverArt
}; };
} }
+5 -3
View File
@@ -4,10 +4,11 @@
#include <fstream> #include <fstream>
#include <memory> #include <memory>
callback::StreamCallback::StreamCallback() : namespace callback {
StreamCallback::StreamCallback() :
m_counter(0) { } m_counter(0) { }
callback::StreamCallback::StreamCallback(const std::string& songPath) : StreamCallback::StreamCallback(const std::string& songPath) :
m_songPath(songPath), m_songPath(songPath),
m_counter(0), m_counter(0),
m_bytesRead(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) { if (m_counter >= m_fileSize) {
std::cout << "done streaming song" << std::endl; 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; return count;
} }
}
+35 -16
View File
@@ -13,13 +13,13 @@
namespace fs = std::filesystem; namespace fs = std::filesystem;
namespace manager {
manager::TokenManager::TokenManager() TokenManager::TokenManager()
{ {
} }
model::LoginResult manager::TokenManager::retrieveToken(const model::BinaryPath& bConf) model::LoginResult TokenManager::retrieveToken(const model::BinaryPath& bConf)
{ {
auto cred = parseAuthCredentials(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); auto authPair = fetchAuthHeader(auth);
@@ -65,9 +65,26 @@ bool manager::TokenManager::isTokenValid(std::string& auth, type::Scope scope)
switch (scope) { switch (scope) {
case type::Scope::upload: case type::Scope::upload:
return tokenSupportsScope(scopes, "upload:songs"); return tokenSupportsScope(scopes, "upload:songs");
break;
case type::Scope::download: case type::Scope::download:
return tokenSupportsScope(scopes, "download:songs"); 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: default:
break; break;
} }
@@ -75,7 +92,7 @@ bool manager::TokenManager::isTokenValid(std::string& auth, type::Scope scope)
return false; return false;
} }
bool manager::TokenManager::testAuth(const model::BinaryPath& bConf) bool TokenManager::testAuth(const model::BinaryPath& bConf)
{ {
auto cred = parseAuthCredentials(bConf); auto cred = parseAuthCredentials(bConf);
auto reqObj = createTokenBody(cred); 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()}, auto resp = cpr::Post(cpr::Url{uri}, cpr::Body{obj.dump()},
cpr::Header{{"Content-type", "application/json"}, 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; nlohmann::json obj;
obj["client_id"] = auth.clientId; 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"); exe_path.append("/authcredentials.json");
auto con = manager::DirectoryManager::credentialConfigContent(exe_path); auto con = DirectoryManager::credentialConfigContent(exe_path);
model::AuthCredentials auth; model::AuthCredentials auth;
auth.uri = "https://"; auth.uri = "https://";
@@ -129,9 +146,9 @@ model::AuthCredentials manager::TokenManager::parseAuthCredentials(std::string_v
return auth; 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; model::AuthCredentials auth;
auth.uri = "https://"; auth.uri = "https://";
@@ -144,7 +161,7 @@ model::AuthCredentials manager::TokenManager::parseAuthCredentials(const model::
return auth; return auth;
} }
std::vector<std::string> manager::TokenManager::extractScopes(const jwt::decoded_jwt&& decoded) std::vector<std::string> TokenManager::extractScopes(const jwt::decoded_jwt&& decoded)
{ {
std::vector<std::string> scopes; std::vector<std::string> scopes;
@@ -162,7 +179,7 @@ std::vector<std::string> manager::TokenManager::extractScopes(const jwt::decoded
return scopes; return scopes;
} }
std::pair<bool, std::vector<std::string>> manager::TokenManager::fetchAuthHeader(const std::string& auth) std::pair<bool, std::vector<std::string>> TokenManager::fetchAuthHeader(const std::string& auth)
{ {
std::istringstream iss(auth); std::istringstream iss(auth);
std::vector<std::string> authHeader{std::istream_iterator<std::string>(iss), std::vector<std::string> authHeader{std::istream_iterator<std::string>(iss),
@@ -182,10 +199,12 @@ std::pair<bool, std::vector<std::string>> manager::TokenManager::fetchAuthHeader
} }
bool manager::TokenManager::tokenSupportsScope(const std::vector<std::string> scopes, const std::string&& scope) bool TokenManager::tokenSupportsScope(const std::vector<std::string> scopes,
const std::string&& scope)
{ {
return std::any_of(scopes.begin(), scopes.end(), return std::any_of(scopes.begin(), scopes.end(),
[&](std::string foundScope) { [&](std::string foundScope) {
return (foundScope.compare(scope) == 0); return (foundScope.compare(scope) == 0);
}); });
} }
}