diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d52c10..f2e2609 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ set(SOURCES src/database/SongRepository.cpp src/database/UserRepository.cpp src/database/YearRepository.cpp + src/dto/conversion/DtoConversions.cpp src/Main.cpp src/manager/AlbumManager.cpp src/manager/ArtistManager.cpp @@ -56,6 +57,7 @@ set(HEADERS include/dto/LoginResultDto.hpp include/dto/SongDto.hpp include/dto/YearDto.hpp + include/dto/conversion/DtoConversions.h include/manager/AlbumManager.h include/manager/ArtistManager.h include/manager/CoverArtManager.h diff --git a/include/controller/LoginController.hpp b/include/controller/LoginController.hpp index 0d51079..78bcbbf 100644 --- a/include/controller/LoginController.hpp +++ b/include/controller/LoginController.hpp @@ -10,13 +10,13 @@ #include "oatpp/web/server/api/ApiController.hpp" #include "dto/LoginResultDto.hpp" +#include "dto/conversion/DtoConversions.h" #include "manager/TokenManager.h" #include "manager/UserManager.h" #include "model/Models.h" namespace controller { -class LoginController : public oatpp::web::server::api::ApiController -{ +class LoginController : public oatpp::web::server::api::ApiController { public: LoginController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) : oatpp::web::server::api::ApiController(objectMapper), exe_path(p) @@ -32,29 +32,21 @@ public: OATPP_LOGI("icarus", "logging in"); manager::UserManager usrMgr(m_bConf); - auto user = manager::UserManager::userDtoConv(usr); + auto user = dto::conversion::DtoConversions::toUser(usr); - if (!usrMgr.doesUserExist(user)) { + if (!usrMgr.doesUserExist(user) || !usrMgr.validatePassword(user)) { + auto logRes = dto::LoginResultDto::createShared(); + logRes->message = "invalid credentials"; std::cout << "user does not exist" << std::endl; - return createResponse(Status::CODE_401, "invalid credentials"); + return createDtoResponse(Status::CODE_401, logRes); } std::cout << "user exists" << std::endl; - if (!usrMgr.validatePassword(user)) { - std::cout << "password is not valid" << std::endl; - return createResponse(Status::CODE_401, "invalid credentials"); - } - manager::TokenManager tok; auto token = tok.retrieveToken(m_bConf); - auto logRes = dto::LoginResultDto::createShared(); - logRes->id = 0; // TODO: change this later on to something meaningful or remove it - logRes->username = usr->username->c_str(); - logRes->token = token.accessToken.c_str(); - logRes->token_type = token.tokenType.c_str(); - logRes->expiration = token.expiration; + auto logRes = dto::conversion::DtoConversions::toLoginResultDto(user, token); logRes->message = "Successful"; return createDtoResponse(Status::CODE_200, logRes); diff --git a/include/controller/RegisterController.hpp b/include/controller/RegisterController.hpp index 6724501..b1b3fc7 100644 --- a/include/controller/RegisterController.hpp +++ b/include/controller/RegisterController.hpp @@ -9,27 +9,28 @@ #include "oatpp/web/server/api/ApiController.hpp" #include "dto/LoginResultDto.hpp" +#include "dto/conversion/DtoConversions.h" #include "manager/UserManager.h" #include "model/Models.h" -namespace controller -{ - class RegisterController : public oatpp::web::server::api::ApiController - { +namespace controller { + class RegisterController : public oatpp::web::server::api::ApiController { public: RegisterController(const model::BinaryPath& bConf, - OATPP_COMPONENT(std::shared_ptr, objectMapper)) : + OATPP_COMPONENT(std::shared_ptr, objectMapper)) : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) { } #include OATPP_CODEGEN_BEGIN(ApiController) - ENDPOINT("POST", "api/v1/register", registerUser, BODY_DTO(dto::UserDto::ObjectWrapper, usr)) { + ENDPOINT("POST", "api/v1/register", registerUser, + BODY_DTO(dto::UserDto::ObjectWrapper, usr)) { manager::UserManager usrMgr(m_bConf); - auto user = usrMgr.userDtoConv(usr); + auto user = dto::conversion::DtoConversions::toUser(usr); - usrMgr.registerUser(user); + auto res = usrMgr.registerUser(user); + auto registerResult = dto::conversion::DtoConversions::toRegisterResultDto(res); - return createResponse(Status::CODE_200, "Reg"); + return createDtoResponse(Status::CODE_200, registerResult); } #include OATPP_CODEGEN_END(ApiController) private: diff --git a/include/controller/SongController.hpp b/include/controller/SongController.hpp index 07baa28..1aab05d 100644 --- a/include/controller/SongController.hpp +++ b/include/controller/SongController.hpp @@ -30,8 +30,7 @@ namespace fs = std::filesystem; 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) diff --git a/include/dto/LoginResultDto.hpp b/include/dto/LoginResultDto.hpp index 43f22d6..1f0548e 100644 --- a/include/dto/LoginResultDto.hpp +++ b/include/dto/LoginResultDto.hpp @@ -4,12 +4,12 @@ #include "oatpp/core/data/mapping/type/Object.hpp" #include "oatpp/core/macro/codegen.hpp" -namespace dto -{ +#include "model/Models.h" + +namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) - class LoginResultDto : public oatpp::data::mapping::type::Object - { + class LoginResultDto : public oatpp::data::mapping::type::Object { DTO_INIT(LoginResultDto, Object) DTO_FIELD(Int32, id); @@ -20,8 +20,15 @@ namespace dto DTO_FIELD(String, message); }; - class UserDto : public oatpp::data::mapping::type::Object - { + class RegisterResultDto : public oatpp::data::mapping::type::Object { + DTO_INIT(RegisterResultDto, Object) + + DTO_FIELD(String, username); + DTO_FIELD(Boolean, registered); + DTO_FIELD(String, message); + }; + + class UserDto : public oatpp::data::mapping::type::Object { DTO_INIT(UserDto, Object) DTO_FIELD(Int32, userId); @@ -34,6 +41,7 @@ namespace dto }; #include OATPP_CODEGEN_END(DTO) + } #endif diff --git a/include/dto/SongDto.hpp b/include/dto/SongDto.hpp index 12b90c8..fccdda8 100644 --- a/include/dto/SongDto.hpp +++ b/include/dto/SongDto.hpp @@ -4,6 +4,8 @@ #include "oatpp/core/data/mapping/type/Object.hpp" #include "oatpp/core/macro/codegen.hpp" +#include "model/Models.h" + namespace dto { #include OATPP_CODEGEN_BEGIN(DTO) @@ -24,6 +26,8 @@ namespace dto }; #include OATPP_CODEGEN_END(DTO) + + } #endif diff --git a/include/dto/conversion/DtoConversions.h b/include/dto/conversion/DtoConversions.h new file mode 100644 index 0000000..f8b1b9b --- /dev/null +++ b/include/dto/conversion/DtoConversions.h @@ -0,0 +1,22 @@ +#ifndef DTOCONVERSIONS_H_ +#define DTOCONVERSIONS_H_ + +#include "dto/LoginResultDto.hpp" +#include "dto/SongDto.hpp" +#include "model/Models.h" + +namespace dto { namespace conversion { + class DtoConversions { + public: + static dto::LoginResultDto::ObjectWrapper toLoginResultDto(const model::User&, const model::Token&); + + static dto::RegisterResultDto::ObjectWrapper toRegisterResultDto( + const model::RegisterResult&); + + static model::Song toSong(dto::SongDto::ObjectWrapper&); + + static model::User toUser(dto::UserDto::ObjectWrapper&); + }; +}} + +#endif diff --git a/include/manager/TokenManager.h b/include/manager/TokenManager.h index 686b233..d027ad2 100644 --- a/include/manager/TokenManager.h +++ b/include/manager/TokenManager.h @@ -14,12 +14,11 @@ #include "type/Scopes.h" namespace manager { -class TokenManager -{ +class TokenManager { public: TokenManager(); - model::LoginResult retrieveToken(const model::BinaryPath&); + model::Token retrieveToken(const model::BinaryPath&); bool isTokenValid(std::string&, type::Scope); bool testAuth(const model::BinaryPath&); @@ -34,7 +33,7 @@ private: 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&&); }; } diff --git a/include/manager/UserManager.h b/include/manager/UserManager.h index e33a538..0734cef 100644 --- a/include/manager/UserManager.h +++ b/include/manager/UserManager.h @@ -7,18 +7,16 @@ #include "model/Models.h" namespace manager { -class UserManager -{ +class UserManager { public: UserManager(const model::BinaryPath&); + model::RegisterResult registerUser(model::User&); + bool doesUserExist(const model::User&); bool validatePassword(const model::User&); void printUser(const model::User&); - void registerUser(model::User&); - - static model::User userDtoConv(dto::UserDto::ObjectWrapper&); private: model::BinaryPath m_bConf; }; diff --git a/include/model/Models.h b/include/model/Models.h index 13f3789..0e80dfb 100644 --- a/include/model/Models.h +++ b/include/model/Models.h @@ -5,8 +5,7 @@ #include namespace model { -struct Song -{ +struct Song { Song() = default; Song(const int id) : id(id) { } @@ -28,8 +27,7 @@ struct Song int yearId; }; -struct Artist -{ +struct Artist { Artist() = default; Artist(const Song& song) { @@ -42,8 +40,7 @@ struct Artist std::string artist; }; -struct Album -{ +struct Album { Album() = default; Album(const Song& song) { @@ -59,8 +56,7 @@ struct Album std::vector songs; }; -struct Genre -{ +struct Genre { Genre() = default; Genre(const Song& song) { @@ -74,8 +70,7 @@ struct Genre }; -struct Year -{ +struct Year { Year() = default; Year(const Song& song) { @@ -88,8 +83,7 @@ struct Year int year; }; -struct Cover -{ +struct Cover { Cover() = default; Cover(const Song& song) { @@ -105,8 +99,22 @@ struct Cover std::vector data; }; -struct LoginResult -{ +class Token { +public: + Token() = default; + Token(const std::string& accessToken) : + accessToken(accessToken) { } + Token(const std::string& accessToken, const std::string& tokenType, + const int expiration) : + accessToken(accessToken), tokenType(tokenType), + expiration(expiration) { } + + std::string accessToken; + int expiration; + std::string tokenType; +}; + +struct LoginResult { int userId; std::string username; std::string accessToken; @@ -115,8 +123,14 @@ struct LoginResult int expiration; }; -struct User -{ +class RegisterResult { +public: + std::string username; + bool registered; + std::string message; +}; + +struct User { int id; std::string firstname; std::string lastname; @@ -126,16 +140,14 @@ struct User std::string password; }; -struct PassSec -{ +struct PassSec { int id; std::string hashPassword; std::string salt; int userId; }; -struct AuthCredentials -{ +struct AuthCredentials { std::string domain; std::string apiIdentifier; std::string clientId; @@ -144,16 +156,14 @@ struct AuthCredentials std::string endpoint; }; -struct DatabaseConnection -{ +struct DatabaseConnection { std::string server; std::string username; std::string password; std::string database; }; -struct BinaryPath -{ +struct BinaryPath { BinaryPath() = default; BinaryPath(const char *p) : path(std::move(p)) { } BinaryPath(std::string& p) : path(p) { } diff --git a/src/dto/conversion/DtoConversions.cpp b/src/dto/conversion/DtoConversions.cpp new file mode 100644 index 0000000..084e2c3 --- /dev/null +++ b/src/dto/conversion/DtoConversions.cpp @@ -0,0 +1,54 @@ +#include "dto/conversion/DtoConversions.h" + +namespace dto { namespace conversion { + dto::LoginResultDto::ObjectWrapper DtoConversions::toLoginResultDto(const model::User& user, + const model::Token& token) { + auto logRes = dto::LoginResultDto::createShared(); + logRes->username = user.username.c_str(); + logRes->token = token.accessToken.c_str(); + logRes->token_type = token.tokenType.c_str(); + logRes->expiration = token.expiration; + + return logRes; + } + + + dto::RegisterResultDto::ObjectWrapper DtoConversions::toRegisterResultDto( + const model::RegisterResult& regRes) { + auto result = dto::RegisterResultDto::createShared(); + result->message = regRes.message.c_str(); + result->registered = regRes.registered; + result->username = regRes.username.c_str(); + + return result; + } + + + model::Song DtoConversions::toSong(dto::SongDto::ObjectWrapper& songDto) { + model::Song song; + song.id = (songDto->id.getPtr() == nullptr) ? 0 : songDto->id->getValue(); + song.title = (songDto->title == nullptr) ? "" : songDto->title->c_str(); + song.album = (songDto->album == nullptr) ? "" : songDto->album->c_str(); + song.artist = (songDto->artist == nullptr) ? "" : songDto->artist->c_str(); + song.genre = (songDto->genre == nullptr) ? "" : songDto->genre->c_str(); + song.year = (songDto->year.getPtr() == nullptr) ? 0 : songDto->year->getValue(); + song.track = (songDto->track.getPtr() == nullptr) ? 0 : songDto->track->getValue(); + song.disc = (songDto->disc.getPtr() == nullptr) ? 0 : songDto->disc->getValue(); + + return song; + } + + + model::User DtoConversions::toUser(dto::UserDto::ObjectWrapper& userDto) { + model::User user; + user.id = (userDto->userId.getPtr() == nullptr) ? 0 : userDto->userId->getValue(); + user.firstname = (userDto->firstname == nullptr) ? "" : userDto->firstname->c_str(); + user.lastname = (userDto->lastname == nullptr) ? "" : userDto->lastname->c_str(); + user.phone = (userDto->phone == nullptr) ? "" : userDto->phone->c_str(); + user.email = (userDto->email == nullptr) ? "" : userDto->email->c_str(); + user.username = (userDto->username == nullptr) ? "" : userDto->username->c_str(); + user.password = (userDto->password == nullptr) ? "" : userDto->password->c_str(); + + return user; + } +}} diff --git a/src/manager/SongManager.cpp b/src/manager/SongManager.cpp index a4a9601..8ddbbea 100644 --- a/src/manager/SongManager.cpp +++ b/src/manager/SongManager.cpp @@ -308,8 +308,8 @@ void manager::SongManager::saveMisc(model::Song& song) auto musicRootPath = pathConfigContent["root_music_path"].get(); auto cov = covMgr.saveCover(song); + const auto songPath = createSongPath(song); - auto songPath = createSongPath(song); if (fs::exists(songPath)) { std::cout << "deleting old song with the same metadata" << std::endl; fs::remove(songPath); diff --git a/src/manager/TokenManager.cpp b/src/manager/TokenManager.cpp index ab9cf9a..72edbf0 100644 --- a/src/manager/TokenManager.cpp +++ b/src/manager/TokenManager.cpp @@ -19,28 +19,21 @@ TokenManager::TokenManager() } -model::LoginResult TokenManager::retrieveToken(const model::BinaryPath& bConf) +model::Token TokenManager::retrieveToken(const model::BinaryPath& bConf) { auto cred = parseAuthCredentials(bConf); - auto reqObj = createTokenBody(cred); std::string uri{cred.uri}; uri.append("/"); uri.append(cred.endpoint); - auto r = cpr::Post(cpr::Url{uri}, - cpr::Body{reqObj.dump()}, - cpr::Header{{"Content-Type", "application/json"}, - {"Connection", "keep-alive"}}); - - + auto r = sendRequest(uri, reqObj); auto postRes = nlohmann::json::parse(r.text); - model::LoginResult lr; - lr.accessToken = postRes["access_token"].get(); - lr.tokenType = postRes["token_type"].get(); - lr.expiration = postRes["expires_in"].get(); + model::Token lr(std::move(postRes["access_token"].get()), + std::move(postRes["token_type"].get()), + postRes["expires_in"].get()); return lr; } @@ -129,6 +122,7 @@ nlohmann::json TokenManager::createTokenBody(const model::AuthCredentials& auth) } +[[depreacted("use the other function with the same name")]] model::AuthCredentials TokenManager::parseAuthCredentials(std::string_view path) { auto exe_path = DirectoryManager::configPath(path); @@ -165,7 +159,7 @@ std::vector TokenManager::extractScopes(const jwt::decoded_jwt&& de { std::vector scopes; - for (auto d : decoded.get_payload_claims()) { + for (auto& d : decoded.get_payload_claims()) { if (d.first.compare("scope") == 0) { std::cout << "found scope" << std::endl; std::string allScopes(d.second.to_json().get()); @@ -188,7 +182,7 @@ std::pair> TokenManager::fetchAuthHeader(const st bool foundBearer = false; if (std::any_of(authHeader.begin(), authHeader.end(), - [](std::string word) { + [&](std::string_view word) { return (word.compare("Bearer") == 0); })) { std::cout << "Bearer found" << std::endl; @@ -199,11 +193,11 @@ std::pair> TokenManager::fetchAuthHeader(const st } -bool TokenManager::tokenSupportsScope(const std::vector scopes, +bool TokenManager::tokenSupportsScope(const std::vector& scopes, const std::string&& scope) { return std::any_of(scopes.begin(), scopes.end(), - [&](std::string foundScope) { + [&](std::string_view foundScope) { return (foundScope.compare(scope) == 0); }); } diff --git a/src/manager/UserManager.cpp b/src/manager/UserManager.cpp index 650f01c..e5f8d8a 100644 --- a/src/manager/UserManager.cpp +++ b/src/manager/UserManager.cpp @@ -9,45 +9,10 @@ namespace manager { UserManager::UserManager(const model::BinaryPath& bConf) : m_bConf(bConf) { } -bool UserManager::doesUserExist(const model::User& user) -{ - database::UserRepository userRepo(m_bConf); - return userRepo.doesUserRecordExist(user, type::UserFilter::username); -} - -bool UserManager::validatePassword(const model::User& user) -{ - database::UserRepository userRepo(m_bConf); - model::User usr; - usr.username = user.username; - usr = userRepo.retrieveUserRecord(usr, type::UserFilter::username); - - model::PassSec userSec; - userSec.userId = usr.id; - userSec = userRepo.retrieverUserSaltRecord(userSec, type::SaltFilter::userId); - userSec.hashPassword = usr.password; - - utility::PasswordEncryption passEnc; - - return passEnc.isPasswordValid(user, userSec); -} - - -void UserManager::printUser(const model::User& user) -{ - std::cout << "\nuser info" << std::endl; - std::cout << "id: " << user.id << std::endl; - std::cout << "firstname: " << user.firstname << std::endl; - std::cout << "lastname: " << user.lastname << std::endl; - std::cout << "phone: " << user.phone << std::endl; - std::cout << "email: " << user.email << std::endl; - std::cout << "username: " << user.username << std::endl; - std::cout << "password: " << user.password<< std::endl; -} - -void UserManager::registerUser(model::User& user) -{ +model::RegisterResult UserManager::registerUser(model::User& user) { + model::RegisterResult result; + result.username = user.username; printUser(user); utility::PasswordEncryption passEnc; @@ -66,22 +31,46 @@ void UserManager::registerUser(model::User& user) hashed.userId = usr.id; usrRepo.saveUserSalt(hashed); + result.registered = true; + result.message = "successfully registered"; printUser(usr); + + return result; } -model::User UserManager::userDtoConv(dto::UserDto::ObjectWrapper& userDto) -{ - model::User user; +bool UserManager::doesUserExist(const model::User& user) { + database::UserRepository userRepo(m_bConf); - user.id = (userDto->userId.getPtr() == nullptr) ? 0 : userDto->userId->getValue(); - user.firstname = (userDto->firstname == nullptr) ? "" : userDto->firstname->c_str(); - user.lastname = (userDto->lastname == nullptr) ? "" : userDto->lastname->c_str(); - user.phone = (userDto->phone == nullptr) ? "" : userDto->phone->c_str(); - user.email = (userDto->email == nullptr) ? "" : userDto->email->c_str(); - user.username = (userDto->username == nullptr) ? "" : userDto->username->c_str(); - user.password = (userDto->password == nullptr) ? "" : userDto->password->c_str(); + return userRepo.doesUserRecordExist(user, type::UserFilter::username); +} - return user; +bool UserManager::validatePassword(const model::User& user) { + database::UserRepository userRepo(m_bConf); + model::User usr; + usr.username = user.username; + usr = userRepo.retrieveUserRecord(usr, type::UserFilter::username); + + model::PassSec userSec; + userSec.userId = usr.id; + userSec = userRepo.retrieverUserSaltRecord(userSec, type::SaltFilter::userId); + userSec.hashPassword = usr.password; + + utility::PasswordEncryption passEnc; + + return passEnc.isPasswordValid(user, userSec); } + + +void UserManager::printUser(const model::User& user) { + std::cout << "\nuser info" << std::endl; + std::cout << "id: " << user.id << std::endl; + std::cout << "firstname: " << user.firstname << std::endl; + std::cout << "lastname: " << user.lastname << std::endl; + std::cout << "phone: " << user.phone << std::endl; + std::cout << "email: " << user.email << std::endl; + std::cout << "username: " << user.username << std::endl; + std::cout << "password: " << user.password<< std::endl; +} + }