From 0fc16daf86a9ba90530fb46fd99310c14ca4dd6a Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 17 Aug 2019 16:04:54 -0400 Subject: [PATCH 01/36] Tying something out --- .gitmodules | 11 +- {Libs => 3rdparty}/cpr | 0 3rdparty/oatpp | 1 + 3rdparty/taglib | 1 + Authorization/Handlers/HasScopeHandler.cs | 31 - Authorization/HasScopeRequirement.cs | 19 - CMakeLists.txt | 65 ++ Constants/DirectoryPaths.cs | 11 - Controllers/Managers/BaseManagers.cs | 13 - Controllers/Managers/CoverArtManager.cs | 104 --- Controllers/Managers/DirectoryManager.cs | 41 - Controllers/Managers/SongManager.cs | 753 ------------------ Controllers/Managers/TokenManager.cs | 51 -- Controllers/Utilities/MetadataRetriever.cs | 74 -- Controllers/Utilities/PasswordEncryption.cs | 90 --- Controllers/Utilities/SongCompression.cs | 129 --- Controllers/v1/AlbumController.cs | 77 -- Controllers/v1/ArtistController.cs | 76 -- Controllers/v1/CoverArtController.cs | 87 -- Controllers/v1/GenreController.cs | 76 -- Controllers/v1/LoginController.cs | 95 --- Controllers/v1/RegisterController.cs | 70 -- .../v1/SongCompressedDataControllers.cs | 64 -- Controllers/v1/SongController.cs | 114 --- Controllers/v1/SongDataController.cs | 152 ---- Controllers/v1/SongStreamController.cs | 61 -- Controllers/v1/YearController.cs | 76 -- Database/Contexts/AlbumContext.cs | 25 - Database/Contexts/ArtistContext.cs | 25 - Database/Contexts/CoverArtContext.cs | 25 - Database/Contexts/GenreContext.cs | 24 - Database/Contexts/SongContext.cs | 75 -- Database/Contexts/UserContext.cs | 30 - Database/Contexts/YearContext.cs | 25 - Database/Repositories/AlbumRepository.cs | 386 --------- Database/Repositories/ArtistRepository.cs | 355 --------- Database/Repositories/BaseRepository.cs | 23 - Database/Repositories/CoverArtRepository.cs | 282 ------- Database/Repositories/GenreRepository.cs | 447 ----------- Database/Repositories/SongRepository.cs | 315 -------- Database/Repositories/UserRepository.cs | 229 ------ Database/Repositories/YearRepository.cs | 367 --------- Icarus.csproj | 34 - Icarus.csproj.user | 9 - Icarus.sln | 34 - Libs/CMakeLists.txt | 28 - Libs/include/imageFile.h | 38 - Migrations/.empty | 0 Models/Album.cs | 24 - Models/Artist.cs | 22 - Models/BaseResult.cs | 12 - Models/CoverArt.cs | 34 - Models/Genre.cs | 22 - Models/LoginResult.cs | 36 - Models/RegisterResult.cs | 14 - Models/Song.cs | 73 -- Models/SongData.cs | 12 - Models/SongResult.cs | 14 - Models/TokenReq.cs | 22 - Models/User.cs | 33 - Models/Year.cs | 22 - Program.cs | 47 -- Properties/launchSettings.json | 30 - Startup.cs | 157 ---- Types/CoverArtTypes.cs | 10 - Types/DirectoryTypes.cs | 10 - appsettings.Development.json | 22 - build/3rdparty/jwt-cpp | 1 + Libs/conanfile.txt => conanfile.txt | 0 {Libs/include => include}/directory_manager.h | 0 include/imageFile.h | 48 ++ .../include => include}/metadata_retriever.h | 0 {Libs/include => include}/models.h | 0 nlog.config | 33 - src/appComponent.hpp | 34 + src/controller/loginController.hpp | 34 + {Libs/src => src}/directory_manager.cpp | 0 src/dto/loginResultDto.hpp | 19 + {Libs/src => src}/imageFile.cpp | 0 src/loginHandler.cpp | 2 + src/loginHandler.hpp | 29 + src/main.cpp | 43 + {Libs/src => src}/metadata_retriever.cpp | 12 +- {Libs/src => src}/token_manager.cpp | 0 84 files changed, 295 insertions(+), 5694 deletions(-) rename {Libs => 3rdparty}/cpr (100%) create mode 160000 3rdparty/oatpp create mode 160000 3rdparty/taglib delete mode 100644 Authorization/Handlers/HasScopeHandler.cs delete mode 100644 Authorization/HasScopeRequirement.cs create mode 100644 CMakeLists.txt delete mode 100644 Constants/DirectoryPaths.cs delete mode 100644 Controllers/Managers/BaseManagers.cs delete mode 100644 Controllers/Managers/CoverArtManager.cs delete mode 100644 Controllers/Managers/DirectoryManager.cs delete mode 100644 Controllers/Managers/SongManager.cs delete mode 100644 Controllers/Managers/TokenManager.cs delete mode 100644 Controllers/Utilities/MetadataRetriever.cs delete mode 100644 Controllers/Utilities/PasswordEncryption.cs delete mode 100644 Controllers/Utilities/SongCompression.cs delete mode 100644 Controllers/v1/AlbumController.cs delete mode 100644 Controllers/v1/ArtistController.cs delete mode 100644 Controllers/v1/CoverArtController.cs delete mode 100644 Controllers/v1/GenreController.cs delete mode 100644 Controllers/v1/LoginController.cs delete mode 100644 Controllers/v1/RegisterController.cs delete mode 100644 Controllers/v1/SongCompressedDataControllers.cs delete mode 100644 Controllers/v1/SongController.cs delete mode 100644 Controllers/v1/SongDataController.cs delete mode 100644 Controllers/v1/SongStreamController.cs delete mode 100644 Controllers/v1/YearController.cs delete mode 100644 Database/Contexts/AlbumContext.cs delete mode 100644 Database/Contexts/ArtistContext.cs delete mode 100644 Database/Contexts/CoverArtContext.cs delete mode 100644 Database/Contexts/GenreContext.cs delete mode 100644 Database/Contexts/SongContext.cs delete mode 100644 Database/Contexts/UserContext.cs delete mode 100644 Database/Contexts/YearContext.cs delete mode 100644 Database/Repositories/AlbumRepository.cs delete mode 100644 Database/Repositories/ArtistRepository.cs delete mode 100644 Database/Repositories/BaseRepository.cs delete mode 100644 Database/Repositories/CoverArtRepository.cs delete mode 100644 Database/Repositories/GenreRepository.cs delete mode 100644 Database/Repositories/SongRepository.cs delete mode 100644 Database/Repositories/UserRepository.cs delete mode 100644 Database/Repositories/YearRepository.cs delete mode 100644 Icarus.csproj delete mode 100644 Icarus.csproj.user delete mode 100644 Icarus.sln delete mode 100644 Libs/CMakeLists.txt delete mode 100644 Libs/include/imageFile.h delete mode 100644 Migrations/.empty delete mode 100644 Models/Album.cs delete mode 100644 Models/Artist.cs delete mode 100644 Models/BaseResult.cs delete mode 100644 Models/CoverArt.cs delete mode 100644 Models/Genre.cs delete mode 100644 Models/LoginResult.cs delete mode 100644 Models/RegisterResult.cs delete mode 100644 Models/Song.cs delete mode 100644 Models/SongData.cs delete mode 100644 Models/SongResult.cs delete mode 100644 Models/TokenReq.cs delete mode 100644 Models/User.cs delete mode 100644 Models/Year.cs delete mode 100644 Program.cs delete mode 100644 Properties/launchSettings.json delete mode 100644 Startup.cs delete mode 100644 Types/CoverArtTypes.cs delete mode 100644 Types/DirectoryTypes.cs delete mode 100644 appsettings.Development.json create mode 160000 build/3rdparty/jwt-cpp rename Libs/conanfile.txt => conanfile.txt (100%) rename {Libs/include => include}/directory_manager.h (100%) create mode 100644 include/imageFile.h rename {Libs/include => include}/metadata_retriever.h (100%) rename {Libs/include => include}/models.h (100%) delete mode 100644 nlog.config create mode 100644 src/appComponent.hpp create mode 100644 src/controller/loginController.hpp rename {Libs/src => src}/directory_manager.cpp (100%) create mode 100644 src/dto/loginResultDto.hpp rename {Libs/src => src}/imageFile.cpp (100%) create mode 100644 src/loginHandler.cpp create mode 100644 src/loginHandler.hpp create mode 100644 src/main.cpp rename {Libs/src => src}/metadata_retriever.cpp (92%) rename {Libs/src => src}/token_manager.cpp (100%) diff --git a/.gitmodules b/.gitmodules index 06db291..bb89d93 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,12 @@ [submodule "Libs/cpr"] - path = Libs/cpr + path = 3rdparty/cpr url = https://github.com/whoshuu/cpr.git +[submodule "3rdparty/taglib"] + path = 3rdparty/taglib + url = https://github.com/taglib/taglib +[submodule "3rdparty/oatpp"] + path = 3rdparty/oatpp + url = https://github.com/oatpp/oatpp +[submodule "build/3rdparty/jwt-cpp"] + path = build/3rdparty/jwt-cpp + url = https://github.com/Thalhammer/jwt-cpp diff --git a/Libs/cpr b/3rdparty/cpr similarity index 100% rename from Libs/cpr rename to 3rdparty/cpr diff --git a/3rdparty/oatpp b/3rdparty/oatpp new file mode 160000 index 0000000..2156421 --- /dev/null +++ b/3rdparty/oatpp @@ -0,0 +1 @@ +Subproject commit 215642129d79d9d0335b4618e75dd2ba634aceb2 diff --git a/3rdparty/taglib b/3rdparty/taglib new file mode 160000 index 0000000..79bc9cc --- /dev/null +++ b/3rdparty/taglib @@ -0,0 +1 @@ +Subproject commit 79bc9ccf8ea5606da2a86e1bfb5439e73a146272 diff --git a/Authorization/Handlers/HasScopeHandler.cs b/Authorization/Handlers/HasScopeHandler.cs deleted file mode 100644 index 7c50cf4..0000000 --- a/Authorization/Handlers/HasScopeHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Linq; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Authorization; - -using Icarus.Authorization; - -namespace Icarus.Authorization.Handlers -{ - public class HasScopeHandler : AuthorizationHandler - { - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, HasScopeRequirement requirement) - { - if (!context.User.HasClaim(c => c.Type == "scope" && c.Issuer == requirement.Issuer)) - { - return Task.CompletedTask; - } - - var scopes = context.User.FindFirst(c => - c.Type == "scope" && c.Issuer == requirement.Issuer).Value.Split(' '); - - if (scopes.Any(s => s == requirement.Scope)) - { - context.Succeed(requirement); - } - - return Task.CompletedTask; - } - } -} diff --git a/Authorization/HasScopeRequirement.cs b/Authorization/HasScopeRequirement.cs deleted file mode 100644 index d62bda5..0000000 --- a/Authorization/HasScopeRequirement.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; - -using Microsoft.AspNetCore.Authorization; - -namespace Icarus.Authorization -{ - public class HasScopeRequirement : IAuthorizationRequirement - { - public string Issuer { get; } - public string Scope { get; } - - - public HasScopeRequirement(string scope, string issuer) - { - Scope = scope ?? throw new ArgumentNullException(nameof(scope)); - Issuer = issuer ?? throw new ArgumentNullException(nameof(issuer)); - } - } -} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..dc1a8de --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,65 @@ +cmake_minimum_required(VERSION 3.10) + +project(icarus) + +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) + +set(SOURCES + src/appComponent.hpp + src/controller/loginController.hpp + src/directory_manager.cpp + src/dto/loginResultDto.hpp + src/imageFile.cpp + src/main.cpp + src/metadata_retriever.cpp + src/token_manager.cpp +) +set(HEADERS + include/models.h + include/directory_manager.h + include/imageFile.h + include/metadata_retriever.h +) + +set (TAGLIB + ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/taglib/3rdparty +) + +set(TAGLIB_HEADERS + "${CMAKE_SOURCE_DIR}/build/3rdparty/taglib" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/ape" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/asf" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/dsdiff" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/dsf" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/flac" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/it" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mod" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mp4" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpc" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpeg" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpeg/id3v2" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/mpeg/id3v2/frames" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/ogg" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/riff" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/s3m" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/toolkit" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/trueaudio" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/wavpack" + "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/xm" +) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup() + +include_directories(include ${CPR_INCLUDE_DIRS} ${TAGLIB} ${TAGLIB_HEADERS}) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/cpr) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/taglib) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/oatpp) + +add_executable(icarus ${SOURCES} ${HEADERS}) +target_include_directories(icarus PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include) +target_link_libraries(icarus "-lstdc++fs" tag oatpp ${CONAN_LIBS} ${CPR_LIBRARIES}) diff --git a/Constants/DirectoryPaths.cs b/Constants/DirectoryPaths.cs deleted file mode 100644 index 49ccb32..0000000 --- a/Constants/DirectoryPaths.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.IO; - -namespace Icarus.Constants -{ - public class DirectoryPaths - { - public static string CoverArtPath => - Directory.GetCurrentDirectory() + "/Images/Stock/CoverArt.png"; - } -} diff --git a/Controllers/Managers/BaseManagers.cs b/Controllers/Managers/BaseManagers.cs deleted file mode 100644 index 125457d..0000000 --- a/Controllers/Managers/BaseManagers.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -using NLog; - -namespace Icarus.Controllers.Managers -{ - public class BaseManager - { - #region Fields - protected static Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); - #endregion - } -} diff --git a/Controllers/Managers/CoverArtManager.cs b/Controllers/Managers/CoverArtManager.cs deleted file mode 100644 index 8b22480..0000000 --- a/Controllers/Managers/CoverArtManager.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -using Icarus.Constants; -using Icarus.Controllers.Utilities; -using Icarus.Database.Repositories; -using Icarus.Models; -using Icarus.Types; - -namespace Icarus.Controllers.Managers -{ - public class CoverArtManager : BaseManager - { - #region Fields - private string _rootCoverArtPath; - #endregion - - - #region Constructors - public CoverArtManager(string rootPath) - { - _rootCoverArtPath = rootPath; - Initialize(); - } - #endregion - - - #region Methods - public void SaveCoverArtToDatabase(ref Song song, ref CoverArt coverArt, - CoverArtRepository coverArtRepository) - { - _logger.Info("Saving cover art record to the database"); - coverArtRepository.SaveCoverArt(coverArt); - - coverArt = coverArtRepository.GetCoverArt(CoverArtField.SongTitle, - coverArt); - - song.CoverArtId = coverArt.CoverArtId; - _logger.Info("Cover art Process saving complete"); - } - public void DeleteCoverArtFromDatabase(CoverArt coverArt, - CoverArtRepository coverArtRepository) - { - _logger.Info("Attempting to delete cover art from the database"); - coverArtRepository.DeleteCoverArt(coverArt); - } - public void DeleteCoverArt(CoverArt coverArt) - { - var stockCoverArtPath = _rootCoverArtPath + "CoverArtPath.png"; - DirectoryManager.delete_cover_art(coverArt.ImagePath, stockCoverArtPath); - } - - public CoverArt SaveCoverArt(Song song) - { - var sng = SongManager.ConvertSongToSng(song); - - var cov = ConvertCoverArtToCovArt(new CoverArt - { - SongTitle = song.Title, - ImagePath = _rootCoverArtPath - }); - - MetadataRetriever.update_cover_art(ref cov, - ref sng, _rootCoverArtPath); - - return ConvertCovArtToCoverArt(cov); - } - - public static CovArt ConvertCoverArtToCovArt(CoverArt cover) - { - return new CovArt - { - SongTitle = cover.SongTitle, - ImagePath = cover.ImagePath - }; - } - public static CoverArt ConvertCovArtToCoverArt(CovArt cov) - { - return new CoverArt - { - SongTitle = cov.SongTitle, - ImagePath = cov.ImagePath - }; - } - - private void Initialize() - { - var stockCover = _rootCoverArtPath + "CoverArt.png"; - DirectoryManager.copy_stock_cover_art(stockCover, - DirectoryPaths.CoverArtPath); - } - #region Testing - private void PrintCoverArtDetails(CoverArt cover) - { - Console.WriteLine("\nCover art"); - Console.WriteLine($"Song Title: {cover.SongTitle}"); - Console.WriteLine($"ImagePath: {cover.ImagePath}\n"); - } - #endregion - #endregion - } -} diff --git a/Controllers/Managers/DirectoryManager.cs b/Controllers/Managers/DirectoryManager.cs deleted file mode 100644 index 5dd03a0..0000000 --- a/Controllers/Managers/DirectoryManager.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; - -using Microsoft.Extensions.Configuration; - -using Icarus.Models; -using Icarus.Types; - -namespace Icarus.Controllers.Managers -{ - public class DirectoryManager : BaseManager - { - #region Methods - #region C++ libs - [DllImport("libicarus.so")] - public static extern void create_directory(Sng song, string root_path, StringBuilder created_dir); - - [DllImport("libicarus.so")] - public static extern void copy_stock_cover_art(string target_path, string source_path); - - [DllImport("libicarus.so")] - public static extern void copy_song(string target_path, string source_path); - - [DllImport("libicarus.so")] - public static extern void delete_cover_art(string cover_art_path, string stock_path); - - [DllImport("libicarus.so")] - public static extern void delete_empty_directories(Sng song, string root_path); - - [DllImport("libicarus.so")] - public static extern void delete_from_filesystem(Sng song); - - [DllImport("libicarus.so")] - public static extern void delete_song_empty_directories(Sng song, string root_path); - #endregion - #endregion - } -} diff --git a/Controllers/Managers/SongManager.cs b/Controllers/Managers/SongManager.cs deleted file mode 100644 index 643762a..0000000 --- a/Controllers/Managers/SongManager.cs +++ /dev/null @@ -1,753 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; - -using Icarus.Controllers.Utilities; -using Icarus.Models; -using Icarus.Database.Contexts; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.Managers -{ - public class SongManager : BaseManager - { - #region Fields - private Song _song; - private IConfiguration _config; - private string _tempDirectoryRoot; - private string _archiveDirectoryRoot; - private string _compressedSongFilename; - private string _message; - #endregion - - - #region Properties - public Song SongDetails - { - get => _song; - set => _song = value; - } - - public string ArchiveDirectoryRoot - { - get => _archiveDirectoryRoot; - set => _archiveDirectoryRoot = value; - } - public string CompressedSongFilename - { - get => _compressedSongFilename; - set => _compressedSongFilename = value; - } - public string Message - { - get => _message; - set => _message = value; - } - #endregion - - - #region Constructors - public SongManager() - { - } - public SongManager(IConfiguration config) - { - _config = config; - } - public SongManager(IConfiguration config, string tempDirectoryRoot) - { - _config = config; - _tempDirectoryRoot = tempDirectoryRoot; - } - #endregion - - - #region Methods - public SongResult UpdateSong(Song song, SongRepository songStore, AlbumRepository albumStore, - ArtistRepository artistStore, GenreRepository genreStore, YearRepository yearStore) - { - var result = new SongResult(); - - try - { - var oldSongRecord = songStore.GetSong(song); - song.SongPath = oldSongRecord.SongPath; - var oldSng = ConvertSongToSng(oldSongRecord); - var updatedSng = ConvertSongToSng(song); - - MetadataRetriever.update_metadata(ref updatedSng, ref oldSng); - - var updatedSong = ConvertSngToSong(updatedSng); - - var updatedAlbum = UpdateAlbumInDatabase(oldSongRecord, updatedSong, albumStore); - oldSongRecord.AlbumId = updatedAlbum.AlbumId; - - var updatedArtist = UpdateArtistInDatabase(oldSongRecord, updatedSong, artistStore); - oldSongRecord.ArtistId = updatedArtist.ArtistId; - - var updatedGenre = UpdateGenreInDatabase(oldSongRecord, updatedSong, genreStore); - oldSongRecord.GenreId = updatedGenre.GenreId; - - var updatedYear = UpdateYearInDatabase(oldSongRecord, updatedSong, yearStore); - oldSongRecord.YearId = updatedYear.YearId; - - UpdateSongInDatabase(ref oldSongRecord, ref updatedSong, songStore, ref result); - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - - result.Message = $"An error occurred: {msg}"; - result.SongTitle = song.Title; - } - - return result; - } - - - public void DeleteSong(Song song, SongRepository songStore, - AlbumRepository albumStore, ArtistRepository artistStore, - GenreRepository genreStore, YearRepository yearStore, - CoverArtRepository coverStore) - { - try - { - DirectoryManager.delete_song_empty_directories( - ConvertSongToSng(song), - _config.GetValue("RootMusicPath")); - _logger.Info("Song deleted from the filesystem"); - - var coverMgr = new CoverArtManager(_config.GetValue( - "CoverArtPath")); - var coverArt = coverStore.GetCoverArt(song); - coverMgr.DeleteCoverArt(coverArt); - - coverMgr.DeleteCoverArtFromDatabase(coverArt, coverStore); - DeleteSongFromDatabase(song, songStore, albumStore, artistStore, - genreStore, yearStore); - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - public async Task SaveSongToFileSystem(IFormFile songFile, SongRepository songStore, - AlbumRepository albumStore, ArtistRepository artistStore, - GenreRepository genreStore, YearRepository yearStore, - CoverArtRepository coverArtStore) - { - try - { - _logger.Info("Starting the process of saving the song to the filesystem"); - - var song = await SaveSongTemp(songFile, - Path.Combine(_tempDirectoryRoot, songFile.FileName)); - - var rootPath = _config.GetValue("RootMusicPath"); - var strCount = rootPath.Length + song.Artist.Length + - song.AlbumTitle.Length + 2; - - var filePathSB = new StringBuilder(strCount); - - DirectoryManager.create_directory(ConvertSongToSng(song), - rootPath, filePathSB); - - var tmpSongPath = song.SongPath; - - song.SongPath = filePathSB.ToString().Substring(0, strCount); - - if (!songFile.FileName.EndsWith(".mp3")) - song.SongPath += $"{songFile.FileName}.mp3"; - else - song.SongPath += $"{songFile.FileName}"; - - _logger.Info($"Absolute song path: {song.SongPath}"); - - DirectoryManager.copy_song(song.SongPath, tmpSongPath); - - var coverMgr = new CoverArtManager(_config.GetValue("CoverArtPath")); - var coverArt = coverMgr.SaveCoverArt(song); - - coverMgr.SaveCoverArtToDatabase(ref song, ref coverArt, - coverArtStore); - SaveSongToDatabase(song, songStore, albumStore, artistStore, genreStore, - yearStore); - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - public async Task RetrieveSong(Song songMetaData) - { - SongData song = new SongData(); - try - { - Console.WriteLine("Fetching song from filesystem"); - song = await RetrieveSongFromFileSystem(songMetaData); - } - catch (Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error occurred: {exMsg}"); - } - - return song; - } - - public static Sng ConvertSongToSng(Song song) - { - return new Sng - { - Id = (song.Id == 0) ? 0 : song.Id, - Title = (string.IsNullOrEmpty(song.Title)) ? string.Empty : - song.Title, - Artist = (string.IsNullOrEmpty(song.Artist)) ? string.Empty : - song.Artist, - Album = (string.IsNullOrEmpty(song.AlbumTitle)) ? string.Empty : - song.AlbumTitle, - Genre = (string.IsNullOrEmpty(song.Genre)) ? string.Empty : - song.Genre, - Year = (song.Year == null) ? 0 : song.Year.Value, - Duration = song.Duration, - SongPath = song.SongPath - }; - } - public static Song ConvertSngToSong(Sng song) - { - return new Song - { - Id = song.Id, - Title = song.Title, - Artist = song.Artist, - AlbumTitle = song.Album, - Genre = song.Genre, - Year = (song.Year == 0) ? 0 : song.Year, - Duration = song.Duration, - SongPath = song.SongPath - }; - } - - - private async Task RetrieveSongFromFileSystem(Song details) - { - return new SongData - { - Data = await System.IO.File.ReadAllBytesAsync(details.SongPath) - }; - } - private async Task SaveSongTemp(IFormFile songFile, string filePath) - { - using (var filestream = new FileStream(filePath, FileMode.Create)) - { - _logger.Info("Saving song to temporary directory"); - await songFile.CopyToAsync(filestream); - } - - var sng = new Sng(); - MetadataRetriever.retrieve_metadata(ref sng, filePath); - var song = ConvertSngToSong(sng); - - _logger.Info("Assigning song filename"); - song.Filename = songFile.FileName; - song.SongPath = filePath; - - return song; - } - - private bool SongRecordChanged(Song currentSong, Song songUpdates) - { - var currentTitle = currentSong.Title; - var currentArtist = currentSong.Artist; - var currentAlbum = currentSong.AlbumTitle; - var currentGenre = currentSong.Genre; - var currentYear = currentSong.Year; - - if (!currentTitle.Equals(songUpdates.Title) || !currentArtist.Equals(songUpdates.Artist) || - !currentAlbum.Equals(songUpdates.AlbumTitle) || - !currentGenre.Equals(songUpdates.Genre) || currentYear != songUpdates.Year) - return true; - - return false; - } - - private void SaveSongToDatabase(Song song, SongRepository songStore, AlbumRepository albumStore, - ArtistRepository artistStore, GenreRepository genreStore, YearRepository yearStore) - { - _logger.Info("Starting process to save the song to the database"); - - SaveAlbumToDatabase(ref song, albumStore); - SaveArtistToDatabase(ref song, artistStore); - SaveGenreToDatabase(ref song, genreStore); - SaveYearToDatabase(ref song, yearStore); - - var info = "Saving Song to DB"; - Console.WriteLine(info); - _logger.Info(info); - - songStore.SaveSong(song); - } - private void SaveAlbumToDatabase(ref Song song, AlbumRepository albumStore) - { - _logger.Info("Starting process to save the album record of the song to the database"); - - var album = new Album() - { - Title = song.AlbumTitle, - AlbumArtist = song.Artist - }; - - if (!albumStore.DoesAlbumExist(song)) - { - album.SongCount = 1; - albumStore.SaveAlbum(album); - album = albumStore.GetAlbum(song); - } - else - { - var albumRetrieved = albumStore.GetAlbum(song); - album.AlbumId = albumRetrieved.AlbumId; - album.SongCount = albumRetrieved.SongCount + 1; - - albumStore.UpdateAlbum(album); - } - - song.AlbumId = album.AlbumId; - } - private void SaveArtistToDatabase(ref Song song, ArtistRepository artistStore) - { - _logger.Info("Starting process to save the artist record of the song to the database"); - - var artist = new Artist - { - Name = song.Artist, - SongCount = 1 - }; - - if (!artistStore.DoesArtistExist(song)) - { - artist.SongCount = 1; - artistStore.SaveArtist(artist); - artist = artistStore.GetArtist(song); - } - else - { - var artistRetrieved = artistStore.GetArtist(song); - artist.ArtistId = artistRetrieved.ArtistId; - artist.SongCount = artistRetrieved.SongCount + 1; - - artistStore.UpdateArtist(artist); - } - - song.ArtistId = artist.ArtistId; - } - private void SaveGenreToDatabase(ref Song song, GenreRepository genreStore) - { - _logger.Info("Starting process to save the genre record of the song to the database"); - - var genre = new Genre - { - GenreName = song.Genre, - SongCount = 1 - }; - - if (!genreStore.DoesGenreExist(song)) - { - genreStore.SaveGenre(genre); - genre = genreStore.GetGenre(song); - } - else - { - var genreRetrieved = genreStore.GetGenre(song); - genre.GenreId = genreRetrieved.GenreId; - genre.SongCount = genreRetrieved.SongCount + 1; - - genreStore.UpdateGenre(genre); - } - - song.GenreId = genre.GenreId; - } - private void SaveYearToDatabase(ref Song song, YearRepository yearStore) - { - _logger.Info("Starting process to save the year record of the song to the database"); - - var year = new Year - { - YearValue = song.Year.Value, - SongCount = 1 - }; - - if (!yearStore.DoesYearExist(song)) - { - yearStore.SaveYear(year); - year = yearStore.GetSongYear(song); - } - else - { - var yearRetrieved = yearStore.GetSongYear(song); - year.YearId = yearRetrieved.YearId; - year.SongCount = yearRetrieved.SongCount + 1; - - yearStore.UpdateYear(year); - } - - song.YearId = year.YearId; - } - - public Song SongCopy(Song song) - { - var updatedSongRecord = new Song - { - Id = song.Id, - Title = song.Title, - Artist = song.Artist, - AlbumTitle = song.AlbumTitle, - Genre = song.Genre, - Year = song.Year, - Duration = song.Duration, - Filename = song.Filename, - SongPath = song.SongPath, - ArtistId = song.ArtistId, - AlbumId = song.AlbumId, - GenreId = song.GenreId, - YearId = song.YearId - }; - - return updatedSongRecord; - } - - private Album UpdateAlbumInDatabase(Song oldSongRecord, Song newSongRecord, AlbumRepository albumStore) - { - var albumRecord = albumStore.GetAlbum(oldSongRecord, true); - var oldAlbumTitle = oldSongRecord.AlbumTitle; - var oldAlbumArtist = oldSongRecord.Artist; - var newAlbumTitle = newSongRecord.AlbumTitle; - var newAlbumArtist = newSongRecord.Artist; - - var info = string.Empty; - - if (string.IsNullOrEmpty(newAlbumArtist)) - newAlbumArtist = oldAlbumArtist; - if (string.IsNullOrEmpty(newAlbumTitle)) - newAlbumTitle = oldAlbumTitle; - - if ((string.IsNullOrEmpty(newAlbumTitle) && string.IsNullOrEmpty(newAlbumArtist) || - oldAlbumTitle.Equals(newAlbumTitle) && oldAlbumArtist.Equals(newAlbumArtist))) - { - _logger.Info("No change to the song's album"); - return albumRecord; - } - - info = "Change to the song's album"; - _logger.Info(info); - - if (!albumStore.DoesAlbumExist(newSongRecord)) - { - _logger.Info("Creating new album record"); - - albumStore.SaveAlbum(new Album - { - Title = newAlbumTitle, - AlbumArtist = newAlbumArtist - }); - - newSongRecord.AlbumTitle = newAlbumTitle; - - return albumStore.GetAlbum(newSongRecord, true); - } - else - { - _logger.Info("Updating existing album record"); - - var existingAlbumRecord = albumStore.GetAlbum(newSongRecord); - existingAlbumRecord.AlbumArtist = newAlbumArtist; - - albumStore.UpdateAlbum(existingAlbumRecord); - - return existingAlbumRecord; - } - } - private Artist UpdateArtistInDatabase(Song oldSongRecord, Song newSongRecord, ArtistRepository artistStore) - { - var oldArtistRecord = artistStore.GetArtist(oldSongRecord, true); - var oldArtistName = oldArtistRecord.Name; - var newArtistName = newSongRecord.Artist; - - if (string.IsNullOrEmpty(newArtistName) || oldArtistName.Equals(newArtistName)) - { - _logger.Info("No change to the song's Artist"); - return oldArtistRecord; - } - - _logger.Info("Change to the song's record found"); - - if (oldArtistRecord.SongCount <= 1) - { - _logger.Info("Deleting artist record that no longer has any songs"); - - artistStore.DeleteArtist(oldArtistRecord); - } - - if (!artistStore.DoesArtistExist(newSongRecord)) - { - _logger.Info("Creating new artist record"); - - var newArtistRecord = new Artist - { - Name = newArtistName - }; - - artistStore.SaveArtist(newArtistRecord); - - return artistStore.GetArtist(newSongRecord, true); - } - else - { - _logger.Info("Updating existing artist record"); - - var existingArtistRecord = artistStore.GetArtist(newSongRecord); - - artistStore.UpdateArtist(existingArtistRecord); - - return existingArtistRecord; - } - } - private Genre UpdateGenreInDatabase(Song oldSongRecord, Song newSongRecord, GenreRepository genreStore) - { - var oldGenreRecord = genreStore.GetGenre(oldSongRecord, true); - var oldGenreName = oldGenreRecord.GenreName; - var newGenreName = newSongRecord.Genre; - - if (string.IsNullOrEmpty(newGenreName) || oldGenreName.Equals(newGenreName)) - { - _logger.Info("No change to the song's Genre"); - return oldGenreRecord; - } - - _logger.Info("Change to the song's genre found"); - - if (oldGenreRecord.SongCount <= 1) - { - _logger.Info("Deleting genre record"); - - genreStore.DeleteGenre(oldGenreRecord); - } - - if (!genreStore.DoesGenreExist(newSongRecord)) - { - _logger.Info("Creating new genre record"); - - var newGenreRecord = new Genre - { - GenreName = newGenreName - }; - - genreStore.SaveGenre(newGenreRecord); - - return genreStore.GetGenre(newSongRecord, true); - } - else - { - _logger.Info("Updating existing genre record"); - - var existingGenreRecord = genreStore.GetGenre(newSongRecord); - - genreStore.UpdateGenre(existingGenreRecord); - return genreStore.GetGenre(existingGenreRecord); - } - } - private Year UpdateYearInDatabase(Song oldSongRecord, Song newSongRecord, YearRepository yearStore) - { - var oldYearRecord = yearStore.GetSongYear(oldSongRecord, true); - var oldYearValue = oldYearRecord.YearValue; - var newYearValue = newSongRecord.Year; - - if (oldYearValue == newYearValue || newYearValue == 0 || newYearValue == null) - { - _logger.Info("No change to the song's Year"); - return oldYearRecord; - } - - _logger.Info("Change to the song's year found"); - - if (oldYearRecord.SongCount <= 1) - { - _logger.Info("Deleting year record"); - - yearStore.DeleteYear(oldYearRecord); - } - - if(!yearStore.DoesYearExist(newSongRecord)) - { - _logger.Info("Creating new year record"); - - var newYearRecord = new Year - { - YearValue = newYearValue.Value - }; - - yearStore.SaveYear(newYearRecord); - - return yearStore.GetSongYear(newSongRecord, true); - } - else - { - _logger.Info("Updating existing year record"); - - var existingYearRecord = yearStore.GetSongYear(newSongRecord); - - yearStore.UpdateYear(existingYearRecord); - - return existingYearRecord; - } - } - private void UpdateSongInDatabase(ref Song oldSongRecord, ref Song newSongRecord, SongRepository songStore, - ref SongResult result) - { - var updatedSongRecord = SongCopy(oldSongRecord); - var artistOrAlbumChanged = false; - - if (!SongRecordChanged(oldSongRecord, newSongRecord)) - { - _logger.Info("No change to the song record"); - return; - } - - _logger.Info("Changes to song record found"); - - if (!string.IsNullOrEmpty(newSongRecord.Title)) - updatedSongRecord.Title = newSongRecord.Title; - if (!string.IsNullOrEmpty(newSongRecord.AlbumTitle)) - { - updatedSongRecord.AlbumTitle = newSongRecord.AlbumTitle; - artistOrAlbumChanged = true; - } - if (!string.IsNullOrEmpty(newSongRecord.Artist)) - { - updatedSongRecord.Artist = newSongRecord.Artist; - artistOrAlbumChanged = true; - } - if (!string.IsNullOrEmpty(newSongRecord.Genre)) - { - updatedSongRecord.Genre = newSongRecord.Genre; - } - if (newSongRecord.Year > 0) - updatedSongRecord.Year = newSongRecord.Year; - else - updatedSongRecord.Year = oldSongRecord.Year; - - _logger.Info("Applied changes to song record"); - - if (artistOrAlbumChanged) - { - _logger.Info("Change to song's album or artist"); - - var rootPath = _config.GetValue("RootMusicPath"); - var strCount = rootPath.Length + updatedSongRecord.Artist.Length + - updatedSongRecord.AlbumTitle.Length + 2; - var updatedPath = new StringBuilder(strCount); - - DirectoryManager.create_directory(ConvertSongToSng(updatedSongRecord), - rootPath, updatedPath); - - var newSongPath = updatedPath.ToString().Substring(0, strCount) + - updatedSongRecord.Filename; - - DirectoryManager.copy_song(newSongPath, updatedSongRecord.SongPath); - - updatedSongRecord.SongPath = newSongPath; - } - - _logger.Info("Saving song metadata to the database"); - - if (songStore.DoesSongExist(newSongRecord)) - songStore.UpdateSong(updatedSongRecord); - else - songStore.SaveSong(updatedSongRecord); - - newSongRecord = updatedSongRecord; - - result.Message = "Successfully updated song"; - result.SongTitle = updatedSongRecord.Title; - } - - private void DeleteSongFromDatabase(Song song, SongRepository songStore, AlbumRepository albumStore, - ArtistRepository artistStore, GenreRepository genreStore, YearRepository yearStore) - { - _logger.Info("Starting process to delete records related to the song from the database"); - - DeleteAlbumFromDatabase(song, albumStore); - DeleteArtistFromDatabase(song, artistStore); - DeleteGenreFromDatabase(song, genreStore); - DeleteYearFromDatabase(song, yearStore); - - songStore.DeleteSong(song); - } - private void DeleteAlbumFromDatabase(Song song, AlbumRepository albumStore) - { - if (!albumStore.DoesAlbumExist(song)) - { - _logger.Info("Cannot delete the album record because it does not exist"); - return; - } - - var album = albumStore.GetAlbum(song, true); - - if (album.SongCount <= 1) - albumStore.DeleteAlbum(album); - } - private void DeleteArtistFromDatabase(Song song, ArtistRepository artistStore) - { - if (!artistStore.DoesArtistExist(song)) - { - _logger.Info("Cannot delete the artist record because it does not exist"); - return; - } - - var artist = artistStore.GetArtist(song, true); - - if (artist.SongCount <= 1) - artistStore.DeleteArtist(artist); - } - private void DeleteGenreFromDatabase(Song song, GenreRepository genreStore) - { - if (!genreStore.DoesGenreExist(song)) - { - _logger.Info("Cannot delete the genre record because it does not exist"); - return; - } - - var genre = genreStore.GetGenre(song, true); - - if (genre.SongCount <= 1) - genreStore.DeleteGenre(genre); - } - private void DeleteYearFromDatabase(Song song, YearRepository yearStore) - { - if (!yearStore.DoesYearExist(song)) - { - _logger.Info("Cannot delete the year record because it does not exist"); - return; - } - - var year = yearStore.GetSongYear(song, true); - - if (year.SongCount <= 1) - yearStore.DeleteYear(year); - } - #endregion - } -} diff --git a/Controllers/Managers/TokenManager.cs b/Controllers/Managers/TokenManager.cs deleted file mode 100644 index 9f771cf..0000000 --- a/Controllers/Managers/TokenManager.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; - -using Microsoft.Extensions.Configuration; -using Newtonsoft.Json; -//using RestSharp; - -using Icarus.Models; - -namespace Icarus.Controllers.Managers -{ - public class TokenManager : BaseManager - { - #region Fields - private IConfiguration _config; - #endregion - - - #region Properties - #endregion - - - #region Constructors - public TokenManager(IConfiguration config) - { - _config = config; - } - #endregion - - - #region Methods - #region c++ Libs - [DllImport("libicarus.so")] - public static extern IntPtr retrieve_token(ref TokenReq req); - #endregion - - public static LoginResult ConvertLogResToLoginResult(ref LogRes res) - { - return new LoginResult - { - Token = res.Token, - TokenType = res.TokenType, - Expiration = res.Expiration, - Message = res.Message - }; - } - #endregion - } -} diff --git a/Controllers/Utilities/MetadataRetriever.cs b/Controllers/Utilities/MetadataRetriever.cs deleted file mode 100644 index 2e1b97e..0000000 --- a/Controllers/Utilities/MetadataRetriever.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; - -using Microsoft.Extensions.Logging; -using NLog; -//using TagLib; - -using Icarus.Models; -using Icarus.Controllers.Managers; - -namespace Icarus.Controllers.Utilities -{ - public class MetadataRetriever - { - #region Fields - private static NLog.Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); - private string _message; - #endregion - - - #region Properties - public string Message - { - get => _message; - set => _message = value; - } - #endregion - - - #region Methods - public static void PrintMetadata(Song song) - { - Console.WriteLine("\n\nMetadata of the song:"); - Console.WriteLine($"Id: {song.Id}"); - Console.WriteLine($"Title: {song.Title}"); - Console.WriteLine($"Artist: {song.Artist}"); - Console.WriteLine($"Album: {song.AlbumTitle}"); - Console.WriteLine($"Genre: {song.Genre}"); - Console.WriteLine($"Year: {song.Year}"); - Console.WriteLine($"Duration: {song.Duration}"); - Console.WriteLine($"AlbumId: {song.AlbumId}"); - Console.WriteLine($"ArtistId: {song.ArtistId}"); - Console.WriteLine($"GenreId: {song.GenreId}"); - Console.WriteLine($"YearId: {song.YearId}"); - Console.WriteLine($"Song Path: {song.SongPath}"); - Console.WriteLine($"Filename: {song.Filename}"); - Console.WriteLine("\n"); - - _logger.Info("Metadata of the song"); - _logger.Info($"Title: {song.Title}"); - _logger.Info($"Artist: {song.Artist}"); - _logger.Info($"Album: {song.AlbumTitle}"); - _logger.Info($"Genre: {song.Genre}"); - _logger.Info($"Year: {song.Year}"); - _logger.Info($"Duration: {song.Duration}"); - } - - #region C++ Libs - [DllImport("libicarus.so")] - public static extern void retrieve_metadata(ref Sng sng, - string file_path); - - [DllImport("libicarus.so")] - public static extern void update_metadata(ref Sng sng_updated, - ref Sng sng_old); - - [DllImport("libicarus.so")] - public static extern void update_cover_art(ref CovArt cov, - ref Sng sng, string root_cover_path); - #endregion - #endregion - } -} diff --git a/Controllers/Utilities/PasswordEncryption.cs b/Controllers/Utilities/PasswordEncryption.cs deleted file mode 100644 index 53825e8..0000000 --- a/Controllers/Utilities/PasswordEncryption.cs +++ /dev/null @@ -1,90 +0,0 @@ -using System; -using System.Security.Cryptography; - -using BCrypt.Net; -using Microsoft.AspNetCore.Cryptography.KeyDerivation; -using NLog; - -using Icarus.Models; - -namespace Icarus.Controllers.Utilities -{ - public class PasswordEncryption - { - #region Fields - private static Logger _logger = NLog.LogManager.GetCurrentClassLogger(); - #endregion - - - #region Properties - #endregion - - - #region Constructor - #endregion - - - #region Methods - public bool VerifyPassword(User user, string password) - { - try - { - var result = BCrypt.Net.BCrypt.Verify(password, user.Password); - - return result; - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return false; - } - - public string HashPassword(User user) - { - try - { - string hashedPassword = string.Empty; - hashedPassword = BCrypt.Net.BCrypt.HashPassword(user.Password); - - _logger.Info("Successfully hashed password"); - - return hashedPassword; - - } - catch (Exception ex) - { - var exMsg = ex.Message; - _logger.Error(exMsg, "An error occurred"); - } - - return null; - } - - string GenerateHash(string password, byte[] salt) - { - - string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2( - password: password, salt: salt, - prf: KeyDerivationPrf.HMACSHA1, - iterationCount: 10000, - numBytesRequested: 256/8)); - - return hashed; - } - - byte[] GenerateSalt() - { - byte[] salt = new byte[128/8]; - - using (var rng = RandomNumberGenerator.Create()) - rng.GetBytes(salt); - - - return salt; - } - #endregion - } -} diff --git a/Controllers/Utilities/SongCompression.cs b/Controllers/Utilities/SongCompression.cs deleted file mode 100644 index f86e356..0000000 --- a/Controllers/Utilities/SongCompression.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Http; - -using Ionic.Zip; - -using Icarus.Models; - -namespace Icarus.Controllers.Utilities -{ - public class SongCompression - { - #region Fields - string _compressedSongFilename; - string _tempDirectory; - byte[] _uncompressedSong; - #endregion - - - #region Propterties - public string CompressedSongFilename - { - get => _compressedSongFilename; - set => _compressedSongFilename = value; - } - #endregion - - - #region Constructors - public SongCompression() - { - } - public SongCompression(string tempDirectory) - { - _tempDirectory = tempDirectory; - } - public SongCompression(byte[] uncompressedSong) - { - _uncompressedSong = uncompressedSong; - } - #endregion - - - #region Methods - public async Task RetrieveCompressedSong(Song song) - { - SongData songData = new SongData(); - try - { - var archivePath = RetrieveCompressesSongPath(song); - Console.WriteLine($"Compressed song saved to: {archivePath}"); - - songData.Data = await System.IO.File.ReadAllBytesAsync(archivePath); - } - catch(Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error ocurred: \n{exMsg}"); - } - - return songData; - } - - public string RetrieveCompressesSongPath(Song songDetails) - { - string tmpZipFilePath = _tempDirectory + songDetails.Filename; - - try - { - using (ZipFile zip = new ZipFile()) - { - zip.AddFile(songDetails.SongPath); - zip.Save(tmpZipFilePath); - } - Console.WriteLine("Successfully compressed"); - } - catch (Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine("An error ocurred"); - Console.WriteLine(exMsg); - } - - if (songDetails.Filename.Contains(".mp3")) - { - _compressedSongFilename = StripMP3Extension(songDetails.Filename); - } - - return tmpZipFilePath; - } - - // Method not being used - public byte[] CompressedSong(byte[] uncompressedSong) - { - byte[] compressedSong = null; - try - { - Console.WriteLine("Song has been successfully compressed"); - } - catch (Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine("An error ocurred:"); - Console.WriteLine(exMsg); - } - - return compressedSong; - } - - - string StripMP3Extension(string filename) - { - Console.WriteLine($"Before: {filename}"); - int filenameLength = filename.Length; - Console.WriteLine($"Filename length {filenameLength}"); - var endIndex = filenameLength - 1; - var startIndex = endIndex - 3; - Console.WriteLine($"Starting index {startIndex} and ending index {endIndex}"); - var stripped = filename.Remove(startIndex, 4); - stripped += ".zip"; - Console.WriteLine($"After {stripped}"); - - return stripped; - } - #endregion - } -} diff --git a/Controllers/v1/AlbumController.cs b/Controllers/v1/AlbumController.cs deleted file mode 100644 index 0c518cb..0000000 --- a/Controllers/v1/AlbumController.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/album")] - [ApiController] - public class AlbumController : ControllerBase - { - #region Fields - private readonly ILogger _logger; - #endregion - - - #region Properties - #endregion - - - #region Constructors - public AlbumController(ILogger logger) - { - _logger = logger; - } - #endregion - - - #region HTTP Routes - [HttpGet] - [Authorize("read:albums")] - public IActionResult Get() - { - List albums = new List(); - - AlbumRepository albumStoreContext = HttpContext.RequestServices - .GetService(typeof(AlbumRepository)) as AlbumRepository; - - albums = albumStoreContext.GetAlbums(); - - if (albums.Count > 0) - return Ok(albums); - else - return NotFound(); - } - - [HttpGet("{id}")] - [Authorize("read:albums")] - public IActionResult Get(int id) - { - Album album = new Album - { - AlbumId = id - }; - - AlbumRepository albumStoreContext = HttpContext.RequestServices - .GetService(typeof(AlbumRepository)) as AlbumRepository; - - if (albumStoreContext.DoesAlbumExist(album)) - { - album = albumStoreContext.GetAlbum(album); - - return Ok(album); - } - else - return NotFound(); - } - #endregion - } -} diff --git a/Controllers/v1/ArtistController.cs b/Controllers/v1/ArtistController.cs deleted file mode 100644 index 19d21ba..0000000 --- a/Controllers/v1/ArtistController.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/artist")] - [ApiController] - public class ArtistController : ControllerBase - { - #region Fields - private readonly ILogger _logger; - #endregion - - - #region Properties - #endregion - - - #region Constructors - public ArtistController(ILogger logger) - { - _logger = logger; - } - #endregion - - - #region HTTP Routes - [HttpGet] - [Authorize("read:artists")] - public IActionResult Get() - { - ArtistRepository artistStoreContext = HttpContext.RequestServices - .GetService(typeof(ArtistRepository)) as ArtistRepository; - - var artists = artistStoreContext.GetArtists(); - - if (artists.Count > 0) - return Ok(artists); - else - return NotFound(); - } - - [HttpGet("{id}")] - [Authorize("read:artists")] - public IActionResult Get(int id) - { - Artist artist = new Artist - { - ArtistId = id - }; - - ArtistRepository artistStoreContext = HttpContext.RequestServices - .GetService(typeof(ArtistRepository)) as ArtistRepository; - - if (artistStoreContext.DoesArtistExist(artist)) - { - artist = artistStoreContext.GetArtist(artist); - - return Ok(artist); - } - else - return NotFound(); - } - #endregion - } -} diff --git a/Controllers/v1/CoverArtController.cs b/Controllers/v1/CoverArtController.cs deleted file mode 100644 index f43bd6f..0000000 --- a/Controllers/v1/CoverArtController.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Controllers.Managers; -using Icarus.Database.Repositories; -using Icarus.Models; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/coverart")] - [ApiController] - public class CoverArtController : ControllerBase - { - #region Fields - private readonly ILogger _logger; - #endregion - - - #region Constructors - public CoverArtController(ILogger logger) - { - _logger = logger; - } - #endregion - - - #region HTTP Routes - public IActionResult Get() - { - var coverArtRepository = HttpContext - .RequestServices - .GetService( - typeof(CoverArtRepository)) as CoverArtRepository; - - var coverArtRecords = coverArtRepository.GetCoverArtRecords(); - - if (coverArtRecords == null) - { - _logger.LogInformation("No cover art records"); - return NotFound(); - } - else - { - _logger.LogInformation("Found cover art records"); - return Ok(coverArtRecords); - } - - } - - [HttpGet("{id}")] - [Authorize("download:cover_art")] - public async Task Get(int id) - { - var coverArt = new CoverArt { CoverArtId = id }; - - var coverArtRepository = HttpContext - .RequestServices - .GetService( - typeof(CoverArtRepository)) as CoverArtRepository; - - coverArt = coverArtRepository.GetCoverArt(coverArt); - - if (coverArt != null) - { - _logger.LogInformation("Found cover art record"); - var coverArtBytes = await System.IO.File.ReadAllBytesAsync( - coverArt.ImagePath); - - return File(coverArtBytes, "application/x-msdownload", - coverArt.SongTitle); - } - else - { - _logger.LogInformation("Cover art not found"); - return NotFound(); - } - } - #endregion - } -} diff --git a/Controllers/v1/GenreController.cs b/Controllers/v1/GenreController.cs deleted file mode 100644 index fe50694..0000000 --- a/Controllers/v1/GenreController.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/genre")] - [ApiController] - public class GenreController : ControllerBase - { - #region Fields - private readonly ILogger _logger; - #endregion - - - #region Properties - #endregion - - - #region Constructors - public GenreController(ILogger logger) - { - _logger = logger; - } - #endregion - - - #region HTTP Routes - [HttpGet] - [Authorize("read:genre")] - public IActionResult Get() - { - var genres = new List(); - - var genreStore = HttpContext.RequestServices - .GetService(typeof(GenreRepository)) as GenreRepository; - - genres = genreStore.GetGenres(); - - if (genres.Count > 0) - return Ok(genres); - else - return NotFound(new List()); - } - - [HttpGet("{id}")] - [Authorize("read:genre")] - public IActionResult Get(int id) - { - var genre = new Genre - { - GenreId = id - }; - - var genreStore = HttpContext.RequestServices - .GetService(typeof(GenreRepository)) as GenreRepository; - - if (genreStore.DoesGenreExist(genre)) - { - genre = genreStore.GetGenre(genre); - - return Ok(genre); - } - else - return NotFound(new Genre()); - } - #endregion - } -} diff --git a/Controllers/v1/LoginController.cs b/Controllers/v1/LoginController.cs deleted file mode 100644 index 0997a75..0000000 --- a/Controllers/v1/LoginController.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; -using System.Threading.Tasks; -using System.Runtime.InteropServices; - -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Controllers.Managers; -using Icarus.Controllers.Utilities; -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/login")] - [ApiController] - public class LoginController : ControllerBase - { - #region Fields - private IConfiguration _config; - private ILogger _logger; - #endregion - - - #region Properties - #endregion - - - #region Contructors - public LoginController(IConfiguration config, ILogger logger) - { - _config = config; - _logger = logger; - } - #endregion - - - #region HTTP endpoints - public IActionResult Post([FromBody] User user) - { - UserRepository context = HttpContext.RequestServices - .GetService(typeof(UserRepository)) as UserRepository; - - _logger.LogInformation("Starting process of validating credentials"); - - var loginRes = new LoginResult - { - Username = user.Username, - Message = "Invalid credentials" - }; - - if (context.DoesUserExist(user)) - { - var password = user.Password; - user = context.RetrieveUser(user); - - var validatePass = new PasswordEncryption(); - var validated = validatePass.VerifyPassword(user, password); - if (!validated) - { - _logger.LogInformation(loginRes.Message); - - return Ok(loginRes); - } - - _logger.LogInformation("Successfully validated user credentials"); - - var tok = new TokenReq - { - ClientId = _config["Auth0:ClientId"], - ClientSecret = _config["Auth0:ClientSecret"], - Audience = _config["Auth0:ApiIdentifier"], - GrantType = "client_credentials", - URI = $"https://{_config["Auth0:Domain"]}", - Endpoint = "oauth/token" - }; - - IntPtr logRes = TokenManager.retrieve_token(ref tok); - var lr = (LogRes)Marshal.PtrToStructure(logRes, typeof(LogRes)); - loginRes = TokenManager.ConvertLogResToLoginResult(ref lr); - loginRes.Username = user.Username; - loginRes.UserId = user.Id; - - return Ok(loginRes); - } - else - return NotFound(loginRes); - } - #endregion - } -} diff --git a/Controllers/v1/RegisterController.cs b/Controllers/v1/RegisterController.cs deleted file mode 100644 index 7fad923..0000000 --- a/Controllers/v1/RegisterController.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; - -using Icarus.Controllers.Managers; -using Icarus.Controllers.Utilities; -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/register")] - [ApiController] - public class RegisterController : ControllerBase - { - #region Fields - private IConfiguration _config; - #endregion - - - #region Properties - #endregion - - - #region Constructor - public RegisterController(IConfiguration config) - { - _config = config; - } - #endregion - - [HttpPost] - public IActionResult Post([FromBody] User user) - { - PasswordEncryption pe = new PasswordEncryption(); - user.Password = pe.HashPassword(user); - user.EmailVerified = false; - - UserRepository context = HttpContext.RequestServices - .GetService(typeof(UserRepository)) as UserRepository; - - context.SaveUser(user); - - var registerResult = new RegisterResult - { - Username = user.Username - }; - - if (context.DoesUserExist(user)) - { - registerResult.Message = "Successful registration"; - registerResult.SuccessfullyRegistered = true; - - return Ok(registerResult); - } - else - { - registerResult.Message = "Registration failed"; - registerResult.SuccessfullyRegistered = false; - - return Ok(registerResult); - } - } - } -} diff --git a/Controllers/v1/SongCompressedDataControllers.cs b/Controllers/v1/SongCompressedDataControllers.cs deleted file mode 100644 index e2a3324..0000000 --- a/Controllers/v1/SongCompressedDataControllers.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; - -using Icarus.Controllers.Managers; -using Icarus.Controllers.Utilities; -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/song/compressed/data")] - [ApiController] - public class SongCompressedDataController : ControllerBase - { - #region Fields - private IConfiguration _config; - private string _songTempDir; - private string _archiveDir; - #endregion - - - #region Properties - #endregion - - - #region Constructor - public SongCompressedDataController(IConfiguration config) - { - _config = config; - _songTempDir = _config.GetValue("TemporaryMusicPath"); - _archiveDir = _config.GetValue("ArchivePath"); - } - #endregion - - - #region API Routes - [HttpGet("{id}")] - [Authorize("download:songs")] - public async Task Get(int id) - { - SongRepository context = HttpContext.RequestServices - .GetService(typeof(SongRepository)) as SongRepository; - - SongCompression cmp = new SongCompression(_archiveDir); - - Console.WriteLine($"Archive directory root: {_archiveDir}"); - - Console.WriteLine("Starting process of retrieving comrpessed song"); - SongData song = await cmp.RetrieveCompressedSong(context.GetSong(id)); - - return File(song.Data, "application/x-msdownload", cmp.CompressedSongFilename); - } - #endregion - } -} diff --git a/Controllers/v1/SongController.cs b/Controllers/v1/SongController.cs deleted file mode 100644 index f3b9d7a..0000000 --- a/Controllers/v1/SongController.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Controllers.Managers; -using Icarus.Controllers.Utilities; -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/song")] - [ApiController] - public class SongController : ControllerBase - { - #region Fields - private readonly ILogger _logger; - private IConfiguration _config; - private SongManager _songMgr; - #endregion - - - #region Properties - #endregion - - - #region Constructor - public SongController(IConfiguration config, ILogger logger) - { - _config = config; - _logger = logger; - _songMgr = new SongManager(config); - } - #endregion - - - [HttpGet] - [Authorize("read:song_details")] - public IActionResult Get() - { - var songs = new List(); - Console.WriteLine("Attemtping to retrieve songs"); - _logger.LogInformation("Attempting to retrieve songs"); - - var context = HttpContext.RequestServices - .GetService(typeof(SongRepository)) as SongRepository; - - songs = context.GetAllSongs(); - - if (songs.Count > 0) - return Ok(songs); - else - return NotFound(); - } - - [HttpGet("{id}")] - [Authorize("read:song_details")] - public IActionResult Get(int id) - { - var context = HttpContext.RequestServices - .GetService(typeof(SongRepository)) as SongRepository; - - var song = new Song { Id = id }; - song = context.GetSong(song); - - if (song.Id != 0) - return Ok(song); - else - return NotFound(); - } - - [Authorize("update:songs")] - [HttpPut("{id}")] - public IActionResult Put(int id, [FromBody] Song song) - { - var context = HttpContext.RequestServices - .GetService(typeof(SongRepository)) as SongRepository; - - var artistStore = HttpContext.RequestServices - .GetService(typeof(ArtistRepository)) as ArtistRepository; - - var albumStore = HttpContext.RequestServices - .GetService(typeof(AlbumRepository)) as AlbumRepository; - - var genreStore = HttpContext.RequestServices - .GetService(typeof(GenreRepository)) as GenreRepository; - - var yearStore = HttpContext.RequestServices - .GetService(typeof(YearRepository)) as YearRepository; - - song.Id = id; - Console.WriteLine("Retrieving filepath of song"); - _logger.LogInformation("Retrieving filepath of song"); - - if (!context.DoesSongExist(song)) - return NotFound(new SongResult - { - Message = "Song does not exist" - }); - - var songRes = _songMgr.UpdateSong(song, context, albumStore, artistStore, genreStore, - yearStore); - - return Ok(songRes); - } - } -} diff --git a/Controllers/v1/SongDataController.cs b/Controllers/v1/SongDataController.cs deleted file mode 100644 index 59a5381..0000000 --- a/Controllers/v1/SongDataController.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Controllers.Managers; -using Icarus.Models; -using Icarus.Database.Contexts; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/song/data")] - [ApiController] - public class SongDataController : ControllerBase - { - #region Fields - private SongRepository _songRepository; - private AlbumRepository _albumRepository; - private ArtistRepository _artistRepository; - private GenreRepository _genreRepository; - private YearRepository _yearRepository; - private CoverArtRepository _coverArtRepository; - private IConfiguration _config; - private ILogger _logger; - private SongManager _songMgr; - private string _songTempDir; - #endregion - - - #region Properties - #endregion - - - #region Constructor - public SongDataController(IConfiguration config, ILogger logger) - { - _config = config; - _logger = logger; - _songTempDir = _config.GetValue("TemporaryMusicPath"); - _songMgr = new SongManager(config, _songTempDir); - } - #endregion - - private void Initialize() - { - _songRepository = HttpContext - .RequestServices - .GetService - (typeof(SongRepository)) as SongRepository; - - _albumRepository = HttpContext - .RequestServices - .GetService(typeof(AlbumRepository)) as AlbumRepository; - - _artistRepository = HttpContext - .RequestServices - .GetService(typeof(ArtistRepository)) as ArtistRepository; - - _genreRepository = HttpContext - .RequestServices - .GetService(typeof(GenreRepository)) as GenreRepository; - - _yearRepository = HttpContext - .RequestServices - .GetService(typeof(YearRepository)) as YearRepository; - - _coverArtRepository = HttpContext - .RequestServices - .GetService(typeof(CoverArtRepository)) as CoverArtRepository; - } - - - [HttpGet("{id}")] - [Route("private-scoped")] - [Authorize("download:songs")] - public async Task Get(int id) - { - Initialize(); - var songMetaData = _songRepository.GetSong(id); - - SongData song = await _songMgr.RetrieveSong(songMetaData); - - return File(song.Data, "application/x-msdownload", songMetaData.Filename); - } - - [HttpPost] - [Authorize("upload:songs")] - public async Task Post([FromForm(Name = "file")] List songData) - { - try - { - Initialize(); - - Console.WriteLine("Uploading song..."); - _logger.LogInformation("Uploading song..."); - - Console.WriteLine($"Song Root Path {_songTempDir}"); - _logger.LogInformation($"Song root path {_songTempDir}"); - foreach (var sng in songData) - if (sng.Length > 0) { - Console.WriteLine($"Song filename {sng.FileName}"); - _logger.LogInformation($"Song filename {sng.FileName}"); - - await _songMgr.SaveSongToFileSystem(sng, _songRepository, - _albumRepository, _artistRepository, - _genreRepository, _yearRepository, _coverArtRepository); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.LogError(msg, "An error occurred"); - } - } - - [HttpDelete("{id}")] - [Authorize("delete:songs")] - public IActionResult Delete(int id) - { - Initialize(); - - var songMetaData = new Song{ Id = id }; - songMetaData = _songRepository.GetSong(songMetaData); - - if (string.IsNullOrEmpty(songMetaData.Title)) - { - _logger.LogInformation("Song does not exist"); - return NotFound("Song does not exist"); - } - else - { - _logger.LogInformation("Starting process of deleting song from the filesystem and database"); - - _songMgr.DeleteSong(songMetaData, _songRepository, - _albumRepository, _artistRepository, - _genreRepository, _yearRepository, - _coverArtRepository); - - return Ok(); - } - } - } -} diff --git a/Controllers/v1/SongStreamController.cs b/Controllers/v1/SongStreamController.cs deleted file mode 100644 index 49178d6..0000000 --- a/Controllers/v1/SongStreamController.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http.Headers; -using System.Web; -using System.Threading.Tasks; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Logging; - -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controllers.V1 -{ - [Route("api/v1/song/stream")] - [ApiController] - public class SongStreamController : ControllerBase - { - #region Fields - private ILogger _logger; - #endregion - - - #region Properties - #endregion - - - #region Constructor - public SongStreamController(ILogger logger) - { - _logger = logger; - } - #endregion - - - #region HTTP endpoints - [HttpGet("{id}")] - [Authorize("stream:songs")] - public IActionResult Get(int id) - { - var songStore= HttpContext.RequestServices - .GetService(typeof(SongRepository)) as SongRepository; - - var song = songStore.GetSong(new Song { Id = id }); - - var stream = new FileStream(song.SongPath, FileMode.Open, FileAccess.Read); - stream.Position = 0; - var filename = $"{song.Title}.mp3"; - - _logger.LogInformation("Starting to stream song...>"); - Console.WriteLine("Starting to streamsong..."); - - return File(stream, "application/octet-stream", filename); - } - #endregion - } -} diff --git a/Controllers/v1/YearController.cs b/Controllers/v1/YearController.cs deleted file mode 100644 index 65e7de8..0000000 --- a/Controllers/v1/YearController.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; - -using Icarus.Models; -using Icarus.Database.Repositories; - -namespace Icarus.Controller.V1 -{ - [Route("api/v1/year")] - [ApiController] - public class YearController : ControllerBase - { - #region Fields - private readonly ILogger _logger; - #endregion - - - #region Properties - #endregion - - - #region Constructors - public YearController(ILogger logger) - { - _logger = logger; - } - #endregion - - - #region HTTP Routes - [HttpGet] - [Authorize("read:year")] - public IActionResult Get() - { - var yearValues = new List(); - - var yearStore = HttpContext.RequestServices - .GetService(typeof(YearRepository)) as YearRepository; - - yearValues = yearStore.GetSongYears(); - - if (yearValues.Count > 0) - return Ok(yearValues); - else - return NotFound(new List()); - } - - [HttpGet("{id}")] - [Authorize("read:year")] - public IActionResult Get(int id) - { - var year = new Year - { - YearId = id - }; - - var yearStore = HttpContext.RequestServices - .GetService(typeof(YearRepository)) as YearRepository; - - if (yearStore.DoesYearExist(year)) - { - year = yearStore.GetSongYear(year); - - return Ok(year); - } - else - return NotFound(new Year()); - } - #endregion - } -} diff --git a/Database/Contexts/AlbumContext.cs b/Database/Contexts/AlbumContext.cs deleted file mode 100644 index 640cb23..0000000 --- a/Database/Contexts/AlbumContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore.Extensions; -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Contexts -{ - public class AlbumContext : DbContext - { - public DbSet Albums { get; set; } - - public AlbumContext(DbContextOptions options) : base(options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("Album"); - } - } -} diff --git a/Database/Contexts/ArtistContext.cs b/Database/Contexts/ArtistContext.cs deleted file mode 100644 index fa2afcb..0000000 --- a/Database/Contexts/ArtistContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore; -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Contexts -{ - public class ArtistContext : DbContext - { - public DbSet Artists { get; set; } - - public ArtistContext(DbContextOptions options) : base (options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("Artist"); - } - } -} diff --git a/Database/Contexts/CoverArtContext.cs b/Database/Contexts/CoverArtContext.cs deleted file mode 100644 index 60bbd12..0000000 --- a/Database/Contexts/CoverArtContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore.Extensions; -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Contexts -{ - public class CoverArtContext : DbContext - { - public DbSet CoverArtImages { get; set; } - - public CoverArtContext(DbContextOptions options) : base(options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("CoverArt"); - } - } -} diff --git a/Database/Contexts/GenreContext.cs b/Database/Contexts/GenreContext.cs deleted file mode 100644 index ceb137e..0000000 --- a/Database/Contexts/GenreContext.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore.Extensions; -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Contexts -{ - public class GenreContext : DbContext - { - public DbSet Genres { get; set; } - public GenreContext(DbContextOptions options) : base(options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("Genre"); - } - } -} diff --git a/Database/Contexts/SongContext.cs b/Database/Contexts/SongContext.cs deleted file mode 100644 index a5b5824..0000000 --- a/Database/Contexts/SongContext.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore.Extensions; -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Contexts -{ - public class SongContext : DbContext - { - public DbSet Songs { get; set; } - - - public SongContext(DbContextOptions options) : base(options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("Song"); - - modelBuilder.Entity() - .HasOne(s => s.Album) - .WithMany(al => al.Songs) - .HasForeignKey(s => s.AlbumId) - .OnDelete(DeleteBehavior.SetNull); - - modelBuilder.Entity() - .HasOne(sa => sa.SongArtist) - .WithMany(ar => ar.Songs) - .HasForeignKey(s => s.ArtistId) - .OnDelete(DeleteBehavior.SetNull); - - modelBuilder.Entity() - .HasOne(s => s.SongGenre) - .WithMany(gnr => gnr.Songs) - .HasForeignKey(s => s.GenreId) - .OnDelete(DeleteBehavior.SetNull); - - modelBuilder.Entity() - .HasOne(s => s.SongYear) - .WithMany(yr => yr.Songs) - .HasForeignKey(s => s.YearId) - .OnDelete(DeleteBehavior.SetNull); - - modelBuilder.Entity() - .HasOne(s => s.SongCoverArt) - .WithMany(ca => ca.Songs) - .HasForeignKey(s => s.CoverArtId) - .OnDelete(DeleteBehavior.SetNull); - - modelBuilder.Entity() - .Property(s => s.Year) - .IsRequired(false); - modelBuilder.Entity() - .Property(s => s.YearId) - .IsRequired(false); - modelBuilder.Entity() - .Property(s => s.GenreId) - .IsRequired(false); - modelBuilder.Entity() - .Property(s => s.ArtistId) - .IsRequired(false); - modelBuilder.Entity() - .Property(s => s.AlbumId) - .IsRequired(false); - modelBuilder.Entity() - .Property(s => s.CoverArtId) - .IsRequired(false); - } - } -} diff --git a/Database/Contexts/UserContext.cs b/Database/Contexts/UserContext.cs deleted file mode 100644 index 313b34e..0000000 --- a/Database/Contexts/UserContext.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore.Extensions; -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Contexts -{ - public class UserContext : DbContext - { - public DbSet Users { get; set; } - - - public UserContext(DbContextOptions options) : base(options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("User"); - modelBuilder.Entity() - .Property(u => u.LastLogin).IsRequired(false); - modelBuilder.Entity() - .Property(u => u.DateCreated).HasDefaultValue(DateTime.Now); - } - } -} diff --git a/Database/Contexts/YearContext.cs b/Database/Contexts/YearContext.cs deleted file mode 100644 index 7074468..0000000 --- a/Database/Contexts/YearContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore.Extensions; -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Contexts -{ - public class YearContext : DbContext - { - public DbSet YearValues { get; set; } - - public YearContext(DbContextOptions options) : base(options) { } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.Entity() - .ToTable("Year"); - } - } -} diff --git a/Database/Repositories/AlbumRepository.cs b/Database/Repositories/AlbumRepository.cs deleted file mode 100644 index 860c1bc..0000000 --- a/Database/Repositories/AlbumRepository.cs +++ /dev/null @@ -1,386 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; - -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Repositories -{ - public class AlbumRepository : BaseRepository - { - #region Fields - #endregion - - - #region Properties - #endregion - - - #region Constructors - public AlbumRepository(string connectionString) - { - _connectionString = connectionString; - } - #endregion - - - #region Methods - public List GetAlbumWithoutCount() - { - var albums = new List(); - - if (AnyAlbums()) - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT * FROM Album"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - albums = ParseData(reader); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return albums; - } - public List GetAlbums() - { - List albums = new List(); - - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT alb.*,COUNT(*) AS SongCount FROM Album alb " + - "LEFT JOIN Song sng ON alb.AlbumId=sng.AlbumId WHERE " + - "alb.AlbumId=sng.AlbumId GROUP BY alb.AlbumId"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - albums = ParseData(reader); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return albums; - } - - public Album GetAlbum(Album album) - { - - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb " + - "LEFT JOIN Song sng ON alb.AlbumId=sng.AlbumId WHERE "+ - "alb.AlbumId=@AlbumId LIMIT 1"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId); - - using (var reader = cmd.ExecuteReader()) - album = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return album; - } - public Album GetAlbum(Song song) - { - var album = new Album(); - - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT alb.*, 0 AS SongCount FROM Album alb " + - "WHERE alb.Title=@Title LIMIT 1"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - Console.WriteLine($"Album title {song.AlbumTitle}"); - cmd.Parameters.AddWithValue("@Title", song.AlbumTitle); - - using (var reader = cmd.ExecuteReader()) - album = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return album; - } - public Album GetAlbum(Song song, bool retrieveCount) - { - var album = new Album(); - - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = string.Empty; - if (retrieveCount) - query = "SELECT alb.*, COUNT(*) AS SongCount FROM Album alb " + - "LEFT JOIN Song sng ON alb.AlbumId=sng.AlbumId WHERE " + - "alb.Title=@Title GROUP BY alb.AlbumId LIMIT 1"; - else - query = "SELECT alb.*, 0 AS SongCount FROM Album alb WHERE " + - "alb.Title=@Title LIMIT 1"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Title", song.AlbumTitle); - Console.WriteLine($"repo alb {song.AlbumTitle}"); - - using (var reader = cmd.ExecuteReader()) - album = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return album; - } - - public bool DoesAlbumExist(Album album) - { - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT alb.*, 0 AS SongCount FROM Album alb WHERE alb.AlbumId=@AlbumId"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId); - - using (var reader = cmd.ExecuteReader()) - { - album = ParseSingleData(reader); - - if (album.Title != null) - { - _logger.Info($"Album {album.Title} exists"); - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - return false; - } - public bool DoesAlbumExist(Song song) - { - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT alb.*, 0 AS SongCount FROM Album alb WHERE alb.Title=@Title"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Title", song.AlbumTitle); - - using (var reader = cmd.ExecuteReader()) - { - var album = ParseSingleData(reader); - - if (!String.IsNullOrEmpty(album.Title)) - { - _logger.Info($"Album {album.Title} exists"); - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - return false; - } - - public void SaveAlbum(Album album) - { - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "INSERT INTO Album(Title, AlbumArtist)" + - " VALUES (@Title, @AlbumArtist)"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Title", album.Title); - cmd.Parameters.AddWithValue("@AlbumArtist", album.AlbumArtist); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void UpdateAlbum(Album album) - { - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "UPDATE Album SET Title=@Title, AlbumArtist=" + - "@AlbumArtist WHERE AlbumId=@AlbumId"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Title", album.Title); - cmd.Parameters.AddWithValue("@AlbumArtist", album.AlbumArtist); - cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void DeleteAlbum(Album album) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - var query = "DELETE FROM Album WHERE AlbumId=@AlbumId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@AlbumId", album.AlbumId); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - private List ParseData(MySqlDataReader reader) - { - List albums = new List(); - _logger.Info("Retrieving album records"); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["AlbumId"]); - var title = reader["Title"].ToString(); - var albumArtist = reader["AlbumArtist"].ToString(); - var songCount = Convert.ToInt32(reader["SongCount"]); - albums.Add(new Album - { - AlbumId = id, - Title = title, - AlbumArtist = albumArtist, - SongCount = songCount - }); - } - - _logger.Info("Album records retrieved"); - - return albums; - } - private Album ParseSingleData(MySqlDataReader reader) - { - Album album = new Album(); - _logger.Info("Retrieving single album record"); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["AlbumId"]); - var title = reader["Title"].ToString(); - var albumArtist = reader["AlbumArtist"].ToString(); - var songCount = Convert.ToInt32(reader["SongCount"]); - album = new Album - { - AlbumId = id, - Title = title, - AlbumArtist = albumArtist, - SongCount = songCount - }; - } - _logger.Info("Single ablum retreived"); - - return album; - } - - private bool AnyAlbums() - { - var albums = new List(); - - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT * FROM Album"; - - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - albums = ParseData(reader); - } - - if (albums.Count > 0) - return true; - - return false; - } - #endregion - } -} diff --git a/Database/Repositories/ArtistRepository.cs b/Database/Repositories/ArtistRepository.cs deleted file mode 100644 index e71d993..0000000 --- a/Database/Repositories/ArtistRepository.cs +++ /dev/null @@ -1,355 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; - -using Microsoft.Extensions.Logging; -using MySql.Data.MySqlClient; -//using NLog; - -using Icarus.Models; - -namespace Icarus.Database.Repositories -{ - public class ArtistRepository : BaseRepository - { - #region Fields - #endregion - - - #region Properties - #endregion - - - #region Constructors - public ArtistRepository(string connectionString) - { - _connectionString = connectionString; - } - #endregion - - - #region Methods - public List GetArtists() - { - List artists = new List(); - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT art.*, COUNT(*) AS SongCount FROM Artist " + - "art LEFT JOIN Song sng ON art.ArtistId=sng.ArtistId " + - "GROUP BY art.ArtistId"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - artists = ParseData(reader); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return artists; - } - - public Artist GetArtist(Artist artist) - { - try - { - _logger.Info("Retrieving artist record from the database"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT art.*, COUNT(*) AS SongCount FROM Artist " + - "art LEFT JOIN Song sng ON art.ArtistId=sng.ArtistId " + - "WHERE art.ArtistId=@ArtistId"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId); - - using (var reader = cmd.ExecuteReader()) - artist = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return artist; - } - public Artist GetArtist(Song song) - { - Artist artist = new Artist(); - try - { - _logger.Info("Retrieving artist record from the database"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT art.*, 0 AS SongCount FROM Artist " + - "art WHERE art.Name=@Name"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Name", song.Artist); - - using (var reader = cmd.ExecuteReader()) - artist = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return artist; - } - public Artist GetArtist(Song song, bool retrieveCount) - { - var artist = new Artist(); - - try - { - _logger.Info("Retrieving artist record from the database"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - var query = string.Empty; - - if (retrieveCount) - query = "SELECT art.*, COUNT(*) AS SongCount FROM Artist " + - "art LEFT JOIN Song sng ON art.ArtistId=sng.ArtistId " + - "WHERE art.Name=@Name GROUP BY art.ArtistId LIMIT 1"; - else - query = "SELECT art.*, 0 AS SongCount FROM Artist art " + - "WHERE art.Name=@Name LIMIT 1"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Name", song.Artist); - - using (var reader = cmd.ExecuteReader()) - artist = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return artist; - } - - public bool DoesArtistExist(Artist artist) - { - try - { - _logger.Info("Checking to see if Artist exists"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT art.*, 0 AS SongCount FROM Artist art WHERE art.ArtistId=@ArtistId"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId); - - using (var reader = cmd.ExecuteReader()) - { - artist = ParseSingleData(reader); - - if (artist.Name != null) - { - _logger.Info($"Artist {artist.Name} exists"); - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info("Could not successfully retrieve Artist"); - - return false; - } - public bool DoesArtistExist(Song song) - { - try - { - _logger.Info("Checking to see if Artist exists"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT art.*, 0 AS SongCount FROM Artist art WHERE art.Name=@Name"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Name", song.Artist); - - using (var reader = cmd.ExecuteReader()) - { - var artist = ParseSingleData(reader); - - if (!String.IsNullOrEmpty(artist.Name)) - { - _logger.Info($"Artist {artist.Name} exists"); - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info("Could not successfully retrieve Artist"); - - return false; - } - - - public void SaveArtist(Artist artist) - { - try - { - _logger.Info("Saving artist record"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "INSERT INTO Artist(Name) VALUES(@Name)"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Name", artist.Name); - - cmd.ExecuteNonQuery(); - } - } - - _logger.Info("Artist record has successfully been saved"); - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void UpdateArtist(Artist artist) - { - try - { - _logger.Info("Updating artist record"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "UPDATE Artist SET Name=@Name WHERE ArtistId=@ArtistId"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Name", artist.Name); - cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId); - - cmd.ExecuteNonQuery(); - } - } - - _logger.Info("Artist record has successfully been saved"); - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void DeleteArtist(Artist artist) - { - try - { - _logger.Info("Deleting artist record"); - - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "DELETE FROM Artist WHERE ArtistId=@ArtistId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@ArtistId", artist.ArtistId); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - private List ParseData(MySqlDataReader reader) - { - List artists = new List(); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["ArtistId"]); - var name = reader["Name"].ToString(); - var songCount = Convert.ToInt32(reader["SongCount"].ToString()); - artists.Add(new Artist - { - ArtistId = id, - Name = name, - SongCount = songCount - }); - } - - _logger.Info("Artist records retrieved"); - - return artists; - } - - private Artist ParseSingleData(MySqlDataReader reader) - { - Artist artist = new Artist(); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["ArtistId"]); - var name = reader["Name"].ToString(); - var songCount = Convert.ToInt32(reader["SongCount"].ToString()); - artist.ArtistId = id; - artist.Name = name; - artist.SongCount = songCount; - } - - _logger.Info("Single artist record retrieved"); - - return artist; - } - #endregion - } -} diff --git a/Database/Repositories/BaseRepository.cs b/Database/Repositories/BaseRepository.cs deleted file mode 100644 index 687a73f..0000000 --- a/Database/Repositories/BaseRepository.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -using MySql.Data.MySqlClient; -using NLog; - -namespace Icarus.Database.Repositories -{ - public class BaseRepository - { - #region Fields - protected string _connectionString; - protected static Logger _logger = NLog.LogManager.GetCurrentClassLogger(); - #endregion - - - #region Methods - protected MySqlConnection GetConnection() - { - return new MySqlConnection(_connectionString); - } - #endregion - } -} diff --git a/Database/Repositories/CoverArtRepository.cs b/Database/Repositories/CoverArtRepository.cs deleted file mode 100644 index c728c75..0000000 --- a/Database/Repositories/CoverArtRepository.cs +++ /dev/null @@ -1,282 +0,0 @@ -using System; -using System.Collections.Generic; - -using MySql.Data.MySqlClient; - -using Icarus.Models; -using Icarus.Types; - -namespace Icarus.Database.Repositories -{ - public class CoverArtRepository : BaseRepository - { - #region Constructors - public CoverArtRepository(string connectionString) - { - _connectionString = connectionString; - } - #endregion - - - #region Methods - public List GetCoverArtRecords() - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - _logger.Info("Querying cover art records"); - - var query = "SELECT cv.*, sng.Id AS SongId FROM CoverArt " + - "cv LEFT JOIN Song sng ON cv.CoverArtId=sng.CoverArtId"; - - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - return ParseData(reader); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return null; - } - public CoverArt GetCoverArt(CoverArt cover) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - _logger.Info("Querying cover art record"); - - var query = "SELECT * FROM CoverArt WHERE " + - "CoverArtId=@CoverArtId"; - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters - .AddWithValue("@CoverArtId", cover.CoverArtId); - - using (var reader = cmd.ExecuteReader()) - return ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return null; - } - public CoverArt GetCoverArt(Song song) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - _logger.Info("Querying cover art record"); - - var query = "SELECT cov.* FROM CoverArt cov LEFT JOIN " + - "Song sng ON cov.CoverArtId=sng.CoverArtId WHERE " + - "sng.Id=@SongId"; - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@SongId", song.Id); - - using (var reader = cmd.ExecuteReader()) - return ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return null; - } - public CoverArt GetCoverArt(CoverArtField field, CoverArt cover) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - _logger.Info("Querying cover art record"); - - using (var cmd = new MySqlCommand(BuildQuery(field), conn)) - { - switch (field) - { - case CoverArtField.SongTitle: - cmd.Parameters.AddWithValue("@SongTitle", - cover.SongTitle); - break; - case CoverArtField.ImagePath: - cmd.Parameters.AddWithValue("@ImagePath", - cover.ImagePath); - break; - } - - using (var reader = cmd.ExecuteReader()) - return ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return null; - } - - public bool DoesCoverArtExist(CoverArt cover) - { - return GetCoverArt(cover) != null ? true : false; - } - public bool DoesCoverArtExist(Song song) - { - return GetCoverArt(song) != null ? true : false; - } - - public void SaveCoverArt(CoverArt coverArt) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - _logger.Info("Saving cover art record"); - - var query = "INSERT INTO CoverArt(SongTitle, ImagePath) " + - "VALUES(@SongTitle, @ImagePath)"; - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters - .AddWithValue("@SongTitle", coverArt.SongTitle); - cmd.Parameters - .AddWithValue("@ImagePath", coverArt.ImagePath); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void DeleteCoverArt(CoverArt cover) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - _logger.Info("Deleting cover art record"); - - var query = "DELETE FROM CoverArt WHERE " + - "CoverArtId=@CoverArtId"; - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters - .AddWithValue("@CoverArtId", cover.CoverArtId); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - private List ParseData(MySqlDataReader reader) - { - if (reader.HasRows) - { - var coverArtList = new List(); - _logger.Info("Parsing cover art records"); - while (reader.Read()) - coverArtList.Add(new CoverArt - { - CoverArtId = Convert.ToInt32(reader["CoverArtId"]), - SongTitle = reader["SongTitle"].ToString(), - ImagePath = reader["ImagePath"].ToString(), - SongId = Convert.ToInt32(reader["SongId"].ToString()) - }); - - return coverArtList; - } - - return null; - } - - private CoverArt ParseSingleData(MySqlDataReader reader) - { - if (reader.HasRows) - { - _logger.Info("Parsing single cover art record"); - reader.Read(); - - return new CoverArt - { - CoverArtId = Convert.ToInt32(reader["CoverArtId"]), - SongTitle = reader["SongTitle"].ToString(), - ImagePath = reader["ImagePath"].ToString() - }; - } - - return null; - } - - private string BuildQuery(CoverArtField field) - { - switch (field) - { - case CoverArtField.SongTitle: - return "SELECT * FROM CoverArt WHERE SongTitle=@SongTitle"; - case CoverArtField.ImagePath: - return "SELECT * FROM CoverArt WHERE ImagePath=" + - "@ImagePath"; - } - - return null; - } - - private bool? AnyCoverArt() - { - using (var conn = GetConnection()) - { - conn.Open(); - - _logger.Info("Checking to see if there are any cover art " + - "records"); - - var query = "SELECT * FROM CoverArt"; - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - return reader.HasRows; - } - } - #endregion - } -} diff --git a/Database/Repositories/GenreRepository.cs b/Database/Repositories/GenreRepository.cs deleted file mode 100644 index d3e4749..0000000 --- a/Database/Repositories/GenreRepository.cs +++ /dev/null @@ -1,447 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; - -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Repositories -{ - public class GenreRepository : BaseRepository - { - #region Fields - #endregion - - - #region Properties - #endregion - - - #region Constructors - public GenreRepository(string connectionString) - { - _connectionString = connectionString; - } - #endregion - - - #region Methods - public List GetGenresWithoutCount() - { - _logger.Info("Retrieving all genre records without song counts"); - - var genres = new List(); - - if (AnyGenre()) - { - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT * FROM Genre"; - - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - genres = ParseData(reader); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - return genres; - } - public List GetGenres() - { - _logger.Info("Retrieving Genre records"); - - var genres = new List(); - - if (AnyGenre()) - { - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre " + - "gnr LEFT JOIN Song sng ON gnr.GenreId=sng.GenreId " + - "GROUP BY gnr.GenreId"; - - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - genres = ParseData(reader); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - return genres; - } - - public Genre GetGenre(Genre genre) - { - _logger.Info("Retrieving Genre record"); - - if (DoesGenreExist(genre)) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre " + - "gnr LEFT JOIN Song sng ON gnr.GenreId=sng.GenreId " + - "WHERE gnr.GenreId=@GenreId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreId", genre.GenreId); - - using (var reader = cmd.ExecuteReader()) - genre = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - return genre; - } - public Genre GetGenre(Song song) - { - _logger.Info("Retrieving Genre record"); - - var genre = new Genre(); - - if (DoesGenreExist(song)) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT gnr.*, 0 AS SongCount FROM Genre " + - "gnr WHERE gnr.GenreName=@GenreName"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreName", song.Genre); - _logger.Info($"Song genre:\n\n\n {song.Genre}"); - - using (var reader = cmd.ExecuteReader()) - genre = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - return genre; - } - public Genre GetGenre(Song song, bool retrieveCount) - { - _logger.Info("Retrieving Genre record"); - - var genre = new Genre(); - - if (DoesGenreExist(song)) - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = string.Empty; - - if (retrieveCount) - query = "SELECT gnr.*, COUNT(*) AS SongCount FROM Genre gnr " + - "LEFT JOIN Song sng ON gnr.GenreId=sng.GenreId " + - "WHERE gnr.GenreName=@GenreName GROUP BY gnr.GenreId " + - "LIMIT 1"; - else - query = "SELECT gnr.*, 0 AS SongCount FROM Genre gnr " + - "WHERE gnr.GenreName=@GenreName LIMIT 1"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreName", song.Genre); - _logger.Info($"Song genre:\n\n\n {song.Genre}"); - - using (var reader = cmd.ExecuteReader()) - genre = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - return genre; - } - - public bool DoesGenreExist(Genre genre) - { - _logger.Info("Checking to see if Genre record exists"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT gnr.*, 0 AS SongCount FROM Genre gnr WHERE " + - "gnr.GenreId=@GenreId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreId", genre.GenreId); - - using (var reader = cmd.ExecuteReader()) - { - genre = ParseSingleData(reader); - var genreName = genre.GenreName; - - if (!string.IsNullOrEmpty(genreName)) - { - _logger.Info("Genre exists"); - - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info("Genre does not exist"); - - return false; - } - public bool DoesGenreExist(Song song) - { - _logger.Info("Checking to see if Genre record exists"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT gnr.*, 0 AS SongCount FROM Genre gnr WHERE " + - "gnr.GenreName=@GenreName"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreName", song.Genre); - - using (var reader = cmd.ExecuteReader()) - { - var genre = ParseSingleData(reader); - var genreName = genre.GenreName; - - if (!string.IsNullOrEmpty(genreName)) - { - _logger.Info("Genre exists"); - - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info("Genre does not exist"); - - return false; - } - - public void SaveGenre(Genre genre) - { - _logger.Info("Saving Genre record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "INSERT INTO Genre(GenreName) VALUES(@GenreName)"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreName", genre.GenreName); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void UpdateGenre(Genre genre) - { - _logger.Info("Updating Genre record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "UPDATE Genre SET GenreName=@GenreName " + - "WHERE GenreId=@GenreId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreName", genre.GenreName); - cmd.Parameters.AddWithValue("@GenreId", genre.GenreId); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void DeleteGenre(Genre genre) - { - _logger.Info("Deleting Genre record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "DELETE FROM Genre WHERE GenreId=@GenreId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@GenreId", genre.GenreId); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - private List ParseData(MySqlDataReader reader) - { - var genres = new List(); - _logger.Info("Retrieving genre records"); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["GenreId"].ToString()); - var genreName = reader["GenreName"].ToString(); - var songCount = Convert.ToInt32(reader["SongCount"].ToString()); - - genres.Add(new Genre - { - GenreId = id, - GenreName = genreName, - SongCount = songCount - }); - } - - _logger.Info("Genre records retrieved"); - - return genres; - } - - private Genre ParseSingleData(MySqlDataReader reader) - { - var genre = new Genre(); - _logger.Info("Retrieving single genre record"); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["GenreId"].ToString()); - var genreName = reader["GenreName"].ToString(); - var songCount = Convert.ToInt32(reader["SongCount"].ToString()); - genre.GenreId = id; - genre.GenreName = genreName; - genre.SongCount = songCount; - } - - _logger.Info("Single genre record retrieved"); - - return genre; - } - - private bool AnyGenre() - { - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT * FROM Genre"; - - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - return reader.HasRows; - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info("No genre records found"); - - return false; - } - #endregion - } -} diff --git a/Database/Repositories/SongRepository.cs b/Database/Repositories/SongRepository.cs deleted file mode 100644 index 95dfa7c..0000000 --- a/Database/Repositories/SongRepository.cs +++ /dev/null @@ -1,315 +0,0 @@ -using System; -using System.Collections.Generic; - -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Repositories -{ - public class SongRepository : BaseRepository - { - #region Constructors - public SongRepository(string connectionString) - { - _connectionString = connectionString; - } - #endregion - - - #region Methods - public void SaveSong(Song song) - { - try - { - _logger.Info("Saving song to the database"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - string query = "INSERT INTO Song(Title, AlbumTitle, Artist," + - " Year, Genre, Duration, Filename, SongPath, AlbumId, " + - "ArtistId, GenreId, YearId, CoverArtId) VALUES(@Title," + - " @AlbumTitle, @Artist, @Year, @Genre, @Duration, " + - "@Filename, @SongPath, @AlbumId, @ArtistId, @GenreId," + - " @YearId, @CoverArtId)"; - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Title", song.Title); - cmd.Parameters.AddWithValue("@AlbumTitle", song.AlbumTitle); - cmd.Parameters.AddWithValue("@Artist", song.Artist); - cmd.Parameters.AddWithValue("@Year", song.Year); - cmd.Parameters.AddWithValue("@Genre", song.Genre); - cmd.Parameters.AddWithValue("@Duration", song.Duration); - cmd.Parameters.AddWithValue("@Filename", song.Filename); - cmd.Parameters.AddWithValue("@SongPath", song.SongPath); - cmd.Parameters.AddWithValue("@AlbumId", song.AlbumId); - cmd.Parameters.AddWithValue("@ArtistId", song.ArtistId); - cmd.Parameters.AddWithValue("@GenreId", song.GenreId); - cmd.Parameters.AddWithValue("@YearId", song.YearId); - cmd.Parameters.AddWithValue("@CoverArtId", song.CoverArtId); - - cmd.ExecuteNonQuery(); - } - } - _logger.Info("Successfully saved song to the database"); - } - catch(Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error occurred:\n{exMsg}"); - _logger.Error(exMsg, "An error occurred"); - } - } - public void UpdateSong(Song song) - { - try - { - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - - string query = "UPDATE Song SET Title=@Title, AlbumTitle=@AlbumTitle, " + - "Artist=@Artist, Year=@Year, Genre=@Genre, Duration=@Duration, " + - "Filename=@Filename, SongPath=@SongPath, AlbumId=@AlbumId, " + - "ArtistId=@ArtistId, GenreId=@GenreId, YearId=@YearId WHERE Id=@Id"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Title", song.Title); - cmd.Parameters.AddWithValue("@AlbumTitle", song.AlbumTitle); - cmd.Parameters.AddWithValue("@Artist", song.Artist); - cmd.Parameters.AddWithValue("@Year", song.Year); - cmd.Parameters.AddWithValue("@Genre", song.Genre); - cmd.Parameters.AddWithValue("@Duration", song.Duration); - cmd.Parameters.AddWithValue("@Filename", song.Filename); - cmd.Parameters.AddWithValue("@SongPath", song.SongPath); - cmd.Parameters.AddWithValue("@Id", song.Id); - cmd.Parameters.AddWithValue("@AlbumId", song.AlbumId); - cmd.Parameters.AddWithValue("@ArtistId", song.ArtistId); - cmd.Parameters.AddWithValue("@GenreId", song.GenreId); - cmd.Parameters.AddWithValue("@YearId", song.YearId); - - cmd.ExecuteNonQuery(); - } - } - _logger.Info("Updated song"); - } - catch (Exception ex) - { - var msg = ex.Message; - Console.WriteLine("An error occurred in SongRepository:"); - Console.WriteLine(msg); - _logger.Error(msg, "An error occurred"); - } - } - public void DeleteSong(Song song) - { - try - { - _logger.Info("Deleting song record"); - - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "Delete FROM Song WHERE Id=@Id"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Id", song.Id); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void DeleteSong(int id) - { - try - { - _logger.Info("Deleting song record"); - - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - string query = "DELETE FROM Song WHERE Id=@Id"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Id", id); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error occurred:\n{exMsg}"); - _logger.Error(exMsg, "An error occurred"); - } - } - - public List GetAllSongs() - { - var songs = new List(); - - try - { - _logger.Info("Retrieving songs from the database"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT * FROM Song"; - - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - songs = ParseData(reader); - } - } - catch (Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error ocurred:\n{exMsg}"); - songs.Clear(); - _logger.Error(exMsg, "An error occurred"); - } - - return songs; - } - - public Song GetSong(Song song) - { - try - { - _logger.Info("Retrieving song from database"); - - using (var conn = GetConnection()) - { - conn.Open(); - var query = "SELECT * FROM Song WHERE Id=@Id"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Id", song.Id); - - using (var reader = cmd.ExecuteReader()) - song = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return song; - } - public Song GetSong(int id) - { - Song song = new Song(); - - try - { - _logger.Info("Retrieving song from database"); - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT * FROM Song WHERE Id=@Id"; - - MySqlCommand cmd = new MySqlCommand(query, conn); - cmd.Parameters.AddWithValue("@Id", id); - - using (var reader = cmd.ExecuteReader()) - song = ParseSingleData(reader); - } - _logger.Info("Song found"); - } - catch(Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error ocurred: {exMsg}"); - _logger.Error(exMsg, "An error occurred"); - } - - return song; - } - - public bool DoesSongExist(Song song) - { - _logger.Info("Checking to see if the song exists"); - var songInDatabase = GetSong(song); - var title = songInDatabase.Title; - - if (!string.IsNullOrEmpty(title)) - { - _logger.Info("Song exists"); - return true; - } - - _logger.Info("Song does not exists"); - - return false; - } - - private List ParseData(MySqlDataReader reader) - { - - var songs = new List(); - while (reader.Read()) - { - songs.Add(new Song - { - Id = Convert.ToInt32(reader["Id"]), - Title = reader["Title"].ToString(), - AlbumTitle = reader["AlbumTitle"].ToString(), - Artist = reader["Artist"].ToString(), - Year = Convert.ToInt32(reader["Year"]), - Genre = reader["Genre"].ToString(), - Duration = Convert.ToInt32(reader["Duration"]), - Filename = reader["Filename"].ToString(), - SongPath = reader["SongPath"].ToString(), - AlbumId = Convert.ToInt32(reader["AlbumId"].ToString()), - ArtistId = Convert.ToInt32(reader["ArtistId"].ToString()), - GenreId = Convert.ToInt32(reader["GenreId"].ToString()), - YearId = Convert.ToInt32(reader["YearId"].ToString()), - CoverArtId = Convert.ToInt32(reader["CoverArtId"].ToString()) - }); - } - - return songs; - } - - private Song ParseSingleData(MySqlDataReader reader) - { - var song = new Song(); - - while (reader.Read()) - { - song.Id = Convert.ToInt32(reader["Id"]); - song.Title = reader["Title"].ToString(); - song.AlbumTitle = reader["AlbumTitle"].ToString(); - song.Artist = reader["Artist"].ToString(); - song.Year = Convert.ToInt32(reader["Year"].ToString()); - song.Genre = reader["Genre"].ToString(); - song.Duration = Convert.ToInt32(reader["Duration"]); - song.Filename = reader["Filename"].ToString(); - song.SongPath = reader["SongPath"].ToString(); - song.AlbumId = Convert.ToInt32(reader["AlbumId"].ToString()); - song.ArtistId = Convert.ToInt32(reader["ArtistId"].ToString()); - song.GenreId = Convert.ToInt32(reader["GenreId"].ToString()); - song.YearId = Convert.ToInt32(reader["YearId"].ToString()); - song.CoverArtId = Convert.ToInt32(reader["CoverArtId"].ToString()); - } - - return song; - } - #endregion - } -} diff --git a/Database/Repositories/UserRepository.cs b/Database/Repositories/UserRepository.cs deleted file mode 100644 index 52e778b..0000000 --- a/Database/Repositories/UserRepository.cs +++ /dev/null @@ -1,229 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; - -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Repositories -{ - public class UserRepository: BaseRepository - { - #region Fields - #endregion - - - #region Properties - #endregion - - - #region Constructor - public UserRepository(string connectionString) - { - _connectionString = connectionString; - } - #endregion - - - #region Methods - public void SaveUser(User user) - { - try - { - _logger.Info("Saving user"); - - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - string query = "INSERT INTO User(Username, Password, Nickname, Email" + - ", PhoneNumber, Firstname, Lastname, EmailVerified) " + - "VALUES(@Username, @Password, @Nickname, @Email, @PhoneNumber," + - " @Firstname, @Lastname, @EmailVerified)"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Username", user.Username); - cmd.Parameters.AddWithValue("@Password", user.Password); - cmd.Parameters.AddWithValue("@Nickname", user.Nickname); - cmd.Parameters.AddWithValue("@Email", user.Email); - cmd.Parameters.AddWithValue("@PhoneNumber", user.PhoneNumber); - cmd.Parameters.AddWithValue("@Firstname", user.Firstname); - cmd.Parameters.AddWithValue("@Lastname", user.Lastname); - cmd.Parameters.AddWithValue("@EmailVerified", user.EmailVerified); - - - cmd.ExecuteNonQuery(); - } - } - - _logger.Info("Successfully saved user"); - } - catch (Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error occurred:\n{exMsg}"); - _logger.Error(exMsg, "An error occurred"); - } - } - - public User RetrieveUser(User user) - { - try - { - _logger.Info("Retrieving user"); - - using (MySqlConnection conn = GetConnection()) - { - conn.Open(); - var query = "SELECT * FROM User WHERE Username=@Username"; - - using (MySqlCommand cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Username", user.Username); - - using (var reader = cmd.ExecuteReader()) - user = ParseSingleData(reader); - } - } - - _logger.Info("Successfully retrieved user"); - - return user; - } - catch (Exception ex) - { - var exMsg = ex.Message; - Console.WriteLine($"An error occurred:\n{exMsg}"); - _logger.Error(exMsg, "An error occurred"); - } - - return null; - } - - public bool DoesUserExist(User user) - { - var username = user.Username; - try - { - _logger.Info($"Checking to see if {user.Username} exists"); - - using (var conn = GetConnection()) - { - conn.Open(); - var query = "SELECT * FROM User WHERE Username=@Username"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@Username", user.Username); - - using (var reader = cmd.ExecuteReader()) - { - user = ParseSingleData(reader, true); - username = user.Username; - - if (!string.IsNullOrEmpty(username)) - { - _logger.Info($"The user {username} exists"); - - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info($"The user {username} does not exists"); - - return false; - } - - private User ParseSingleData(MySqlDataReader reader) - { - var user = new User(); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["Id"].ToString()); - var username = reader["Username"].ToString(); - var password = reader["Password"].ToString(); - var nickname = reader["Nickname"].ToString(); - var email = reader["Email"].ToString(); - var phoneNumber = reader["PhoneNumber"].ToString(); - var emailVerified = reader["EmailVerified"].ToString() == "1"; - var firstname = reader["Firstname"].ToString(); - var lastname = reader["Lastname"].ToString(); - var rawLastLogin = reader["LastLogin"].ToString(); - - var parsedDateCreated = DateTime.Parse(reader["DateCreated"].ToString()); - - var dateCreated = DateTime.Parse(parsedDateCreated.ToString("yyyy-MM-dd HH:mm:ss")); - - if (!string.IsNullOrEmpty(rawLastLogin)) - { - var parsedLastLogin = DateTime.Parse(rawLastLogin); - var lastLogin = DateTime.Parse(parsedLastLogin.ToString("yyyy-MM-dd HH:mm:ss")); - user.LastLogin = lastLogin; - } - - user.Id = id; - user.Username = username; - user.Password = password; - user.Nickname = nickname; - user.Email = email; - user.PhoneNumber = phoneNumber; - user.EmailVerified = emailVerified; - user.Firstname = firstname; - user.Lastname = lastname; - user.DateCreated = dateCreated; - } - - return user; - } - private User ParseSingleData(MySqlDataReader reader, bool ignoreLastLogin) - { - var user = new User(); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["Id"].ToString()); - var username = reader["Username"].ToString(); - var nickname = reader["Nickname"].ToString(); - var email = reader["Email"].ToString(); - var phoneNumber = reader["PhoneNumber"].ToString(); - var emailVerified = reader["EmailVerified"].ToString() == "1"; - var firstname = reader["Firstname"].ToString(); - var lastname = reader["Lastname"].ToString(); - - var parsedDateCreated = DateTime.Parse(reader["DateCreated"].ToString()); - - var dateCreated = DateTime.Parse(parsedDateCreated.ToString("yyyy-MM-dd HH:mm:ss")); - - if (!ignoreLastLogin) - { - var parsedLastLogin = DateTime.Parse(reader["LastLogin"].ToString()); - var lastLogin = DateTime.Parse(parsedLastLogin.ToString("yyyy-MM-dd HH:mm:ss")); - user.LastLogin = lastLogin; - } - - user.Id = id; - user.Username = username; - user.Nickname = nickname; - user.Email = email; - user.PhoneNumber = phoneNumber; - user.EmailVerified = emailVerified; - user.Firstname = firstname; - user.Lastname = lastname; - user.DateCreated = dateCreated; - } - - return user; - } - #endregion - } -} diff --git a/Database/Repositories/YearRepository.cs b/Database/Repositories/YearRepository.cs deleted file mode 100644 index e44cde0..0000000 --- a/Database/Repositories/YearRepository.cs +++ /dev/null @@ -1,367 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; - -using MySql.Data.MySqlClient; - -using Icarus.Models; - -namespace Icarus.Database.Repositories -{ - public class YearRepository : BaseRepository - { - #region Fields - #endregion - - - #region Properties - #endregion - - - #region Constructors - public YearRepository(string connectionString) - { - _connectionString = connectionString; - } - #endregion - - - #region Methods - public List GetSongYears() - { - _logger.Info("Retrieving Year records"); - - var yearValues = new List(); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT yr.*, COUNT(*) AS SongCount FROM Year " + - "yr LEFT JOIN Song sng ON yr.YearId=sng.YearId " + - "GROUP BY yr.YearId"; - - using (var cmd = new MySqlCommand(query, conn)) - using (var reader = cmd.ExecuteReader()) - yearValues = ParseData(reader); - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return yearValues; - } - - public Year GetSongYear(Year year) - { - _logger.Info("Retrieving Year record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT yr.*, COUNT(*) AS SongCount FROM Year " + - "yr LEFT JOIN Song sng ON yr.YearId=sng.YearId WHERE " + - "YearId=@YearId GROUP BY yr.YearId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearId", year.YearId); - - using (var reader = cmd.ExecuteReader()) - year = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return year; - } - public Year GetSongYear(Song song) - { - var year = new Year(); - - _logger.Info("Retrieving Year record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT yr.*, 0 AS SongCount FROM Year " + - "yr WHERE yr.YearValue=@YearValue"; - - using(var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearValue", song.Year); - - using (var reader = cmd.ExecuteReader()) - year = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return year; - } - public Year GetSongYear(Song song, bool retrieveCount) - { - var year = new Year(); - - _logger.Info("Retrieving year record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = string.Empty; - - if (retrieveCount) - query = "SELECT yr.*, COUNT(*) AS SongCount FROM Year yr " + - "LEFT JOIN Song sng ON yr.YearValue=sng.Year WHERE " + - "yr.YearValue=@YearValue GROUP BY yr.YearId LIMIT 1"; - else - query = "SELECT yr.*, 0 AS SongCount FROM Year yr " + - "WHERE yr.YearValue=@YearValue LIMIT 1"; - - using(var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearValue", song.Year); - - using (var reader = cmd.ExecuteReader()) - year = ParseSingleData(reader); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - return year; - } - - public bool DoesYearExist(Year year) - { - _logger.Info("Checking to see if Year record exists"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT yr.*, 0 AS SongCount FROM Year yr WHERE " + - "yr.YearId=@YearId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearId", year.YearId); - - using (var reader = cmd.ExecuteReader()) - { - year = ParseSingleData(reader); - - if (year.YearValue > 0) - { - _logger.Info("Year record exists"); - - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info("Year record does not exist"); - - return false; - } - public bool DoesYearExist(Song song) - { - _logger.Info("Checking to see if Year record exists"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "SELECT yr.*, 0 AS SongCount FROM Year yr WHERE " + - "yr.YearValue=@YearValue"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearValue", song.Year); - - using (var reader = cmd.ExecuteReader()) - { - var year = ParseSingleData(reader); - - if (year.YearValue > 0) - { - _logger.Info("Year record exists"); - - return true; - } - } - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - - _logger.Info("Year record does not exist"); - - return false; - } - - public void SaveYear(Year year) - { - _logger.Info("Saving Year record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "INSERT INTO Year(YearValue) VALUES(@YearValue)"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearValue", year.YearValue); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void UpdateYear(Year year) - { - _logger.Info("Deleting Year record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "UPDATE Year SET YearValue=@YearValue WHERE YearId=@YearId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearId", year.YearId); - cmd.Parameters.AddWithValue("@YearValue", year.YearValue); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - public void DeleteYear(Year year) - { - _logger.Info("Deleting Year record"); - - try - { - using (var conn = GetConnection()) - { - conn.Open(); - - var query = "DELETE FROM Year WHERE YearId=@YearId"; - - using (var cmd = new MySqlCommand(query, conn)) - { - cmd.Parameters.AddWithValue("@YearId", year.YearId); - - cmd.ExecuteNonQuery(); - } - } - } - catch (Exception ex) - { - var msg = ex.Message; - _logger.Error(msg, "An error occurred"); - } - } - - private List ParseData(MySqlDataReader reader) - { - var yearValues = new List(); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["YearId"].ToString()); - var year = Convert.ToInt32(reader["YearValue"].ToString()); - var songCount = Convert.ToInt32(reader["SongCount"].ToString()); - - yearValues.Add(new Year - { - YearId = id, - YearValue = year, - SongCount = songCount - }); - } - - - return yearValues; - } - - private Year ParseSingleData(MySqlDataReader reader) - { - var yearValue = new Year(); - - while (reader.Read()) - { - var id = Convert.ToInt32(reader["YearId"].ToString()); - var year = Convert.ToInt32(reader["YearValue"].ToString()); - var songCount = Convert.ToInt32(reader["SongCount"].ToString()); - - yearValue.YearId = id; - yearValue.YearValue = year; - yearValue.SongCount = songCount; - } - - return yearValue; - } - #endregion - } -} diff --git a/Icarus.csproj b/Icarus.csproj deleted file mode 100644 index 9fa232a..0000000 --- a/Icarus.csproj +++ /dev/null @@ -1,34 +0,0 @@ - - - - netcoreapp2.2 - InProcess - - - - - - - - - - - runtime; build; native; contentfiles; analyzers - all - - - - - - - - - - - - - - - - - diff --git a/Icarus.csproj.user b/Icarus.csproj.user deleted file mode 100644 index 4912ce6..0000000 --- a/Icarus.csproj.user +++ /dev/null @@ -1,9 +0,0 @@ - - - - ProjectDebugger - - - Icarus - - \ No newline at end of file diff --git a/Icarus.sln b/Icarus.sln deleted file mode 100644 index f4826b6..0000000 --- a/Icarus.sln +++ /dev/null @@ -1,34 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Icarus", "Icarus.csproj", "{3BEBAB33-17BF-4183-9664-3D537A684138}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x64.ActiveCfg = Debug|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x64.Build.0 = Debug|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x86.ActiveCfg = Debug|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Debug|x86.Build.0 = Debug|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Release|Any CPU.Build.0 = Release|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x64.ActiveCfg = Release|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x64.Build.0 = Release|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x86.ActiveCfg = Release|Any CPU - {3BEBAB33-17BF-4183-9664-3D537A684138}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/Libs/CMakeLists.txt b/Libs/CMakeLists.txt deleted file mode 100644 index f2d1db4..0000000 --- a/Libs/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(icarus) - -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_STANDARD 17) - -set(SOURCES - src/directory_manager.cpp - src/imageFile.cpp - src/metadata_retriever.cpp - src/token_manager.cpp -) -set(HEADERS - include/models.h - include/directory_manager.h - include/imageFile.h - include/metadata_retriever.h -) - -include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) -conan_basic_setup() - -add_subdirectory(cpr) - -add_library(icarus SHARED ${SOURCES} ${HEADERS}) -include_directories(${CPR_INCLUDE_DIRS} include) -target_link_libraries(icarus "-lstdc++fs" tag ${CONAN_LIBS} ${CPR_LIBRARIES}) diff --git a/Libs/include/imageFile.h b/Libs/include/imageFile.h deleted file mode 100644 index 18322a8..0000000 --- a/Libs/include/imageFile.h +++ /dev/null @@ -1,38 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class imageFile : public TagLib::File -{ -public: - imageFile(const char *file); - /** - imageFile(const char *file) : TagLib::File(file) - { - - } - */ - - TagLib::ByteVector data(); - /** - TagLib::ByteVector data() - { - return readBlock(length()); - } - */ - - -private: - virtual TagLib::Tag *tag() const { return 0; } - virtual TagLib::AudioProperties *audioProperties() const { return 0; } - virtual bool save() { return false; } -}; diff --git a/Migrations/.empty b/Migrations/.empty deleted file mode 100644 index e69de29..0000000 diff --git a/Models/Album.cs b/Models/Album.cs deleted file mode 100644 index 7a120b0..0000000 --- a/Models/Album.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class Album - { - [JsonProperty("id")] - public int AlbumId { get; set; } - [JsonProperty("title")] - public string Title { get; set; } - [JsonProperty("album_artist")] - public string AlbumArtist { get; set; } - [JsonProperty("song_count")] - [NotMapped] - public int SongCount { get; set; } - - [JsonIgnore] - public List Songs { get; set; } - } -} diff --git a/Models/Artist.cs b/Models/Artist.cs deleted file mode 100644 index dee0d6a..0000000 --- a/Models/Artist.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class Artist - { - [JsonProperty("id")] - public int ArtistId { get; set; } - [JsonProperty("name")] - public string Name { get; set; } - [JsonProperty("song_count")] - [NotMapped] - public int SongCount { get; set; } - - [JsonIgnore] - public List Songs { get; set; } - } -} diff --git a/Models/BaseResult.cs b/Models/BaseResult.cs deleted file mode 100644 index 2b3ef1a..0000000 --- a/Models/BaseResult.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class BaseResult - { - [JsonProperty("message")] - public string Message { get; set; } - } -} diff --git a/Models/CoverArt.cs b/Models/CoverArt.cs deleted file mode 100644 index 6880421..0000000 --- a/Models/CoverArt.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Runtime.InteropServices; -using System.Text; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class CoverArt - { - [JsonProperty("id")] - public int CoverArtId { get; set; } - [JsonProperty("title")] - public string SongTitle { get; set; } - [JsonIgnore] - public string ImagePath { get; set; } - [NotMapped] - [JsonProperty("song_id")] - public int SongId { get; set; } - [JsonIgnore] - public List Songs { get; set; } - } - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct CovArt - { - public int CoverArtId; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string SongTitle; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string ImagePath; - } -} diff --git a/Models/Genre.cs b/Models/Genre.cs deleted file mode 100644 index 7ba1ada..0000000 --- a/Models/Genre.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class Genre - { - [JsonProperty("id")] - public int GenreId { get; set; } - [JsonProperty("genre")] - public string GenreName { get; set; } - [JsonProperty("song_count")] - [NotMapped] - public int SongCount { get; set; } - - [JsonIgnore] - public List Songs { get; set; } - } -} diff --git a/Models/LoginResult.cs b/Models/LoginResult.cs deleted file mode 100644 index e03df38..0000000 --- a/Models/LoginResult.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class LoginResult : BaseResult - { - [JsonProperty("id")] - public int UserId { get; set; } - [JsonProperty("username")] - public string Username { get; set; } - [JsonProperty("token")] - public string Token { get; set; } - [JsonProperty("token_type")] - public string TokenType { get; set; } - [JsonProperty("expiration")] - public int Expiration { get; set; } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi), Serializable] - public struct LogRes - { - public int UserId; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Username; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Token; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string TokenType; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Message; - public int Expiration; - } -} diff --git a/Models/RegisterResult.cs b/Models/RegisterResult.cs deleted file mode 100644 index 31a8641..0000000 --- a/Models/RegisterResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class RegisterResult : BaseResult - { - [JsonProperty("username")] - public string Username { get; set; } - [JsonProperty("successfully_registered")] - public bool SuccessfullyRegistered { get; set; } - } -} diff --git a/Models/Song.cs b/Models/Song.cs deleted file mode 100644 index a09f368..0000000 --- a/Models/Song.cs +++ /dev/null @@ -1,73 +0,0 @@ -using System; -using System.ComponentModel.DataAnnotations.Schema; -using System.Runtime.InteropServices; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class Song - { - [JsonProperty("id")] - public int Id { get; set; } - [JsonProperty("title")] - public string Title { get; set; } - [JsonProperty("album")] - public string AlbumTitle { get; set; } - [JsonProperty("artist")] - public string Artist { get; set; } - [JsonProperty("year")] - public int? Year { get; set; } - [JsonProperty("genre")] - public string Genre { get; set; } - [JsonProperty("duration")] - public int Duration { get; set; } - [JsonProperty("filename")] - public string Filename { get; set; } - [JsonProperty("song_path")] - public string SongPath { get; set; } - - [JsonIgnore] - public Album Album { get; set; } - [JsonIgnore] - public int? AlbumId { get; set; } - - [JsonIgnore] - public Artist SongArtist { get; set; } - [JsonIgnore] - public int? ArtistId { get; set; } - - [JsonIgnore] - public Genre SongGenre { get; set; } - [JsonIgnore] - public int? GenreId { get; set; } - - [JsonIgnore] - public Year SongYear { get; set; } - [JsonIgnore] - public int? YearId { get; set; } - - [JsonIgnore] - public CoverArt SongCoverArt { get; set; } - [JsonIgnore] - public int? CoverArtId { get; set; } - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct Sng - { - public int Id; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Title; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Artist; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Album; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Genre; - public int Year; - public int Duration; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string SongPath; - } -} diff --git a/Models/SongData.cs b/Models/SongData.cs deleted file mode 100644 index ccef51e..0000000 --- a/Models/SongData.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using System.Text; - -namespace Icarus.Models -{ - public class SongData - { - public int Id { get; set; } - public byte[] Data { get; set; } - public int SongId { get; set; } - } -} diff --git a/Models/SongResult.cs b/Models/SongResult.cs deleted file mode 100644 index 5763b3c..0000000 --- a/Models/SongResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class SongResult - { - [JsonProperty("message")] - public string Message { get; set; } - [JsonProperty("song_title")] - public string SongTitle { get; set; } - } -} diff --git a/Models/TokenReq.cs b/Models/TokenReq.cs deleted file mode 100644 index 9b3b9ed..0000000 --- a/Models/TokenReq.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Icarus.Models -{ - [StructLayout(LayoutKind.Sequential)] - public struct TokenReq - { - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string ClientId; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string ClientSecret; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Audience; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string GrantType; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string URI; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] - public string Endpoint; - } -} diff --git a/Models/User.cs b/Models/User.cs deleted file mode 100644 index f4ec760..0000000 --- a/Models/User.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class User - { - [JsonProperty("id")] - public int Id { get; set; } - [JsonProperty("username")] - public string Username { get; set; } - [JsonProperty("nickname")] - public string Nickname { get; set; } - [JsonProperty("password")] - public string Password { get; set; } - [JsonProperty("email")] - public string Email { get; set; } - [JsonProperty("phone_number")] - public string PhoneNumber { get; set; } - [JsonProperty("first_name")] - public string Firstname { get; set; } - [JsonProperty("last_name")] - public string Lastname { get; set; } - [JsonProperty("email_verified")] - public bool EmailVerified { get; set; } - [JsonProperty("date_created")] - public DateTime DateCreated { get; set; } - [JsonProperty("last_login")] - public DateTime? LastLogin { get; set; } - } -} diff --git a/Models/Year.cs b/Models/Year.cs deleted file mode 100644 index b4e855b..0000000 --- a/Models/Year.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; - -using Newtonsoft.Json; - -namespace Icarus.Models -{ - public class Year - { - [JsonProperty("id")] - public int YearId { get; set; } - [JsonProperty("year")] - public int YearValue { get; set; } - [JsonProperty("song_count")] - [NotMapped] - public int SongCount { get; set; } - - [JsonIgnore] - public List Songs { get; set; } - } -} diff --git a/Program.cs b/Program.cs deleted file mode 100644 index 6d088d6..0000000 --- a/Program.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -using Microsoft.AspNetCore; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using NLog.Web; - -namespace Icarus -{ - public class Program - { - public static void Main(string[] args) - { - var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); - - try - { - logger.Debug("init main"); - CreateWebHostBuilder(args).Build().Run(); - } - catch (Exception ex) - { - logger.Error(ex, "An error occurred"); - throw; - } - finally - { - NLog.LogManager.Shutdown(); - } - } - - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => - WebHost.CreateDefaultBuilder(args).UseStartup() - .UseUrls("http://localhost:5002") - .ConfigureLogging(logging => - { - logging.ClearProviders(); - logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); - }) - .UseNLog(); - } -} diff --git a/Properties/launchSettings.json b/Properties/launchSettings.json deleted file mode 100644 index 82a1227..0000000 --- a/Properties/launchSettings.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/launchsettings.json", - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:20781", - "sslPort": 44394 - } - }, - "profiles": { - "IIS Express": { - "commandName": "IISExpress", - "launchBrowser": true, - "launchUrl": "api/values", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "Icarus": { - "commandName": "Project", - "launchBrowser": true, - "launchUrl": "api/values", - "applicationUrl": "http://localhost:5002", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } -} diff --git a/Startup.cs b/Startup.cs deleted file mode 100644 index 5d0ddbf..0000000 --- a/Startup.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using System.IdentityModel.Tokens.Jwt; - -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Microsoft.EntityFrameworkCore; -using MySql.Data; -using MySql.Data.EntityFrameworkCore.Extensions; -using MySql.Data.MySqlClient; -using NLog; -using NLog.Web; -using NLog.Web.AspNetCore; - -using Icarus.Authorization; -using Icarus.Authorization.Handlers; -using Icarus.Database.Contexts; -using Icarus.Database.Repositories; - -namespace Icarus -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); - services.AddSingleton(Configuration); - - string domain = $"https://{Configuration["Auth0:Domain"]}/"; - - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(options => - { - options.Authority = domain; - options.Audience = Configuration["Auth0:ApiIdentifier"]; - }); - - services.AddAuthorization(options => - { - options.AddPolicy("download:songs", policy => - policy.Requirements - .Add(new HasScopeRequirement("download:songs", domain))); - - options.AddPolicy("download:cover_art", policy => - policy.Requirements - .Add(new HasScopeRequirement("download:cover_art", domain))); - - options.AddPolicy("upload:songs", policy => - policy.Requirements - .Add(new HasScopeRequirement("upload:songs", domain))); - - options.AddPolicy("delete:songs", policy => - policy.Requirements - .Add(new HasScopeRequirement("delete:songs", domain))); - - options.AddPolicy("read:song_details", policy => - policy.Requirements - .Add(new HasScopeRequirement("read:song_details", domain))); - - options.AddPolicy("update:songs", policy => - policy.Requirements - .Add(new HasScopeRequirement("update:songs", domain))); - - options.AddPolicy("read:artists", policy => - policy.Requirements - .Add(new HasScopeRequirement("read:artists", domain))); - - options.AddPolicy("read:albums", policy => - policy.Requirements - .Add(new HasScopeRequirement("read:albums", domain))); - - options.AddPolicy("read:genre", policy => - policy.Requirements - .Add(new HasScopeRequirement("read:genre", domain))); - - options.AddPolicy("read:year", policy => - policy.Requirements - .Add(new HasScopeRequirement("read:year", domain))); - - options.AddPolicy("stream:songs", policy => - policy.Requirements - .Add(new HasScopeRequirement("stream:songs", domain))); - }); - - - services.AddSingleton(); - - var connString = Configuration.GetConnectionString("DefaultConnection"); - - services.Add(new ServiceDescriptor(typeof(SongRepository), - new SongRepository(Configuration.GetConnectionString("DefaultConnection")))); - - services.Add(new ServiceDescriptor(typeof(AlbumRepository), - new AlbumRepository(Configuration.GetConnectionString("DefaultConnection")))); - - services.Add(new ServiceDescriptor(typeof(ArtistRepository), - new ArtistRepository(Configuration.GetConnectionString("DefaultConnection")))); - - services.Add(new ServiceDescriptor(typeof(GenreRepository), - new GenreRepository(Configuration.GetConnectionString("DefaultConnection")))); - - services.Add(new ServiceDescriptor(typeof(YearRepository), - new YearRepository(Configuration.GetConnectionString("DefaultConnection")))); - - services.Add(new ServiceDescriptor(typeof(CoverArtRepository), - new CoverArtRepository(Configuration.GetConnectionString("DefaultConnection")))); - - services.Add(new ServiceDescriptor(typeof(UserRepository), - new UserRepository(Configuration.GetConnectionString("DefaultConnection")))); - - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - services.AddDbContext(options => options.UseMySQL(connString)); - } - - // Called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env) - { - if (env.IsDevelopment()) - app.UseDeveloperExceptionPage(); - else - // The default HSTS value is 30 days. - // You may want to change this for production scenarios - app.UseHsts(); - - app.UseAuthentication(); - - app.UseHttpsRedirection(); - app.UseMvc(); - } - } -} diff --git a/Types/CoverArtTypes.cs b/Types/CoverArtTypes.cs deleted file mode 100644 index 98edd43..0000000 --- a/Types/CoverArtTypes.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Icarus.Types -{ - public enum CoverArtField - { - SongTitle = 0, - ImagePath - }; -} diff --git a/Types/DirectoryTypes.cs b/Types/DirectoryTypes.cs deleted file mode 100644 index fcad47c..0000000 --- a/Types/DirectoryTypes.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace Icarus.Types -{ - public enum DirectoryType - { - Music = 0, - CoverArt - }; -} diff --git a/appsettings.Development.json b/appsettings.Development.json deleted file mode 100644 index 827e74a..0000000 --- a/appsettings.Development.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Debug", - "System": "Information", - "Microsoft": "Information" - } - }, - "Auth0": { - "Domain": "[domain].auth0.com", - "ApiIdentifier": "https://[identifier]/api", - "ClientId": "", - "ClientSecret": "" - }, - "ConnectionStrings": { - "DefaultConnection": "Server=;Database=;Uid=;Pwd=;" - }, - "RootMusicPath": "/music/path/", - "TemporaryMusicPath": "/music/temp/path/", - "ArchivePath": "/archive/path/", - "CoverArtPath": "/cover/art/path/" -} diff --git a/build/3rdparty/jwt-cpp b/build/3rdparty/jwt-cpp new file mode 160000 index 0000000..27f3298 --- /dev/null +++ b/build/3rdparty/jwt-cpp @@ -0,0 +1 @@ +Subproject commit 27f32983fb310f4406e6da6c43700202c93bf18c diff --git a/Libs/conanfile.txt b/conanfile.txt similarity index 100% rename from Libs/conanfile.txt rename to conanfile.txt diff --git a/Libs/include/directory_manager.h b/include/directory_manager.h similarity index 100% rename from Libs/include/directory_manager.h rename to include/directory_manager.h diff --git a/include/imageFile.h b/include/imageFile.h new file mode 100644 index 0000000..d6d5e86 --- /dev/null +++ b/include/imageFile.h @@ -0,0 +1,48 @@ +#include + +//#include +#include +//#include +//#include +//#include +#include +//#include +#include +//#include +#include +//#include +#include +//#include +#include +//#include +#include +//#include +#include +//#include +#include + +class imageFile : public TagLib::File +{ +public: + imageFile(const char *file); + /** + imageFile(const char *file) : TagLib::File(file) + { + + } + */ + + TagLib::ByteVector data(); + /** + TagLib::ByteVector data() + { + return readBlock(length()); + } + */ + + +private: + virtual TagLib::Tag *tag() const { return 0; } + virtual TagLib::AudioProperties *audioProperties() const { return 0; } + virtual bool save() { return false; } +}; diff --git a/Libs/include/metadata_retriever.h b/include/metadata_retriever.h similarity index 100% rename from Libs/include/metadata_retriever.h rename to include/metadata_retriever.h diff --git a/Libs/include/models.h b/include/models.h similarity index 100% rename from Libs/include/models.h rename to include/models.h diff --git a/nlog.config b/nlog.config deleted file mode 100644 index 34dc456..0000000 --- a/nlog.config +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/appComponent.hpp b/src/appComponent.hpp new file mode 100644 index 0000000..2ddc5b7 --- /dev/null +++ b/src/appComponent.hpp @@ -0,0 +1,34 @@ +#ifndef APPCOMPONENT_H_ +#define APPCOMPONENT_H_ + +#include + +#include "oatpp/core/macro/component.hpp" +#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp/web/server/HttpConnectionHandler.hpp" + +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, serverConnectionHandler)([] { + OATPP_COMPONENT(std::shared_ptr, router); + + return oatpp::web::server::HttpConnectionHandler::createShared(router); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { + return oatpp::parser::json::mapping::ObjectMapper::createShared(); + }()); +private: +}; + +#endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp new file mode 100644 index 0000000..3d2ff6c --- /dev/null +++ b/src/controller/loginController.hpp @@ -0,0 +1,34 @@ +#ifndef LOGINCONTROLLER_H_ +#define LOGINCONTROLLER_H_ + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/macro/component.hpp" +#include "oatpp/web/server/api/ApiController.hpp" + +#include "../dto/loginResultDto.hpp" + +class loginController : public oatpp::web::server::api::ApiController +{ +public: + loginController(OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper) + { } + + #include OATPP_CODEGEN_BEGIN(ApiController) + + ENDPOINT("POST", "/api/v1/login", root) + { + OATPP_LOGI("icarus", "logging in"); + + auto logRes = loginResultDto::createShared(); + logRes->access_token = "sdfsdfsdfsdert"; + logRes->token_type = "Special"; + + return createDtoResponse(Status::CODE_200, logRes); + } + + #include OATPP_CODEGEN_END(ApiController) +private: +}; + +#endif diff --git a/Libs/src/directory_manager.cpp b/src/directory_manager.cpp similarity index 100% rename from Libs/src/directory_manager.cpp rename to src/directory_manager.cpp diff --git a/src/dto/loginResultDto.hpp b/src/dto/loginResultDto.hpp new file mode 100644 index 0000000..05b7b88 --- /dev/null +++ b/src/dto/loginResultDto.hpp @@ -0,0 +1,19 @@ +#ifndef LOGINRESULTDTO_H_ +#define LOGINRESULTDTO_H_ + +#include "oatpp/core/data/mapping/type/Object.hpp" +#include "oatpp/core/macro/codegen.hpp" + +#include OATPP_CODEGEN_BEGIN(DTO) + +class loginResultDto : public oatpp::data::mapping::type::Object +{ + DTO_INIT(loginResultDto, Object) + + DTO_FIELD(String, access_token); + DTO_FIELD(String, token_type); +}; + +#include OATPP_CODEGEN_END(DTO) + +#endif diff --git a/Libs/src/imageFile.cpp b/src/imageFile.cpp similarity index 100% rename from Libs/src/imageFile.cpp rename to src/imageFile.cpp diff --git a/src/loginHandler.cpp b/src/loginHandler.cpp new file mode 100644 index 0000000..4223142 --- /dev/null +++ b/src/loginHandler.cpp @@ -0,0 +1,2 @@ +#include "loginHandler.h" + diff --git a/src/loginHandler.hpp b/src/loginHandler.hpp new file mode 100644 index 0000000..a40a71b --- /dev/null +++ b/src/loginHandler.hpp @@ -0,0 +1,29 @@ +#ifndef LOGINHANDLER_H_ +#define LOGINHANDLER_H_ + +#include + +#include "oatpp/network/server/Server.hpp" +#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" +#include "oatpp/web/server/HttpConnectionHandler.hpp" + +#include "dto/loginResultDto.hpp" +//#include "dto/loginResultDto.hpp" + +class loginHandler : public oatpp::web::server::HttpRequestHandler +{ +public: + + std::shared_ptr handle(const std::shared_ptr& request) override + { + auto logRes = loginResultDto::createShared(); + logRes->access_token = "hahahahahahaha"; + logRes->token_type = "Fly"; + + return ResponseFactory::createResponse(Status::CODE_200, "ddd"); + } +private: + OATPP_COMPONENT(std::shared_ptr, m_objectMapper); +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..741ed6c --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,43 @@ +#include +#include + +#include "oatpp/network/server/Server.hpp" +#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" +#include "oatpp/web/server/HttpConnectionHandler.hpp" + +#include "appComponent.hpp" +#include "controller/loginController.hpp" +//#include "loginHandler.hpp" + +void run() +{ + appComponent component; + + //auto router = oatpp::web::server::HttpRouter::createShared(); + OATPP_COMPONENT(std::shared_ptr, router); + + //router->route("GET", "/test", std::make_shared()); + auto logController = std::make_shared(); + logController->addEndpointsToRouter(router); + + OATPP_COMPONENT(std::shared_ptr, connectionHandler); + + OATPP_COMPONENT(std::shared_ptr, connectionProvider); + + oatpp::network::server::Server server(connectionProvider, connectionHandler); + + OATPP_LOGI("icarus", "Server running on port %s", connectionProvider->getProperty("port").getData()); + + server.run(); +} + +int main(int argc, char **argv) +{ + oatpp::base::Environment::init(); + + run(); + + oatpp::base::Environment::destroy(); + + return 0; +} diff --git a/Libs/src/metadata_retriever.cpp b/src/metadata_retriever.cpp similarity index 92% rename from Libs/src/metadata_retriever.cpp rename to src/metadata_retriever.cpp index b740523..1df9863 100644 --- a/Libs/src/metadata_retriever.cpp +++ b/src/metadata_retriever.cpp @@ -5,10 +5,14 @@ #include #include -#include -#include -#include -#include +//#include +#include +//#include +#include +//#include +#include +//#include +#include #include "directory_manager.h" #include "metadata_retriever.h" diff --git a/Libs/src/token_manager.cpp b/src/token_manager.cpp similarity index 100% rename from Libs/src/token_manager.cpp rename to src/token_manager.cpp From 9ae9b08520a0648c0e4f3348a2dab4ef1514f644 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 17 Aug 2019 16:17:43 -0400 Subject: [PATCH 02/36] changed path of jwt-cpp submodule --- .gitmodules | 3 +++ {build/3rdparty => 3rdparty}/jwt-cpp | 0 2 files changed, 3 insertions(+) rename {build/3rdparty => 3rdparty}/jwt-cpp (100%) diff --git a/.gitmodules b/.gitmodules index bb89d93..d18c440 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "build/3rdparty/jwt-cpp"] path = build/3rdparty/jwt-cpp url = https://github.com/Thalhammer/jwt-cpp +[submodule "3rdparty/jwt-cpp"] + path = 3rdparty/jwt-cpp + url = https://github.com/Thalhammer/jwt-cpp diff --git a/build/3rdparty/jwt-cpp b/3rdparty/jwt-cpp similarity index 100% rename from build/3rdparty/jwt-cpp rename to 3rdparty/jwt-cpp From 5230e69832de0f23e631c1371cdf60182ab81701 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 17 Aug 2019 18:53:50 -0400 Subject: [PATCH 03/36] more changes --- CMakeLists.txt | 4 +++ authcredentials.json | 6 +++++ include/models.h | 20 +++++++++++++++ include/token_manager.h | 18 ++++++++++++++ src/controller/loginController.hpp | 25 +++++++++++++++---- src/main.cpp | 13 +++++++--- src/token_manager.cpp | 39 +++++++++++++++++++++++++++--- 7 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 authcredentials.json create mode 100644 include/token_manager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dc1a8de..9815658 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(HEADERS include/directory_manager.h include/imageFile.h include/metadata_retriever.h + include/token_manager.h ) set (TAGLIB @@ -60,6 +61,9 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/cpr) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/taglib) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/oatpp) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/appsettings.json ${CMAKE_BINARY_DIR}/bin/appsettings.json COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/authcredentials.json ${CMAKE_BINARY_DIR}/bin/authcredentials.json COPYONLY) + add_executable(icarus ${SOURCES} ${HEADERS}) target_include_directories(icarus PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include) target_link_libraries(icarus "-lstdc++fs" tag oatpp ${CONAN_LIBS} ${CPR_LIBRARIES}) diff --git a/authcredentials.json b/authcredentials.json new file mode 100644 index 0000000..463d848 --- /dev/null +++ b/authcredentials.json @@ -0,0 +1,6 @@ +{ + "Domain": "[domain].auth0.com", + "ApiIdentifier": "https://[identifier]/api", + "ClientId": "dfdfdfdf", + "ClientSecret": "dfdfdfdf" +} diff --git a/include/models.h b/include/models.h index dbc5c67..1b71544 100644 --- a/include/models.h +++ b/include/models.h @@ -1,6 +1,8 @@ #ifndef MODELS_H_ #define MODELS_H_ +#include + struct Song { int Id; @@ -30,6 +32,24 @@ struct LoginRes int Expiration; }; +struct loginResult +{ + int user_id; + std::string username; + std::string access_token; + std::string token_type; + std::string message; + int expiration; +}; + +struct auth_credentials +{ + std::string domain; + std::string api_identifier; + std::string client_id; + std::string client_secret; +}; + struct TokenReq { char ClientId[1024]; diff --git a/include/token_manager.h b/include/token_manager.h new file mode 100644 index 0000000..6d32217 --- /dev/null +++ b/include/token_manager.h @@ -0,0 +1,18 @@ +#ifndef TOKEN_MANAGER_H_ +#define TOKEN_MANAGER_H_ + +#include "models.h" + +class token_manager +{ +public: + token_manager(); + + loginResult retrieve_token(); + + //LoginRes* retrieve_token(TokenReq *tok); +private: + auth_credentials parse_auth_credentials(); +}; + +#endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 3d2ff6c..7cd7683 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -1,18 +1,29 @@ #ifndef LOGINCONTROLLER_H_ #define LOGINCONTROLLER_H_ +#include +#include +#include + #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/web/server/api/ApiController.hpp" #include "../dto/loginResultDto.hpp" +#include "token_manager.h" + +namespace fs = std::filesystem; class loginController : public oatpp::web::server::api::ApiController { public: - loginController(OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper) - { } + loginController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), exe_path(fs::canonical(p.c_str()).parent_path().string()) + { + std::cout << "p is " << p << std::endl; + std::cout << "working path " << exe_path.string() << std::endl; + } + #include OATPP_CODEGEN_BEGIN(ApiController) @@ -20,15 +31,19 @@ public: { OATPP_LOGI("icarus", "logging in"); + token_manager tok; + auto token = tok.retrieve_token(); + auto logRes = loginResultDto::createShared(); - logRes->access_token = "sdfsdfsdfsdert"; - logRes->token_type = "Special"; + logRes->access_token = token.access_token.c_str(); + logRes->token_type = token.token_type.c_str(); return createDtoResponse(Status::CODE_200, logRes); } #include OATPP_CODEGEN_END(ApiController) private: + fs::path exe_path; }; #endif diff --git a/src/main.cpp b/src/main.cpp index 741ed6c..68ea3b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include #include "oatpp/network/server/Server.hpp" #include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" @@ -9,7 +11,9 @@ #include "controller/loginController.hpp" //#include "loginHandler.hpp" -void run() +namespace fs = std::filesystem; + +void run(const std::string& working_path) { appComponent component; @@ -17,7 +21,7 @@ void run() OATPP_COMPONENT(std::shared_ptr, router); //router->route("GET", "/test", std::make_shared()); - auto logController = std::make_shared(); + auto logController = std::make_shared(working_path); logController->addEndpointsToRouter(router); OATPP_COMPONENT(std::shared_ptr, connectionHandler); @@ -31,11 +35,14 @@ void run() server.run(); } + int main(int argc, char **argv) { oatpp::base::Environment::init(); + std::string working_path = argv[0]; + //std::cout << fs::canonical(fs::path(working_path.c_str())).parent_path().string() << std::endl; - run(); + run(working_path); oatpp::base::Environment::destroy(); diff --git a/src/token_manager.cpp b/src/token_manager.cpp index 7162920..e529fd7 100644 --- a/src/token_manager.cpp +++ b/src/token_manager.cpp @@ -1,18 +1,48 @@ #include +#include #include +#include #include #include #include -#include "models.h" +//#include "models.h" +#include "token_manager.h" + +namespace fs = std::filesystem; + +//extern "C" +//{ -extern "C" +token_manager::token_manager() { +} +loginResult token_manager::retrieve_token() +{ + auto cred = parse_auth_credentials(); -LoginRes* retrieve_token(TokenReq *tok) + loginResult lr; + lr.access_token = "dsfdsf"; + lr.token_type = "demo"; + + return lr; +} + +auth_credentials token_manager::parse_auth_credentials() +{ + auth_credentials auth; + //auto ss = working_path.string(); + //auto path = fs::canonical(fs::path(".")); + //std::cout << "canonical path " << path.string() << std::endl; + + return auth; +} + +/** +LoginRes* token_manager::retrieve_token(TokenReq *tok) { LoginRes *res = new LoginRes; @@ -38,4 +68,5 @@ LoginRes* retrieve_token(TokenReq *tok) return res; } -} +*/ +//} From d26c16aa69a5841f407e6afc2333b92d6eb29694 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 18 Aug 2019 11:57:08 -0400 Subject: [PATCH 04/36] database stuff --- .gitmodules | 6 +++ 3rdparty/mysql-connector-cpp | 1 + CMakeLists.txt | 20 +++++++- include/database/base_repository.h | 19 ++++++++ include/models.h | 10 ++++ include/token_manager.h | 7 +-- src/controller/loginController.hpp | 16 +++---- src/database/base_repository.cpp | 25 ++++++++++ src/dto/loginResultDto.hpp | 9 ++++ src/main.cpp | 71 +++++++++++++++++++++++++++- src/token_manager.cpp | 75 ++++++++++++++++-------------- 11 files changed, 211 insertions(+), 48 deletions(-) create mode 160000 3rdparty/mysql-connector-cpp create mode 100644 include/database/base_repository.h create mode 100644 src/database/base_repository.cpp diff --git a/.gitmodules b/.gitmodules index d18c440..a71061f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,9 @@ [submodule "3rdparty/jwt-cpp"] path = 3rdparty/jwt-cpp url = https://github.com/Thalhammer/jwt-cpp +[submodule "3rdparty/ormpp"] + path = 3rdparty/ormpp + url = https://github.com/qicosmos/ormpp +[submodule "3rdparty/mysql-connector-cpp"] + path = 3rdparty/mysql-connector-cpp + url = https://github.com/mysql/mysql-connector-cpp diff --git a/3rdparty/mysql-connector-cpp b/3rdparty/mysql-connector-cpp new file mode 160000 index 0000000..64731f9 --- /dev/null +++ b/3rdparty/mysql-connector-cpp @@ -0,0 +1 @@ +Subproject commit 64731f9625d5bcff86236c9fce2a1f5c55d60242 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9815658..1cce78a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,9 +5,12 @@ project(icarus) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) +#add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) + set(SOURCES src/appComponent.hpp src/controller/loginController.hpp + src/database/base_repository.cpp src/directory_manager.cpp src/dto/loginResultDto.hpp src/imageFile.cpp @@ -16,6 +19,7 @@ set(SOURCES src/token_manager.cpp ) set(HEADERS + include/database/base_repository.h include/models.h include/directory_manager.h include/imageFile.h @@ -52,18 +56,32 @@ set(TAGLIB_HEADERS "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/xm" ) +set (ORM_DIR + ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ormpp +) + +set (MYSQL + /usr/local/mysql/connector-c++-8.0/lib64 + ) +set (MYSQL_INCLUDE + /usr/local/mysql/connector-c++-8.0/include/mysqlx + /usr/local/mysql/connector-c++-8.0/include/mysqlx/common + ) + include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() +link_directories(${MYSQL}) include_directories(include ${CPR_INCLUDE_DIRS} ${TAGLIB} ${TAGLIB_HEADERS}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/cpr) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/taglib) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/oatpp) +#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/mysql-connector-cpp) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/appsettings.json ${CMAKE_BINARY_DIR}/bin/appsettings.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/authcredentials.json ${CMAKE_BINARY_DIR}/bin/authcredentials.json COPYONLY) add_executable(icarus ${SOURCES} ${HEADERS}) target_include_directories(icarus PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include) -target_link_libraries(icarus "-lstdc++fs" tag oatpp ${CONAN_LIBS} ${CPR_LIBRARIES}) +target_link_libraries(icarus "-lstdc++fs" tag oatpp mysqlclient ${CONAN_LIBS} ${CPR_LIBRARIES}) diff --git a/include/database/base_repository.h b/include/database/base_repository.h new file mode 100644 index 0000000..d8c8e43 --- /dev/null +++ b/include/database/base_repository.h @@ -0,0 +1,19 @@ +#ifndef BASE_REPOSITORY_H_ +#define BASE_REPOSITORY_H_ + +#include + +#include + +#include "models.h" + +class base_repository +{ +public: + MYSQL* setup_mysql_connection(database_connection); + + MYSQL_RES* perform_mysql_query(MYSQL*, std::string&); +private: +}; + +#endif diff --git a/include/models.h b/include/models.h index 1b71544..c2532e1 100644 --- a/include/models.h +++ b/include/models.h @@ -48,6 +48,16 @@ struct auth_credentials std::string api_identifier; std::string client_id; std::string client_secret; + std::string uri; + std::string endpoint; +}; + +struct database_connection +{ + std::string server; + std::string username; + std::string password; + std::string database; }; struct TokenReq diff --git a/include/token_manager.h b/include/token_manager.h index 6d32217..4d7b80b 100644 --- a/include/token_manager.h +++ b/include/token_manager.h @@ -1,6 +1,8 @@ #ifndef TOKEN_MANAGER_H_ #define TOKEN_MANAGER_H_ +#include + #include "models.h" class token_manager @@ -9,10 +11,9 @@ public: token_manager(); loginResult retrieve_token(); - - //LoginRes* retrieve_token(TokenReq *tok); + loginResult retrieve_token(std::string_view); private: - auth_credentials parse_auth_credentials(); + auth_credentials parse_auth_credentials(std::string_view); }; #endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 7cd7683..772a17d 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -18,32 +18,32 @@ 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(fs::canonical(p.c_str()).parent_path().string()) - { - std::cout << "p is " << p << std::endl; - std::cout << "working path " << exe_path.string() << std::endl; - } + : oatpp::web::server::api::ApiController(objectMapper), exe_path(std::move(p)) + { } #include OATPP_CODEGEN_BEGIN(ApiController) - ENDPOINT("POST", "/api/v1/login", root) + ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(userDto::ObjectWrapper, usr)) { OATPP_LOGI("icarus", "logging in"); + std::cout << "user: " << usr->username->c_str() << std::endl; + token_manager tok; - auto token = tok.retrieve_token(); + auto token = tok.retrieve_token(exe_path); auto logRes = loginResultDto::createShared(); logRes->access_token = token.access_token.c_str(); logRes->token_type = token.token_type.c_str(); + logRes->expiration = token.expiration; return createDtoResponse(Status::CODE_200, logRes); } #include OATPP_CODEGEN_END(ApiController) private: - fs::path exe_path; + std::string exe_path; }; #endif diff --git a/src/database/base_repository.cpp b/src/database/base_repository.cpp new file mode 100644 index 0000000..c67c065 --- /dev/null +++ b/src/database/base_repository.cpp @@ -0,0 +1,25 @@ +#include "database/base_repository.h" + +MYSQL* base_repository::setup_mysql_connection(database_connection details) +{ + MYSQL *connection = mysql_init(NULL); + + // connect to the database with the details attached. + if (!mysql_real_connect(connection,details.server.c_str(), details.username.c_str(), details.password.c_str(), details.database.c_str(), 0, NULL, 0)) { + printf("Conection error : %s\n", mysql_error(connection)); + exit(1); + } + return connection; +} + +MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, std::string& query) +{ + // send the query to the database + if (mysql_query(conn, query.c_str())) + { + printf("MySQL query error : %s\n", mysql_error(conn)); + exit(1); + } + + return mysql_use_result(conn); +} diff --git a/src/dto/loginResultDto.hpp b/src/dto/loginResultDto.hpp index 05b7b88..a43ec02 100644 --- a/src/dto/loginResultDto.hpp +++ b/src/dto/loginResultDto.hpp @@ -12,6 +12,15 @@ class loginResultDto : public oatpp::data::mapping::type::Object DTO_FIELD(String, access_token); DTO_FIELD(String, token_type); + DTO_FIELD(Int32, expiration); +}; + +class userDto : public oatpp::data::mapping::type::Object +{ + DTO_INIT(userDto, Object) + + DTO_FIELD(String, username); + DTO_FIELD(String, password); }; #include OATPP_CODEGEN_END(DTO) diff --git a/src/main.cpp b/src/main.cpp index 68ea3b4..f779651 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,15 +1,18 @@ +#include #include #include #include #include +#include "models.h" +#include #include "oatpp/network/server/Server.hpp" #include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" #include "oatpp/web/server/HttpConnectionHandler.hpp" #include "appComponent.hpp" #include "controller/loginController.hpp" -//#include "loginHandler.hpp" +#include "database/base_repository.h" namespace fs = std::filesystem; @@ -35,13 +38,77 @@ void run(const std::string& working_path) server.run(); } +MYSQL* mysql_connection_setup(database_connection mysql_details) +{ + // first of all create a mysql instance and initialize the variables within + MYSQL *connection = mysql_init(NULL); + + // connect to the database with the details attached. + if (!mysql_real_connect(connection,mysql_details.server.c_str(), mysql_details.username.c_str(), mysql_details.password.c_str(), mysql_details.database.c_str(), 0, NULL, 0)) { + printf("Conection error : %s\n", mysql_error(connection)); + exit(1); + } + return connection; +} + +MYSQL_RES* mysql_perform_query(MYSQL *connection, char *sql_query) +{ + // send the query to the database + if (mysql_query(connection, sql_query)) + { + printf("MySQL query error : %s\n", mysql_error(connection)); + exit(1); + } + + return mysql_use_result(connection); +} + +void test_database() +{ + database_connection mysqlD; + mysqlD.server = ""; // where the mysql database is + mysqlD.username = ""; // the root user of mysql + mysqlD.password = ""; // the password of the root user in mysql + mysqlD.database = ""; // the databse to pick + + base_repository base; + auto conn = base.setup_mysql_connection(mysqlD); + + // assign the results return to the MYSQL_RES pointer + const std::string query = "SELECT *, NULL FROM Song"; + auto res = base.perform_mysql_query(conn, query); + auto num_of_fields = mysql_num_fields(res); + + printf("MySQL Tables in mysql database:\n"); + auto row_count = 1; + + for (MYSQL_ROW row = NULL; (row = mysql_fetch_row(res)) != NULL;) { + std::cout << " row " << row_count << std::endl; + for (auto i = 0; i != num_of_fields; ++i) { + auto val = row[i]; + + if ( val == NULL) { + std::cout << "found null value " << std::endl; + continue; + } + std::cout << val << " "; + } + std::cout << std::endl; + } + + /* clean up the database result set */ + mysql_free_result(res); + /* clean up the database link */ + mysql_close(conn); +} + int main(int argc, char **argv) { oatpp::base::Environment::init(); std::string working_path = argv[0]; - //std::cout << fs::canonical(fs::path(working_path.c_str())).parent_path().string() << std::endl; + test_database(); run(working_path); oatpp::base::Environment::destroy(); diff --git a/src/token_manager.cpp b/src/token_manager.cpp index e529fd7..73aab95 100644 --- a/src/token_manager.cpp +++ b/src/token_manager.cpp @@ -1,20 +1,18 @@ #include +#include #include #include +#include #include #include #include #include -//#include "models.h" #include "token_manager.h" namespace fs = std::filesystem; -//extern "C" -//{ - token_manager::token_manager() { @@ -22,51 +20,60 @@ token_manager::token_manager() loginResult token_manager::retrieve_token() { - auto cred = parse_auth_credentials(); - loginResult lr; lr.access_token = "dsfdsf"; lr.token_type = "demo"; return lr; } - -auth_credentials token_manager::parse_auth_credentials() +loginResult token_manager::retrieve_token(std::string_view path) { - auth_credentials auth; - //auto ss = working_path.string(); - //auto path = fs::canonical(fs::path(".")); - //std::cout << "canonical path " << path.string() << std::endl; - - return auth; -} - -/** -LoginRes* token_manager::retrieve_token(TokenReq *tok) -{ - LoginRes *res = new LoginRes; + auto cred = parse_auth_credentials(path); nlohmann::json reqObj; - reqObj["client_id"] = tok->ClientId; - reqObj["client_secret"] = tok->ClientSecret; - reqObj["audience"] = tok->Audience; - reqObj["grant_type"] = tok->GrantType; + reqObj["client_id"] = cred.client_id; + reqObj["client_secret"] = cred.client_secret; + reqObj["audience"] = cred.api_identifier; + reqObj["grant_type"] = "client_credentials"; - std::string uri{tok->URI}; + std::string uri{cred.uri}; uri.append("/"); - uri.append(tok->Endpoint); + uri.append(cred.endpoint); auto r = cpr::Post(cpr::Url{uri}, cpr::Body{reqObj.dump()}, - cpr::Header{{"Content-Type", "application/json"}}); + cpr::Header{{"Content-Type", "application/json"}, + {"Connection", "keep-alive"}}); auto post_res = nlohmann::json::parse(r.text); - strcpy(res->Token, post_res["access_token"].get().c_str()); - strcpy(res->TokenType, post_res["token_type"].get().c_str()); - res->Expiration = post_res["expires_in"].get(); - strcpy(res->Message, "Success"); - return res; + loginResult lr; + lr.access_token = post_res["access_token"].get(); + lr.token_type = post_res["token_type"].get(); + lr.expiration = post_res["expires_in"].get(); + + return lr; +} + +auth_credentials token_manager::parse_auth_credentials(std::string_view path) +{ + auto exe_path = fs::canonical(path).parent_path().string(); + exe_path.append("/authcredentials.json"); + + std::fstream a(exe_path, std::ios::in); + std::stringstream s; + s << a.rdbuf(); + a.close(); + + auto con = nlohmann::json::parse(s.str()); + + auth_credentials auth; + auth.uri = "https://"; + auth.uri.append(con["Domain"]); + auth.api_identifier = con["ApiIdentifier"]; + auth.client_id = con["ClientId"]; + auth.client_secret = con["ClientSecret"]; + auth.endpoint = "oauth/token"; + + return auth; } -*/ -//} From 10b546d8b8e92b46fdc2f0b60d55047457ea9740 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 18 Aug 2019 16:13:14 -0400 Subject: [PATCH 05/36] removed mysqlconnector c++ submodule. Linking issues, using the C API instead --- .gitmodules | 3 --- 3rdparty/mysql-connector-cpp | 1 - 2 files changed, 4 deletions(-) delete mode 160000 3rdparty/mysql-connector-cpp diff --git a/.gitmodules b/.gitmodules index a71061f..03137ae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,6 +16,3 @@ [submodule "3rdparty/ormpp"] path = 3rdparty/ormpp url = https://github.com/qicosmos/ormpp -[submodule "3rdparty/mysql-connector-cpp"] - path = 3rdparty/mysql-connector-cpp - url = https://github.com/mysql/mysql-connector-cpp diff --git a/3rdparty/mysql-connector-cpp b/3rdparty/mysql-connector-cpp deleted file mode 160000 index 64731f9..0000000 --- a/3rdparty/mysql-connector-cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 64731f9625d5bcff86236c9fce2a1f5c55d60242 From e9aa5f799c61c94fd43057881ed1b4c9b4be0ce9 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 18 Aug 2019 16:15:47 -0400 Subject: [PATCH 06/36] Added database configuration file --- CMakeLists.txt | 15 ++------------- database.json | 7 +++++++ include/database/base_repository.h | 2 +- src/database/base_repository.cpp | 2 +- 4 files changed, 11 insertions(+), 15 deletions(-) create mode 100644 database.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cce78a..7c15d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,6 @@ project(icarus) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) -#add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0) - set(SOURCES src/appComponent.hpp src/controller/loginController.hpp @@ -20,10 +18,10 @@ set(SOURCES ) set(HEADERS include/database/base_repository.h - include/models.h include/directory_manager.h include/imageFile.h include/metadata_retriever.h + include/models.h include/token_manager.h ) @@ -60,27 +58,18 @@ set (ORM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ormpp ) -set (MYSQL - /usr/local/mysql/connector-c++-8.0/lib64 - ) -set (MYSQL_INCLUDE - /usr/local/mysql/connector-c++-8.0/include/mysqlx - /usr/local/mysql/connector-c++-8.0/include/mysqlx/common - ) - include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() -link_directories(${MYSQL}) include_directories(include ${CPR_INCLUDE_DIRS} ${TAGLIB} ${TAGLIB_HEADERS}) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/cpr) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/taglib) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/oatpp) -#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/mysql-connector-cpp) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/appsettings.json ${CMAKE_BINARY_DIR}/bin/appsettings.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/authcredentials.json ${CMAKE_BINARY_DIR}/bin/authcredentials.json COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/database.json ${CMAKE_BINARY_DIR}/bin/database.json COPYONLY) add_executable(icarus ${SOURCES} ${HEADERS}) target_include_directories(icarus PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include) diff --git a/database.json b/database.json new file mode 100644 index 0000000..661decf --- /dev/null +++ b/database.json @@ -0,0 +1,7 @@ + +{ + "server": "server", + "database": "database", + "username": "username", + "password": "password" +} diff --git a/include/database/base_repository.h b/include/database/base_repository.h index d8c8e43..110f29e 100644 --- a/include/database/base_repository.h +++ b/include/database/base_repository.h @@ -12,7 +12,7 @@ class base_repository public: MYSQL* setup_mysql_connection(database_connection); - MYSQL_RES* perform_mysql_query(MYSQL*, std::string&); + MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&); private: }; diff --git a/src/database/base_repository.cpp b/src/database/base_repository.cpp index c67c065..886c66b 100644 --- a/src/database/base_repository.cpp +++ b/src/database/base_repository.cpp @@ -12,7 +12,7 @@ MYSQL* base_repository::setup_mysql_connection(database_connection details) return connection; } -MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, std::string& query) +MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, const std::string& query) { // send the query to the database if (mysql_query(conn, query.c_str())) From bbd8186114b9821de086e73df815f70f39b8f3da Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 18 Aug 2019 16:44:59 -0400 Subject: [PATCH 07/36] Added songcontroller, work on uploading a song --- CMakeLists.txt | 1 + src/controller/loginController.hpp | 3 ++- src/controller/songController.hpp | 39 ++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/controller/songController.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c15d95..2fddb0f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD 17) set(SOURCES src/appComponent.hpp src/controller/loginController.hpp + src/controller/songController.hpp src/database/base_repository.cpp src/directory_manager.cpp src/dto/loginResultDto.hpp diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 772a17d..a8f6c2b 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" @@ -18,7 +19,7 @@ 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(std::move(p)) + : oatpp::web::server::api::ApiController(objectMapper), exe_path(p) { } diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp new file mode 100644 index 0000000..999185c --- /dev/null +++ b/src/controller/songController.hpp @@ -0,0 +1,39 @@ +#ifndef SONGCONTROLLER_H_ +#define SONGCONTROLLER_H_ + +#include +#include +#include +#include + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/macro/component.hpp" +#include "oatpp/web/mime/multipart/InMemoryPartReader.hpp" +#include "oatpp/web/mime/multipart/Reader.hpp" +#include "oatpp/web/server/api/ApiController.hpp" + +//#include "../dto/DTO.h" + +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), exe_path(p) + { } + + #include OATPP_CODEGEN_BEGIN(ApiController) + + // TODO: work on uploading a song + ENDPOINT("POST", "/api/v1/song/data", songUpload, + REQUEST(std::shared_ptr, request)) + { + + return createResonse(Status::CODE_200, "OK"); + } + + #include OATPP_CODEGEN_END(ApiController) +private: + std::string exe_path; +}; + +#endif From 4072526d350739d7b730a91e0d5d97f462287165 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 18 Aug 2019 22:58:04 -0400 Subject: [PATCH 08/36] Able to upload song. Left TODO on what's next --- CMakeLists.txt | 2 ++ include/managers/song_manager.h | 19 ++++++++++++ include/models.h | 2 ++ src/controller/songController.hpp | 51 +++++++++++++++++++++++++++++-- src/main.cpp | 32 +++---------------- src/managers/song_manager.cpp | 22 +++++++++++++ 6 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 include/managers/song_manager.h create mode 100644 src/managers/song_manager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fddb0f..d9a6e09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ set(SOURCES src/dto/loginResultDto.hpp src/imageFile.cpp src/main.cpp + src/managers/song_manager.cpp src/metadata_retriever.cpp src/token_manager.cpp ) @@ -21,6 +22,7 @@ set(HEADERS include/database/base_repository.h include/directory_manager.h include/imageFile.h + include/managers/song_manager.h include/metadata_retriever.h include/models.h include/token_manager.h diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h new file mode 100644 index 0000000..5cef72b --- /dev/null +++ b/include/managers/song_manager.h @@ -0,0 +1,19 @@ +#ifndef SONGMANAGER_H_ +#define SONGMANAGER_H_ + +#include +#include + +#include "models.h" + +class song_manager +{ +public: + song_manager(std::string&); + + void saveSong(Song&); +private: + std::string exe_path; +}; + +#endif diff --git a/include/models.h b/include/models.h index c2532e1..4842e0a 100644 --- a/include/models.h +++ b/include/models.h @@ -2,6 +2,7 @@ #define MODELS_H_ #include +#include struct Song { @@ -13,6 +14,7 @@ struct Song int Year; int Duration; char SongPath[1024]; + std::vector data; }; struct Cover diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 999185c..ba4b780 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" @@ -12,7 +13,8 @@ #include "oatpp/web/mime/multipart/Reader.hpp" #include "oatpp/web/server/api/ApiController.hpp" -//#include "../dto/DTO.h" +#include "managers/song_manager.h" +#include "models.h" class songController : public oatpp::web::server::api::ApiController { @@ -24,16 +26,61 @@ public: #include OATPP_CODEGEN_BEGIN(ApiController) // TODO: work on uploading a song + // and clean up ENDPOINT("POST", "/api/v1/song/data", songUpload, REQUEST(std::shared_ptr, request)) { + auto mp = std::make_shared(request->getHeaders()); - return createResonse(Status::CODE_200, "OK"); + oatpp::web::mime::multipart::Reader mp_reader(mp.get()); + + mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(dataSize)); + + request->transferBody(&mp_reader); + + auto file = mp->getNamedPart("file"); + + OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); + + auto stream = file->getInputStream(); + //char *buff = new char[file->getKnownSize()]; + auto buff = std::unique_ptr(new char[file->getKnownSize()]); + //std::vector buff; + //buff.reserve(file->getKnownSize()); + //std::string buff; + //std::vector buff; + auto buffSize = stream->read(buff.get(), file->getKnownSize()-1); + //auto buffSize = stream->read(&buff[0], file->getKnownSize()-1); + std::cout << "buff size " << buffSize << std::endl; + /** + std::cout << "buff " << buff << std::endl; + //std::cout << stream.get() << std::endl; + */ + std::vector data(buff.get(), buff.get() + buffSize); + std::cout << "size of data " << data.size() << std::endl; + + Song sng; + sng.data = std::move(data); + //sng.data = std::move(buff); + //std::cout << "data buff " << sng.data << std::endl; + std::cout << "data size " << sng.data.size() << std::endl; + song_manager s_mgr(exe_path); + s_mgr.saveSong(sng); + /* */ + + //std::string fileStr = file->getInMemoryData()->c_str(); + //std::cout << fileStr << std::endl; + //std::cout << "known size " << file->getKnownSize() << std::endl; + //std::cout << "size " << fileStr.size() << std::endl; + + return createResponse(Status::CODE_200, "OK"); } #include OATPP_CODEGEN_END(ApiController) private: std::string exe_path; + + const long dataSize = 1000000000000; }; #endif diff --git a/src/main.cpp b/src/main.cpp index f779651..8cdd48a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,6 +12,7 @@ #include "appComponent.hpp" #include "controller/loginController.hpp" +#include "controller/songController.hpp" #include "database/base_repository.h" namespace fs = std::filesystem; @@ -20,12 +21,12 @@ void run(const std::string& working_path) { appComponent component; - //auto router = oatpp::web::server::HttpRouter::createShared(); OATPP_COMPONENT(std::shared_ptr, router); - //router->route("GET", "/test", std::make_shared()); auto logController = std::make_shared(working_path); + auto sngController = std::make_shared(working_path); logController->addEndpointsToRouter(router); + sngController->addEndpointsToRouter(router); OATPP_COMPONENT(std::shared_ptr, connectionHandler); @@ -38,31 +39,6 @@ void run(const std::string& working_path) server.run(); } -MYSQL* mysql_connection_setup(database_connection mysql_details) -{ - // first of all create a mysql instance and initialize the variables within - MYSQL *connection = mysql_init(NULL); - - // connect to the database with the details attached. - if (!mysql_real_connect(connection,mysql_details.server.c_str(), mysql_details.username.c_str(), mysql_details.password.c_str(), mysql_details.database.c_str(), 0, NULL, 0)) { - printf("Conection error : %s\n", mysql_error(connection)); - exit(1); - } - return connection; -} - -MYSQL_RES* mysql_perform_query(MYSQL *connection, char *sql_query) -{ - // send the query to the database - if (mysql_query(connection, sql_query)) - { - printf("MySQL query error : %s\n", mysql_error(connection)); - exit(1); - } - - return mysql_use_result(connection); -} - void test_database() { database_connection mysqlD; @@ -108,7 +84,7 @@ int main(int argc, char **argv) oatpp::base::Environment::init(); std::string working_path = argv[0]; - test_database(); + //test_database(); run(working_path); oatpp::base::Environment::destroy(); diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp new file mode 100644 index 0000000..8504f09 --- /dev/null +++ b/src/managers/song_manager.cpp @@ -0,0 +1,22 @@ +#include "managers/song_manager.h" + +#include +#include + +namespace fs = std::filesystem; + +song_manager::song_manager(std::string& x_path) + : exe_path(x_path) +{ } + +void song_manager::saveSong(Song& song) +{ + constexpr auto tmp_song = "/tmp/song.mp3"; + if (fs::exists(fs::path(tmp_song))) { + std::cout << "deleting old song " << std::endl; + fs::remove(fs::path(tmp_song)); + } + std::fstream s(tmp_song, std::fstream::binary | std::fstream::out); + s.write((char*)&song.data[0], song.data.size()); + s.close(); +} From 3e94e0e22e666ae4c9da342d873530d1c867ec1d Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 19 Aug 2019 22:19:47 -0400 Subject: [PATCH 09/36] Left some TODO's. Next thing is to check if the token is valid --- CMakeLists.txt | 7 ++++- include/token_manager.h | 4 +++ include/types/scopes.h | 10 ++++++++ src/controller/loginController.hpp | 7 ++--- src/controller/songController.hpp | 41 ++++++++++++++---------------- src/dto/loginResultDto.hpp | 5 +++- src/token_manager.cpp | 12 +++++++++ 7 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 include/types/scopes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d9a6e09..e771f40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set(HEADERS include/metadata_retriever.h include/models.h include/token_manager.h + include/types/scopes.h ) set (TAGLIB @@ -57,6 +58,10 @@ set(TAGLIB_HEADERS "${CMAKE_SOURCE_DIR}/3rdparty/taglib/taglib/xm" ) +set(JWT_CPP_INCLUDE + ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include +) + set (ORM_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ormpp ) @@ -75,5 +80,5 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/authcredentials.json ${CMAKE_BINARY_D configure_file(${CMAKE_CURRENT_SOURCE_DIR}/database.json ${CMAKE_BINARY_DIR}/bin/database.json COPYONLY) add_executable(icarus ${SOURCES} ${HEADERS}) -target_include_directories(icarus PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include) +target_include_directories(icarus PUBLIC ${JWT_CPP_INCLUDE}) target_link_libraries(icarus "-lstdc++fs" tag oatpp mysqlclient ${CONAN_LIBS} ${CPR_LIBRARIES}) diff --git a/include/token_manager.h b/include/token_manager.h index 4d7b80b..4b15d49 100644 --- a/include/token_manager.h +++ b/include/token_manager.h @@ -1,9 +1,11 @@ #ifndef TOKEN_MANAGER_H_ #define TOKEN_MANAGER_H_ +#include #include #include "models.h" +#include "types/scopes.h" class token_manager { @@ -12,6 +14,8 @@ public: loginResult retrieve_token(); loginResult retrieve_token(std::string_view); + + bool is_token_valid(std::string&, Scope); private: auth_credentials parse_auth_credentials(std::string_view); }; diff --git a/include/types/scopes.h b/include/types/scopes.h new file mode 100644 index 0000000..c95fd1c --- /dev/null +++ b/include/types/scopes.h @@ -0,0 +1,10 @@ +#ifndef SCOPES_H_ +#define SCOPES_H_ + +enum class Scope +{ + upload = 0, + download +}; + +#endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index a8f6c2b..7c9e7ee 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -29,15 +29,16 @@ public: { OATPP_LOGI("icarus", "logging in"); - std::cout << "user: " << usr->username->c_str() << std::endl; - token_manager tok; auto token = tok.retrieve_token(exe_path); auto logRes = loginResultDto::createShared(); - logRes->access_token = token.access_token.c_str(); + logRes->id = 0; // TODO: change this later on to something meaningful + logRes->username = usr->username->c_str(); + logRes->token = token.access_token.c_str(); logRes->token_type = token.token_type.c_str(); logRes->expiration = token.expiration; + logRes->message = "Successful"; return createDtoResponse(Status::CODE_200, logRes); } diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index ba4b780..82d26e7 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -15,6 +15,8 @@ #include "managers/song_manager.h" #include "models.h" +#include "token_manager.h" +#include "types/scopes.h" class songController : public oatpp::web::server::api::ApiController { @@ -30,6 +32,20 @@ public: ENDPOINT("POST", "/api/v1/song/data", songUpload, REQUEST(std::shared_ptr, request)) { + auto authHeader = request->getHeader("Authorization"); + + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + + auto auth = authHeader->std_str(); + + std::cout << "auth " << auth << std::endl; + + token_manager tok; + if (!tok.is_token_valid(auth, Scope::upload)) { + // TODO: prevent user from moving forward + // token did not have the specified scope (permission) + } + auto mp = std::make_shared(request->getHeaders()); oatpp::web::mime::multipart::Reader mp_reader(mp.get()); @@ -43,35 +59,16 @@ public: OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); auto stream = file->getInputStream(); - //char *buff = new char[file->getKnownSize()]; auto buff = std::unique_ptr(new char[file->getKnownSize()]); - //std::vector buff; - //buff.reserve(file->getKnownSize()); - //std::string buff; - //std::vector buff; - auto buffSize = stream->read(buff.get(), file->getKnownSize()-1); - //auto buffSize = stream->read(&buff[0], file->getKnownSize()-1); - std::cout << "buff size " << buffSize << std::endl; - /** - std::cout << "buff " << buff << std::endl; - //std::cout << stream.get() << std::endl; - */ + auto buffSize = stream->read(buff.get(), file->getKnownSize()); + std::vector data(buff.get(), buff.get() + buffSize); - std::cout << "size of data " << data.size() << std::endl; Song sng; sng.data = std::move(data); - //sng.data = std::move(buff); - //std::cout << "data buff " << sng.data << std::endl; - std::cout << "data size " << sng.data.size() << std::endl; + song_manager s_mgr(exe_path); s_mgr.saveSong(sng); - /* */ - - //std::string fileStr = file->getInMemoryData()->c_str(); - //std::cout << fileStr << std::endl; - //std::cout << "known size " << file->getKnownSize() << std::endl; - //std::cout << "size " << fileStr.size() << std::endl; return createResponse(Status::CODE_200, "OK"); } diff --git a/src/dto/loginResultDto.hpp b/src/dto/loginResultDto.hpp index a43ec02..935bbc7 100644 --- a/src/dto/loginResultDto.hpp +++ b/src/dto/loginResultDto.hpp @@ -10,9 +10,12 @@ class loginResultDto : public oatpp::data::mapping::type::Object { DTO_INIT(loginResultDto, Object) - DTO_FIELD(String, access_token); + DTO_FIELD(Int32, id); + DTO_FIELD(String, username); + DTO_FIELD(String, token); DTO_FIELD(String, token_type); DTO_FIELD(Int32, expiration); + DTO_FIELD(String, message); }; class userDto : public oatpp::data::mapping::type::Object diff --git a/src/token_manager.cpp b/src/token_manager.cpp index 73aab95..c8c4299 100644 --- a/src/token_manager.cpp +++ b/src/token_manager.cpp @@ -55,6 +55,18 @@ loginResult token_manager::retrieve_token(std::string_view path) return lr; } +bool token_manager::is_token_valid(std::string& auth, Scope scope) +{ + switch (scope) { + case Scope::upload: + break; + default: + break; + } + + return true; +} + auth_credentials token_manager::parse_auth_credentials(std::string_view path) { auto exe_path = fs::canonical(path).parent_path().string(); From e42a55119324b2e4082bfcb1890ad126eebefa41 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Tue, 20 Aug 2019 19:56:26 -0400 Subject: [PATCH 10/36] Now have to check to see if the token has the correct scope --- src/controller/songController.hpp | 2 +- src/token_manager.cpp | 51 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 82d26e7..d7f7db2 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -38,7 +38,7 @@ public: auto auth = authHeader->std_str(); - std::cout << "auth " << auth << std::endl; + //std::cout << "auth " << auth << std::endl; token_manager tok; if (!tok.is_token_valid(auth, Scope::upload)) { diff --git a/src/token_manager.cpp b/src/token_manager.cpp index c8c4299..22b434c 100644 --- a/src/token_manager.cpp +++ b/src/token_manager.cpp @@ -1,12 +1,15 @@ #include +#include #include #include #include #include #include +#include #include #include +#include #include #include "token_manager.h" @@ -57,6 +60,54 @@ loginResult token_manager::retrieve_token(std::string_view path) bool token_manager::is_token_valid(std::string& auth, Scope scope) { + std::istringstream iss(auth); + std::vector authHeader{std::istream_iterator(iss), + std::istream_iterator() + }; + + auto wordCount = 0; + /** + for (auto& word : authHeader) { + std::cout << "word " << wordCount++ << " " << word << std::endl; + } + */ + + if (!std::any_of(authHeader.begin(), authHeader.end(), [](std::string word) + { + std::cout << "comparing " << word << " to Bearer" << std::endl; + return (word.compare("Bearer") == 0); + })) { + std::cout << "Bearer not found" << std::endl; + return false; + } + + auto token = authHeader.at(authHeader.size()-1); + std::cout << "going to decode " << token << std::endl; + auto decoded = jwt::decode(token); + + std::vector scopes; + for (auto d : decoded.get_payload_claims()) { + if (d.first.compare("scope") == 0) { + std::cout << "found scope" << std::endl; + std::string all_scopes(d.second.to_json().get()); + std::istringstream iss(all_scopes); + + scopes.assign(std::istream_iterator(iss), + std::istream_iterator()); + //std::cout << scopes << std::endl; + } + } + + std::cout << "printing all scopes" << std::endl; + + for (auto& scope_obj : scopes) { + std::cout << scope_obj << std::endl; + } + + + std::cout << "goodbye" << std::endl; + exit(1); + switch (scope) { case Scope::upload: break; From 92f0d4702bc0f458abdc1bfa9de57178b01c6195 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Tue, 20 Aug 2019 22:45:25 -0400 Subject: [PATCH 11/36] Factoring --- CMakeLists.txt | 18 ++-- include/database/base_repository.h | 4 +- include/directory_manager.h | 14 --- include/managers/directory_manager.h | 26 ++++++ include/managers/song_manager.h | 2 +- include/{ => managers}/token_manager.h | 11 ++- include/metadata_retriever.h | 3 - include/models.h | 24 ++--- include/models/models.h | 77 ++++++++++++++++ include/{ => utilities}/imageFile.h | 0 include/utilities/metadata_retriever.h | 19 ++++ src/controller/loginController.hpp | 2 +- src/controller/songController.hpp | 11 +-- src/loginHandler.cpp | 2 - src/loginHandler.hpp | 1 - src/main.cpp | 2 +- src/{ => managers}/directory_manager.cpp | 65 +++++++------- src/{ => managers}/token_manager.cpp | 102 +++++++++++---------- src/metadata_retriever.cpp | 102 --------------------- src/{ => utilities}/imageFile.cpp | 2 +- src/utilities/metadata_retriever.cpp | 108 +++++++++++++++++++++++ 21 files changed, 362 insertions(+), 233 deletions(-) delete mode 100644 include/directory_manager.h create mode 100644 include/managers/directory_manager.h rename include/{ => managers}/token_manager.h (53%) delete mode 100644 include/metadata_retriever.h create mode 100644 include/models/models.h rename include/{ => utilities}/imageFile.h (100%) create mode 100644 include/utilities/metadata_retriever.h delete mode 100644 src/loginHandler.cpp rename src/{ => managers}/directory_manager.cpp (73%) rename src/{ => managers}/token_manager.cpp (68%) delete mode 100644 src/metadata_retriever.cpp rename src/{ => utilities}/imageFile.cpp (80%) create mode 100644 src/utilities/metadata_retriever.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e771f40..237854e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,22 +10,22 @@ set(SOURCES src/controller/loginController.hpp src/controller/songController.hpp src/database/base_repository.cpp - src/directory_manager.cpp src/dto/loginResultDto.hpp - src/imageFile.cpp src/main.cpp + src/managers/directory_manager.cpp src/managers/song_manager.cpp - src/metadata_retriever.cpp - src/token_manager.cpp + src/managers/token_manager.cpp + src/utilities/imageFile.cpp + src/utilities/metadata_retriever.cpp ) set(HEADERS include/database/base_repository.h - include/directory_manager.h - include/imageFile.h + include/managers/directory_manager.h include/managers/song_manager.h - include/metadata_retriever.h - include/models.h - include/token_manager.h + include/managers/token_manager.h + include/models/models.h + include/utilities/imageFile.h + include/utilities/metadata_retriever.h include/types/scopes.h ) diff --git a/include/database/base_repository.h b/include/database/base_repository.h index 110f29e..ea90788 100644 --- a/include/database/base_repository.h +++ b/include/database/base_repository.h @@ -1,11 +1,11 @@ #ifndef BASE_REPOSITORY_H_ #define BASE_REPOSITORY_H_ -#include +#include #include -#include "models.h" +#include "models/models.h" class base_repository { diff --git a/include/directory_manager.h b/include/directory_manager.h deleted file mode 100644 index a20d29a..0000000 --- a/include/directory_manager.h +++ /dev/null @@ -1,14 +0,0 @@ -#include "models.h" - -#include - -std::string create_directory_process(Song, const char*); -std::string read_cover_art(const char*); - -bool delete_song(Song*); - -void copy_stock_to_root(const char*, const std::string); -void copy_song_to_path(const char*, const char*); -void delete_cover_art_file(const std::string); -void delete_directories(Song, const char*); -void delete_song(Song); diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h new file mode 100644 index 0000000..ca44afc --- /dev/null +++ b/include/managers/directory_manager.h @@ -0,0 +1,26 @@ +#ifndef DIRECTORY_MANAGER_H_ +#define DIRECTORY_MANAGER_H_ + +#include + +#include "models/models.h" + +class directory_manager +{ +public: + + std::string create_directory_process(Song, const std::string&); + // Return Cover instead + std::string read_cover_art(const std::string&); + + + void copy_stock_to_root(const std::string&, const std::string&); + void copy_song_to_path(const std::string&, const std::string&); + void delete_cover_art_file(const std::string&, const std::string&); + void delete_directories(Song, const std::string&); + +private: + void delete_song(const Song); +}; + +#endif diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index 5cef72b..18cc8a8 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -4,7 +4,7 @@ #include #include -#include "models.h" +#include "models/models.h" class song_manager { diff --git a/include/token_manager.h b/include/managers/token_manager.h similarity index 53% rename from include/token_manager.h rename to include/managers/token_manager.h index 4b15d49..f8bcbec 100644 --- a/include/token_manager.h +++ b/include/managers/token_manager.h @@ -3,8 +3,12 @@ #include #include +#include +#include -#include "models.h" +#include + +#include "models/models.h" #include "types/scopes.h" class token_manager @@ -18,6 +22,11 @@ public: bool is_token_valid(std::string&, Scope); private: auth_credentials parse_auth_credentials(std::string_view); + + std::vector extract_scopes(const jwt::decoded_jwt&&); + std::pair> fetch_auth_header(const std::string&); + + bool token_supports_scope(const std::vector, const std::string&&); }; #endif diff --git a/include/metadata_retriever.h b/include/metadata_retriever.h deleted file mode 100644 index 80e3dd4..0000000 --- a/include/metadata_retriever.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -#include "models.h" diff --git a/include/models.h b/include/models.h index 4842e0a..3c40b64 100644 --- a/include/models.h +++ b/include/models.h @@ -6,22 +6,24 @@ struct Song { - int Id; - char Title[1024]; - char Artist[1024]; - char Album[1024]; - char Genre[1024]; - int Year; - int Duration; - char SongPath[1024]; + int id; + std::string title; + std::string artist; + std::string album; + std::string genre; + int year; + int duration; + std::string songPath; std::vector data; }; struct Cover { - int Id; - char SongTitle[1024]; - char ImagePath[1024]; + int id; + std::string songTitle; + std::string imagePath; + // Currently not being used but it should + std::vector data; }; struct LoginRes diff --git a/include/models/models.h b/include/models/models.h new file mode 100644 index 0000000..1d027da --- /dev/null +++ b/include/models/models.h @@ -0,0 +1,77 @@ +#ifndef MODELS_H_ +#define MODELS_H_ + +#include +#include + +struct Song +{ + int id; + std::string title; + std::string artist; + std::string album; + std::string genre; + int year; + int duration; + std::string songPath; + std::vector data; +}; + +struct Cover +{ + int id; + std::string songTitle; + std::string imagePath; + // Not being used but it should be + std::vector data; +}; + +struct LoginRes +{ + int UserId; + char Username[1024]; + char Token[1024]; + char TokenType[1024]; + char Message[1024]; + int Expiration; +}; + +struct loginResult +{ + int user_id; + std::string username; + std::string access_token; + std::string token_type; + std::string message; + int expiration; +}; + +struct auth_credentials +{ + std::string domain; + std::string api_identifier; + std::string client_id; + std::string client_secret; + std::string uri; + std::string endpoint; +}; + +struct database_connection +{ + std::string server; + std::string username; + std::string password; + std::string database; +}; + +struct TokenReq +{ + char ClientId[1024]; + char ClientSecret[1024]; + char Audience[1024]; + char GrantType[1024]; + char URI[1024]; + char Endpoint[1024]; +}; + +#endif diff --git a/include/imageFile.h b/include/utilities/imageFile.h similarity index 100% rename from include/imageFile.h rename to include/utilities/imageFile.h diff --git a/include/utilities/metadata_retriever.h b/include/utilities/metadata_retriever.h new file mode 100644 index 0000000..4d14a8c --- /dev/null +++ b/include/utilities/metadata_retriever.h @@ -0,0 +1,19 @@ +#ifndef METADATA_RETRIEVER_H_ +#define METADATA_RETRIEVER_H_ + +#include +#include + +#include "models/models.h" + +class metadata_retriever +{ +public: + Song retrieve_metadata(std::string&); + Cover update_cover_art(Cover, const Song, const std::string&); + + void update_metadata(Song updated_song, const Song old_song); +private: +}; + +#endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 7c9e7ee..e17de5e 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -11,7 +11,7 @@ #include "oatpp/web/server/api/ApiController.hpp" #include "../dto/loginResultDto.hpp" -#include "token_manager.h" +#include "managers/token_manager.h" namespace fs = std::filesystem; diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index d7f7db2..ffc7ef0 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -14,8 +14,8 @@ #include "oatpp/web/server/api/ApiController.hpp" #include "managers/song_manager.h" -#include "models.h" -#include "token_manager.h" +#include "models/models.h" +#include "managers/token_manager.h" #include "types/scopes.h" class songController : public oatpp::web::server::api::ApiController @@ -38,13 +38,8 @@ public: auto auth = authHeader->std_str(); - //std::cout << "auth " << auth << std::endl; - token_manager tok; - if (!tok.is_token_valid(auth, Scope::upload)) { - // TODO: prevent user from moving forward - // token did not have the specified scope (permission) - } + OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Scope::upload), Status::CODE_403, "Not allowed"); auto mp = std::make_shared(request->getHeaders()); diff --git a/src/loginHandler.cpp b/src/loginHandler.cpp deleted file mode 100644 index 4223142..0000000 --- a/src/loginHandler.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "loginHandler.h" - diff --git a/src/loginHandler.hpp b/src/loginHandler.hpp index a40a71b..e131660 100644 --- a/src/loginHandler.hpp +++ b/src/loginHandler.hpp @@ -8,7 +8,6 @@ #include "oatpp/web/server/HttpConnectionHandler.hpp" #include "dto/loginResultDto.hpp" -//#include "dto/loginResultDto.hpp" class loginHandler : public oatpp::web::server::HttpRequestHandler { diff --git a/src/main.cpp b/src/main.cpp index 8cdd48a..b999ed0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,7 +4,6 @@ #include #include -#include "models.h" #include #include "oatpp/network/server/Server.hpp" #include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" @@ -14,6 +13,7 @@ #include "controller/loginController.hpp" #include "controller/songController.hpp" #include "database/base_repository.h" +#include "models/models.h" namespace fs = std::filesystem; diff --git a/src/directory_manager.cpp b/src/managers/directory_manager.cpp similarity index 73% rename from src/directory_manager.cpp rename to src/managers/directory_manager.cpp index 9f47566..e99904a 100644 --- a/src/directory_manager.cpp +++ b/src/managers/directory_manager.cpp @@ -1,14 +1,13 @@ #include #include #include -#include #include -#include "directory_manager.h" +#include "managers/directory_manager.h" namespace fs = std::filesystem; -std::string create_directory_process(Song song, const char *root_path) +std::string directory_manager::create_directory_process(Song song, const std::string& root_path) { auto curr_path = fs::path(root_path); @@ -19,7 +18,7 @@ std::string create_directory_process(Song song, const char *root_path) fs::create_directory(curr_path); } - auto art_path = fs::path(curr_path.string() + song.Artist); + auto art_path = fs::path(curr_path.string() + song.artist); if (fs::exists(art_path)) { std::cout<<"artist path exists"<SongPath); -} - -void copy_stock_to_root(const char *target, const std::string buff) +void directory_manager::copy_stock_to_root(const std::string& target, const std::string& buff) { std::cout<<"starting process"< #include #include -#include #include #include -#include #include -#include "token_manager.h" +#include "managers/token_manager.h" namespace fs = std::filesystem; @@ -60,62 +58,31 @@ loginResult token_manager::retrieve_token(std::string_view path) bool token_manager::is_token_valid(std::string& auth, Scope scope) { - std::istringstream iss(auth); - std::vector authHeader{std::istream_iterator(iss), - std::istream_iterator() - }; + auto authPair = fetch_auth_header(auth); - auto wordCount = 0; - /** - for (auto& word : authHeader) { - std::cout << "word " << wordCount++ << " " << word << std::endl; - } - */ + if (!std::get<0>(authPair)) { + std::cout << "no Bearer found" << std::endl; - if (!std::any_of(authHeader.begin(), authHeader.end(), [](std::string word) - { - std::cout << "comparing " << word << " to Bearer" << std::endl; - return (word.compare("Bearer") == 0); - })) { - std::cout << "Bearer not found" << std::endl; - return false; + return std::get<0>(authPair); } + auto authHeader = std::get<1>(authPair); + auto token = authHeader.at(authHeader.size()-1); - std::cout << "going to decode " << token << std::endl; - auto decoded = jwt::decode(token); - std::vector scopes; - for (auto d : decoded.get_payload_claims()) { - if (d.first.compare("scope") == 0) { - std::cout << "found scope" << std::endl; - std::string all_scopes(d.second.to_json().get()); - std::istringstream iss(all_scopes); - - scopes.assign(std::istream_iterator(iss), - std::istream_iterator()); - //std::cout << scopes << std::endl; - } - } - - std::cout << "printing all scopes" << std::endl; - - for (auto& scope_obj : scopes) { - std::cout << scope_obj << std::endl; - } - - - std::cout << "goodbye" << std::endl; - exit(1); + auto scopes = extract_scopes(jwt::decode(token)); switch (scope) { case Scope::upload: + return token_supports_scope(scopes, "upload:songs"); break; + case Scope::download: + return token_supports_scope(scopes, "download:songs"); default: break; } - return true; + return false; } auth_credentials token_manager::parse_auth_credentials(std::string_view path) @@ -140,3 +107,48 @@ auth_credentials token_manager::parse_auth_credentials(std::string_view path) return auth; } + +std::vector token_manager::extract_scopes(const jwt::decoded_jwt&& decoded) +{ + std::vector scopes; + + for (auto d : decoded.get_payload_claims()) { + if (d.first.compare("scope") == 0) { + std::cout << "found scope" << std::endl; + std::string all_scopes(d.second.to_json().get()); + std::istringstream iss(all_scopes); + + scopes.assign(std::istream_iterator(iss), + std::istream_iterator()); + } + } + + return scopes; +} + +std::pair> token_manager::fetch_auth_header(const std::string& auth) +{ + std::istringstream iss(auth); + std::vector authHeader{std::istream_iterator(iss), + std::istream_iterator() + }; + + bool foundBearer = false; + if (std::any_of(authHeader.begin(), authHeader.end(), + [](std::string word) { + return (word.compare("Bearer") == 0); + })) { + std::cout << "Bearer found" << std::endl; + foundBearer = true; + } + + return std::make_pair(foundBearer, authHeader); +} + +bool token_manager::token_supports_scope(const std::vector scopes, const std::string&& scope) +{ + return std::any_of(scopes.begin(), scopes.end(), + [&](std::string foundScope) { + return (foundScope.compare(scope) == 0); + }); +} diff --git a/src/metadata_retriever.cpp b/src/metadata_retriever.cpp deleted file mode 100644 index 1df9863..0000000 --- a/src/metadata_retriever.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include -#include -#include -#include -#include -#include - -//#include -#include -//#include -#include -//#include -#include -//#include -#include - -#include "directory_manager.h" -#include "metadata_retriever.h" -#include "imageFile.h" - -extern "C" -{ - -void retrieve_metadata(Song*, char*); -void update_metadata(Song*, Song*); - -void retrieve_metadata(Song *sng, char* song_path) -{ - std::cout<<"extern C"<Title, file.tag()->title().toCString()); - strcpy(sng->Artist, file.tag()->artist().toCString()); - strcpy(sng->Album, file.tag()->album().toCString()); - strcpy(sng->Genre, file.tag()->genre().toCString()); - sng->Year = file.tag()->year(); - sng->Duration = file.audioProperties()->lengthInSeconds(); - strcpy(sng->SongPath, song_path); -} -void update_metadata(Song *sng_updated, Song *sng_old) -{ - std::cout<<"updating metadata"<SongPath); - - if (strlen(sng_updated->Title) > 0) { - file.tag()->setTitle(sng_updated->Title); - } - if (strlen(sng_updated->Artist) > 0) { - file.tag()->setArtist(sng_updated->Artist); - } - if (strlen(sng_updated->Album) > 0) { - file.tag()->setAlbum(sng_updated->Album); - } - if (strlen(sng_updated->Genre) > 0) { - file.tag()->setGenre(sng_updated->Genre); - } - if (sng_updated->Year > 0) { - file.tag()->setYear(sng_updated->Year); - } - - file.save(); -} -void update_cover_art(Cover *cov, Song *song, const char *root_path) -{ - TagLib::MPEG::File sngF(song->SongPath); - TagLib::ID3v2::Tag *tag = sngF.ID3v2Tag(); - auto frameList = tag->frameListMap()["APIC"]; - - if (frameList.isEmpty()) { - std::string stock_path{root_path}; - stock_path.append("CoverArt.png"); - strcpy(cov->ImagePath, stock_path.c_str()); - - imageFile stock_img(stock_path.c_str()); - - TagLib::ID3v2::AttachedPictureFrame *pic = - new TagLib::ID3v2::AttachedPictureFrame; - pic->setPicture(stock_img.data()); - pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover); - - tag->addFrame(pic); - - sngF.save(); - std::cout<<"applied stock cover art"<( - frameList.front()); - auto img_path = create_directory_process(*song, root_path); - img_path.append(song->Title); - img_path.append(".png"); - strcpy(cov->ImagePath, img_path.c_str()); - std::cout<ImagePath<ImagePath, std::ios::out | - std::ios::binary); - img_save.write(frame->picture().data(), frame->picture().size()); - img_save.close(); - std::cout<<"saved to "<ImagePath< +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "managers/directory_manager.h" +#include "utilities/imageFile.h" +#include "utilities/metadata_retriever.h" + +Song metadata_retriever::retrieve_metadata(std::string& song_path) +{ + TagLib::FileRef file(song_path.c_str()); + Song song; + song.title = file.tag()->title().toCString(); + song.artist = file.tag()->artist().toCString(); + song.album = file.tag()->album().toCString(); + song.genre = file.tag()->genre().toCString(); + song.year = file.tag()->year(); + song.duration = file.audioProperties()->lengthInSeconds(); + song.songPath = song_path; + + /** + strcpy(sng->Title, file.tag()->title().toCString()); + strcpy(sng->Artist, file.tag()->artist().toCString()); + strcpy(sng->Album, file.tag()->album().toCString()); + strcpy(sng->Genre, file.tag()->genre().toCString()); + sng->Year = file.tag()->year(); + sng->Duration = file.audioProperties()->lengthInSeconds(); + strcpy(sng->SongPath, song_path); + */ + + return song; +} + +Cover metadata_retriever::update_cover_art(Cover cov, const Song song, const std::string& root_path) +{ + TagLib::MPEG::File sngF(song.songPath.c_str()); + TagLib::ID3v2::Tag *tag = sngF.ID3v2Tag(); + auto frameList = tag->frameListMap()["APIC"]; + + if (frameList.isEmpty()) { + std::string stock_path{root_path}; + stock_path.append("CoverArt.png"); + cov.imagePath = stock_path; + //strcpy(cov->ImagePath, stock_path.c_str()); + + imageFile stock_img(cov.imagePath.c_str()); + + TagLib::ID3v2::AttachedPictureFrame *pic = + new TagLib::ID3v2::AttachedPictureFrame; + pic->setPicture(stock_img.data()); + pic->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover); + + tag->addFrame(pic); + + sngF.save(); + std::cout<<"applied stock cover art"<( + frameList.front()); + directory_manager dir; + auto img_path = dir.create_directory_process(song, root_path); + img_path.append(song.title); + img_path.append(".png"); + cov.imagePath = img_path; + //strcpy(cov->ImagePath, img_path.c_str()); + std::cout<picture().data(), frame->picture().size()); + img_save.close(); + std::cout<<"saved to "< 0) { + file.tag()->setTitle(sng_updated.title); + } + if (sng_updated.artist.size() > 0) { + file.tag()->setArtist(sng_updated.artist); + } + if (sng_updated.album.size() > 0) { + file.tag()->setAlbum(sng_updated.album); + } + if (sng_updated.genre.size() > 0) { + file.tag()->setGenre(sng_updated.genre); + } + if (sng_updated.year > 0) { + file.tag()->setYear(sng_updated.year); + } + + file.save(); +} From 2a8290a92937a19953d2d8434fa086a5d2c0e910 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 21 Aug 2019 07:09:39 -0400 Subject: [PATCH 12/36] Added script to create database --- Scripts/MySQL/create_database.sql | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Scripts/MySQL/create_database.sql diff --git a/Scripts/MySQL/create_database.sql b/Scripts/MySQL/create_database.sql new file mode 100644 index 0000000..11a7d57 --- /dev/null +++ b/Scripts/MySQL/create_database.sql @@ -0,0 +1,33 @@ +CREATE DATABASE Icarus; + +USE Icarus; + +CREATE TABLE CoverArt ( + CoverArtId INT NOT NULL AUTO_INCREMENT, + SongTitle TEXT NOT NULL, + ImagePath TEXT NOT NULL, + + PRIMARY KEY (CoverArtId) +); + +CREATE TABLE Song ( + SongId INT NOT NULL AUTO_INCREMENT, + Title TEXT NOT NULL, + Artist TEXT NOT NULL, + Album TEXT NOT NULL, + Genre TEXT NOT NULL, + Year INT NOT NULL, + Duration INT NOT NULL, + CoverArtId INT NOT NULL, + + PRIMARY KEY (SongId), + CONSTRAINT FK_CoverArtId FOREIGN KEY (CoverArtId) REFERENCES CoverArt(CoverArtId) +); + +CREATE TABLE User ( + UserId INT NOT NULL AUTO_INCREMENT, + Username TEXT NOT NULL, + Password TEXT NOT NULL, + + PRIMARY KEY (UserId) +); From 592853695d94dce3550e1200347a0cd838f3e692 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Thu, 22 Aug 2019 19:49:17 -0400 Subject: [PATCH 13/36] Added paths.json file that contain paths --- CMakeLists.txt | 1 + authcredentials.json | 8 ++++---- paths.json | 6 ++++++ 3 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 paths.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 237854e..f0d3fe7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,7 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/oatpp) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/appsettings.json ${CMAKE_BINARY_DIR}/bin/appsettings.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/authcredentials.json ${CMAKE_BINARY_DIR}/bin/authcredentials.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/database.json ${CMAKE_BINARY_DIR}/bin/database.json COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/paths.json ${CMAKE_BINARY_DIR}/bin/paths.json COPYONLY) add_executable(icarus ${SOURCES} ${HEADERS}) target_include_directories(icarus PUBLIC ${JWT_CPP_INCLUDE}) diff --git a/authcredentials.json b/authcredentials.json index 463d848..f900c26 100644 --- a/authcredentials.json +++ b/authcredentials.json @@ -1,6 +1,6 @@ { - "Domain": "[domain].auth0.com", - "ApiIdentifier": "https://[identifier]/api", - "ClientId": "dfdfdfdf", - "ClientSecret": "dfdfdfdf" + "domain": "[domain].auth0.com", + "api_identifier": "https://[identifier]/api", + "client_id": "dfdfdfdf", + "client_secret": "dfdfdfdf" } diff --git a/paths.json b/paths.json new file mode 100644 index 0000000..ec7acac --- /dev/null +++ b/paths.json @@ -0,0 +1,6 @@ +{ + "root_music_path": "/icarus/music/", + "temp_root_path": "/icarus/temp/", + "cover_root_path": "/icarus/cover/", + "archive_root_path": "icarus/archive/" +} From 764185da7da13d624b63ab73737e6436afc2378b Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Thu, 22 Aug 2019 22:40:49 -0400 Subject: [PATCH 14/36] Able to save song and cover art to the appropriate paths. Next is saving it to the database --- CMakeLists.txt | 7 ++ include/database/base_repository.h | 1 + include/database/coverArtRepository.h | 14 ++++ include/database/songRepository.h | 14 ++++ include/managers/coverArtManager.h | 13 +++ include/managers/directory_manager.h | 15 +++- include/managers/song_manager.h | 13 +++ include/utilities/metadata_retriever.h | 2 +- src/controller/songController.hpp | 2 +- src/database/coverArtRepository.cpp | 1 + src/database/songRepository.cpp | 0 src/main.cpp | 7 +- src/managers/coverArtManager.cpp | 14 ++++ src/managers/directory_manager.cpp | 111 +++++++++---------------- src/managers/song_manager.cpp | 77 +++++++++++++++-- src/managers/token_manager.cpp | 20 +++-- src/utilities/metadata_retriever.cpp | 35 ++++---- 17 files changed, 235 insertions(+), 111 deletions(-) create mode 100644 include/database/coverArtRepository.h create mode 100644 include/database/songRepository.h create mode 100644 include/managers/coverArtManager.h create mode 100644 src/database/coverArtRepository.cpp create mode 100644 src/database/songRepository.cpp create mode 100644 src/managers/coverArtManager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f0d3fe7..3176c6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,11 @@ set(SOURCES src/controller/loginController.hpp src/controller/songController.hpp src/database/base_repository.cpp + #src/database/coverArtRepository.cpp + #src/database/songRepository.cpp src/dto/loginResultDto.hpp src/main.cpp + src/managers/coverArtManager.cpp src/managers/directory_manager.cpp src/managers/song_manager.cpp src/managers/token_manager.cpp @@ -20,6 +23,9 @@ set(SOURCES ) set(HEADERS include/database/base_repository.h + #include/database/coverArtRepository.h + #include/database/songRepository.h + include/managers/coverArtManager.h include/managers/directory_manager.h include/managers/song_manager.h include/managers/token_manager.h @@ -79,6 +85,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/appsettings.json ${CMAKE_BINARY_DIR}/ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/authcredentials.json ${CMAKE_BINARY_DIR}/bin/authcredentials.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/database.json ${CMAKE_BINARY_DIR}/bin/database.json COPYONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/paths.json ${CMAKE_BINARY_DIR}/bin/paths.json COPYONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Images/Stock/CoverArt.png ${CMAKE_BINARY_DIR}/bin/CoverArt.png COPYONLY) add_executable(icarus ${SOURCES} ${HEADERS}) target_include_directories(icarus PUBLIC ${JWT_CPP_INCLUDE}) diff --git a/include/database/base_repository.h b/include/database/base_repository.h index ea90788..bc9d74e 100644 --- a/include/database/base_repository.h +++ b/include/database/base_repository.h @@ -10,6 +10,7 @@ class base_repository { public: +protected: MYSQL* setup_mysql_connection(database_connection); MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&); diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h new file mode 100644 index 0000000..0678e2c --- /dev/null +++ b/include/database/coverArtRepository.h @@ -0,0 +1,14 @@ +#ifndef COVERARTREPOSITORY_H_ +#define COVERARTREPOSITORY_H_ + +#include + +#include "models/models.h" + +class coverArtRepository +{ +public: +private: +}; + +#endif diff --git a/include/database/songRepository.h b/include/database/songRepository.h new file mode 100644 index 0000000..f52535d --- /dev/null +++ b/include/database/songRepository.h @@ -0,0 +1,14 @@ +#ifndef SONGREPOSITORY_H_ +#define SONGREPOSITORY_H_ + +#include + +#include "models/models.h" + +class songRespository +{ +public: +private: +}; + +#endif diff --git a/include/managers/coverArtManager.h b/include/managers/coverArtManager.h new file mode 100644 index 0000000..387f059 --- /dev/null +++ b/include/managers/coverArtManager.h @@ -0,0 +1,13 @@ +#ifndef COVERARTMANAGER_H_ +#define COVERARTMANAGER_H_ + +#include "models/models.h" + +class coverArtManager +{ +public: + Cover saveCover(const Song&, std::string&, const std::string&); +private: +}; + +#endif diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h index ca44afc..4537c53 100644 --- a/include/managers/directory_manager.h +++ b/include/managers/directory_manager.h @@ -2,6 +2,9 @@ #define DIRECTORY_MANAGER_H_ #include +#include + +#include #include "models/models.h" @@ -10,12 +13,18 @@ class directory_manager public: std::string create_directory_process(Song, const std::string&); + static std::string configPath(std::string_view); + static std::string contentOfPath(std::string_view); + + static nlohmann::json credentialConfigContent(const std::string&); + static nlohmann::json databaseConfigContent(const std::string&); + static nlohmann::json pathConfigContent(const std::string&); // Return Cover instead - std::string read_cover_art(const std::string&); + //std::string read_cover_art(const std::string&); - void copy_stock_to_root(const std::string&, const std::string&); - void copy_song_to_path(const std::string&, const std::string&); + //void copy_stock_to_root(const std::string&, const std::string&); + //void copy_song_to_path(const std::string&, const std::string&); void delete_cover_art_file(const std::string&, const std::string&); void delete_directories(Song, const std::string&); diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index 18cc8a8..66983a7 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -4,6 +4,8 @@ #include #include +#include + #include "models/models.h" class song_manager @@ -11,8 +13,19 @@ class song_manager public: song_manager(std::string&); + /** + std::string retrieveMusicPath(); + std::string retrieveTempPath(); + */ + + //nlohmann::json pathConfigContent(); + void saveSong(Song&); + + static void printSong(const Song&); private: + void saveSongTemp(Song&); + std::string exe_path; }; diff --git a/include/utilities/metadata_retriever.h b/include/utilities/metadata_retriever.h index 4d14a8c..3a3760b 100644 --- a/include/utilities/metadata_retriever.h +++ b/include/utilities/metadata_retriever.h @@ -10,7 +10,7 @@ class metadata_retriever { public: Song retrieve_metadata(std::string&); - Cover update_cover_art(Cover, const Song, const std::string&); + Cover update_cover_art(const Song&, Cover& cov, const std::string&); void update_metadata(Song updated_song, const Song old_song); private: diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index ffc7ef0..f35e9be 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -14,8 +14,8 @@ #include "oatpp/web/server/api/ApiController.hpp" #include "managers/song_manager.h" -#include "models/models.h" #include "managers/token_manager.h" +#include "models/models.h" #include "types/scopes.h" class songController : public oatpp::web::server::api::ApiController diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp new file mode 100644 index 0000000..43b6363 --- /dev/null +++ b/src/database/coverArtRepository.cpp @@ -0,0 +1 @@ +#include "database/coverArtRepository.h" diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp index b999ed0..0551452 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,6 +48,7 @@ void test_database() mysqlD.database = ""; // the databse to pick base_repository base; + /** auto conn = base.setup_mysql_connection(mysqlD); // assign the results return to the MYSQL_RES pointer @@ -72,10 +73,11 @@ void test_database() std::cout << std::endl; } - /* clean up the database result set */ + // clean up the database result set // mysql_free_result(res); - /* clean up the database link */ + // clean up the database link // mysql_close(conn); + */ } @@ -84,7 +86,6 @@ int main(int argc, char **argv) oatpp::base::Environment::init(); std::string working_path = argv[0]; - //test_database(); run(working_path); oatpp::base::Environment::destroy(); diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp new file mode 100644 index 0000000..b5a0fc9 --- /dev/null +++ b/src/managers/coverArtManager.cpp @@ -0,0 +1,14 @@ +#include "managers/coverArtManager.h" + +#include "utilities/metadata_retriever.h" + +Cover coverArtManager::saveCover(const Song& song, std::string& rootPath, const std::string& stockCoverPath) +{ + metadata_retriever meta; + Cover cov; + cov.imagePath = rootPath; + cov = meta.update_cover_art(song, cov, stockCoverPath); + cov.songTitle = song.title; + + return cov; +} diff --git a/src/managers/directory_manager.cpp b/src/managers/directory_manager.cpp index e99904a..0c5f97c 100644 --- a/src/managers/directory_manager.cpp +++ b/src/managers/directory_manager.cpp @@ -36,6 +36,45 @@ std::string directory_manager::create_directory_process(Song song, const std::st return alb_path.string() + "/"; } + +std::string directory_manager::configPath(std::string_view path) +{ + return fs::canonical(path).parent_path().string(); +} +std::string directory_manager::contentOfPath(std::string_view path) +{ + std::string configPath(path); + std::fstream a(configPath, std::ios::in); + std::stringstream s; + s << a.rdbuf(); + a.close(); + + return s.str(); +} + +nlohmann::json directory_manager::credentialConfigContent(const std::string& exe_path) +{ + auto path = configPath(exe_path); + path.append("/authcredentials.json"); + + return nlohmann::json::parse(contentOfPath(path)); +} +nlohmann::json directory_manager::databaseConfigContent(const std::string& exe_path) +{ + auto path = configPath(exe_path); + path.append("/database.json"); + + return nlohmann::json::parse(contentOfPath(path)); +} +nlohmann::json directory_manager::pathConfigContent(const std::string& exe_path) +{ + auto path = configPath(exe_path); + path.append("/paths.json"); + + return nlohmann::json::parse(contentOfPath(path)); +} + +/** std::string directory_manager::read_cover_art(const std::string& source) { auto source_path = fs::path(source); @@ -80,6 +119,7 @@ void directory_manager::copy_song_to_path(const std::string& target, const std:: fs::remove(source); std::cout<<"copy finished"< #include +#include + +#include + +#include "managers/coverArtManager.h" +#include "managers/directory_manager.h" +#include "utilities/metadata_retriever.h" namespace fs = std::filesystem; @@ -9,14 +16,74 @@ song_manager::song_manager(std::string& x_path) : exe_path(x_path) { } +/** +std::string song_manager::retrieveMusicPath() +{ + std::string pathConfig = directory_manager::configPath(exe_path); + pathConfig.append("/paths.json"); + nlohmann::json config = nlohmann::json::parse(directory_manager::contentOfPath(pathConfig)); + + return config["root_music_path"].get(); +} +std::string song_manager::retrieveTempPath() +{ + auto pathConfig = directory_manager::configPath(exe_path); + pathConfig.append("/paths"); + + return std::string(); +} + +nlohmann::json song_manager::pathConfigContent() +{ + auto path = directory_manager::configPath(exe_path); + path.append("/paths.json"); + + return nlohmann::json::parse(directory_manager::contentOfPath(path)); +} +*/ + void song_manager::saveSong(Song& song) { - constexpr auto tmp_song = "/tmp/song.mp3"; - if (fs::exists(fs::path(tmp_song))) { - std::cout << "deleting old song " << std::endl; - fs::remove(fs::path(tmp_song)); - } + saveSongTemp(song); + metadata_retriever meta; + auto data = std::move(song.data); + song = meta.retrieve_metadata(song.songPath); + song.data = std::move(data); + printSong(song); + + coverArtManager covMgr; + auto coverRootPath = directory_manager::pathConfigContent(exe_path)["cover_root_path"].get(); + auto stockCoverPath = directory_manager::configPath(exe_path); + stockCoverPath.append("/CoverArt.png"); + auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); +} + +void song_manager::printSong(const Song& song) +{ + std::cout << "song" << std::endl; + std::cout << "title: " << song.title << std::endl; + std::cout << "artist: " << song.artist << std::endl; + std::cout << "album: " << song.album << std::endl; + std::cout << "genre: " << song.genre << std::endl; + std::cout << "duration: " << song.duration << std::endl; + std::cout << "year: " << song.year << std::endl; + std::cout << "song path: " << song.songPath << std::endl; +} + +void song_manager::saveSongTemp(Song& song) +{ + auto config = directory_manager::pathConfigContent(exe_path); + + auto tmp_song = config["temp_root_path"].get(); + std::random_device dev; + std::mt19937 rng(dev()); + std::uniform_int_distribution dist(1,1000); + tmp_song.append(std::to_string(dist(rng))); + tmp_song.append(".mp3"); + std::fstream s(tmp_song, std::fstream::binary | std::fstream::out); s.write((char*)&song.data[0], song.data.size()); s.close(); + + song.songPath = tmp_song; } diff --git a/src/managers/token_manager.cpp b/src/managers/token_manager.cpp index 058a75a..24ef2ef 100644 --- a/src/managers/token_manager.cpp +++ b/src/managers/token_manager.cpp @@ -1,3 +1,5 @@ +#include "managers/token_manager.h" + #include #include #include @@ -10,7 +12,7 @@ #include #include -#include "managers/token_manager.h" +#include "managers/directory_manager.h" namespace fs = std::filesystem; @@ -87,22 +89,26 @@ bool token_manager::is_token_valid(std::string& auth, Scope scope) auth_credentials token_manager::parse_auth_credentials(std::string_view path) { - auto exe_path = fs::canonical(path).parent_path().string(); + auto exe_path = directory_manager::configPath(path); exe_path.append("/authcredentials.json"); + //auto content = directory_manager::contentOfPath(exe_path); + /** std::fstream a(exe_path, std::ios::in); std::stringstream s; s << a.rdbuf(); a.close(); + */ - auto con = nlohmann::json::parse(s.str()); + //auto con = nlohmann::json::parse(directory_manager::contentOfPath(exe_path)); + auto con = directory_manager::credentialConfigContent(exe_path); auth_credentials auth; auth.uri = "https://"; - auth.uri.append(con["Domain"]); - auth.api_identifier = con["ApiIdentifier"]; - auth.client_id = con["ClientId"]; - auth.client_secret = con["ClientSecret"]; + auth.uri.append(con["domain"]); + auth.api_identifier = con["api_identifier"]; + auth.client_id = con["client_id"]; + auth.client_secret = con["client_secret"]; auth.endpoint = "oauth/token"; return auth; diff --git a/src/utilities/metadata_retriever.cpp b/src/utilities/metadata_retriever.cpp index e6fc00b..2b51e01 100644 --- a/src/utilities/metadata_retriever.cpp +++ b/src/utilities/metadata_retriever.cpp @@ -14,6 +14,8 @@ #include "utilities/imageFile.h" #include "utilities/metadata_retriever.h" +namespace fs = std::filesystem; + Song metadata_retriever::retrieve_metadata(std::string& song_path) { TagLib::FileRef file(song_path.c_str()); @@ -26,30 +28,23 @@ Song metadata_retriever::retrieve_metadata(std::string& song_path) song.duration = file.audioProperties()->lengthInSeconds(); song.songPath = song_path; - /** - strcpy(sng->Title, file.tag()->title().toCString()); - strcpy(sng->Artist, file.tag()->artist().toCString()); - strcpy(sng->Album, file.tag()->album().toCString()); - strcpy(sng->Genre, file.tag()->genre().toCString()); - sng->Year = file.tag()->year(); - sng->Duration = file.audioProperties()->lengthInSeconds(); - strcpy(sng->SongPath, song_path); - */ return song; } -Cover metadata_retriever::update_cover_art(Cover cov, const Song song, const std::string& root_path) +Cover metadata_retriever::update_cover_art(const Song& song, Cover& cov, const std::string& stockCoverPath) { TagLib::MPEG::File sngF(song.songPath.c_str()); - TagLib::ID3v2::Tag *tag = sngF.ID3v2Tag(); + auto tag = sngF.ID3v2Tag(); auto frameList = tag->frameListMap()["APIC"]; if (frameList.isEmpty()) { - std::string stock_path{root_path}; - stock_path.append("CoverArt.png"); - cov.imagePath = stock_path; - //strcpy(cov->ImagePath, stock_path.c_str()); + cov.imagePath.append("CoverArt.png"); + + if (!fs::exists(cov.imagePath)) { + std::cout << "copying stock cover path" << std::endl; + fs::copy(stockCoverPath, cov.imagePath); + } imageFile stock_img(cov.imagePath.c_str()); @@ -61,23 +56,23 @@ Cover metadata_retriever::update_cover_art(Cover cov, const Song song, const std tag->addFrame(pic); sngF.save(); - std::cout<<"applied stock cover art"<( frameList.front()); directory_manager dir; - auto img_path = dir.create_directory_process(song, root_path); + auto img_path = dir.create_directory_process(song, cov.imagePath); img_path.append(song.title); img_path.append(".png"); cov.imagePath = img_path; - //strcpy(cov->ImagePath, img_path.c_str()); - std::cout<picture().data(), frame->picture().size()); img_save.close(); - std::cout<<"saved to "< Date: Fri, 23 Aug 2019 23:16:42 -0400 Subject: [PATCH 15/36] Working on interfacing with the database. Could do queryies via string/cstring but I'm going to try prepared statements --- CMakeLists.txt | 4 ++-- include/database/base_repository.h | 8 +++++++ include/database/coverArtRepository.h | 6 +++++- include/managers/coverArtManager.h | 5 +++++ include/managers/song_manager.h | 7 ------ src/database/base_repository.cpp | 30 ++++++++++++++++++++++++++ src/database/coverArtRepository.cpp | 8 +++++++ src/managers/coverArtManager.cpp | 7 ++++++ src/managers/song_manager.cpp | 31 +++++---------------------- 9 files changed, 70 insertions(+), 36 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3176c6f..8c64957 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ set(SOURCES src/controller/loginController.hpp src/controller/songController.hpp src/database/base_repository.cpp - #src/database/coverArtRepository.cpp + src/database/coverArtRepository.cpp #src/database/songRepository.cpp src/dto/loginResultDto.hpp src/main.cpp @@ -23,7 +23,7 @@ set(SOURCES ) set(HEADERS include/database/base_repository.h - #include/database/coverArtRepository.h + include/database/coverArtRepository.h #include/database/songRepository.h include/managers/coverArtManager.h include/managers/directory_manager.h diff --git a/include/database/base_repository.h b/include/database/base_repository.h index bc9d74e..d2f6269 100644 --- a/include/database/base_repository.h +++ b/include/database/base_repository.h @@ -10,11 +10,19 @@ class base_repository { public: + base_repository(); + base_repository(const std::string&); protected: + MYSQL* setup_mysql_connection(); MYSQL* setup_mysql_connection(database_connection); MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&); + + database_connection details; private: + void intitalizeDetails(); + + std::string path; }; #endif diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h index 0678e2c..aaf96ed 100644 --- a/include/database/coverArtRepository.h +++ b/include/database/coverArtRepository.h @@ -3,11 +3,15 @@ #include +#include "database/base_repository.h" #include "models/models.h" -class coverArtRepository +class coverArtRepository : public base_repository { public: + coverArtRepository(const std::string&); + + void saveRecord(const Cover&); private: }; diff --git a/include/managers/coverArtManager.h b/include/managers/coverArtManager.h index 387f059..9e5479a 100644 --- a/include/managers/coverArtManager.h +++ b/include/managers/coverArtManager.h @@ -1,13 +1,18 @@ #ifndef COVERARTMANAGER_H_ #define COVERARTMANAGER_H_ +#include + #include "models/models.h" class coverArtManager { public: + coverArtManager(const std::string&); + Cover saveCover(const Song&, std::string&, const std::string&); private: + std::string path; }; #endif diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index 66983a7..ed3daca 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -13,13 +13,6 @@ class song_manager public: song_manager(std::string&); - /** - std::string retrieveMusicPath(); - std::string retrieveTempPath(); - */ - - //nlohmann::json pathConfigContent(); - void saveSong(Song&); static void printSong(const Song&); diff --git a/src/database/base_repository.cpp b/src/database/base_repository.cpp index 886c66b..02b68ca 100644 --- a/src/database/base_repository.cpp +++ b/src/database/base_repository.cpp @@ -1,5 +1,26 @@ #include "database/base_repository.h" +#include + +#include "managers/directory_manager.h" + +base_repository::base_repository() +{ } + +base_repository::base_repository(const std::string& path) : path(path) +{ + intitalizeDetails(); +} + +MYSQL* base_repository::setup_mysql_connection() +{ + MYSQL *conn = mysql_init(nullptr); + + auto res = mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), + details.password.c_str(), details.database.c_str(), 0, nullptr, 0); + + return conn; +} MYSQL* base_repository::setup_mysql_connection(database_connection details) { MYSQL *connection = mysql_init(NULL); @@ -23,3 +44,12 @@ MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, const std::string& return mysql_use_result(conn); } + +void base_repository::intitalizeDetails() +{ + auto databaseConfig = directory_manager::databaseConfigContent(path); + details.database = databaseConfig.get(); + details.password = databaseConfig.get(); + details.server = databaseConfig.get(); + details.username = databaseConfig.get(); +} diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index 43b6363..94dcbe5 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -1 +1,9 @@ #include "database/coverArtRepository.h" + + +coverArtRepository::coverArtRepository(const std::string& path) : base_repository(path) +{ } + +void coverArtRepository::saveRecord(const Cover& cov) +{ +} diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index b5a0fc9..6d186e0 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -1,7 +1,12 @@ #include "managers/coverArtManager.h" +#include "database/coverArtRepository.h" #include "utilities/metadata_retriever.h" +coverArtManager::coverArtManager(const std::string& configPath) : path(configPath) +{ } + + Cover coverArtManager::saveCover(const Song& song, std::string& rootPath, const std::string& stockCoverPath) { metadata_retriever meta; @@ -10,5 +15,7 @@ Cover coverArtManager::saveCover(const Song& song, std::string& rootPath, const cov = meta.update_cover_art(song, cov, stockCoverPath); cov.songTitle = song.title; + coverArtRepository covRepo(path); + return cov; } diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index aaae62e..f7d29e1 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -16,31 +16,6 @@ song_manager::song_manager(std::string& x_path) : exe_path(x_path) { } -/** -std::string song_manager::retrieveMusicPath() -{ - std::string pathConfig = directory_manager::configPath(exe_path); - pathConfig.append("/paths.json"); - nlohmann::json config = nlohmann::json::parse(directory_manager::contentOfPath(pathConfig)); - - return config["root_music_path"].get(); -} -std::string song_manager::retrieveTempPath() -{ - auto pathConfig = directory_manager::configPath(exe_path); - pathConfig.append("/paths"); - - return std::string(); -} - -nlohmann::json song_manager::pathConfigContent() -{ - auto path = directory_manager::configPath(exe_path); - path.append("/paths.json"); - - return nlohmann::json::parse(directory_manager::contentOfPath(path)); -} -*/ void song_manager::saveSong(Song& song) { @@ -51,10 +26,13 @@ void song_manager::saveSong(Song& song) song.data = std::move(data); printSong(song); - coverArtManager covMgr; + coverArtManager covMgr(exe_path); auto coverRootPath = directory_manager::pathConfigContent(exe_path)["cover_root_path"].get(); + //const nlohmann::json databaseConfig = directory_manager::databaseConfigContent(exe_path); + auto stockCoverPath = directory_manager::configPath(exe_path); stockCoverPath.append("/CoverArt.png"); + auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); } @@ -78,6 +56,7 @@ void song_manager::saveSongTemp(Song& song) std::random_device dev; std::mt19937 rng(dev()); std::uniform_int_distribution dist(1,1000); + tmp_song.append(std::to_string(dist(rng))); tmp_song.append(".mp3"); From 1db3eb2f8c7aafde760101403a9a2dedaefc0273 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 Aug 2019 18:41:01 -0400 Subject: [PATCH 16/36] Cover art record saved in the database. Next is to save the song record to the database and then try to download the song afterwards --- CMakeLists.txt | 6 +- include/database/coverArtRepository.h | 4 + include/database/songRepository.h | 13 +++- include/models/models.h | 1 + include/types/coverFilter.h | 11 +++ include/types/songFilter.h | 14 ++++ src/database/base_repository.cpp | 17 +++-- src/database/coverArtRepository.cpp | 103 ++++++++++++++++++++++++++ src/database/songRepository.cpp | 35 +++++++++ src/managers/coverArtManager.cpp | 5 ++ src/managers/song_manager.cpp | 5 ++ 11 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 include/types/coverFilter.h create mode 100644 include/types/songFilter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c64957..80ebf11 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(SOURCES src/controller/songController.hpp src/database/base_repository.cpp src/database/coverArtRepository.cpp - #src/database/songRepository.cpp + src/database/songRepository.cpp src/dto/loginResultDto.hpp src/main.cpp src/managers/coverArtManager.cpp @@ -24,7 +24,7 @@ set(SOURCES set(HEADERS include/database/base_repository.h include/database/coverArtRepository.h - #include/database/songRepository.h + include/database/songRepository.h include/managers/coverArtManager.h include/managers/directory_manager.h include/managers/song_manager.h @@ -32,7 +32,9 @@ set(HEADERS include/models/models.h include/utilities/imageFile.h include/utilities/metadata_retriever.h + include/types/coverFilter.h include/types/scopes.h + include/types/songFilter.h ) set (TAGLIB diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h index aaf96ed..dd5ad11 100644 --- a/include/database/coverArtRepository.h +++ b/include/database/coverArtRepository.h @@ -5,14 +5,18 @@ #include "database/base_repository.h" #include "models/models.h" +#include "types/coverFilter.h" class coverArtRepository : public base_repository { public: coverArtRepository(const std::string&); + Cover retrieveRecord(Cover&, coverFilter); + void saveRecord(const Cover&); private: + Cover parseRecord(MYSQL_RES*); }; #endif diff --git a/include/database/songRepository.h b/include/database/songRepository.h index f52535d..f442c5b 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -1,14 +1,25 @@ #ifndef SONGREPOSITORY_H_ #define SONGREPOSITORY_H_ +#include + #include +#include "database/base_repository.h" #include "models/models.h" +#include "types/songFilter.h" -class songRespository +class songRepository : public base_repository { public: + songRepository(const std::string&); + + Song retrieveRecord(Song&, songFilter); + + void saveRecord(const Song&); private: + std::vector parseRecords(MYSQL_RES*); + Song parseRecord(MYSQL_RES*); }; #endif diff --git a/include/models/models.h b/include/models/models.h index 1d027da..b619b5b 100644 --- a/include/models/models.h +++ b/include/models/models.h @@ -15,6 +15,7 @@ struct Song int duration; std::string songPath; std::vector data; + int coverArtId; }; struct Cover diff --git a/include/types/coverFilter.h b/include/types/coverFilter.h new file mode 100644 index 0000000..b334a8a --- /dev/null +++ b/include/types/coverFilter.h @@ -0,0 +1,11 @@ +#ifndef COVERFILTER_H_ +#define COVERFILTER_H_ + +enum class coverFilter +{ + id = 0, + songTitle, + imagePath +}; + +#endif diff --git a/include/types/songFilter.h b/include/types/songFilter.h new file mode 100644 index 0000000..85a3c46 --- /dev/null +++ b/include/types/songFilter.h @@ -0,0 +1,14 @@ +#ifndef SONGFILTER_H_ +#define SONGFILTER_H_ + +enum class songFilter +{ + id = 0, + title, + album, + artist, + genre, + year +}; + +#endif diff --git a/src/database/base_repository.cpp b/src/database/base_repository.cpp index 02b68ca..c55b91f 100644 --- a/src/database/base_repository.cpp +++ b/src/database/base_repository.cpp @@ -1,5 +1,7 @@ #include "database/base_repository.h" +#include + #include #include "managers/directory_manager.h" @@ -16,8 +18,10 @@ MYSQL* base_repository::setup_mysql_connection() { MYSQL *conn = mysql_init(nullptr); - auto res = mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), - details.password.c_str(), details.database.c_str(), 0, nullptr, 0); + if (!mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), + details.password.c_str(), details.database.c_str(), 0, nullptr, 0)) { + std::cout << "connection error" << std::endl; + } return conn; } @@ -48,8 +52,9 @@ MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, const std::string& void base_repository::intitalizeDetails() { auto databaseConfig = directory_manager::databaseConfigContent(path); - details.database = databaseConfig.get(); - details.password = databaseConfig.get(); - details.server = databaseConfig.get(); - details.username = databaseConfig.get(); + + details.database = databaseConfig["database"].get(); + details.password = databaseConfig["password"].get(); + details.server = databaseConfig["server"].get(); + details.username = databaseConfig["username"].get(); } diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index 94dcbe5..719eadb 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -1,9 +1,112 @@ #include "database/coverArtRepository.h" +#include +#include +#include +#include coverArtRepository::coverArtRepository(const std::string& path) : base_repository(path) { } +Cover coverArtRepository::retrieveRecord(Cover& cov, coverFilter filter = coverFilter::id) +{ + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT * FROM CoverArt WHERE "; + + std::unique_ptr param; + switch (filter) { + case coverFilter::id: + qry << "CoverArtId = " << cov.id; + break; + case coverFilter::songTitle: + param = std::make_unique(new char[cov.songTitle.size()]); + mysql_real_escape_string(conn, *param, cov.songTitle.c_str(), cov.songTitle.size()); + std::cout << *param << std::endl; + qry << "SongTitle = '" << *param << "'"; + break; + case coverFilter::imagePath: + param = std::make_unique(new char[cov.imagePath.size()]); + mysql_real_escape_string(conn, *param, cov.imagePath.c_str(), cov.imagePath.size()); + std::cout << *param << std::endl; + qry << "ImagePath = '" << *param << "'"; + break; + } + + const std::string query = qry.str(); + std::cout << query << std::endl; + auto results = perform_mysql_query(conn, query); + std::cout << "the query has been performed" << std::endl; + + auto covDb = parseRecord(results); + + mysql_close(conn); + std::cout << "done" << std::endl; + + return covDb; +} + + void coverArtRepository::saveRecord(const Cover& cov) { + auto conn = setup_mysql_connection(); + + MYSQL_STMT *stmt; + MYSQL_BIND params[2]; + my_bool isNull; + int status; + + stmt = mysql_stmt_init(conn); + + const std::string query = "INSERT INTO CoverArt(SongTitle, ImagePath) VALUES(?, ?)"; + + status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)cov.songTitle.c_str(); + auto songTitleLength = cov.songTitle.size(); + params[0].length = &songTitleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)cov.imagePath.c_str(); + auto imagePathLength = cov.imagePath.size(); + params[1].length = &imagePathLength; + params[1].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done" << std::endl; +} + +Cover coverArtRepository::parseRecord(MYSQL_RES *results) +{ + std::cout << "parsing record" << std::endl; + Cover cov; + auto fieldNum = mysql_num_fields(results); + + MYSQL_ROW row = mysql_fetch_row(results); + + for (auto i = 0; i != fieldNum; ++i) { + switch (i) { + case 0: + cov.id = std::stoi(row[i]); + break; + case 1: + cov.songTitle = row[i]; + break; + case 2: + cov.imagePath = row[i]; + break; + } + } + std::cout << "done parsing record" << std::endl; + + return cov; } diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index e69de29..55a088c 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -0,0 +1,35 @@ +#include "database/songRepository.h" + +#include +#include +#include +#include + +songRepository::songRepository(const std::string& path) : base_repository(path) +{ } + +Song songRepository::retrieveRecord(Song& song, songFilter) +{ + + return song; +} + +void songRepository::saveRecord(const Song& song) +{ + // TODO: pick up here. Save the song record to the database +} + +std::vector songRepository::parseRecords(MYSQL_RES* results) +{ + std::vector songs; + + + return songs; +} + +Song songRepository::parseRecord(MYSQL_RES* results) +{ + Song song; + + return song; +} diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index 6d186e0..c2fa75d 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -1,6 +1,7 @@ #include "managers/coverArtManager.h" #include "database/coverArtRepository.h" +#include "types/coverFilter.h" #include "utilities/metadata_retriever.h" coverArtManager::coverArtManager(const std::string& configPath) : path(configPath) @@ -16,6 +17,10 @@ Cover coverArtManager::saveCover(const Song& song, std::string& rootPath, const cov.songTitle = song.title; coverArtRepository covRepo(path); + std::cout << "saving record to the database" << std::endl; + covRepo.saveRecord(cov); + std::cout << "retrieving record from database" << std::endl; + cov = covRepo.retrieveRecord(cov, coverFilter::songTitle); return cov; } diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index f7d29e1..cce4592 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -6,6 +6,7 @@ #include +#include "database/songRepository.h" #include "managers/coverArtManager.h" #include "managers/directory_manager.h" #include "utilities/metadata_retriever.h" @@ -34,6 +35,10 @@ void song_manager::saveSong(Song& song) stockCoverPath.append("/CoverArt.png"); auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); + song.coverArtId = cov.id; + + songRepository songRepo(exe_path); + songRepo.saveRecord(song); } void song_manager::printSong(const Song& song) From d54715ac254d13cc615222fdf91f8936ad8a958a Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 25 Aug 2019 01:30:13 -0400 Subject: [PATCH 17/36] Able to insert song records into the database. Left TODO for clean up --- include/database/songRepository.h | 6 ++ src/database/songRepository.cpp | 121 +++++++++++++++++++++++++++++- src/managers/song_manager.cpp | 5 ++ 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/include/database/songRepository.h b/include/database/songRepository.h index f442c5b..580aa86 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -1,6 +1,7 @@ #ifndef SONGREPOSITORY_H_ #define SONGREPOSITORY_H_ +#include #include #include @@ -19,6 +20,11 @@ public: void saveRecord(const Song&); private: std::vector parseRecords(MYSQL_RES*); + + std::unique_ptr bindParams(const Song&); + //std::unique_ptr bindParams(const Song&); + //std::shared_ptr bindParams(const Song&); + Song parseRecord(MYSQL_RES*); }; diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 55a088c..89fa828 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -16,7 +16,74 @@ Song songRepository::retrieveRecord(Song& song, songFilter) void songRepository::saveRecord(const Song& song) { - // TODO: pick up here. Save the song record to the database + // TODO: Yeeesh! Clean this shit up! + auto conn = setup_mysql_connection(); + auto status = 0; + + MYSQL_STMT *stmt; + stmt = mysql_stmt_init(conn); + + std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; + query.append("Year, Duration, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?)"); + + status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + + //auto params = bindParams(song); + //MYSQL_BIND *b; + //b = *params.get(); + //auto status = mysql_stmt_bind_param(stmt, b); + // + MYSQL_BIND params[7]; + + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + auto titleLength = song.title.size(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.artist.c_str(); + auto artistLength = song.artist.size(); + params[1].length = &artistLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.album.c_str(); + auto albumLength = song.album.size(); + params[2].length = &albumLength; + params[2].is_null = 0; + + params[3].buffer_type = MYSQL_TYPE_STRING; + params[3].buffer = (char*)song.genre.c_str(); + auto genreLength = song.genre.size(); + params[3].length = &genreLength; + params[3].is_null = 0; + + params[4].buffer_type = MYSQL_TYPE_LONG; + params[4].buffer = (char*)&song.year; + params[4].length = 0; + params[4].is_null = 0; + + params[5].buffer_type = MYSQL_TYPE_LONG; + params[5].buffer = (char*)&song.duration; + params[5].length = 0; + params[5].is_null = 0; + + params[6].buffer_type = MYSQL_TYPE_LONG; + params[6].buffer = (char*)&song.coverArtId; + params[6].length = 0; + params[6].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done inserting song record" << std::endl; } std::vector songRepository::parseRecords(MYSQL_RES* results) @@ -27,6 +94,58 @@ std::vector songRepository::parseRecords(MYSQL_RES* results) return songs; } +std::unique_ptr songRepository::bindParams(const Song& song) +//std::unique_ptr songRepository::bindParams(const Song& song) +//std::shared_ptr songRepository::bindParams(const Song& song) +{ + MYSQL_BIND params[7]; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + auto titleLength = song.title.size(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.artist.c_str(); + auto artistLength = song.artist.size(); + params[1].length = &artistLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.album.c_str(); + auto albumLength = song.album.size(); + params[2].length = &albumLength; + params[2].is_null = 0; + + params[3].buffer_type = MYSQL_TYPE_STRING; + params[3].buffer = (char*)song.genre.c_str(); + auto genreLength = song.genre.size(); + params[3].length = &genreLength; + params[3].is_null = 0; + + params[4].buffer_type = MYSQL_TYPE_LONG; + params[4].buffer = (char*)&song.year; + params[4].length = 0; + params[4].is_null = 0; + + params[5].buffer_type = MYSQL_TYPE_LONG; + params[5].buffer = (char*)&song.duration; + params[5].length = 0; + params[5].is_null = 0; + + params[6].buffer_type = MYSQL_TYPE_LONG; + params[6].buffer = (char*)&song.coverArtId; + params[6].length = 0; + params[6].is_null = 0; + + std::cout << "binding params" << std::endl; + + //return std::make_unique(params); + return std::make_unique(params); + //return std::make_shared(params); +} + Song songRepository::parseRecord(MYSQL_RES* results) { Song song; diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index cce4592..018c25d 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -37,6 +37,8 @@ void song_manager::saveSong(Song& song) auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); song.coverArtId = cov.id; + printSong(song); + songRepository songRepo(exe_path); songRepo.saveRecord(song); } @@ -51,6 +53,9 @@ void song_manager::printSong(const Song& song) std::cout << "duration: " << song.duration << std::endl; std::cout << "year: " << song.year << std::endl; std::cout << "song path: " << song.songPath << std::endl; + if (song.coverArtId != 0) { + std::cout << "cover art id: " << song.coverArtId << std::endl; + } } void song_manager::saveSongTemp(Song& song) From 2145adb039a3a2ba25b383cc02d2dd2c62850ffd Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 25 Aug 2019 14:54:09 -0400 Subject: [PATCH 18/36] Some clean up for insert song records into the database --- CMakeLists.txt | 1 + include/database/songRepository.h | 6 +- src/database/coverArtRepository.cpp | 1 - src/database/songRepository.cpp | 180 ++++++++++++++++++---------- src/dto/songDto.hpp | 24 ++++ src/managers/song_manager.cpp | 2 - 6 files changed, 143 insertions(+), 71 deletions(-) create mode 100644 src/dto/songDto.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 80ebf11..462216f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES src/database/coverArtRepository.cpp src/database/songRepository.cpp src/dto/loginResultDto.hpp + src/dto/songDto.hpp src/main.cpp src/managers/coverArtManager.cpp src/managers/directory_manager.cpp diff --git a/include/database/songRepository.h b/include/database/songRepository.h index 580aa86..9ce5388 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -15,16 +15,14 @@ class songRepository : public base_repository public: songRepository(const std::string&); + std::vector retrieveRecords(); + Song retrieveRecord(Song&, songFilter); void saveRecord(const Song&); private: std::vector parseRecords(MYSQL_RES*); - std::unique_ptr bindParams(const Song&); - //std::unique_ptr bindParams(const Song&); - //std::shared_ptr bindParams(const Song&); - Song parseRecord(MYSQL_RES*); }; diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index 719eadb..660e0c5 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -34,7 +34,6 @@ Cover coverArtRepository::retrieveRecord(Cover& cov, coverFilter filter = coverF } const std::string query = qry.str(); - std::cout << query << std::endl; auto results = perform_mysql_query(conn, query); std::cout << "the query has been performed" << std::endl; diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 89fa828..3dd8cac 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -5,37 +5,71 @@ #include #include +#include "types/songFilter.h" + songRepository::songRepository(const std::string& path) : base_repository(path) { } -Song songRepository::retrieveRecord(Song& song, songFilter) +std::vector songRepository::retrieveRecords() { + auto conn = setup_mysql_connection(); + const std::string query = "SELECT * FROM Song"; + + auto results = perform_mysql_query(conn, query); + auto songs = parseRecords(results); + + mysql_close(conn); + + + return songs; +} + +Song songRepository::retrieveRecord(Song& song, songFilter filter) +{ + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT * FROM Song WHERE "; + + std::unique_ptr param; + switch (filter) { + case songFilter::id: + qry << "SongId = " << song.id; + break; + case songFilter::title: + param = std::make_unique(new char[song.title.size()]); + mysql_real_escape_string(conn, *param, song.title.c_str(), song.title.size()); + std::cout << *param << std::endl; + qry << "Title = '" << *param << "'"; + break; + default: + break; + } + + const std::string query = qry.str(); + auto results = perform_mysql_query(conn, query); + std::cout << "the query has been performed" << std::endl; + + song = parseRecord(results); + + mysql_close(conn); + std::cout << "done" << std::endl; return song; } void songRepository::saveRecord(const Song& song) { - // TODO: Yeeesh! Clean this shit up! auto conn = setup_mysql_connection(); auto status = 0; - MYSQL_STMT *stmt; - stmt = mysql_stmt_init(conn); + MYSQL_STMT *stmt = mysql_stmt_init(conn); std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; query.append("Year, Duration, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?)"); status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - - //auto params = bindParams(song); - //MYSQL_BIND *b; - //b = *params.get(); - //auto status = mysql_stmt_bind_param(stmt, b); - // MYSQL_BIND params[7]; - memset(params, 0, sizeof(params)); params[0].buffer_type = MYSQL_TYPE_STRING; @@ -88,67 +122,85 @@ void songRepository::saveRecord(const Song& song) std::vector songRepository::parseRecords(MYSQL_RES* results) { - std::vector songs; + auto fieldNum = mysql_num_fields(results); + auto numRows = mysql_num_rows(results); + std::vector songs; + songs.reserve(numRows); + + for (MYSQL_ROW row = nullptr; (row = mysql_fetch_row(results)) != nullptr; ) { + Song song; + + for (auto i = 0; i != fieldNum; ++i) { + switch (i) { + case 0: + song.id = std::stoi(row[i]); + break; + case 1: + song.title = row[i]; + break; + case 2: + song.artist= row[i]; + break; + case 3: + song.album = row[i]; + break; + case 4: + song.genre = row[i]; + break; + case 5: + song.year = std::stoi(row[i]); + break; + case 6: + song.duration = std::stoi(row[i]); + break; + case 7: + song.coverArtId = std::stoi(row[i]); + break; + } + } + + songs.push_back(song); + } return songs; } -std::unique_ptr songRepository::bindParams(const Song& song) -//std::unique_ptr songRepository::bindParams(const Song& song) -//std::shared_ptr songRepository::bindParams(const Song& song) -{ - MYSQL_BIND params[7]; - - params[0].buffer_type = MYSQL_TYPE_STRING; - params[0].buffer = (char*)song.title.c_str(); - auto titleLength = song.title.size(); - params[0].length = &titleLength; - params[0].is_null = 0; - - params[1].buffer_type = MYSQL_TYPE_STRING; - params[1].buffer = (char*)song.artist.c_str(); - auto artistLength = song.artist.size(); - params[1].length = &artistLength; - params[1].is_null = 0; - - params[2].buffer_type = MYSQL_TYPE_STRING; - params[2].buffer = (char*)song.album.c_str(); - auto albumLength = song.album.size(); - params[2].length = &albumLength; - params[2].is_null = 0; - - params[3].buffer_type = MYSQL_TYPE_STRING; - params[3].buffer = (char*)song.genre.c_str(); - auto genreLength = song.genre.size(); - params[3].length = &genreLength; - params[3].is_null = 0; - - params[4].buffer_type = MYSQL_TYPE_LONG; - params[4].buffer = (char*)&song.year; - params[4].length = 0; - params[4].is_null = 0; - - params[5].buffer_type = MYSQL_TYPE_LONG; - params[5].buffer = (char*)&song.duration; - params[5].length = 0; - params[5].is_null = 0; - - params[6].buffer_type = MYSQL_TYPE_LONG; - params[6].buffer = (char*)&song.coverArtId; - params[6].length = 0; - params[6].is_null = 0; - - std::cout << "binding params" << std::endl; - - //return std::make_unique(params); - return std::make_unique(params); - //return std::make_shared(params); -} - Song songRepository::parseRecord(MYSQL_RES* results) { Song song; + auto fieldNum = mysql_num_fields(results); + + MYSQL_ROW row = mysql_fetch_row(results); + + for (auto i = 0; i != fieldNum; ++i) { + switch (i) { + case 0: + song.id = std::stoi(row[i]); + break; + case 1: + song.title = row[i]; + break; + case 2: + song.artist= row[i]; + break; + case 3: + song.album = row[i]; + break; + case 4: + song.genre = row[i]; + break; + case 5: + song.year = std::stoi(row[i]); + break; + case 6: + song.duration = std::stoi(row[i]); + break; + case 7: + song.coverArtId = std::stoi(row[i]); + } + } + std::cout << "done parsing record" << std::endl; return song; } diff --git a/src/dto/songDto.hpp b/src/dto/songDto.hpp new file mode 100644 index 0000000..13723d1 --- /dev/null +++ b/src/dto/songDto.hpp @@ -0,0 +1,24 @@ +#ifndef SONGDTO_H_ +#define SONGDTO_H_ + +#include "oatpp/core/data/mapping/type/Object.hpp" +#include "oatpp/core/macro/codegen.hpp" + +#include OATPP_CODEGEN_BEGIN(DTO) + +class songDto : public oatpp::data::mapping::type::Object +{ + DTO_INIT(songDto, Object) + + DTO_FIELD(Int32, id); + DTO_FIELD(String, title); + DTO_FIELD(String, artist); + DTO_FIELD(String, album); + DTO_FIELD(String, genre); + DTO_FIELD(Int32, year); + DTO_FIELD(Int32, duration); +}; + +#include OATPP_CODEGEN_END(DTO) + +#endif diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index 018c25d..0db2a77 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -25,11 +25,9 @@ void song_manager::saveSong(Song& song) auto data = std::move(song.data); song = meta.retrieve_metadata(song.songPath); song.data = std::move(data); - printSong(song); coverArtManager covMgr(exe_path); auto coverRootPath = directory_manager::pathConfigContent(exe_path)["cover_root_path"].get(); - //const nlohmann::json databaseConfig = directory_manager::databaseConfigContent(exe_path); auto stockCoverPath = directory_manager::configPath(exe_path); stockCoverPath.append("/CoverArt.png"); From 540d665a7eed843ded43d69cfb041c1abf3fbf84 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 25 Aug 2019 15:26:47 -0400 Subject: [PATCH 19/36] Can retrieve all song records --- src/controller/loginController.hpp | 3 --- src/controller/songController.hpp | 36 +++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index e17de5e..35460e9 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -2,7 +2,6 @@ #define LOGINCONTROLLER_H_ #include -#include #include #include @@ -13,8 +12,6 @@ #include "../dto/loginResultDto.hpp" #include "managers/token_manager.h" -namespace fs = std::filesystem; - class loginController : public oatpp::web::server::api::ApiController { public: diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index f35e9be..1824a80 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -2,7 +2,7 @@ #define SONGCONTROLLER_H_ #include -#include +#include #include #include #include @@ -13,6 +13,8 @@ #include "oatpp/web/mime/multipart/Reader.hpp" #include "oatpp/web/server/api/ApiController.hpp" +#include "database/songRepository.h" +#include "../dto/songDto.hpp" #include "managers/song_manager.h" #include "managers/token_manager.h" #include "models/models.h" @@ -27,8 +29,7 @@ public: #include OATPP_CODEGEN_BEGIN(ApiController) - // TODO: work on uploading a song - // and clean up + // endpoint for uploading a song ENDPOINT("POST", "/api/v1/song/data", songUpload, REQUEST(std::shared_ptr, request)) { @@ -68,11 +69,36 @@ public: 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; + songRepository songRepo(exe_path); + 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 = 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; + + songs->pushBack(song); + } + + return createDtoResponse(Status::CODE_200, songs); + } + #include OATPP_CODEGEN_END(ApiController) private: std::string exe_path; - - const long dataSize = 1000000000000; + const long dataSize = std::numeric_limits::max(); }; #endif From fb033541890a5db94377ae6b88c79ec1d2651aa5 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 25 Aug 2019 16:47:52 -0400 Subject: [PATCH 20/36] Working on downloading the song --- Scripts/MySQL/create_database.sql | 1 + include/managers/directory_manager.h | 2 +- src/controller/songController.hpp | 60 ++++++++++++++++++++++++++++ src/database/songRepository.cpp | 21 +++++++--- src/managers/song_manager.cpp | 16 +++++++- 5 files changed, 92 insertions(+), 8 deletions(-) diff --git a/Scripts/MySQL/create_database.sql b/Scripts/MySQL/create_database.sql index 11a7d57..d1149cb 100644 --- a/Scripts/MySQL/create_database.sql +++ b/Scripts/MySQL/create_database.sql @@ -18,6 +18,7 @@ CREATE TABLE Song ( Genre TEXT NOT NULL, Year INT NOT NULL, Duration INT NOT NULL, + SongPath TEXT NOT NULL, CoverArtId INT NOT NULL, PRIMARY KEY (SongId), diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h index 4537c53..283ac10 100644 --- a/include/managers/directory_manager.h +++ b/include/managers/directory_manager.h @@ -12,7 +12,7 @@ class directory_manager { public: - std::string create_directory_process(Song, const std::string&); + static std::string create_directory_process(Song, const std::string&); static std::string configPath(std::string_view); static std::string contentOfPath(std::string_view); diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 1824a80..b293d25 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -1,12 +1,15 @@ #ifndef SONGCONTROLLER_H_ #define SONGCONTROLLER_H_ +#include #include #include #include #include #include +#include "oatpp/core/data/stream/ChunkedBuffer.hpp" +#include "oatpp/core/data/stream/FileStream.hpp" #include "oatpp/core/macro/codegen.hpp" #include "oatpp/core/macro/component.hpp" #include "oatpp/web/mime/multipart/InMemoryPartReader.hpp" @@ -19,6 +22,9 @@ #include "managers/token_manager.h" #include "models/models.h" #include "types/scopes.h" +#include "types/songFilter.h" + +namespace fs = std::filesystem; class songController : public oatpp::web::server::api::ApiController { @@ -95,6 +101,60 @@ public: 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)) { + + songRepository songRepo(exe_path); + Song songDb; + songDb.id = id; + + songDb = songRepo.retrieveRecord(songDb, songFilter::id); + + auto song = 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; + + return createDtoResponse(Status::CODE_200, song); + } + + // TODO: left off here + ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, + PATH(Int32, id)) { + + songRepository songRepo(exe_path); + Song songDb; + songDb.id = id; + songDb = songRepo.retrieveRecord(songDb, songFilter::id); + + std::cout << "constructing FileInputStream" << std::endl; + oatpp::data::stream::FileInputStream file(songDb.songPath.c_str()); + //oatpp::data::stream::FileOutputStream file(songDb.songPath.c_str()); + auto songPath = fs::path(songDb.songPath); + auto songSize = fs::file_size(songPath); + std::cout << "prepping data" << std::endl; + auto data = new char[songSize]; + std::cout << "data will be loaded" << std::endl; + auto byteCount = file.read(&data, songSize); + //auto byteCount = file.write(&data, songSize); + + std::cout << byteCount << " bytes read" << std::endl; + + auto songData = oatpp::data::stream::ChunkedBuffer::createShared(); + songData->write(data, byteCount); + + delete[] data; + + std::cout << "sending file" << std::endl; + + return createResponse(Status::CODE_200, songData); + } + #include OATPP_CODEGEN_END(ApiController) private: std::string exe_path; diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 3dd8cac..0c09e01 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -65,11 +65,11 @@ void songRepository::saveRecord(const Song& song) MYSQL_STMT *stmt = mysql_stmt_init(conn); std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; - query.append("Year, Duration, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?)"); + query.append("Year, Duration, SongPath, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - MYSQL_BIND params[7]; + MYSQL_BIND params[8]; memset(params, 0, sizeof(params)); params[0].buffer_type = MYSQL_TYPE_STRING; @@ -106,10 +106,16 @@ void songRepository::saveRecord(const Song& song) params[5].length = 0; params[5].is_null = 0; - params[6].buffer_type = MYSQL_TYPE_LONG; - params[6].buffer = (char*)&song.coverArtId; - params[6].length = 0; + params[6].buffer_type = MYSQL_TYPE_STRING; + params[6].buffer = (char*)song.songPath.c_str(); + auto pathLength = song.songPath.size(); + params[6].length = &pathLength; params[6].is_null = 0; + + params[7].buffer_type = MYSQL_TYPE_LONG; + params[7].buffer = (char*)&song.coverArtId; + params[7].length = 0; + params[7].is_null = 0; status = mysql_stmt_bind_param(stmt, params); status = mysql_stmt_execute(stmt); @@ -155,6 +161,8 @@ std::vector songRepository::parseRecords(MYSQL_RES* results) song.duration = std::stoi(row[i]); break; case 7: + song.songPath = row[i]; + case 8: song.coverArtId = std::stoi(row[i]); break; } @@ -197,6 +205,9 @@ Song songRepository::parseRecord(MYSQL_RES* results) song.duration = std::stoi(row[i]); break; case 7: + song.songPath = row[i]; + break; + case 8: song.coverArtId = std::stoi(row[i]); } } diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index 0db2a77..04f08b9 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -27,7 +27,9 @@ void song_manager::saveSong(Song& song) song.data = std::move(data); coverArtManager covMgr(exe_path); - auto coverRootPath = directory_manager::pathConfigContent(exe_path)["cover_root_path"].get(); + auto pathConfigContent = directory_manager::pathConfigContent(exe_path); + auto coverRootPath = pathConfigContent["cover_root_path"].get(); + auto musicRootPath = pathConfigContent["root_music_path"].get(); auto stockCoverPath = directory_manager::configPath(exe_path); stockCoverPath.append("/CoverArt.png"); @@ -35,6 +37,16 @@ void song_manager::saveSong(Song& song) auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); song.coverArtId = cov.id; + auto songPath = directory_manager::create_directory_process(song, musicRootPath); + songPath.append(song.title); + songPath.append(".mp3"); + std::cout << std::endl; + std::cout << "temp path: " << song.songPath << std::endl; + std::cout << "new path: " << songPath << std::endl; + fs::copy(song.songPath, songPath); + fs::remove(song.songPath); + song.songPath = std::move(songPath); + printSong(song); songRepository songRepo(exe_path); @@ -43,7 +55,7 @@ void song_manager::saveSong(Song& song) void song_manager::printSong(const Song& song) { - std::cout << "song" << std::endl; + std::cout << std::endl << "song" << std::endl; std::cout << "title: " << song.title << std::endl; std::cout << "artist: " << song.artist << std::endl; std::cout << "album: " << song.album << std::endl; From 48e97e7cd1cf10cc8b0e7cae7b65afb525ff7648 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 25 Aug 2019 22:21:21 -0400 Subject: [PATCH 21/36] Added support for saving downloading song. It doesn't work outside of curl from the command line. The response body is empty, I'll look into it --- src/controller/songController.hpp | 41 ++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index b293d25..ae02bc7 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -132,12 +133,39 @@ public: songDb.id = id; songDb = songRepo.retrieveRecord(songDb, songFilter::id); + std::cout << "song path " << songDb.songPath << std::endl; + + std::ifstream fl(songDb.songPath.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + + //auto rawSong = oatpp::String((v_int32) fl.tellg()); + fl.seekg(0); + //fl.read((char*)rawSong->getData(), rawSong->getSize()); + + std::stringstream buf; + std::copy(std::istreambuf_iterator(fl), + std::istreambuf_iterator(), + std::ostreambuf_iterator(buf) + ); + fl.close(); + + //std::cout << buf.str().c_str() << std::endl; + + //auto raw = buf.str(); + + auto rawSong = std::make_shared(oatpp::String(buf.str().data(), (v_int32)buf.str().size(), true)); + //std::cout << rawSong->c_str() << std::endl; + //std::cout << rawSong->std_str() << std::endl; + //std::shared_ptr rawSong = std::make_shared(); + //rawSong->loadFromFile(songDb.songPath.c_str()); + + /** std::cout << "constructing FileInputStream" << std::endl; oatpp::data::stream::FileInputStream file(songDb.songPath.c_str()); //oatpp::data::stream::FileOutputStream file(songDb.songPath.c_str()); auto songPath = fs::path(songDb.songPath); auto songSize = fs::file_size(songPath); std::cout << "prepping data" << std::endl; + std::cout << "byte size " << songSize << std::endl; auto data = new char[songSize]; std::cout << "data will be loaded" << std::endl; auto byteCount = file.read(&data, songSize); @@ -151,8 +179,19 @@ public: delete[] data; std::cout << "sending file" << std::endl; + */ + /** + auto songData = oatpp::data::stream::ChunkedBuffer::createShared(); + songData->write(buf.str().data(), buf.str().size()); - return createResponse(Status::CODE_200, songData); + //auto response = createResponse(Status::CODE_200, songData); + */ + auto response = createResponse(Status::CODE_200, *rawSong); + response->putHeader("Accept-Ranges", "bytes"); + response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE); + response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); + + return response; } #include OATPP_CODEGEN_END(ApiController) From ed6f98eb5a7f647db3115c2bf9c67379eeafe6cf Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 26 Aug 2019 23:10:24 -0400 Subject: [PATCH 22/36] Added song delete endpoint --- include/database/coverArtRepository.h | 1 + include/database/songRepository.h | 1 + include/managers/song_manager.h | 1 + src/controller/songController.hpp | 11 +++++++++++ src/database/coverArtRepository.cpp | 9 +++++++++ src/database/songRepository.cpp | 14 +++++++++++++- src/managers/song_manager.cpp | 23 +++++++++++++++++++++++ 7 files changed, 59 insertions(+), 1 deletion(-) diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h index dd5ad11..adc91eb 100644 --- a/include/database/coverArtRepository.h +++ b/include/database/coverArtRepository.h @@ -14,6 +14,7 @@ public: Cover retrieveRecord(Cover&, coverFilter); + void deleteRecord(const Cover&); void saveRecord(const Cover&); private: Cover parseRecord(MYSQL_RES*); diff --git a/include/database/songRepository.h b/include/database/songRepository.h index 9ce5388..f0747cd 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -19,6 +19,7 @@ public: Song retrieveRecord(Song&, songFilter); + void deleteRecord(const Song&); void saveRecord(const Song&); private: std::vector parseRecords(MYSQL_RES*); diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index ed3daca..7e7a76e 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -14,6 +14,7 @@ public: song_manager(std::string&); void saveSong(Song&); + void deleteSong(Song&); static void printSong(const Song&); private: diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index ae02bc7..18e4efa 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -194,6 +194,17 @@ public: return response; } + ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { + + Song song; + song.id = id; + + song_manager sngMgr(exe_path); + sngMgr.deleteSong(song); + + return createResponse(Status::CODE_200, "OK"); + } + #include OATPP_CODEGEN_END(ApiController) private: std::string exe_path; diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index 660e0c5..d2d8455 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -45,6 +45,15 @@ Cover coverArtRepository::retrieveRecord(Cover& cov, coverFilter filter = coverF return covDb; } +void coverArtRepository::deleteRecord(const Cover& cov) +{ + auto conn = setup_mysql_connection(); + const std::string query("DELETE FROM CoverArt WHERE CoverArtId = " + std::to_string(cov.id)); + + auto result = perform_mysql_query(conn, query); + + mysql_close(conn); +} void coverArtRepository::saveRecord(const Cover& cov) { diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 0c09e01..3b569cf 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -57,6 +57,18 @@ Song songRepository::retrieveRecord(Song& song, songFilter filter) return song; } +void songRepository::deleteRecord(const Song& song) +{ + auto conn = setup_mysql_connection(); + auto status = 0; + + const std::string query("DELETE FROM Song WHERE SongId = " + std::to_string(song.id)); + + auto result = perform_mysql_query(conn, query); + + mysql_close(conn); +} + void songRepository::saveRecord(const Song& song) { auto conn = setup_mysql_connection(); @@ -64,7 +76,7 @@ void songRepository::saveRecord(const Song& song) MYSQL_STMT *stmt = mysql_stmt_init(conn); - std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; + std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; query.append("Year, Duration, SongPath, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index 04f08b9..5ef9391 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -6,6 +6,7 @@ #include +#include "database/coverArtRepository.h" #include "database/songRepository.h" #include "managers/coverArtManager.h" #include "managers/directory_manager.h" @@ -53,6 +54,28 @@ void song_manager::saveSong(Song& song) songRepo.saveRecord(song); } +void song_manager::deleteSong(Song& song) +{ + coverArtRepository covRepo(exe_path); + songRepository songRepo(exe_path); + + song = songRepo.retrieveRecord(song, songFilter::id); + songRepo.deleteRecord(song); + + Cover cov; + cov.id = song.coverArtId; + cov = covRepo.retrieveRecord(cov, coverFilter::id); + covRepo.deleteRecord(cov); + + + // TODO: only delete coverArt that is not the stock cover + // path + fs::remove(cov.imagePath); + fs::remove(song.songPath); + + // TODO: delete empty directories +} + void song_manager::printSong(const Song& song) { std::cout << std::endl << "song" << std::endl; From d0d10080444fa86281fb22c1b5bc6ad0c08658c4 Mon Sep 17 00:00:00 2001 From: amazing-username Date: Tue, 27 Aug 2019 20:13:18 +0000 Subject: [PATCH 23/36] Fixed bug that caused a failure in retrieving records. Empty directories are deleted when deleting a song. If the song contains the stock cover art, the stock cover art will not be deleted --- src/database/songRepository.cpp | 2 ++ src/managers/song_manager.cpp | 14 ++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 3b569cf..28f9578 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -174,6 +174,7 @@ std::vector songRepository::parseRecords(MYSQL_RES* results) break; case 7: song.songPath = row[i]; + break; case 8: song.coverArtId = std::stoi(row[i]); break; @@ -221,6 +222,7 @@ Song songRepository::parseRecord(MYSQL_RES* results) break; case 8: song.coverArtId = std::stoi(row[i]); + break; } } std::cout << "done parsing record" << std::endl; diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index 5ef9391..1212e9d 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -67,13 +67,19 @@ void song_manager::deleteSong(Song& song) cov = covRepo.retrieveRecord(cov, coverFilter::id); covRepo.deleteRecord(cov); + auto paths = directory_manager::pathConfigContent(exe_path); + const auto coverArtPath = paths["cover_root_path"].get(); + std::string stockCoverArtPath = coverArtPath; + stockCoverArtPath.append("CoverArt.png"); - // TODO: only delete coverArt that is not the stock cover - // path - fs::remove(cov.imagePath); + if (stockCoverArtPath.compare(cov.imagePath) != 0) { + fs::remove(cov.imagePath); + std::cout << "deleting cover art" << std::endl; + } fs::remove(song.songPath); - // TODO: delete empty directories + directory_manager::delete_directories(song, paths["root_music_path"].get()); + directory_manager::delete_directories(song, coverArtPath); } void song_manager::printSong(const Song& song) From b885e3d2c8112aa32d16eb43c44af728c02b42dd Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Tue, 27 Aug 2019 20:33:00 -0400 Subject: [PATCH 24/36] Ok --- include/managers/directory_manager.h | 2 +- src/controller/songController.hpp | 70 +++++----------------------- src/managers/token_manager.cpp | 9 ---- 3 files changed, 13 insertions(+), 68 deletions(-) diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h index 283ac10..e994d6c 100644 --- a/include/managers/directory_manager.h +++ b/include/managers/directory_manager.h @@ -26,7 +26,7 @@ public: //void copy_stock_to_root(const std::string&, const std::string&); //void copy_song_to_path(const std::string&, const std::string&); void delete_cover_art_file(const std::string&, const std::string&); - void delete_directories(Song, const std::string&); + static void delete_directories(Song, const std::string&); private: void delete_song(const Song); diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 18e4efa..eb4018a 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -31,7 +31,7 @@ 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), exe_path(p) + : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) { } #include OATPP_CODEGEN_BEGIN(ApiController) @@ -53,7 +53,7 @@ public: oatpp::web::mime::multipart::Reader mp_reader(mp.get()); - mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(dataSize)); + mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize)); request->transferBody(&mp_reader); @@ -61,16 +61,15 @@ public: OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); - auto stream = file->getInputStream(); auto buff = std::unique_ptr(new char[file->getKnownSize()]); - auto buffSize = stream->read(buff.get(), file->getKnownSize()); + auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize()); std::vector data(buff.get(), buff.get() + buffSize); Song sng; sng.data = std::move(data); - song_manager s_mgr(exe_path); + song_manager s_mgr(m_exe_path); s_mgr.saveSong(sng); return createResponse(Status::CODE_200, "OK"); @@ -81,7 +80,7 @@ public: REQUEST(std::shared_ptr, request)) { std::cout << "starting process of retrieving songs" << std::endl; - songRepository songRepo(exe_path); + songRepository songRepo(m_exe_path); auto songsDb = songRepo.retrieveRecords(); auto songs = oatpp::data::mapping::type::List::createShared(); @@ -106,7 +105,7 @@ public: ENDPOINT("GET", "/api/v1/song/{id}", songRecord, PATH(Int32, id)) { - songRepository songRepo(exe_path); + songRepository songRepo(m_exe_path); Song songDb; songDb.id = id; @@ -124,71 +123,26 @@ public: return createDtoResponse(Status::CODE_200, song); } - // TODO: left off here ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, PATH(Int32, id)) { - songRepository songRepo(exe_path); + songRepository songRepo(m_exe_path); Song songDb; songDb.id = id; songDb = songRepo.retrieveRecord(songDb, songFilter::id); - std::cout << "song path " << songDb.songPath << std::endl; - std::ifstream fl(songDb.songPath.c_str(), std::ios::in | std::ios::binary | std::ios::ate); - - //auto rawSong = oatpp::String((v_int32) fl.tellg()); fl.seekg(0); - //fl.read((char*)rawSong->getData(), rawSong->getSize()); std::stringstream buf; std::copy(std::istreambuf_iterator(fl), std::istreambuf_iterator(), - std::ostreambuf_iterator(buf) - ); + std::ostreambuf_iterator(buf)); fl.close(); - //std::cout << buf.str().c_str() << std::endl; - - //auto raw = buf.str(); - auto rawSong = std::make_shared(oatpp::String(buf.str().data(), (v_int32)buf.str().size(), true)); - //std::cout << rawSong->c_str() << std::endl; - //std::cout << rawSong->std_str() << std::endl; - //std::shared_ptr rawSong = std::make_shared(); - //rawSong->loadFromFile(songDb.songPath.c_str()); - - /** - std::cout << "constructing FileInputStream" << std::endl; - oatpp::data::stream::FileInputStream file(songDb.songPath.c_str()); - //oatpp::data::stream::FileOutputStream file(songDb.songPath.c_str()); - auto songPath = fs::path(songDb.songPath); - auto songSize = fs::file_size(songPath); - std::cout << "prepping data" << std::endl; - std::cout << "byte size " << songSize << std::endl; - auto data = new char[songSize]; - std::cout << "data will be loaded" << std::endl; - auto byteCount = file.read(&data, songSize); - //auto byteCount = file.write(&data, songSize); - - std::cout << byteCount << " bytes read" << std::endl; - - auto songData = oatpp::data::stream::ChunkedBuffer::createShared(); - songData->write(data, byteCount); - - delete[] data; - - std::cout << "sending file" << std::endl; - */ - /** - auto songData = oatpp::data::stream::ChunkedBuffer::createShared(); - songData->write(buf.str().data(), buf.str().size()); - - //auto response = createResponse(Status::CODE_200, songData); - */ + auto response = createResponse(Status::CODE_200, *rawSong); - response->putHeader("Accept-Ranges", "bytes"); - response->putHeader(Header::CONNECTION, Header::Value::CONNECTION_KEEP_ALIVE); response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); return response; @@ -199,7 +153,7 @@ public: Song song; song.id = id; - song_manager sngMgr(exe_path); + song_manager sngMgr(m_exe_path); sngMgr.deleteSong(song); return createResponse(Status::CODE_200, "OK"); @@ -207,8 +161,8 @@ public: #include OATPP_CODEGEN_END(ApiController) private: - std::string exe_path; - const long dataSize = std::numeric_limits::max(); + std::string m_exe_path; + const long m_dataSize = std::numeric_limits::max(); }; #endif diff --git a/src/managers/token_manager.cpp b/src/managers/token_manager.cpp index 24ef2ef..6467aa4 100644 --- a/src/managers/token_manager.cpp +++ b/src/managers/token_manager.cpp @@ -92,15 +92,6 @@ auth_credentials token_manager::parse_auth_credentials(std::string_view path) auto exe_path = directory_manager::configPath(path); exe_path.append("/authcredentials.json"); - //auto content = directory_manager::contentOfPath(exe_path); - /** - std::fstream a(exe_path, std::ios::in); - std::stringstream s; - s << a.rdbuf(); - a.close(); - */ - - //auto con = nlohmann::json::parse(directory_manager::contentOfPath(exe_path)); auto con = directory_manager::credentialConfigContent(exe_path); auth_credentials auth; From 1255aa0ff752abd902a99c38bc5f1a90d014ae8c Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 28 Aug 2019 22:16:33 -0400 Subject: [PATCH 25/36] track and disc numbers are now part of the song's metadata and saved to the database --- Scripts/MySQL/create_database.sql | 2 + include/models.h | 77 ---------------------------- include/models/models.h | 2 + src/controller/songController.hpp | 8 +++ src/database/songRepository.cpp | 40 +++++++++++---- src/dto/songDto.hpp | 2 + src/loginHandler.hpp | 28 ---------- src/main.cpp | 44 +--------------- src/managers/song_manager.cpp | 7 +-- src/utilities/metadata_retriever.cpp | 18 +++++++ 10 files changed, 68 insertions(+), 160 deletions(-) delete mode 100644 include/models.h delete mode 100644 src/loginHandler.hpp diff --git a/Scripts/MySQL/create_database.sql b/Scripts/MySQL/create_database.sql index d1149cb..7e0d410 100644 --- a/Scripts/MySQL/create_database.sql +++ b/Scripts/MySQL/create_database.sql @@ -18,6 +18,8 @@ CREATE TABLE Song ( Genre TEXT NOT NULL, Year INT NOT NULL, Duration INT NOT NULL, + Track INT NOT NULL, + Disc INT NOT NULL, SongPath TEXT NOT NULL, CoverArtId INT NOT NULL, diff --git a/include/models.h b/include/models.h deleted file mode 100644 index 3c40b64..0000000 --- a/include/models.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef MODELS_H_ -#define MODELS_H_ - -#include -#include - -struct Song -{ - int id; - std::string title; - std::string artist; - std::string album; - std::string genre; - int year; - int duration; - std::string songPath; - std::vector data; -}; - -struct Cover -{ - int id; - std::string songTitle; - std::string imagePath; - // Currently not being used but it should - std::vector data; -}; - -struct LoginRes -{ - int UserId; - char Username[1024]; - char Token[1024]; - char TokenType[1024]; - char Message[1024]; - int Expiration; -}; - -struct loginResult -{ - int user_id; - std::string username; - std::string access_token; - std::string token_type; - std::string message; - int expiration; -}; - -struct auth_credentials -{ - std::string domain; - std::string api_identifier; - std::string client_id; - std::string client_secret; - std::string uri; - std::string endpoint; -}; - -struct database_connection -{ - std::string server; - std::string username; - std::string password; - std::string database; -}; - -struct TokenReq -{ - char ClientId[1024]; - char ClientSecret[1024]; - char Audience[1024]; - char GrantType[1024]; - char URI[1024]; - char Endpoint[1024]; -}; - -#endif diff --git a/include/models/models.h b/include/models/models.h index b619b5b..3a045c0 100644 --- a/include/models/models.h +++ b/include/models/models.h @@ -13,6 +13,8 @@ struct Song std::string genre; int year; int duration; + int track; + int disc; std::string songPath; std::vector data; int coverArtId; diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index eb4018a..4e5c43d 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -94,6 +94,8 @@ public: 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); } @@ -119,6 +121,8 @@ public: 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); } @@ -148,6 +152,8 @@ public: return response; } + // TODO: create endpoint for updating songs + ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { Song song; @@ -159,6 +165,8 @@ public: return createResponse(Status::CODE_200, "OK"); } + // TODO: create endpoint for streaming songs + #include OATPP_CODEGEN_END(ApiController) private: std::string m_exe_path; diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 28f9578..593f5ca 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -77,11 +77,11 @@ void songRepository::saveRecord(const Song& song) MYSQL_STMT *stmt = mysql_stmt_init(conn); std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; - query.append("Year, Duration, SongPath, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?, ?)"); + query.append("Year, Duration, Track, Disc, SongPath, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - MYSQL_BIND params[8]; + MYSQL_BIND params[10]; memset(params, 0, sizeof(params)); params[0].buffer_type = MYSQL_TYPE_STRING; @@ -118,16 +118,26 @@ void songRepository::saveRecord(const Song& song) params[5].length = 0; params[5].is_null = 0; - params[6].buffer_type = MYSQL_TYPE_STRING; - params[6].buffer = (char*)song.songPath.c_str(); - auto pathLength = song.songPath.size(); - params[6].length = &pathLength; + params[6].buffer_type = MYSQL_TYPE_LONG; + params[6].buffer = (char*)&song.track; + params[6].length = 0; params[6].is_null = 0; params[7].buffer_type = MYSQL_TYPE_LONG; - params[7].buffer = (char*)&song.coverArtId; + params[7].buffer = (char*)&song.disc; params[7].length = 0; params[7].is_null = 0; + + params[8].buffer_type = MYSQL_TYPE_STRING; + params[8].buffer = (char*)song.songPath.c_str(); + auto pathLength = song.songPath.size(); + params[8].length = &pathLength; + params[8].is_null = 0; + + params[9].buffer_type = MYSQL_TYPE_LONG; + params[9].buffer = (char*)&song.coverArtId; + params[9].length = 0; + params[9].is_null = 0; status = mysql_stmt_bind_param(stmt, params); status = mysql_stmt_execute(stmt); @@ -173,9 +183,15 @@ std::vector songRepository::parseRecords(MYSQL_RES* results) song.duration = std::stoi(row[i]); break; case 7: - song.songPath = row[i]; + song.track = std::stoi(row[i]); break; case 8: + song.disc = std::stoi(row[i]); + break; + case 9: + song.songPath = row[i]; + break; + case 10: song.coverArtId = std::stoi(row[i]); break; } @@ -218,9 +234,15 @@ Song songRepository::parseRecord(MYSQL_RES* results) song.duration = std::stoi(row[i]); break; case 7: - song.songPath = row[i]; + song.track = std::stoi(row[i]); break; case 8: + song.disc = std::stoi(row[i]); + break; + case 9: + song.songPath = row[i]; + break; + case 10: song.coverArtId = std::stoi(row[i]); break; } diff --git a/src/dto/songDto.hpp b/src/dto/songDto.hpp index 13723d1..cc13c11 100644 --- a/src/dto/songDto.hpp +++ b/src/dto/songDto.hpp @@ -15,6 +15,8 @@ class songDto : public oatpp::data::mapping::type::Object DTO_FIELD(String, artist); DTO_FIELD(String, album); DTO_FIELD(String, genre); + DTO_FIELD(Int32, track); + DTO_FIELD(Int32, disc); DTO_FIELD(Int32, year); DTO_FIELD(Int32, duration); }; diff --git a/src/loginHandler.hpp b/src/loginHandler.hpp deleted file mode 100644 index e131660..0000000 --- a/src/loginHandler.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef LOGINHANDLER_H_ -#define LOGINHANDLER_H_ - -#include - -#include "oatpp/network/server/Server.hpp" -#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" -#include "oatpp/web/server/HttpConnectionHandler.hpp" - -#include "dto/loginResultDto.hpp" - -class loginHandler : public oatpp::web::server::HttpRequestHandler -{ -public: - - std::shared_ptr handle(const std::shared_ptr& request) override - { - auto logRes = loginResultDto::createShared(); - logRes->access_token = "hahahahahahaha"; - logRes->token_type = "Fly"; - - return ResponseFactory::createResponse(Status::CODE_200, "ddd"); - } -private: - OATPP_COMPONENT(std::shared_ptr, m_objectMapper); -}; - -#endif diff --git a/src/main.cpp b/src/main.cpp index 0551452..d395bb6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,52 +39,10 @@ void run(const std::string& working_path) server.run(); } -void test_database() -{ - database_connection mysqlD; - mysqlD.server = ""; // where the mysql database is - mysqlD.username = ""; // the root user of mysql - mysqlD.password = ""; // the password of the root user in mysql - mysqlD.database = ""; // the databse to pick - - base_repository base; - /** - auto conn = base.setup_mysql_connection(mysqlD); - - // assign the results return to the MYSQL_RES pointer - const std::string query = "SELECT *, NULL FROM Song"; - auto res = base.perform_mysql_query(conn, query); - auto num_of_fields = mysql_num_fields(res); - - printf("MySQL Tables in mysql database:\n"); - auto row_count = 1; - - for (MYSQL_ROW row = NULL; (row = mysql_fetch_row(res)) != NULL;) { - std::cout << " row " << row_count << std::endl; - for (auto i = 0; i != num_of_fields; ++i) { - auto val = row[i]; - - if ( val == NULL) { - std::cout << "found null value " << std::endl; - continue; - } - std::cout << val << " "; - } - std::cout << std::endl; - } - - // clean up the database result set // - mysql_free_result(res); - // clean up the database link // - mysql_close(conn); - */ -} - - int main(int argc, char **argv) { oatpp::base::Environment::init(); - std::string working_path = argv[0]; + const std::string working_path = argv[0]; run(working_path); diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index 1212e9d..f7be9f0 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -41,8 +41,7 @@ void song_manager::saveSong(Song& song) auto songPath = directory_manager::create_directory_process(song, musicRootPath); songPath.append(song.title); songPath.append(".mp3"); - std::cout << std::endl; - std::cout << "temp path: " << song.songPath << std::endl; + std::cout << "\n\ntemp path: " << song.songPath << std::endl; std::cout << "new path: " << songPath << std::endl; fs::copy(song.songPath, songPath); fs::remove(song.songPath); @@ -84,13 +83,15 @@ void song_manager::deleteSong(Song& song) void song_manager::printSong(const Song& song) { - std::cout << std::endl << "song" << std::endl; + std::cout << "\n\nsong" << std::endl; std::cout << "title: " << song.title << std::endl; std::cout << "artist: " << song.artist << std::endl; std::cout << "album: " << song.album << std::endl; std::cout << "genre: " << song.genre << std::endl; std::cout << "duration: " << song.duration << std::endl; std::cout << "year: " << song.year << std::endl; + std::cout << "track: " << song.track << std::endl; + std::cout << "disc: " << song.disc << std::endl; std::cout << "song path: " << song.songPath << std::endl; if (song.coverArtId != 0) { std::cout << "cover art id: " << song.coverArtId << std::endl; diff --git a/src/utilities/metadata_retriever.cpp b/src/utilities/metadata_retriever.cpp index 2b51e01..ee675af 100644 --- a/src/utilities/metadata_retriever.cpp +++ b/src/utilities/metadata_retriever.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -25,9 +26,24 @@ Song metadata_retriever::retrieve_metadata(std::string& song_path) song.album = file.tag()->album().toCString(); song.genre = file.tag()->genre().toCString(); song.year = file.tag()->year(); + song.track = file.tag()->track(); song.duration = file.audioProperties()->lengthInSeconds(); song.songPath = song_path; + // TODO: Move over to this eventually since at the moment + // I am only targetting mp3 files + // Used to retrieve disc + TagLib::MPEG::File sameFile(song_path.c_str()); + auto tag = sameFile.ID3v2Tag(); + + auto frame = tag->frameList("TPOS"); + if (frame.isEmpty()) { + song.disc = 1; + // TODO: set default disc to 1 if none found + } else { + song.disc = std::stoi(frame.front()->toString().toCString()); + } + return song; } @@ -99,5 +115,7 @@ void metadata_retriever::update_metadata(Song sng_updated, const Song sng_old) file.tag()->setYear(sng_updated.year); } + // TODO: functionality to update the track number and disc number + file.save(); } From d44a5bb1bcbc748763d8a3f8c25ea24733913c69 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 1 Sep 2019 13:54:16 -0400 Subject: [PATCH 26/36] Added Model namespace --- include/database/base_repository.h | 4 +- include/database/coverArtRepository.h | 8 +- include/database/songRepository.h | 12 +-- include/managers/coverArtManager.h | 2 +- include/managers/directory_manager.h | 11 +-- include/managers/song_manager.h | 8 +- include/managers/token_manager.h | 6 +- include/models/models.h | 131 +++++++++++++------------ include/utilities/imageFile.h | 24 ----- include/utilities/metadata_retriever.h | 6 +- src/controller/songController.hpp | 8 +- src/database/base_repository.cpp | 2 +- src/database/coverArtRepository.cpp | 10 +- src/database/songRepository.cpp | 18 ++-- src/managers/coverArtManager.cpp | 4 +- src/managers/directory_manager.cpp | 52 +--------- src/managers/song_manager.cpp | 10 +- src/managers/token_manager.cpp | 12 +-- src/utilities/metadata_retriever.cpp | 8 +- 19 files changed, 131 insertions(+), 205 deletions(-) diff --git a/include/database/base_repository.h b/include/database/base_repository.h index d2f6269..dcc3527 100644 --- a/include/database/base_repository.h +++ b/include/database/base_repository.h @@ -14,11 +14,11 @@ public: base_repository(const std::string&); protected: MYSQL* setup_mysql_connection(); - MYSQL* setup_mysql_connection(database_connection); + MYSQL* setup_mysql_connection(Model::database_connection); MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&); - database_connection details; + Model::database_connection details; private: void intitalizeDetails(); diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h index adc91eb..2add698 100644 --- a/include/database/coverArtRepository.h +++ b/include/database/coverArtRepository.h @@ -12,12 +12,12 @@ class coverArtRepository : public base_repository public: coverArtRepository(const std::string&); - Cover retrieveRecord(Cover&, coverFilter); + Model::Cover retrieveRecord(Model::Cover&, coverFilter); - void deleteRecord(const Cover&); - void saveRecord(const Cover&); + void deleteRecord(const Model::Cover&); + void saveRecord(const Model::Cover&); private: - Cover parseRecord(MYSQL_RES*); + Model::Cover parseRecord(MYSQL_RES*); }; #endif diff --git a/include/database/songRepository.h b/include/database/songRepository.h index f0747cd..ee4ea10 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -15,16 +15,16 @@ class songRepository : public base_repository public: songRepository(const std::string&); - std::vector retrieveRecords(); + std::vector retrieveRecords(); - Song retrieveRecord(Song&, songFilter); + Model::Song retrieveRecord(Model::Song&, songFilter); - void deleteRecord(const Song&); - void saveRecord(const Song&); + void deleteRecord(const Model::Song&); + void saveRecord(const Model::Song&); private: - std::vector parseRecords(MYSQL_RES*); + std::vector parseRecords(MYSQL_RES*); - Song parseRecord(MYSQL_RES*); + Model::Song parseRecord(MYSQL_RES*); }; #endif diff --git a/include/managers/coverArtManager.h b/include/managers/coverArtManager.h index 9e5479a..58c4cec 100644 --- a/include/managers/coverArtManager.h +++ b/include/managers/coverArtManager.h @@ -10,7 +10,7 @@ class coverArtManager public: coverArtManager(const std::string&); - Cover saveCover(const Song&, std::string&, const std::string&); + Model::Cover saveCover(const Model::Song&, std::string&, const std::string&); private: std::string path; }; diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h index e994d6c..af3ca37 100644 --- a/include/managers/directory_manager.h +++ b/include/managers/directory_manager.h @@ -12,24 +12,19 @@ class directory_manager { public: - static std::string create_directory_process(Song, const std::string&); + static std::string create_directory_process(Model::Song, const std::string&); static std::string configPath(std::string_view); static std::string contentOfPath(std::string_view); static nlohmann::json credentialConfigContent(const std::string&); static nlohmann::json databaseConfigContent(const std::string&); static nlohmann::json pathConfigContent(const std::string&); - // Return Cover instead - //std::string read_cover_art(const std::string&); - - //void copy_stock_to_root(const std::string&, const std::string&); - //void copy_song_to_path(const std::string&, const std::string&); void delete_cover_art_file(const std::string&, const std::string&); - static void delete_directories(Song, const std::string&); + static void delete_directories(Model::Song, const std::string&); private: - void delete_song(const Song); + void delete_song(const Model::Song); }; #endif diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index 7e7a76e..e12a87c 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -13,12 +13,12 @@ class song_manager public: song_manager(std::string&); - void saveSong(Song&); - void deleteSong(Song&); + void saveSong(Model::Song&); + void deleteSong(Model::Song&); - static void printSong(const Song&); + static void printSong(const Model::Song&); private: - void saveSongTemp(Song&); + void saveSongTemp(Model::Song&); std::string exe_path; }; diff --git a/include/managers/token_manager.h b/include/managers/token_manager.h index f8bcbec..eafc9a5 100644 --- a/include/managers/token_manager.h +++ b/include/managers/token_manager.h @@ -16,12 +16,12 @@ class token_manager public: token_manager(); - loginResult retrieve_token(); - loginResult retrieve_token(std::string_view); + Model::loginResult retrieve_token(); + Model::loginResult retrieve_token(std::string_view); bool is_token_valid(std::string&, Scope); private: - auth_credentials parse_auth_credentials(std::string_view); + Model::auth_credentials parse_auth_credentials(std::string_view); std::vector extract_scopes(const jwt::decoded_jwt&&); std::pair> fetch_auth_header(const std::string&); diff --git a/include/models/models.h b/include/models/models.h index 3a045c0..b755ed5 100644 --- a/include/models/models.h +++ b/include/models/models.h @@ -4,77 +4,78 @@ #include #include -struct Song +namespace Model { - int id; - std::string title; - std::string artist; - std::string album; - std::string genre; - int year; - int duration; - int track; - int disc; - std::string songPath; - std::vector data; - int coverArtId; -}; + struct Song + { + int id; + std::string title; + std::string artist; + std::string album; + std::string genre; + int year; + int duration; + int track; + int disc; + std::string songPath; + std::vector data; + int coverArtId; + }; -struct Cover -{ - int id; - std::string songTitle; - std::string imagePath; - // Not being used but it should be - std::vector data; -}; + struct Album + { + int id; + std::string title; + int year; + std::vector songs; + }; -struct LoginRes -{ - int UserId; - char Username[1024]; - char Token[1024]; - char TokenType[1024]; - char Message[1024]; - int Expiration; -}; + struct Cover + { + int id; + std::string songTitle; + std::string imagePath; + // Not being used but it should be + std::vector data; + }; -struct loginResult -{ - int user_id; - std::string username; - std::string access_token; - std::string token_type; - std::string message; - int expiration; -}; + struct LoginRes + { + int UserId; + char Username[1024]; + char Token[1024]; + char TokenType[1024]; + char Message[1024]; + int Expiration; + }; -struct auth_credentials -{ - std::string domain; - std::string api_identifier; - std::string client_id; - std::string client_secret; - std::string uri; - std::string endpoint; -}; + struct loginResult + { + int user_id; + std::string username; + std::string access_token; + std::string token_type; + std::string message; + int expiration; + }; -struct database_connection -{ - std::string server; - std::string username; - std::string password; - std::string database; -}; + struct auth_credentials + { + std::string domain; + std::string api_identifier; + std::string client_id; + std::string client_secret; + std::string uri; + std::string endpoint; + }; -struct TokenReq -{ - char ClientId[1024]; - char ClientSecret[1024]; - char Audience[1024]; - char GrantType[1024]; - char URI[1024]; - char Endpoint[1024]; -}; + struct database_connection + { + std::string server; + std::string username; + std::string password; + std::string database; + }; +} #endif diff --git a/include/utilities/imageFile.h b/include/utilities/imageFile.h index d6d5e86..9e95cdd 100644 --- a/include/utilities/imageFile.h +++ b/include/utilities/imageFile.h @@ -1,45 +1,21 @@ #include -//#include #include -//#include -//#include -//#include #include -//#include #include -//#include #include -//#include #include -//#include #include -//#include #include -//#include #include -//#include #include class imageFile : public TagLib::File { public: imageFile(const char *file); - /** - imageFile(const char *file) : TagLib::File(file) - { - - } - */ TagLib::ByteVector data(); - /** - TagLib::ByteVector data() - { - return readBlock(length()); - } - */ - private: virtual TagLib::Tag *tag() const { return 0; } diff --git a/include/utilities/metadata_retriever.h b/include/utilities/metadata_retriever.h index 3a3760b..4801216 100644 --- a/include/utilities/metadata_retriever.h +++ b/include/utilities/metadata_retriever.h @@ -9,10 +9,10 @@ class metadata_retriever { public: - Song retrieve_metadata(std::string&); - Cover update_cover_art(const Song&, Cover& cov, const std::string&); + Model::Song retrieve_metadata(std::string&); + Model::Cover update_cover_art(const Model::Song&, Model::Cover& cov, const std::string&); - void update_metadata(Song updated_song, const Song old_song); + void update_metadata(Model::Song updated_song, const Model::Song old_song); private: }; diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 4e5c43d..6c203a5 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -66,7 +66,7 @@ public: std::vector data(buff.get(), buff.get() + buffSize); - Song sng; + Model::Song sng; sng.data = std::move(data); song_manager s_mgr(m_exe_path); @@ -108,7 +108,7 @@ public: PATH(Int32, id)) { songRepository songRepo(m_exe_path); - Song songDb; + Model::Song songDb; songDb.id = id; songDb = songRepo.retrieveRecord(songDb, songFilter::id); @@ -131,7 +131,7 @@ public: PATH(Int32, id)) { songRepository songRepo(m_exe_path); - Song songDb; + Model::Song songDb; songDb.id = id; songDb = songRepo.retrieveRecord(songDb, songFilter::id); @@ -156,7 +156,7 @@ public: ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { - Song song; + Model::Song song; song.id = id; song_manager sngMgr(m_exe_path); diff --git a/src/database/base_repository.cpp b/src/database/base_repository.cpp index c55b91f..c405461 100644 --- a/src/database/base_repository.cpp +++ b/src/database/base_repository.cpp @@ -25,7 +25,7 @@ MYSQL* base_repository::setup_mysql_connection() return conn; } -MYSQL* base_repository::setup_mysql_connection(database_connection details) +MYSQL* base_repository::setup_mysql_connection(Model::database_connection details) { MYSQL *connection = mysql_init(NULL); diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index d2d8455..0e3b20a 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -8,7 +8,7 @@ coverArtRepository::coverArtRepository(const std::string& path) : base_repository(path) { } -Cover coverArtRepository::retrieveRecord(Cover& cov, coverFilter filter = coverFilter::id) +Model::Cover coverArtRepository::retrieveRecord(Model::Cover& cov, coverFilter filter = coverFilter::id) { std::stringstream qry; auto conn = setup_mysql_connection(); @@ -45,7 +45,7 @@ Cover coverArtRepository::retrieveRecord(Cover& cov, coverFilter filter = coverF return covDb; } -void coverArtRepository::deleteRecord(const Cover& cov) +void coverArtRepository::deleteRecord(const Model::Cover& cov) { auto conn = setup_mysql_connection(); const std::string query("DELETE FROM CoverArt WHERE CoverArtId = " + std::to_string(cov.id)); @@ -55,7 +55,7 @@ void coverArtRepository::deleteRecord(const Cover& cov) mysql_close(conn); } -void coverArtRepository::saveRecord(const Cover& cov) +void coverArtRepository::saveRecord(const Model::Cover& cov) { auto conn = setup_mysql_connection(); @@ -93,10 +93,10 @@ void coverArtRepository::saveRecord(const Cover& cov) std::cout << "done" << std::endl; } -Cover coverArtRepository::parseRecord(MYSQL_RES *results) +Model::Cover coverArtRepository::parseRecord(MYSQL_RES *results) { std::cout << "parsing record" << std::endl; - Cover cov; + Model::Cover cov; auto fieldNum = mysql_num_fields(results); MYSQL_ROW row = mysql_fetch_row(results); diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 593f5ca..86c5f0c 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -10,7 +10,7 @@ songRepository::songRepository(const std::string& path) : base_repository(path) { } -std::vector songRepository::retrieveRecords() +std::vector songRepository::retrieveRecords() { auto conn = setup_mysql_connection(); const std::string query = "SELECT * FROM Song"; @@ -24,7 +24,7 @@ std::vector songRepository::retrieveRecords() return songs; } -Song songRepository::retrieveRecord(Song& song, songFilter filter) +Model::Song songRepository::retrieveRecord(Model::Song& song, songFilter filter) { std::stringstream qry; auto conn = setup_mysql_connection(); @@ -57,7 +57,7 @@ Song songRepository::retrieveRecord(Song& song, songFilter filter) return song; } -void songRepository::deleteRecord(const Song& song) +void songRepository::deleteRecord(const Model::Song& song) { auto conn = setup_mysql_connection(); auto status = 0; @@ -69,7 +69,7 @@ void songRepository::deleteRecord(const Song& song) mysql_close(conn); } -void songRepository::saveRecord(const Song& song) +void songRepository::saveRecord(const Model::Song& song) { auto conn = setup_mysql_connection(); auto status = 0; @@ -148,16 +148,16 @@ void songRepository::saveRecord(const Song& song) std::cout << "done inserting song record" << std::endl; } -std::vector songRepository::parseRecords(MYSQL_RES* results) +std::vector songRepository::parseRecords(MYSQL_RES* results) { auto fieldNum = mysql_num_fields(results); auto numRows = mysql_num_rows(results); - std::vector songs; + std::vector songs; songs.reserve(numRows); for (MYSQL_ROW row = nullptr; (row = mysql_fetch_row(results)) != nullptr; ) { - Song song; + Model::Song song; for (auto i = 0; i != fieldNum; ++i) { switch (i) { @@ -203,9 +203,9 @@ std::vector songRepository::parseRecords(MYSQL_RES* results) return songs; } -Song songRepository::parseRecord(MYSQL_RES* results) +Model::Song songRepository::parseRecord(MYSQL_RES* results) { - Song song; + Model::Song song; auto fieldNum = mysql_num_fields(results); MYSQL_ROW row = mysql_fetch_row(results); diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index c2fa75d..f732b25 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -8,10 +8,10 @@ coverArtManager::coverArtManager(const std::string& configPath) : path(configPat { } -Cover coverArtManager::saveCover(const Song& song, std::string& rootPath, const std::string& stockCoverPath) +Model::Cover coverArtManager::saveCover(const Model::Song& song, std::string& rootPath, const std::string& stockCoverPath) { metadata_retriever meta; - Cover cov; + Model::Cover cov; cov.imagePath = rootPath; cov = meta.update_cover_art(song, cov, stockCoverPath); cov.songTitle = song.title; diff --git a/src/managers/directory_manager.cpp b/src/managers/directory_manager.cpp index 0c5f97c..c8b8acc 100644 --- a/src/managers/directory_manager.cpp +++ b/src/managers/directory_manager.cpp @@ -7,7 +7,7 @@ namespace fs = std::filesystem; -std::string directory_manager::create_directory_process(Song song, const std::string& root_path) +std::string directory_manager::create_directory_process(Model::Song song, const std::string& root_path) { auto curr_path = fs::path(root_path); @@ -74,52 +74,6 @@ nlohmann::json directory_manager::pathConfigContent(const std::string& exe_path) return nlohmann::json::parse(contentOfPath(path)); } -/** -std::string directory_manager::read_cover_art(const std::string& source) -{ - auto source_path = fs::path(source); - - std::fstream cov(source, std::ios::in | std::ios::binary); - - cov.seekg(0); - - std::stringstream buf; - std::copy(std::istreambuf_iterator(cov), - std::istreambuf_iterator(), - std::ostreambuf_iterator(buf)); - - return buf.str(); -} - -void directory_manager::copy_stock_to_root(const std::string& target, const std::string& buff) -{ - std::cout<<"starting process"<(); lr.token_type = post_res["token_type"].get(); lr.expiration = post_res["expires_in"].get(); @@ -87,14 +87,14 @@ bool token_manager::is_token_valid(std::string& auth, Scope scope) return false; } -auth_credentials token_manager::parse_auth_credentials(std::string_view path) +Model::auth_credentials token_manager::parse_auth_credentials(std::string_view path) { auto exe_path = directory_manager::configPath(path); exe_path.append("/authcredentials.json"); auto con = directory_manager::credentialConfigContent(exe_path); - auth_credentials auth; + Model::auth_credentials auth; auth.uri = "https://"; auth.uri.append(con["domain"]); auth.api_identifier = con["api_identifier"]; diff --git a/src/utilities/metadata_retriever.cpp b/src/utilities/metadata_retriever.cpp index ee675af..c39c532 100644 --- a/src/utilities/metadata_retriever.cpp +++ b/src/utilities/metadata_retriever.cpp @@ -17,10 +17,10 @@ namespace fs = std::filesystem; -Song metadata_retriever::retrieve_metadata(std::string& song_path) +Model::Song metadata_retriever::retrieve_metadata(std::string& song_path) { TagLib::FileRef file(song_path.c_str()); - Song song; + Model::Song song; song.title = file.tag()->title().toCString(); song.artist = file.tag()->artist().toCString(); song.album = file.tag()->album().toCString(); @@ -48,7 +48,7 @@ Song metadata_retriever::retrieve_metadata(std::string& song_path) return song; } -Cover metadata_retriever::update_cover_art(const Song& song, Cover& cov, const std::string& stockCoverPath) +Model::Cover metadata_retriever::update_cover_art(const Model::Song& song, Model::Cover& cov, const std::string& stockCoverPath) { TagLib::MPEG::File sngF(song.songPath.c_str()); auto tag = sngF.ID3v2Tag(); @@ -94,7 +94,7 @@ Cover metadata_retriever::update_cover_art(const Song& song, Cover& cov, const s return cov; } -void metadata_retriever::update_metadata(Song sng_updated, const Song sng_old) +void metadata_retriever::update_metadata(Model::Song sng_updated, const Model::Song sng_old) { std::cout<<"updating metadata"< Date: Sun, 1 Sep 2019 14:14:46 -0400 Subject: [PATCH 27/36] Added Manager namespace --- include/managers/coverArtManager.h | 17 +++++++++------- include/managers/directory_manager.h | 30 +++++++++++++++------------- include/managers/song_manager.h | 23 +++++++++++---------- include/managers/token_manager.h | 27 ++++++++++++++----------- src/controller/loginController.hpp | 2 +- src/controller/songController.hpp | 6 +++--- src/database/base_repository.cpp | 2 +- src/managers/coverArtManager.cpp | 4 ++-- src/managers/directory_manager.cpp | 18 ++++++++--------- src/managers/song_manager.cpp | 24 +++++++++++----------- src/managers/token_manager.cpp | 20 +++++++++---------- src/utilities/metadata_retriever.cpp | 4 ++-- 12 files changed, 94 insertions(+), 83 deletions(-) diff --git a/include/managers/coverArtManager.h b/include/managers/coverArtManager.h index 58c4cec..9ba399f 100644 --- a/include/managers/coverArtManager.h +++ b/include/managers/coverArtManager.h @@ -5,14 +5,17 @@ #include "models/models.h" -class coverArtManager +namespace Manager { -public: - coverArtManager(const std::string&); + class coverArtManager + { + public: + coverArtManager(const std::string&); - Model::Cover saveCover(const Model::Song&, std::string&, const std::string&); -private: - std::string path; -}; + Model::Cover saveCover(const Model::Song&, std::string&, const std::string&); + private: + std::string path; + }; +} #endif diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h index af3ca37..48a293d 100644 --- a/include/managers/directory_manager.h +++ b/include/managers/directory_manager.h @@ -8,23 +8,25 @@ #include "models/models.h" -class directory_manager +namespace Manager { -public: + class directory_manager + { + public: + static std::string create_directory_process(Model::Song, const std::string&); + static std::string configPath(std::string_view); + static std::string contentOfPath(std::string_view); - static std::string create_directory_process(Model::Song, const std::string&); - static std::string configPath(std::string_view); - static std::string contentOfPath(std::string_view); + static nlohmann::json credentialConfigContent(const std::string&); + static nlohmann::json databaseConfigContent(const std::string&); + static nlohmann::json pathConfigContent(const std::string&); - static nlohmann::json credentialConfigContent(const std::string&); - static nlohmann::json databaseConfigContent(const std::string&); - static nlohmann::json pathConfigContent(const std::string&); + void delete_cover_art_file(const std::string&, const std::string&); + static void delete_directories(Model::Song, const std::string&); - void delete_cover_art_file(const std::string&, const std::string&); - static void delete_directories(Model::Song, const std::string&); - -private: - void delete_song(const Model::Song); -}; + private: + void delete_song(const Model::Song); + }; +} #endif diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index e12a87c..1309411 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -8,19 +8,22 @@ #include "models/models.h" -class song_manager +namespace Manager { -public: - song_manager(std::string&); + class song_manager + { + public: + song_manager(std::string&); - void saveSong(Model::Song&); - void deleteSong(Model::Song&); + void saveSong(Model::Song&); + void deleteSong(Model::Song&); - static void printSong(const Model::Song&); -private: - void saveSongTemp(Model::Song&); + static void printSong(const Model::Song&); + private: + void saveSongTemp(Model::Song&); - std::string exe_path; -}; + std::string exe_path; + }; +} #endif diff --git a/include/managers/token_manager.h b/include/managers/token_manager.h index eafc9a5..e80df7b 100644 --- a/include/managers/token_manager.h +++ b/include/managers/token_manager.h @@ -11,22 +11,25 @@ #include "models/models.h" #include "types/scopes.h" -class token_manager +namespace Manager { -public: - token_manager(); + class token_manager + { + public: + token_manager(); - Model::loginResult retrieve_token(); - Model::loginResult retrieve_token(std::string_view); + Model::loginResult retrieve_token(); + Model::loginResult retrieve_token(std::string_view); - bool is_token_valid(std::string&, Scope); -private: - Model::auth_credentials parse_auth_credentials(std::string_view); + bool is_token_valid(std::string&, Scope); + private: + Model::auth_credentials parse_auth_credentials(std::string_view); - std::vector extract_scopes(const jwt::decoded_jwt&&); - std::pair> fetch_auth_header(const std::string&); + std::vector extract_scopes(const jwt::decoded_jwt&&); + std::pair> fetch_auth_header(const std::string&); - bool token_supports_scope(const std::vector, const std::string&&); -}; + bool token_supports_scope(const std::vector, const std::string&&); + }; +} #endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 35460e9..02b57b4 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -26,7 +26,7 @@ public: { OATPP_LOGI("icarus", "logging in"); - token_manager tok; + Manager::token_manager tok; auto token = tok.retrieve_token(exe_path); auto logRes = loginResultDto::createShared(); diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 6c203a5..1dbfee5 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -46,7 +46,7 @@ public: auto auth = authHeader->std_str(); - token_manager tok; + Manager::token_manager tok; OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Scope::upload), Status::CODE_403, "Not allowed"); auto mp = std::make_shared(request->getHeaders()); @@ -69,7 +69,7 @@ public: Model::Song sng; sng.data = std::move(data); - song_manager s_mgr(m_exe_path); + Manager::song_manager s_mgr(m_exe_path); s_mgr.saveSong(sng); return createResponse(Status::CODE_200, "OK"); @@ -159,7 +159,7 @@ public: Model::Song song; song.id = id; - song_manager sngMgr(m_exe_path); + Manager::song_manager sngMgr(m_exe_path); sngMgr.deleteSong(song); return createResponse(Status::CODE_200, "OK"); diff --git a/src/database/base_repository.cpp b/src/database/base_repository.cpp index c405461..30385e9 100644 --- a/src/database/base_repository.cpp +++ b/src/database/base_repository.cpp @@ -51,7 +51,7 @@ MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, const std::string& void base_repository::intitalizeDetails() { - auto databaseConfig = directory_manager::databaseConfigContent(path); + auto databaseConfig = Manager::directory_manager::databaseConfigContent(path); details.database = databaseConfig["database"].get(); details.password = databaseConfig["password"].get(); diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index f732b25..e72b417 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -4,11 +4,11 @@ #include "types/coverFilter.h" #include "utilities/metadata_retriever.h" -coverArtManager::coverArtManager(const std::string& configPath) : path(configPath) +Manager::coverArtManager::coverArtManager(const std::string& configPath) : path(configPath) { } -Model::Cover coverArtManager::saveCover(const Model::Song& song, std::string& rootPath, const std::string& stockCoverPath) +Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::string& rootPath, const std::string& stockCoverPath) { metadata_retriever meta; Model::Cover cov; diff --git a/src/managers/directory_manager.cpp b/src/managers/directory_manager.cpp index c8b8acc..4d765d0 100644 --- a/src/managers/directory_manager.cpp +++ b/src/managers/directory_manager.cpp @@ -7,7 +7,7 @@ namespace fs = std::filesystem; -std::string directory_manager::create_directory_process(Model::Song song, const std::string& root_path) +std::string Manager::directory_manager::create_directory_process(Model::Song song, const std::string& root_path) { auto curr_path = fs::path(root_path); @@ -37,11 +37,11 @@ std::string directory_manager::create_directory_process(Model::Song song, const return alb_path.string() + "/"; } -std::string directory_manager::configPath(std::string_view path) +std::string Manager::directory_manager::configPath(std::string_view path) { return fs::canonical(path).parent_path().string(); } -std::string directory_manager::contentOfPath(std::string_view path) +std::string Manager::directory_manager::contentOfPath(std::string_view path) { std::string configPath(path); std::fstream a(configPath, std::ios::in); @@ -52,21 +52,21 @@ std::string directory_manager::contentOfPath(std::string_view path) return s.str(); } -nlohmann::json directory_manager::credentialConfigContent(const std::string& exe_path) +nlohmann::json Manager::directory_manager::credentialConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); path.append("/authcredentials.json"); return nlohmann::json::parse(contentOfPath(path)); } -nlohmann::json directory_manager::databaseConfigContent(const std::string& exe_path) +nlohmann::json Manager::directory_manager::databaseConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); path.append("/database.json"); return nlohmann::json::parse(contentOfPath(path)); } -nlohmann::json directory_manager::pathConfigContent(const std::string& exe_path) +nlohmann::json Manager::directory_manager::pathConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); path.append("/paths.json"); @@ -74,7 +74,7 @@ nlohmann::json directory_manager::pathConfigContent(const std::string& exe_path) return nlohmann::json::parse(contentOfPath(path)); } -void directory_manager::delete_cover_art_file(const std::string& cov_path, const std::string& stock_cover_path) +void Manager::directory_manager::delete_cover_art_file(const std::string& cov_path, const std::string& stock_cover_path) { if (cov_path.compare(stock_cover_path) == 0) { std::cout << "cover has stock cover art, will not deleted" << std::endl; @@ -84,7 +84,7 @@ void directory_manager::delete_cover_art_file(const std::string& cov_path, const fs::remove(cov); } } -void directory_manager::delete_directories(Model::Song song, const std::string& root_path) +void Manager::directory_manager::delete_directories(Model::Song song, const std::string& root_path) { std::cout<<"checking to for empty directories to delete"<(); auto musicRootPath = pathConfigContent["root_music_path"].get(); - auto stockCoverPath = directory_manager::configPath(exe_path); + auto stockCoverPath = Manager::directory_manager::configPath(exe_path); stockCoverPath.append("/CoverArt.png"); auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); song.coverArtId = cov.id; - auto songPath = directory_manager::create_directory_process(song, musicRootPath); + auto songPath = Manager::directory_manager::create_directory_process(song, musicRootPath); songPath.append(song.title); songPath.append(".mp3"); std::cout << "\n\ntemp path: " << song.songPath << std::endl; @@ -53,7 +53,7 @@ void song_manager::saveSong(Model::Song& song) songRepo.saveRecord(song); } -void song_manager::deleteSong(Model::Song& song) +void Manager::song_manager::deleteSong(Model::Song& song) { coverArtRepository covRepo(exe_path); songRepository songRepo(exe_path); @@ -66,7 +66,7 @@ void song_manager::deleteSong(Model::Song& song) cov = covRepo.retrieveRecord(cov, coverFilter::id); covRepo.deleteRecord(cov); - auto paths = directory_manager::pathConfigContent(exe_path); + auto paths = Manager::directory_manager::pathConfigContent(exe_path); const auto coverArtPath = paths["cover_root_path"].get(); std::string stockCoverArtPath = coverArtPath; stockCoverArtPath.append("CoverArt.png"); @@ -77,11 +77,11 @@ void song_manager::deleteSong(Model::Song& song) } fs::remove(song.songPath); - directory_manager::delete_directories(song, paths["root_music_path"].get()); - directory_manager::delete_directories(song, coverArtPath); + Manager::directory_manager::delete_directories(song, paths["root_music_path"].get()); + Manager::directory_manager::delete_directories(song, coverArtPath); } -void song_manager::printSong(const Model::Song& song) +void Manager::song_manager::printSong(const Model::Song& song) { std::cout << "\n\nsong" << std::endl; std::cout << "title: " << song.title << std::endl; @@ -98,9 +98,9 @@ void song_manager::printSong(const Model::Song& song) } } -void song_manager::saveSongTemp(Model::Song& song) +void Manager::song_manager::saveSongTemp(Model::Song& song) { - auto config = directory_manager::pathConfigContent(exe_path); + auto config = Manager::directory_manager::pathConfigContent(exe_path); auto tmp_song = config["temp_root_path"].get(); std::random_device dev; diff --git a/src/managers/token_manager.cpp b/src/managers/token_manager.cpp index c5c2e87..247e541 100644 --- a/src/managers/token_manager.cpp +++ b/src/managers/token_manager.cpp @@ -17,11 +17,11 @@ namespace fs = std::filesystem; -token_manager::token_manager() +Manager::token_manager::token_manager() { } -Model::loginResult token_manager::retrieve_token() +Model::loginResult Manager::token_manager::retrieve_token() { Model::loginResult lr; lr.access_token = "dsfdsf"; @@ -29,7 +29,7 @@ Model::loginResult token_manager::retrieve_token() return lr; } -Model::loginResult token_manager::retrieve_token(std::string_view path) +Model::loginResult Manager::token_manager::retrieve_token(std::string_view path) { auto cred = parse_auth_credentials(path); @@ -58,7 +58,7 @@ Model::loginResult token_manager::retrieve_token(std::string_view path) return lr; } -bool token_manager::is_token_valid(std::string& auth, Scope scope) +bool Manager::token_manager::is_token_valid(std::string& auth, Scope scope) { auto authPair = fetch_auth_header(auth); @@ -87,12 +87,12 @@ bool token_manager::is_token_valid(std::string& auth, Scope scope) return false; } -Model::auth_credentials token_manager::parse_auth_credentials(std::string_view path) +Model::auth_credentials Manager::token_manager::parse_auth_credentials(std::string_view path) { - auto exe_path = directory_manager::configPath(path); + auto exe_path = Manager::directory_manager::configPath(path); exe_path.append("/authcredentials.json"); - auto con = directory_manager::credentialConfigContent(exe_path); + auto con = Manager::directory_manager::credentialConfigContent(exe_path); Model::auth_credentials auth; auth.uri = "https://"; @@ -105,7 +105,7 @@ Model::auth_credentials token_manager::parse_auth_credentials(std::string_view p return auth; } -std::vector token_manager::extract_scopes(const jwt::decoded_jwt&& decoded) +std::vector Manager::token_manager::extract_scopes(const jwt::decoded_jwt&& decoded) { std::vector scopes; @@ -123,7 +123,7 @@ std::vector token_manager::extract_scopes(const jwt::decoded_jwt&& return scopes; } -std::pair> token_manager::fetch_auth_header(const std::string& auth) +std::pair> Manager::token_manager::fetch_auth_header(const std::string& auth) { std::istringstream iss(auth); std::vector authHeader{std::istream_iterator(iss), @@ -142,7 +142,7 @@ std::pair> token_manager::fetch_auth_header(const return std::make_pair(foundBearer, authHeader); } -bool token_manager::token_supports_scope(const std::vector scopes, const std::string&& scope) +bool Manager::token_manager::token_supports_scope(const std::vector scopes, const std::string&& scope) { return std::any_of(scopes.begin(), scopes.end(), [&](std::string foundScope) { diff --git a/src/utilities/metadata_retriever.cpp b/src/utilities/metadata_retriever.cpp index c39c532..d3ad3cb 100644 --- a/src/utilities/metadata_retriever.cpp +++ b/src/utilities/metadata_retriever.cpp @@ -76,8 +76,8 @@ Model::Cover metadata_retriever::update_cover_art(const Model::Song& song, Model } else { auto frame = dynamic_cast( frameList.front()); - directory_manager dir; - auto img_path = dir.create_directory_process(song, cov.imagePath); + + auto img_path = Manager::directory_manager::create_directory_process(song, cov.imagePath); img_path.append(song.title); img_path.append(".png"); cov.imagePath = img_path; From f75ebe14a74c3aa3637735ccc693ddb006019f45 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 1 Sep 2019 15:10:46 -0400 Subject: [PATCH 28/36] Added manager classes for song metadata --- CMakeLists.txt | 16 ++++++++++++ include/database/albumRepository.h | 0 include/database/artistRepository.h | 18 ++++++++++++++ include/database/base_repository.h | 31 +++++++++++++---------- include/database/genreRepository.h | 0 include/database/yearRepository.h | 0 include/managers/albumManager.h | 0 include/managers/artistManager.h | 0 include/managers/genreManager.h | 0 include/managers/token_manager.h | 2 ++ include/managers/yearManager.h | 0 include/models/models.h | 38 +++++++++++++++++++++-------- src/controller/loginController.hpp | 7 +++++- src/controller/songController.hpp | 6 ++--- src/database/albumRepository.cpp | 0 src/database/artistRepository.cpp | 6 +++++ src/database/genreRepository.cpp | 0 src/database/yearRepository.cpp | 0 src/main.cpp | 14 +++++++---- src/managers/albumManager.cpp | 0 src/managers/artistManager.cpp | 0 src/managers/coverArtManager.cpp | 2 +- src/managers/genreManager.cpp | 0 src/managers/song_manager.cpp | 6 ++--- src/managers/token_manager.cpp | 17 +++++++++++++ src/managers/yearManager.cpp | 0 26 files changed, 127 insertions(+), 36 deletions(-) create mode 100644 include/database/albumRepository.h create mode 100644 include/database/artistRepository.h create mode 100644 include/database/genreRepository.h create mode 100644 include/database/yearRepository.h create mode 100644 include/managers/albumManager.h create mode 100644 include/managers/artistManager.h create mode 100644 include/managers/genreManager.h create mode 100644 include/managers/yearManager.h create mode 100644 src/database/albumRepository.cpp create mode 100644 src/database/artistRepository.cpp create mode 100644 src/database/genreRepository.cpp create mode 100644 src/database/yearRepository.cpp create mode 100644 src/managers/albumManager.cpp create mode 100644 src/managers/artistManager.cpp create mode 100644 src/managers/genreManager.cpp create mode 100644 src/managers/yearManager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 462216f..eed89b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,27 +9,43 @@ set(SOURCES src/appComponent.hpp src/controller/loginController.hpp src/controller/songController.hpp + src/database/albumRepository.cpp + src/database/artistRepository.cpp src/database/base_repository.cpp src/database/coverArtRepository.cpp + src/database/genreRepository.cpp src/database/songRepository.cpp + src/database/yearRepository.cpp src/dto/loginResultDto.hpp src/dto/songDto.hpp src/main.cpp + src/managers/albumManager.cpp + src/managers/artistManager.cpp src/managers/coverArtManager.cpp src/managers/directory_manager.cpp + src/managers/genreManager.cpp src/managers/song_manager.cpp src/managers/token_manager.cpp + src/managers/yearManager.cpp src/utilities/imageFile.cpp src/utilities/metadata_retriever.cpp ) set(HEADERS + include/database/albumRepository.h + include/database/artistRepository.h include/database/base_repository.h include/database/coverArtRepository.h + include/database/genreRepository.h include/database/songRepository.h + include/database/yearRepository.h + include/managers/albumManager.h + include/managers/artistManager.h include/managers/coverArtManager.h include/managers/directory_manager.h + include/managers/genreManager.h include/managers/song_manager.h include/managers/token_manager.h + include/managers/yearManager.h include/models/models.h include/utilities/imageFile.h include/utilities/metadata_retriever.h diff --git a/include/database/albumRepository.h b/include/database/albumRepository.h new file mode 100644 index 0000000..e69de29 diff --git a/include/database/artistRepository.h b/include/database/artistRepository.h new file mode 100644 index 0000000..f104a8a --- /dev/null +++ b/include/database/artistRepository.h @@ -0,0 +1,18 @@ +#ifndef ARTISTREPOSITORY_H_ +#define ARTISTREPOSITORY_H_ + +#include "database/base_repository.h" +#include "models/models.h" +#include "types/coverFilter.h" + +namespace Database +{ + class artistRepository : public base_repository + { + public: + artistRepository(const Model::BinaryPath&); + private: + }; +} + +#endif diff --git a/include/database/base_repository.h b/include/database/base_repository.h index dcc3527..ad63c95 100644 --- a/include/database/base_repository.h +++ b/include/database/base_repository.h @@ -7,22 +7,27 @@ #include "models/models.h" -class base_repository +namespace Database { -public: - base_repository(); - base_repository(const std::string&); -protected: - MYSQL* setup_mysql_connection(); - MYSQL* setup_mysql_connection(Model::database_connection); + class base_repository + { + public: + base_repository(); + base_repository(const std::string&); + base_repository(const BinaryPath&); + protected: + MYSQL* setup_mysql_connection(); + MYSQL* setup_mysql_connection(Model::database_connection); - MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&); + MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&); - Model::database_connection details; -private: - void intitalizeDetails(); + Model::database_connection details; + private: + void intitalizeDetails(); - std::string path; -}; + std::string path; + Model::BinaryPath m_binConf; + }; +} #endif diff --git a/include/database/genreRepository.h b/include/database/genreRepository.h new file mode 100644 index 0000000..e69de29 diff --git a/include/database/yearRepository.h b/include/database/yearRepository.h new file mode 100644 index 0000000..e69de29 diff --git a/include/managers/albumManager.h b/include/managers/albumManager.h new file mode 100644 index 0000000..e69de29 diff --git a/include/managers/artistManager.h b/include/managers/artistManager.h new file mode 100644 index 0000000..e69de29 diff --git a/include/managers/genreManager.h b/include/managers/genreManager.h new file mode 100644 index 0000000..e69de29 diff --git a/include/managers/token_manager.h b/include/managers/token_manager.h index e80df7b..9407674 100644 --- a/include/managers/token_manager.h +++ b/include/managers/token_manager.h @@ -20,10 +20,12 @@ namespace Manager Model::loginResult retrieve_token(); Model::loginResult retrieve_token(std::string_view); + Model::loginResult retrieve_token(const BinaryPath&); bool is_token_valid(std::string&, Scope); private: Model::auth_credentials parse_auth_credentials(std::string_view); + Model::auth_credentials parse_auth_credentials(const BinaryPath&); std::vector extract_scopes(const jwt::decoded_jwt&&); std::pair> fetch_auth_header(const std::string&); diff --git a/include/managers/yearManager.h b/include/managers/yearManager.h new file mode 100644 index 0000000..e69de29 diff --git a/include/models/models.h b/include/models/models.h index b755ed5..2d30e01 100644 --- a/include/models/models.h +++ b/include/models/models.h @@ -20,6 +20,16 @@ namespace Model std::string songPath; std::vector data; int coverArtId; + int artistId; + int albumId; + int genreId; + int yearId; + }; + + struct Artist + { + int id; + std::string artist; }; struct Album @@ -30,6 +40,19 @@ namespace Model std::vector songs; }; + struct Genre + { + int id; + std::string category; + + }; + + struct Year + { + int id; + int year; + }; + struct Cover { int id; @@ -39,16 +62,6 @@ namespace Model std::vector data; }; - struct LoginRes - { - int UserId; - char Username[1024]; - char Token[1024]; - char TokenType[1024]; - char Message[1024]; - int Expiration; - }; - struct loginResult { int user_id; @@ -76,6 +89,11 @@ namespace Model std::string password; std::string database; }; + + struct BinaryPath + { + std::string path; + }; } #endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 02b57b4..4c0a0be 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -18,6 +18,9 @@ public: loginController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) : oatpp::web::server::api::ApiController(objectMapper), exe_path(p) { } + loginController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + :oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) + { } #include OATPP_CODEGEN_BEGIN(ApiController) @@ -27,7 +30,8 @@ public: OATPP_LOGI("icarus", "logging in"); Manager::token_manager tok; - auto token = tok.retrieve_token(exe_path); + //auto token = tok.retrieve_token(exe_path); + auto token = tok.retrieve_token(bconf); auto logRes = loginResultDto::createShared(); logRes->id = 0; // TODO: change this later on to something meaningful @@ -43,6 +47,7 @@ public: #include OATPP_CODEGEN_END(ApiController) private: std::string exe_path; + Model::BinaryPath m_bConf; }; #endif diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 1dbfee5..cb1718f 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -80,7 +80,7 @@ public: REQUEST(std::shared_ptr, request)) { std::cout << "starting process of retrieving songs" << std::endl; - songRepository songRepo(m_exe_path); + Database::songRepository songRepo(m_exe_path); auto songsDb = songRepo.retrieveRecords(); auto songs = oatpp::data::mapping::type::List::createShared(); @@ -107,7 +107,7 @@ public: ENDPOINT("GET", "/api/v1/song/{id}", songRecord, PATH(Int32, id)) { - songRepository songRepo(m_exe_path); + Database::songRepository songRepo(m_exe_path); Model::Song songDb; songDb.id = id; @@ -130,7 +130,7 @@ public: ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, PATH(Int32, id)) { - songRepository songRepo(m_exe_path); + Database::songRepository songRepo(m_exe_path); Model::Song songDb; songDb.id = id; songDb = songRepo.retrieveRecord(songDb, songFilter::id); diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/database/artistRepository.cpp b/src/database/artistRepository.cpp new file mode 100644 index 0000000..4d5fb35 --- /dev/null +++ b/src/database/artistRepository.cpp @@ -0,0 +1,6 @@ +#include "database/artistRepository.h" + +Database::artistRepository::artistRepository(const Model::BinaryPath& binConf) + : base_repository(binConf) +{ +} diff --git a/src/database/genreRepository.cpp b/src/database/genreRepository.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/database/yearRepository.cpp b/src/database/yearRepository.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/main.cpp b/src/main.cpp index d395bb6..2ef6f01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,14 +17,15 @@ namespace fs = std::filesystem; -void run(const std::string& working_path) +//void run(const std::string& working_path) +void run(const Model::BinaryPath& bConf) { appComponent component; OATPP_COMPONENT(std::shared_ptr, router); - auto logController = std::make_shared(working_path); - auto sngController = std::make_shared(working_path); + auto logController = std::make_shared(bConf); + auto sngController = std::make_shared(bConf); logController->addEndpointsToRouter(router); sngController->addEndpointsToRouter(router); @@ -42,9 +43,12 @@ void run(const std::string& working_path) int main(int argc, char **argv) { oatpp::base::Environment::init(); - const std::string working_path = argv[0]; + //const std::string working_path = argv[0]; + Model::BinaryPath bConf; + bConf.path = argv[0] - run(working_path); + //run(working_path); + run(bConf); oatpp::base::Environment::destroy(); diff --git a/src/managers/albumManager.cpp b/src/managers/albumManager.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/managers/artistManager.cpp b/src/managers/artistManager.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index e72b417..350a80f 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -16,7 +16,7 @@ Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::s cov = meta.update_cover_art(song, cov, stockCoverPath); cov.songTitle = song.title; - coverArtRepository covRepo(path); + Database::coverArtRepository covRepo(path); std::cout << "saving record to the database" << std::endl; covRepo.saveRecord(cov); std::cout << "retrieving record from database" << std::endl; diff --git a/src/managers/genreManager.cpp b/src/managers/genreManager.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index 4614e5c..c1244a1 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -49,14 +49,14 @@ void Manager::song_manager::saveSong(Model::Song& song) printSong(song); - songRepository songRepo(exe_path); + Database::songRepository songRepo(exe_path); songRepo.saveRecord(song); } void Manager::song_manager::deleteSong(Model::Song& song) { - coverArtRepository covRepo(exe_path); - songRepository songRepo(exe_path); + Database::coverArtRepository covRepo(exe_path); + Database::songRepository songRepo(exe_path); song = songRepo.retrieveRecord(song, songFilter::id); songRepo.deleteRecord(song); diff --git a/src/managers/token_manager.cpp b/src/managers/token_manager.cpp index 247e541..c4e04ec 100644 --- a/src/managers/token_manager.cpp +++ b/src/managers/token_manager.cpp @@ -104,6 +104,23 @@ Model::auth_credentials Manager::token_manager::parse_auth_credentials(std::stri return auth; } +Model::auth_credentials Manager::token_manager::parse_auth_credentials(const BinaryPath& bConf) +{ + auto exePath = Manager::directory_manager::configPath(bConf); + exe_path.append("/auth_credentials.json"); + + auto con = Manager::directory_manager::credentialConfigContent(exePath); + + Model::auth_credentials auth; + auth.uri = "https://"; + auth.uri.append(con["domain"]); + auth.api_identifier = con["api_identifier"]; + auth.client_id = con["client_id"]; + auth.client_secret = con["client_secret"]; + auth.endpoint = "oauth/token"; + + return auth; +} std::vector Manager::token_manager::extract_scopes(const jwt::decoded_jwt&& decoded) { diff --git a/src/managers/yearManager.cpp b/src/managers/yearManager.cpp new file mode 100644 index 0000000..e69de29 From 1ec3511bc54aa564064315c2d409ad10c42c647b Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 1 Sep 2019 16:16:06 -0400 Subject: [PATCH 29/36] Added Controller namespace --- include/database/base_repository.h | 3 +- include/database/coverArtRepository.h | 22 ++- include/database/songRepository.h | 26 +-- include/managers/coverArtManager.h | 2 + include/managers/directory_manager.h | 6 +- include/managers/song_manager.h | 2 + include/managers/token_manager.h | 4 +- src/controller/loginController.hpp | 63 +++---- src/controller/songController.hpp | 231 +++++++++++++------------- src/database/base_repository.cpp | 25 ++- src/database/coverArtRepository.cpp | 13 +- src/database/songRepository.cpp | 17 +- src/main.cpp | 6 +- src/managers/coverArtManager.cpp | 5 +- src/managers/directory_manager.cpp | 30 +++- src/managers/song_manager.cpp | 20 ++- src/managers/token_manager.cpp | 32 +++- 17 files changed, 305 insertions(+), 202 deletions(-) diff --git a/include/database/base_repository.h b/include/database/base_repository.h index ad63c95..2281879 100644 --- a/include/database/base_repository.h +++ b/include/database/base_repository.h @@ -14,7 +14,7 @@ namespace Database public: base_repository(); base_repository(const std::string&); - base_repository(const BinaryPath&); + base_repository(const Model::BinaryPath&); protected: MYSQL* setup_mysql_connection(); MYSQL* setup_mysql_connection(Model::database_connection); @@ -24,6 +24,7 @@ namespace Database Model::database_connection details; private: void intitalizeDetails(); + void initializeDetails(const Model::BinaryPath&); std::string path; Model::BinaryPath m_binConf; diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h index 2add698..dde2b3d 100644 --- a/include/database/coverArtRepository.h +++ b/include/database/coverArtRepository.h @@ -7,17 +7,21 @@ #include "models/models.h" #include "types/coverFilter.h" -class coverArtRepository : public base_repository +namespace Database { -public: - coverArtRepository(const std::string&); + class coverArtRepository : public base_repository + { + public: + coverArtRepository(const std::string&); + coverArtRepository(const Model::BinaryPath&); - Model::Cover retrieveRecord(Model::Cover&, coverFilter); + Model::Cover retrieveRecord(Model::Cover&, coverFilter); - void deleteRecord(const Model::Cover&); - void saveRecord(const Model::Cover&); -private: - Model::Cover parseRecord(MYSQL_RES*); -}; + void deleteRecord(const Model::Cover&); + void saveRecord(const Model::Cover&); + private: + Model::Cover parseRecord(MYSQL_RES*); + }; +} #endif diff --git a/include/database/songRepository.h b/include/database/songRepository.h index ee4ea10..352cd0e 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -10,21 +10,25 @@ #include "models/models.h" #include "types/songFilter.h" -class songRepository : public base_repository +namespace Database { -public: - songRepository(const std::string&); + class songRepository : public base_repository + { + public: + songRepository(const std::string&); + songRepository(const Model::BinaryPath&); - std::vector retrieveRecords(); + std::vector retrieveRecords(); - Model::Song retrieveRecord(Model::Song&, songFilter); + Model::Song retrieveRecord(Model::Song&, songFilter); - void deleteRecord(const Model::Song&); - void saveRecord(const Model::Song&); -private: - std::vector parseRecords(MYSQL_RES*); + void deleteRecord(const Model::Song&); + void saveRecord(const Model::Song&); + private: + std::vector parseRecords(MYSQL_RES*); - Model::Song parseRecord(MYSQL_RES*); -}; + Model::Song parseRecord(MYSQL_RES*); + }; +} #endif diff --git a/include/managers/coverArtManager.h b/include/managers/coverArtManager.h index 9ba399f..edd0831 100644 --- a/include/managers/coverArtManager.h +++ b/include/managers/coverArtManager.h @@ -11,9 +11,11 @@ namespace Manager { public: coverArtManager(const std::string&); + coverArtManager(const Model::BinaryPath& bConf); Model::Cover saveCover(const Model::Song&, std::string&, const std::string&); private: + Model::BinaryPath m_bConf; std::string path; }; } diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h index 48a293d..2535e5a 100644 --- a/include/managers/directory_manager.h +++ b/include/managers/directory_manager.h @@ -15,11 +15,15 @@ namespace Manager public: static std::string create_directory_process(Model::Song, const std::string&); static std::string configPath(std::string_view); - static std::string contentOfPath(std::string_view); + static std::string configPath(const Model::BinaryPath&); + static std::string contentOfPath(const std::string&); static nlohmann::json credentialConfigContent(const std::string&); + static nlohmann::json credentialConfigContent(const Model::BinaryPath&); static nlohmann::json databaseConfigContent(const std::string&); + static nlohmann::json databaseConfigContent(const Model::BinaryPath&); static nlohmann::json pathConfigContent(const std::string&); + static nlohmann::json pathConfigContent(const Model::BinaryPath&); void delete_cover_art_file(const std::string&, const std::string&); static void delete_directories(Model::Song, const std::string&); diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index 1309411..1865b19 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -14,6 +14,7 @@ namespace Manager { public: song_manager(std::string&); + song_manager(const Model::BinaryPath&); void saveSong(Model::Song&); void deleteSong(Model::Song&); @@ -22,6 +23,7 @@ namespace Manager private: void saveSongTemp(Model::Song&); + Model::BinaryPath m_bConf; std::string exe_path; }; } diff --git a/include/managers/token_manager.h b/include/managers/token_manager.h index 9407674..6df05d9 100644 --- a/include/managers/token_manager.h +++ b/include/managers/token_manager.h @@ -20,12 +20,12 @@ namespace Manager Model::loginResult retrieve_token(); Model::loginResult retrieve_token(std::string_view); - Model::loginResult retrieve_token(const BinaryPath&); + Model::loginResult retrieve_token(const Model::BinaryPath&); bool is_token_valid(std::string&, Scope); private: Model::auth_credentials parse_auth_credentials(std::string_view); - Model::auth_credentials parse_auth_credentials(const BinaryPath&); + Model::auth_credentials parse_auth_credentials(const Model::BinaryPath&); std::vector extract_scopes(const jwt::decoded_jwt&&); std::pair> fetch_auth_header(const std::string&); diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 4c0a0be..8db3c43 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -12,42 +12,43 @@ #include "../dto/loginResultDto.hpp" #include "managers/token_manager.h" -class loginController : public oatpp::web::server::api::ApiController +namespace Controller { -public: - loginController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), exe_path(p) - { } - loginController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - :oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) - { } - - - #include OATPP_CODEGEN_BEGIN(ApiController) - - ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(userDto::ObjectWrapper, usr)) + class loginController : public oatpp::web::server::api::ApiController { - OATPP_LOGI("icarus", "logging in"); + public: + loginController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), exe_path(p) + { } + loginController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + :oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) + { } - Manager::token_manager tok; - //auto token = tok.retrieve_token(exe_path); - auto token = tok.retrieve_token(bconf); - auto logRes = loginResultDto::createShared(); - logRes->id = 0; // TODO: change this later on to something meaningful - logRes->username = usr->username->c_str(); - logRes->token = token.access_token.c_str(); - logRes->token_type = token.token_type.c_str(); - logRes->expiration = token.expiration; - logRes->message = "Successful"; + #include OATPP_CODEGEN_BEGIN(ApiController) + + ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(userDto::ObjectWrapper, usr)) { + OATPP_LOGI("icarus", "logging in"); - return createDtoResponse(Status::CODE_200, logRes); - } + Manager::token_manager tok; + //auto token = tok.retrieve_token(exe_path); + auto token = tok.retrieve_token(m_bConf); - #include OATPP_CODEGEN_END(ApiController) -private: - std::string exe_path; - Model::BinaryPath m_bConf; -}; + auto logRes = loginResultDto::createShared(); + logRes->id = 0; // TODO: change this later on to something meaningful + logRes->username = usr->username->c_str(); + logRes->token = token.access_token.c_str(); + logRes->token_type = token.token_type.c_str(); + logRes->expiration = token.expiration; + logRes->message = "Successful"; + return createDtoResponse(Status::CODE_200, logRes); + } + + #include OATPP_CODEGEN_END(ApiController) + private: + std::string exe_path; + Model::BinaryPath m_bConf; + }; +} #endif diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index cb1718f..1a224ff 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -27,65 +27,98 @@ namespace fs = std::filesystem; -class songController : public oatpp::web::server::api::ApiController +namespace Controller { -public: - songController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) - : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) - { } - - #include OATPP_CODEGEN_BEGIN(ApiController) - - // endpoint for uploading a song - ENDPOINT("POST", "/api/v1/song/data", songUpload, - REQUEST(std::shared_ptr, request)) + class songController : public oatpp::web::server::api::ApiController { - auto authHeader = request->getHeader("Authorization"); + public: + songController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) + { } - OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + songController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) + { } - auto auth = authHeader->std_str(); - - Manager::token_manager tok; - OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Scope::upload), Status::CODE_403, "Not allowed"); + #include OATPP_CODEGEN_BEGIN(ApiController) - auto mp = std::make_shared(request->getHeaders()); - - oatpp::web::mime::multipart::Reader mp_reader(mp.get()); - - mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize)); - - request->transferBody(&mp_reader); - - auto file = mp->getNamedPart("file"); - - OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); - - auto buff = std::unique_ptr(new char[file->getKnownSize()]); - auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize()); - - std::vector data(buff.get(), buff.get() + buffSize); - - Model::Song sng; - sng.data = std::move(data); - - Manager::song_manager s_mgr(m_exe_path); - s_mgr.saveSong(sng); - - return createResponse(Status::CODE_200, "OK"); - } - - // endpoint for retrieving all song records in json format - ENDPOINT("GET", "/api/v1/song", songRecords, + // endpoint for uploading a song + ENDPOINT("POST", "/api/v1/song/data", songUpload, REQUEST(std::shared_ptr, request)) - { - std::cout << "starting process of retrieving songs" << std::endl; - Database::songRepository songRepo(m_exe_path); - auto songsDb = songRepo.retrieveRecords(); - auto songs = oatpp::data::mapping::type::List::createShared(); + { + auto authHeader = request->getHeader("Authorization"); + + OATPP_ASSERT_HTTP(authHeader, Status::CODE_403, "Nope"); + + auto auth = authHeader->std_str(); + + Manager::token_manager tok; + OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Scope::upload), Status::CODE_403, "Not allowed"); + + auto mp = std::make_shared(request->getHeaders()); + + oatpp::web::mime::multipart::Reader mp_reader(mp.get()); + + mp_reader.setPartReader("file", oatpp::web::mime::multipart::createInMemoryPartReader(m_dataSize)); + + request->transferBody(&mp_reader); + + auto file = mp->getNamedPart("file"); + + OATPP_ASSERT_HTTP(file, Status::CODE_400, "file is null"); + + auto buff = std::unique_ptr(new char[file->getKnownSize()]); + auto buffSize = file->getInputStream()->read(buff.get(), file->getKnownSize()); + + std::vector data(buff.get(), buff.get() + buffSize); + + Model::Song sng; + sng.data = std::move(data); + + Manager::song_manager s_mgr(m_bConf); + s_mgr.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 = 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; + songDb.id = id; + + songDb = songRepo.retrieveRecord(songDb, songFilter::id); - std::cout << "creating object to send" << std::endl; - for (auto& songDb : songsDb) { auto song = songDto::createShared(); song->id = songDb.id; song->title = songDb.title.c_str(); @@ -97,80 +130,54 @@ public: song->track = songDb.track; song->disc = songDb.disc; - songs->pushBack(song); + return createDtoResponse(Status::CODE_200, 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, + ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, PATH(Int32, id)) { - Database::songRepository songRepo(m_exe_path); - Model::Song songDb; - songDb.id = id; + Database::songRepository songRepo(m_bConf); + Model::Song songDb; + songDb.id = id; + songDb = songRepo.retrieveRecord(songDb, songFilter::id); - songDb = songRepo.retrieveRecord(songDb, songFilter::id); + std::ifstream fl(songDb.songPath.c_str(), std::ios::in | std::ios::binary | std::ios::ate); + fl.seekg(0); - auto song = 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; + std::stringstream buf; + std::copy(std::istreambuf_iterator(fl), + std::istreambuf_iterator(), + std::ostreambuf_iterator(buf)); + fl.close(); - return createDtoResponse(Status::CODE_200, song); - } - - ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, - PATH(Int32, id)) { - - Database::songRepository songRepo(m_exe_path); - Model::Song songDb; - songDb.id = id; - songDb = songRepo.retrieveRecord(songDb, songFilter::id); - - std::ifstream fl(songDb.songPath.c_str(), std::ios::in | std::ios::binary | std::ios::ate); - fl.seekg(0); - - std::stringstream buf; - std::copy(std::istreambuf_iterator(fl), - std::istreambuf_iterator(), - std::ostreambuf_iterator(buf)); - fl.close(); - - auto rawSong = std::make_shared(oatpp::String(buf.str().data(), (v_int32)buf.str().size(), true)); + auto rawSong = std::make_shared(oatpp::String(buf.str().data(), (v_int32)buf.str().size(), true)); - 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 + // TODO: create endpoint for updating songs - ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { + ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { - Model::Song song; - song.id = id; + Model::Song song; + song.id = id; - Manager::song_manager sngMgr(m_exe_path); - sngMgr.deleteSong(song); + Manager::song_manager sngMgr(m_bConf); + sngMgr.deleteSong(song); - return createResponse(Status::CODE_200, "OK"); - } + return createResponse(Status::CODE_200, "OK"); + } - // TODO: create endpoint for streaming songs - - #include OATPP_CODEGEN_END(ApiController) -private: - std::string m_exe_path; - const long m_dataSize = std::numeric_limits::max(); -}; + // TODO: create endpoint for streaming songs + #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/src/database/base_repository.cpp b/src/database/base_repository.cpp index 30385e9..aa801d8 100644 --- a/src/database/base_repository.cpp +++ b/src/database/base_repository.cpp @@ -6,15 +6,19 @@ #include "managers/directory_manager.h" -base_repository::base_repository() +Database::base_repository::base_repository() { } -base_repository::base_repository(const std::string& path) : path(path) +Database::base_repository::base_repository(const std::string& path) : path(path) { intitalizeDetails(); } +Database::base_repository::base_repository(const Model::BinaryPath& bConf) +{ + initializeDetails(bConf); +} -MYSQL* base_repository::setup_mysql_connection() +MYSQL* Database::base_repository::setup_mysql_connection() { MYSQL *conn = mysql_init(nullptr); @@ -25,7 +29,7 @@ MYSQL* base_repository::setup_mysql_connection() return conn; } -MYSQL* base_repository::setup_mysql_connection(Model::database_connection details) +MYSQL* Database::base_repository::setup_mysql_connection(Model::database_connection details) { MYSQL *connection = mysql_init(NULL); @@ -37,7 +41,7 @@ MYSQL* base_repository::setup_mysql_connection(Model::database_connection detail return connection; } -MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, const std::string& query) +MYSQL_RES* Database::base_repository::perform_mysql_query(MYSQL *conn, const std::string& query) { // send the query to the database if (mysql_query(conn, query.c_str())) @@ -49,7 +53,7 @@ MYSQL_RES* base_repository::perform_mysql_query(MYSQL *conn, const std::string& return mysql_use_result(conn); } -void base_repository::intitalizeDetails() +void Database::base_repository::intitalizeDetails() { auto databaseConfig = Manager::directory_manager::databaseConfigContent(path); @@ -58,3 +62,12 @@ void base_repository::intitalizeDetails() details.server = databaseConfig["server"].get(); details.username = databaseConfig["username"].get(); } +void Database::base_repository::initializeDetails(const Model::BinaryPath& bConf) +{ + auto databaseConfig = Manager::directory_manager::databaseConfigContent(bConf); + + details.database = databaseConfig["database"].get(); + details.server = databaseConfig["server"].get(); + details.username = databaseConfig["username"].get(); + details.password = databaseConfig["password"].get(); +} diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index 0e3b20a..1c0c7bd 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -5,10 +5,13 @@ #include #include -coverArtRepository::coverArtRepository(const std::string& path) : base_repository(path) +Database::coverArtRepository::coverArtRepository(const std::string& path) : base_repository(path) { } -Model::Cover coverArtRepository::retrieveRecord(Model::Cover& cov, coverFilter filter = coverFilter::id) +Database::coverArtRepository::coverArtRepository(const Model::BinaryPath& bConf) : base_repository(bConf) +{ } + +Model::Cover Database::coverArtRepository::retrieveRecord(Model::Cover& cov, coverFilter filter = coverFilter::id) { std::stringstream qry; auto conn = setup_mysql_connection(); @@ -45,7 +48,7 @@ Model::Cover coverArtRepository::retrieveRecord(Model::Cover& cov, coverFilter f return covDb; } -void coverArtRepository::deleteRecord(const Model::Cover& cov) +void Database::coverArtRepository::deleteRecord(const Model::Cover& cov) { auto conn = setup_mysql_connection(); const std::string query("DELETE FROM CoverArt WHERE CoverArtId = " + std::to_string(cov.id)); @@ -55,7 +58,7 @@ void coverArtRepository::deleteRecord(const Model::Cover& cov) mysql_close(conn); } -void coverArtRepository::saveRecord(const Model::Cover& cov) +void Database::coverArtRepository::saveRecord(const Model::Cover& cov) { auto conn = setup_mysql_connection(); @@ -93,7 +96,7 @@ void coverArtRepository::saveRecord(const Model::Cover& cov) std::cout << "done" << std::endl; } -Model::Cover coverArtRepository::parseRecord(MYSQL_RES *results) +Model::Cover Database::coverArtRepository::parseRecord(MYSQL_RES *results) { std::cout << "parsing record" << std::endl; Model::Cover cov; diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 86c5f0c..ea4e313 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -7,10 +7,13 @@ #include "types/songFilter.h" -songRepository::songRepository(const std::string& path) : base_repository(path) +Database::songRepository::songRepository(const std::string& path) : base_repository(path) { } -std::vector songRepository::retrieveRecords() +Database::songRepository::songRepository(const Model::BinaryPath& bConf) : base_repository(bConf) +{ } + +std::vector Database::songRepository::retrieveRecords() { auto conn = setup_mysql_connection(); const std::string query = "SELECT * FROM Song"; @@ -24,7 +27,7 @@ std::vector songRepository::retrieveRecords() return songs; } -Model::Song songRepository::retrieveRecord(Model::Song& song, songFilter filter) +Model::Song Database::songRepository::retrieveRecord(Model::Song& song, songFilter filter) { std::stringstream qry; auto conn = setup_mysql_connection(); @@ -57,7 +60,7 @@ Model::Song songRepository::retrieveRecord(Model::Song& song, songFilter filter) return song; } -void songRepository::deleteRecord(const Model::Song& song) +void Database::songRepository::deleteRecord(const Model::Song& song) { auto conn = setup_mysql_connection(); auto status = 0; @@ -69,7 +72,7 @@ void songRepository::deleteRecord(const Model::Song& song) mysql_close(conn); } -void songRepository::saveRecord(const Model::Song& song) +void Database::songRepository::saveRecord(const Model::Song& song) { auto conn = setup_mysql_connection(); auto status = 0; @@ -148,7 +151,7 @@ void songRepository::saveRecord(const Model::Song& song) std::cout << "done inserting song record" << std::endl; } -std::vector songRepository::parseRecords(MYSQL_RES* results) +std::vector Database::songRepository::parseRecords(MYSQL_RES* results) { auto fieldNum = mysql_num_fields(results); auto numRows = mysql_num_rows(results); @@ -203,7 +206,7 @@ std::vector songRepository::parseRecords(MYSQL_RES* results) return songs; } -Model::Song songRepository::parseRecord(MYSQL_RES* results) +Model::Song Database::songRepository::parseRecord(MYSQL_RES* results) { Model::Song song; auto fieldNum = mysql_num_fields(results); diff --git a/src/main.cpp b/src/main.cpp index 2ef6f01..ca0a705 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,8 +24,8 @@ void run(const Model::BinaryPath& bConf) OATPP_COMPONENT(std::shared_ptr, router); - auto logController = std::make_shared(bConf); - auto sngController = std::make_shared(bConf); + auto logController = std::make_shared(bConf); + auto sngController = std::make_shared(bConf); logController->addEndpointsToRouter(router); sngController->addEndpointsToRouter(router); @@ -45,7 +45,7 @@ int main(int argc, char **argv) oatpp::base::Environment::init(); //const std::string working_path = argv[0]; Model::BinaryPath bConf; - bConf.path = argv[0] + bConf.path = argv[0]; //run(working_path); run(bConf); diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index 350a80f..120ec73 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -7,6 +7,9 @@ Manager::coverArtManager::coverArtManager(const std::string& configPath) : path(configPath) { } +Manager::coverArtManager::coverArtManager(const Model::BinaryPath& bConf) : m_bConf(bConf) +{ } + Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::string& rootPath, const std::string& stockCoverPath) { @@ -16,7 +19,7 @@ Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::s cov = meta.update_cover_art(song, cov, stockCoverPath); cov.songTitle = song.title; - Database::coverArtRepository covRepo(path); + Database::coverArtRepository covRepo(m_bConf); std::cout << "saving record to the database" << std::endl; covRepo.saveRecord(cov); std::cout << "retrieving record from database" << std::endl; diff --git a/src/managers/directory_manager.cpp b/src/managers/directory_manager.cpp index 4d765d0..9702aa5 100644 --- a/src/managers/directory_manager.cpp +++ b/src/managers/directory_manager.cpp @@ -41,10 +41,13 @@ std::string Manager::directory_manager::configPath(std::string_view path) { return fs::canonical(path).parent_path().string(); } -std::string Manager::directory_manager::contentOfPath(std::string_view path) +std::string Manager::directory_manager::configPath(const Model::BinaryPath& bConf) { - std::string configPath(path); - std::fstream a(configPath, std::ios::in); + return fs::canonical(bConf.path).parent_path().string(); +} +std::string Manager::directory_manager::contentOfPath(const std::string& path) +{ + std::fstream a(path, std::ios::in); std::stringstream s; s << a.rdbuf(); a.close(); @@ -59,6 +62,13 @@ nlohmann::json Manager::directory_manager::credentialConfigContent(const std::st return nlohmann::json::parse(contentOfPath(path)); } +nlohmann::json Manager::directory_manager::credentialConfigContent(const Model::BinaryPath& bConf) +{ + auto path = configPath(bConf); + path.append("/authcredentials.json"); + + return nlohmann::json::parse(contentOfPath(path)); +} nlohmann::json Manager::directory_manager::databaseConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); @@ -66,6 +76,13 @@ nlohmann::json Manager::directory_manager::databaseConfigContent(const std::stri return nlohmann::json::parse(contentOfPath(path)); } +nlohmann::json Manager::directory_manager::databaseConfigContent(const Model::BinaryPath& bConf) +{ + auto path = configPath(bConf); + path.append("/database.json"); + + return nlohmann::json::parse(contentOfPath(path)); +} nlohmann::json Manager::directory_manager::pathConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); @@ -73,6 +90,13 @@ nlohmann::json Manager::directory_manager::pathConfigContent(const std::string& return nlohmann::json::parse(contentOfPath(path)); } +nlohmann::json Manager::directory_manager::pathConfigContent(const Model::BinaryPath& bConf) +{ + auto path = configPath(bConf); + path.append("/paths.json"); + + return nlohmann::json::parse(contentOfPath(path)); +} void Manager::directory_manager::delete_cover_art_file(const std::string& cov_path, const std::string& stock_cover_path) { diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index c1244a1..cc7c1c6 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -18,6 +18,10 @@ Manager::song_manager::song_manager(std::string& x_path) : exe_path(x_path) { } +Manager::song_manager::song_manager(const Model::BinaryPath& bConf) + : m_bConf(bConf) +{ } + void Manager::song_manager::saveSong(Model::Song& song) { @@ -27,12 +31,12 @@ void Manager::song_manager::saveSong(Model::Song& song) song = meta.retrieve_metadata(song.songPath); song.data = std::move(data); - coverArtManager covMgr(exe_path); - auto pathConfigContent = Manager::directory_manager::pathConfigContent(exe_path); + coverArtManager covMgr(m_bConf); + auto pathConfigContent = Manager::directory_manager::pathConfigContent(m_bConf); auto coverRootPath = pathConfigContent["cover_root_path"].get(); auto musicRootPath = pathConfigContent["root_music_path"].get(); - auto stockCoverPath = Manager::directory_manager::configPath(exe_path); + auto stockCoverPath = Manager::directory_manager::configPath(m_bConf); stockCoverPath.append("/CoverArt.png"); auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); @@ -49,14 +53,14 @@ void Manager::song_manager::saveSong(Model::Song& song) printSong(song); - Database::songRepository songRepo(exe_path); + Database::songRepository songRepo(m_bConf); songRepo.saveRecord(song); } void Manager::song_manager::deleteSong(Model::Song& song) { - Database::coverArtRepository covRepo(exe_path); - Database::songRepository songRepo(exe_path); + Database::coverArtRepository covRepo(m_bConf); + Database::songRepository songRepo(m_bConf); song = songRepo.retrieveRecord(song, songFilter::id); songRepo.deleteRecord(song); @@ -66,7 +70,7 @@ void Manager::song_manager::deleteSong(Model::Song& song) cov = covRepo.retrieveRecord(cov, coverFilter::id); covRepo.deleteRecord(cov); - auto paths = Manager::directory_manager::pathConfigContent(exe_path); + auto paths = Manager::directory_manager::pathConfigContent(m_bConf); const auto coverArtPath = paths["cover_root_path"].get(); std::string stockCoverArtPath = coverArtPath; stockCoverArtPath.append("CoverArt.png"); @@ -100,7 +104,7 @@ void Manager::song_manager::printSong(const Model::Song& song) void Manager::song_manager::saveSongTemp(Model::Song& song) { - auto config = Manager::directory_manager::pathConfigContent(exe_path); + auto config = Manager::directory_manager::pathConfigContent(m_bConf); auto tmp_song = config["temp_root_path"].get(); std::random_device dev; diff --git a/src/managers/token_manager.cpp b/src/managers/token_manager.cpp index c4e04ec..c9a0a47 100644 --- a/src/managers/token_manager.cpp +++ b/src/managers/token_manager.cpp @@ -57,6 +57,34 @@ Model::loginResult Manager::token_manager::retrieve_token(std::string_view path) return lr; } +Model::loginResult Manager::token_manager::retrieve_token(const Model::BinaryPath& bConf) +{ + auto cred = parse_auth_credentials(bConf); + + nlohmann::json reqObj; + reqObj["client_id"] = cred.client_id; + reqObj["client_secret"] = cred.client_secret; + reqObj["audience"] = cred.api_identifier; + reqObj["grant_type"] = "client_credentials"; + + 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 post_res = nlohmann::json::parse(r.text); + + Model::loginResult lr; + lr.access_token = post_res["access_token"].get(); + lr.token_type = post_res["token_type"].get(); + lr.expiration = post_res["expires_in"].get(); + + return lr; +} bool Manager::token_manager::is_token_valid(std::string& auth, Scope scope) { @@ -104,10 +132,10 @@ Model::auth_credentials Manager::token_manager::parse_auth_credentials(std::stri return auth; } -Model::auth_credentials Manager::token_manager::parse_auth_credentials(const BinaryPath& bConf) +Model::auth_credentials Manager::token_manager::parse_auth_credentials(const Model::BinaryPath& bConf) { auto exePath = Manager::directory_manager::configPath(bConf); - exe_path.append("/auth_credentials.json"); + exePath.append("/auth_credentials.json"); auto con = Manager::directory_manager::credentialConfigContent(exePath); From dfd4906371145b1ed7d6047f613110643cba8144 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 1 Sep 2019 16:56:52 -0400 Subject: [PATCH 30/36] Added Utility and Type namespaces --- include/database/albumRepository.h | 17 +++++++++++++++++ include/database/coverArtRepository.h | 2 +- include/database/genreRepository.h | 17 +++++++++++++++++ include/database/songRepository.h | 2 +- include/database/yearRepository.h | 17 +++++++++++++++++ include/managers/albumManager.h | 17 +++++++++++++++++ include/managers/artistManager.h | 17 +++++++++++++++++ include/managers/genreManager.h | 17 +++++++++++++++++ include/managers/token_manager.h | 2 +- include/managers/yearManager.h | 17 +++++++++++++++++ include/types/coverFilter.h | 13 ++++++++----- include/types/scopes.h | 11 +++++++---- include/types/songFilter.h | 19 +++++++++++-------- include/utilities/imageFile.h | 26 +++++++++++++++++--------- include/utilities/metadata_retriever.h | 17 ++++++++++------- src/controller/songController.hpp | 6 +++--- src/database/albumRepository.cpp | 5 +++++ src/database/coverArtRepository.cpp | 8 ++++---- src/database/genreRepository.cpp | 5 +++++ src/database/songRepository.cpp | 6 +++--- src/database/yearRepository.cpp | 5 +++++ src/managers/albumManager.cpp | 5 +++++ src/managers/artistManager.cpp | 5 +++++ src/managers/coverArtManager.cpp | 4 ++-- src/managers/genreManager.cpp | 5 +++++ src/managers/song_manager.cpp | 6 +++--- src/managers/token_manager.cpp | 6 +++--- src/managers/yearManager.cpp | 5 +++++ src/utilities/imageFile.cpp | 4 ++-- src/utilities/metadata_retriever.cpp | 6 +++--- 30 files changed, 233 insertions(+), 59 deletions(-) diff --git a/include/database/albumRepository.h b/include/database/albumRepository.h index e69de29..6525da2 100644 --- a/include/database/albumRepository.h +++ b/include/database/albumRepository.h @@ -0,0 +1,17 @@ +#ifndef ALBUMREPOSITORY_H_ +#define ALBUMREPOSITORY_H_ + +#include "database/base_repository.h" +#include "models/models.h" + +namespace Database +{ + class albumRepository : public base_repository + { + public: + albumRepository(const Model::BinaryPath&); + private: + }; +} + +#endif diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h index dde2b3d..115c320 100644 --- a/include/database/coverArtRepository.h +++ b/include/database/coverArtRepository.h @@ -15,7 +15,7 @@ namespace Database coverArtRepository(const std::string&); coverArtRepository(const Model::BinaryPath&); - Model::Cover retrieveRecord(Model::Cover&, coverFilter); + Model::Cover retrieveRecord(Model::Cover&, Type::coverFilter); void deleteRecord(const Model::Cover&); void saveRecord(const Model::Cover&); diff --git a/include/database/genreRepository.h b/include/database/genreRepository.h index e69de29..50f9858 100644 --- a/include/database/genreRepository.h +++ b/include/database/genreRepository.h @@ -0,0 +1,17 @@ +#ifndef GENREREPOSITORY_H_ +#define GENREREPOSITORY_H_ + +#include "database/base_repository.h" +#include "models/models.h" + +namespace Database +{ + class genreRepository : public base_repository + { + public: + genreRepository(const Model::BinaryPath&); + private: + }; +} + +#endif diff --git a/include/database/songRepository.h b/include/database/songRepository.h index 352cd0e..0bc05f6 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -20,7 +20,7 @@ namespace Database std::vector retrieveRecords(); - Model::Song retrieveRecord(Model::Song&, songFilter); + Model::Song retrieveRecord(Model::Song&, Type::songFilter); void deleteRecord(const Model::Song&); void saveRecord(const Model::Song&); diff --git a/include/database/yearRepository.h b/include/database/yearRepository.h index e69de29..d6157ce 100644 --- a/include/database/yearRepository.h +++ b/include/database/yearRepository.h @@ -0,0 +1,17 @@ +#ifndef YEARREPOSITORY_H_ +#define YEARREPOSITORY_H_ + +#include "database/base_repository.h" +#include "models/models.h" + +namespace Database +{ + class yearRepository : public base_repository + { + public: + yearRepository(const Model::BinaryPath&); + private: + }; +} + +#endif diff --git a/include/managers/albumManager.h b/include/managers/albumManager.h index e69de29..c6a83a2 100644 --- a/include/managers/albumManager.h +++ b/include/managers/albumManager.h @@ -0,0 +1,17 @@ +#ifndef ALBUMMANAGER_H_ +#define ALBUMMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class albumManager + { + public: + albumManager(const Model::BinaryPath&); + private: + Model::BinaryPath m_bConf; + }; +} + +#endif diff --git a/include/managers/artistManager.h b/include/managers/artistManager.h index e69de29..f34db3e 100644 --- a/include/managers/artistManager.h +++ b/include/managers/artistManager.h @@ -0,0 +1,17 @@ +#ifndef ARTISTMANAGER_H_ +#define ARTISTMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class artistManager + { + public: + artistManager(const Model::BinaryPath&); + private: + Model::BinaryPath m_bConf; + }; +} + +#endif diff --git a/include/managers/genreManager.h b/include/managers/genreManager.h index e69de29..f456e8d 100644 --- a/include/managers/genreManager.h +++ b/include/managers/genreManager.h @@ -0,0 +1,17 @@ +#ifndef GENREMANAGER_H_ +#define GENREMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class genreManager + { + public: + genreManager(const Model::BinaryPath&); + private: + Model::BinaryPath m_bConf; + }; +} + +#endif diff --git a/include/managers/token_manager.h b/include/managers/token_manager.h index 6df05d9..fc4b3f9 100644 --- a/include/managers/token_manager.h +++ b/include/managers/token_manager.h @@ -22,7 +22,7 @@ namespace Manager Model::loginResult retrieve_token(std::string_view); Model::loginResult retrieve_token(const Model::BinaryPath&); - bool is_token_valid(std::string&, Scope); + bool is_token_valid(std::string&, Type::Scope); private: Model::auth_credentials parse_auth_credentials(std::string_view); Model::auth_credentials parse_auth_credentials(const Model::BinaryPath&); diff --git a/include/managers/yearManager.h b/include/managers/yearManager.h index e69de29..db7fc99 100644 --- a/include/managers/yearManager.h +++ b/include/managers/yearManager.h @@ -0,0 +1,17 @@ +#ifndef YEARMANAGER_H_ +#define YEARMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class yearManager + { + public: + yearManager(const Model::BinaryPath&); + private: + Model::BinaryPath m_bConf; + }; +} + +#endif diff --git a/include/types/coverFilter.h b/include/types/coverFilter.h index b334a8a..0129ea8 100644 --- a/include/types/coverFilter.h +++ b/include/types/coverFilter.h @@ -1,11 +1,14 @@ #ifndef COVERFILTER_H_ #define COVERFILTER_H_ -enum class coverFilter +namespace Type { - id = 0, - songTitle, - imagePath -}; + enum class coverFilter + { + id = 0, + songTitle, + imagePath + }; +} #endif diff --git a/include/types/scopes.h b/include/types/scopes.h index c95fd1c..e0fd4a6 100644 --- a/include/types/scopes.h +++ b/include/types/scopes.h @@ -1,10 +1,13 @@ #ifndef SCOPES_H_ #define SCOPES_H_ -enum class Scope +namespace Type { - upload = 0, - download -}; + enum class Scope + { + upload = 0, + download + }; +} #endif diff --git a/include/types/songFilter.h b/include/types/songFilter.h index 85a3c46..d2d9973 100644 --- a/include/types/songFilter.h +++ b/include/types/songFilter.h @@ -1,14 +1,17 @@ #ifndef SONGFILTER_H_ #define SONGFILTER_H_ -enum class songFilter +namespace Type { - id = 0, - title, - album, - artist, - genre, - year -}; + enum class songFilter + { + id = 0, + title, + album, + artist, + genre, + year + }; +} #endif diff --git a/include/utilities/imageFile.h b/include/utilities/imageFile.h index 9e95cdd..49432c6 100644 --- a/include/utilities/imageFile.h +++ b/include/utilities/imageFile.h @@ -1,3 +1,6 @@ +#ifndef IMAGEFILE_H_ +#define IMAGEFILE_H_ + #include #include @@ -10,15 +13,20 @@ #include #include -class imageFile : public TagLib::File +namespace Utility { -public: - imageFile(const char *file); + class imageFile : public TagLib::File + { + public: + imageFile(const char *file); - TagLib::ByteVector data(); + TagLib::ByteVector data(); -private: - virtual TagLib::Tag *tag() const { return 0; } - virtual TagLib::AudioProperties *audioProperties() const { return 0; } - virtual bool save() { return false; } -}; + private: + virtual TagLib::Tag *tag() const { return 0; } + virtual TagLib::AudioProperties *audioProperties() const { return 0; } + virtual bool save() { return false; } + }; +} + +#endif diff --git a/include/utilities/metadata_retriever.h b/include/utilities/metadata_retriever.h index 4801216..1543143 100644 --- a/include/utilities/metadata_retriever.h +++ b/include/utilities/metadata_retriever.h @@ -6,14 +6,17 @@ #include "models/models.h" -class metadata_retriever +namespace Utility { -public: - Model::Song retrieve_metadata(std::string&); - Model::Cover update_cover_art(const Model::Song&, Model::Cover& cov, const std::string&); + class metadata_retriever + { + public: + Model::Song retrieve_metadata(std::string&); + Model::Cover update_cover_art(const Model::Song&, Model::Cover& cov, const std::string&); - void update_metadata(Model::Song updated_song, const Model::Song old_song); -private: -}; + void update_metadata(Model::Song updated_song, const Model::Song old_song); + private: + }; +} #endif diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 1a224ff..95b80b1 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -53,7 +53,7 @@ namespace Controller auto auth = authHeader->std_str(); Manager::token_manager tok; - OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Scope::upload), Status::CODE_403, "Not allowed"); + OATPP_ASSERT_HTTP(tok.is_token_valid(auth, Type::Scope::upload), Status::CODE_403, "Not allowed"); auto mp = std::make_shared(request->getHeaders()); @@ -117,7 +117,7 @@ namespace Controller Model::Song songDb; songDb.id = id; - songDb = songRepo.retrieveRecord(songDb, songFilter::id); + songDb = songRepo.retrieveRecord(songDb, Type::songFilter::id); auto song = songDto::createShared(); song->id = songDb.id; @@ -139,7 +139,7 @@ namespace Controller Database::songRepository songRepo(m_bConf); Model::Song songDb; songDb.id = id; - songDb = songRepo.retrieveRecord(songDb, songFilter::id); + songDb = songRepo.retrieveRecord(songDb, Type::songFilter::id); std::ifstream fl(songDb.songPath.c_str(), std::ios::in | std::ios::binary | std::ios::ate); fl.seekg(0); diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp index e69de29..99d41f1 100644 --- a/src/database/albumRepository.cpp +++ b/src/database/albumRepository.cpp @@ -0,0 +1,5 @@ +#include "database/albumRepository.h" + +Database::albumRepository::albumRepository(const Model::BinaryPath& bConf) + : base_repository(bConf) +{ } diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index 1c0c7bd..bab5aea 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -11,7 +11,7 @@ Database::coverArtRepository::coverArtRepository(const std::string& path) : base Database::coverArtRepository::coverArtRepository(const Model::BinaryPath& bConf) : base_repository(bConf) { } -Model::Cover Database::coverArtRepository::retrieveRecord(Model::Cover& cov, coverFilter filter = coverFilter::id) +Model::Cover Database::coverArtRepository::retrieveRecord(Model::Cover& cov, Type::coverFilter filter = Type::coverFilter::id) { std::stringstream qry; auto conn = setup_mysql_connection(); @@ -19,16 +19,16 @@ Model::Cover Database::coverArtRepository::retrieveRecord(Model::Cover& cov, cov std::unique_ptr param; switch (filter) { - case coverFilter::id: + case Type::coverFilter::id: qry << "CoverArtId = " << cov.id; break; - case coverFilter::songTitle: + case Type::coverFilter::songTitle: param = std::make_unique(new char[cov.songTitle.size()]); mysql_real_escape_string(conn, *param, cov.songTitle.c_str(), cov.songTitle.size()); std::cout << *param << std::endl; qry << "SongTitle = '" << *param << "'"; break; - case coverFilter::imagePath: + case Type::coverFilter::imagePath: param = std::make_unique(new char[cov.imagePath.size()]); mysql_real_escape_string(conn, *param, cov.imagePath.c_str(), cov.imagePath.size()); std::cout << *param << std::endl; diff --git a/src/database/genreRepository.cpp b/src/database/genreRepository.cpp index e69de29..5e49c8c 100644 --- a/src/database/genreRepository.cpp +++ b/src/database/genreRepository.cpp @@ -0,0 +1,5 @@ +#include "database/genreRepository.h" + +Database::genreRepository::genreRepository(const Model::BinaryPath& bConf) + : base_repository(bConf) +{ } diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index ea4e313..4e9262b 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -27,7 +27,7 @@ std::vector Database::songRepository::retrieveRecords() return songs; } -Model::Song Database::songRepository::retrieveRecord(Model::Song& song, songFilter filter) +Model::Song Database::songRepository::retrieveRecord(Model::Song& song, Type::songFilter filter) { std::stringstream qry; auto conn = setup_mysql_connection(); @@ -35,10 +35,10 @@ Model::Song Database::songRepository::retrieveRecord(Model::Song& song, songFilt std::unique_ptr param; switch (filter) { - case songFilter::id: + case Type::songFilter::id: qry << "SongId = " << song.id; break; - case songFilter::title: + case Type::songFilter::title: param = std::make_unique(new char[song.title.size()]); mysql_real_escape_string(conn, *param, song.title.c_str(), song.title.size()); std::cout << *param << std::endl; diff --git a/src/database/yearRepository.cpp b/src/database/yearRepository.cpp index e69de29..5e14f28 100644 --- a/src/database/yearRepository.cpp +++ b/src/database/yearRepository.cpp @@ -0,0 +1,5 @@ +#include "database/yearRepository.h" + +Database::yearRepository::yearRepository(const Model::BinaryPath& bConf) + : base_repository(bConf) +{ } diff --git a/src/managers/albumManager.cpp b/src/managers/albumManager.cpp index e69de29..46f4d6e 100644 --- a/src/managers/albumManager.cpp +++ b/src/managers/albumManager.cpp @@ -0,0 +1,5 @@ +#include "managers/albumManager.h" + +Manager::albumManager::albumManager(const Model::BinaryPath& bConf) + : m_bConf(bConf) +{ } diff --git a/src/managers/artistManager.cpp b/src/managers/artistManager.cpp index e69de29..1364c5c 100644 --- a/src/managers/artistManager.cpp +++ b/src/managers/artistManager.cpp @@ -0,0 +1,5 @@ +#include "managers/artistManager.h" + +Manager::artistManager::artistManager(const Model::BinaryPath& bConf) + : m_bConf(bConf) +{ } diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index 120ec73..711c3b6 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -13,7 +13,7 @@ Manager::coverArtManager::coverArtManager(const Model::BinaryPath& bConf) : m_bC Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::string& rootPath, const std::string& stockCoverPath) { - metadata_retriever meta; + Utility::metadata_retriever meta; Model::Cover cov; cov.imagePath = rootPath; cov = meta.update_cover_art(song, cov, stockCoverPath); @@ -23,7 +23,7 @@ Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::s std::cout << "saving record to the database" << std::endl; covRepo.saveRecord(cov); std::cout << "retrieving record from database" << std::endl; - cov = covRepo.retrieveRecord(cov, coverFilter::songTitle); + cov = covRepo.retrieveRecord(cov, Type::coverFilter::songTitle); return cov; } diff --git a/src/managers/genreManager.cpp b/src/managers/genreManager.cpp index e69de29..2c6dc71 100644 --- a/src/managers/genreManager.cpp +++ b/src/managers/genreManager.cpp @@ -0,0 +1,5 @@ +#include "managers/genreManager.h" + +Manager::genreManager::genreManager(const Model::BinaryPath& bConf) + : m_bConf(bConf) +{ } diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index cc7c1c6..d59100c 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -26,7 +26,7 @@ Manager::song_manager::song_manager(const Model::BinaryPath& bConf) void Manager::song_manager::saveSong(Model::Song& song) { saveSongTemp(song); - metadata_retriever meta; + Utility::metadata_retriever meta; auto data = std::move(song.data); song = meta.retrieve_metadata(song.songPath); song.data = std::move(data); @@ -62,12 +62,12 @@ void Manager::song_manager::deleteSong(Model::Song& song) Database::coverArtRepository covRepo(m_bConf); Database::songRepository songRepo(m_bConf); - song = songRepo.retrieveRecord(song, songFilter::id); + song = songRepo.retrieveRecord(song, Type::songFilter::id); songRepo.deleteRecord(song); Model::Cover cov; cov.id = song.coverArtId; - cov = covRepo.retrieveRecord(cov, coverFilter::id); + cov = covRepo.retrieveRecord(cov, Type::coverFilter::id); covRepo.deleteRecord(cov); auto paths = Manager::directory_manager::pathConfigContent(m_bConf); diff --git a/src/managers/token_manager.cpp b/src/managers/token_manager.cpp index c9a0a47..d9f55c4 100644 --- a/src/managers/token_manager.cpp +++ b/src/managers/token_manager.cpp @@ -86,7 +86,7 @@ Model::loginResult Manager::token_manager::retrieve_token(const Model::BinaryPat return lr; } -bool Manager::token_manager::is_token_valid(std::string& auth, Scope scope) +bool Manager::token_manager::is_token_valid(std::string& auth, Type::Scope scope) { auto authPair = fetch_auth_header(auth); @@ -103,10 +103,10 @@ bool Manager::token_manager::is_token_valid(std::string& auth, Scope scope) auto scopes = extract_scopes(jwt::decode(token)); switch (scope) { - case Scope::upload: + case Type::Scope::upload: return token_supports_scope(scopes, "upload:songs"); break; - case Scope::download: + case Type::Scope::download: return token_supports_scope(scopes, "download:songs"); default: break; diff --git a/src/managers/yearManager.cpp b/src/managers/yearManager.cpp index e69de29..bc6538d 100644 --- a/src/managers/yearManager.cpp +++ b/src/managers/yearManager.cpp @@ -0,0 +1,5 @@ +#include "managers/yearManager.h" + +Manager::yearManager::yearManager(const Model::BinaryPath& bConf) + : m_bConf(bConf) +{ } diff --git a/src/utilities/imageFile.cpp b/src/utilities/imageFile.cpp index 7b9c10d..dad7a7c 100644 --- a/src/utilities/imageFile.cpp +++ b/src/utilities/imageFile.cpp @@ -1,10 +1,10 @@ #include "utilities/imageFile.h" -imageFile::imageFile(const char *file) : TagLib::File(file) +Utility::imageFile::imageFile(const char *file) : TagLib::File(file) { } -TagLib::ByteVector imageFile::data() +TagLib::ByteVector Utility::imageFile::data() { return readBlock(length()); } diff --git a/src/utilities/metadata_retriever.cpp b/src/utilities/metadata_retriever.cpp index d3ad3cb..e10dea9 100644 --- a/src/utilities/metadata_retriever.cpp +++ b/src/utilities/metadata_retriever.cpp @@ -17,7 +17,7 @@ namespace fs = std::filesystem; -Model::Song metadata_retriever::retrieve_metadata(std::string& song_path) +Model::Song Utility::metadata_retriever::retrieve_metadata(std::string& song_path) { TagLib::FileRef file(song_path.c_str()); Model::Song song; @@ -48,7 +48,7 @@ Model::Song metadata_retriever::retrieve_metadata(std::string& song_path) return song; } -Model::Cover metadata_retriever::update_cover_art(const Model::Song& song, Model::Cover& cov, const std::string& stockCoverPath) +Model::Cover Utility::metadata_retriever::update_cover_art(const Model::Song& song, Model::Cover& cov, const std::string& stockCoverPath) { TagLib::MPEG::File sngF(song.songPath.c_str()); auto tag = sngF.ID3v2Tag(); @@ -94,7 +94,7 @@ Model::Cover metadata_retriever::update_cover_art(const Model::Song& song, Model return cov; } -void metadata_retriever::update_metadata(Model::Song sng_updated, const Model::Song sng_old) +void Utility::metadata_retriever::update_metadata(Model::Song sng_updated, const Model::Song sng_old) { std::cout<<"updating metadata"< Date: Sun, 1 Sep 2019 17:08:00 -0400 Subject: [PATCH 31/36] Move Dto's to Dto in include directory and created Dto namespace --- CMakeLists.txt | 4 ++-- include/dto/loginResultDto.hpp | 34 ++++++++++++++++++++++++++++++ include/dto/songDto.hpp | 29 +++++++++++++++++++++++++ src/controller/loginController.hpp | 6 +++--- src/controller/songController.hpp | 8 +++---- src/dto/loginResultDto.hpp | 31 --------------------------- src/dto/songDto.hpp | 26 ----------------------- 7 files changed, 72 insertions(+), 66 deletions(-) create mode 100644 include/dto/loginResultDto.hpp create mode 100644 include/dto/songDto.hpp delete mode 100644 src/dto/loginResultDto.hpp delete mode 100644 src/dto/songDto.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index eed89b3..80ac244 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,6 @@ set(SOURCES src/database/genreRepository.cpp src/database/songRepository.cpp src/database/yearRepository.cpp - src/dto/loginResultDto.hpp - src/dto/songDto.hpp src/main.cpp src/managers/albumManager.cpp src/managers/artistManager.cpp @@ -38,6 +36,8 @@ set(HEADERS include/database/genreRepository.h include/database/songRepository.h include/database/yearRepository.h + include/dto/loginResultDto.hpp + include/dto/songDto.hpp include/managers/albumManager.h include/managers/artistManager.h include/managers/coverArtManager.h diff --git a/include/dto/loginResultDto.hpp b/include/dto/loginResultDto.hpp new file mode 100644 index 0000000..d0956fd --- /dev/null +++ b/include/dto/loginResultDto.hpp @@ -0,0 +1,34 @@ +#ifndef LOGINRESULTDTO_H_ +#define LOGINRESULTDTO_H_ + +#include "oatpp/core/data/mapping/type/Object.hpp" +#include "oatpp/core/macro/codegen.hpp" + +namespace Dto +{ + #include OATPP_CODEGEN_BEGIN(DTO) + + class loginResultDto : public oatpp::data::mapping::type::Object + { + DTO_INIT(loginResultDto, Object) + + DTO_FIELD(Int32, id); + DTO_FIELD(String, username); + DTO_FIELD(String, token); + DTO_FIELD(String, token_type); + DTO_FIELD(Int32, expiration); + DTO_FIELD(String, message); + }; + + class userDto : public oatpp::data::mapping::type::Object + { + DTO_INIT(userDto, Object) + + DTO_FIELD(String, username); + DTO_FIELD(String, password); + }; + + #include OATPP_CODEGEN_END(DTO) +} + +#endif diff --git a/include/dto/songDto.hpp b/include/dto/songDto.hpp new file mode 100644 index 0000000..e0dcc70 --- /dev/null +++ b/include/dto/songDto.hpp @@ -0,0 +1,29 @@ +#ifndef SONGDTO_H_ +#define SONGDTO_H_ + +#include "oatpp/core/data/mapping/type/Object.hpp" +#include "oatpp/core/macro/codegen.hpp" + +namespace Dto +{ + #include OATPP_CODEGEN_BEGIN(DTO) + + class songDto : public oatpp::data::mapping::type::Object + { + DTO_INIT(songDto, Object) + + DTO_FIELD(Int32, id); + DTO_FIELD(String, title); + DTO_FIELD(String, artist); + DTO_FIELD(String, album); + DTO_FIELD(String, genre); + DTO_FIELD(Int32, track); + DTO_FIELD(Int32, disc); + DTO_FIELD(Int32, year); + DTO_FIELD(Int32, duration); + }; + + #include OATPP_CODEGEN_END(DTO) +} + +#endif diff --git a/src/controller/loginController.hpp b/src/controller/loginController.hpp index 8db3c43..1ff42ca 100644 --- a/src/controller/loginController.hpp +++ b/src/controller/loginController.hpp @@ -9,7 +9,7 @@ #include "oatpp/core/macro/component.hpp" #include "oatpp/web/server/api/ApiController.hpp" -#include "../dto/loginResultDto.hpp" +#include "dto/loginResultDto.hpp" #include "managers/token_manager.h" namespace Controller @@ -27,14 +27,14 @@ namespace Controller #include OATPP_CODEGEN_BEGIN(ApiController) - ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(userDto::ObjectWrapper, usr)) { + ENDPOINT("POST", "/api/v1/login", data, BODY_DTO(Dto::userDto::ObjectWrapper, usr)) { OATPP_LOGI("icarus", "logging in"); Manager::token_manager tok; //auto token = tok.retrieve_token(exe_path); auto token = tok.retrieve_token(m_bConf); - auto logRes = loginResultDto::createShared(); + auto logRes = Dto::loginResultDto::createShared(); logRes->id = 0; // TODO: change this later on to something meaningful logRes->username = usr->username->c_str(); logRes->token = token.access_token.c_str(); diff --git a/src/controller/songController.hpp b/src/controller/songController.hpp index 95b80b1..54b6ee7 100644 --- a/src/controller/songController.hpp +++ b/src/controller/songController.hpp @@ -18,7 +18,7 @@ #include "oatpp/web/server/api/ApiController.hpp" #include "database/songRepository.h" -#include "../dto/songDto.hpp" +#include "dto/songDto.hpp" #include "managers/song_manager.h" #include "managers/token_manager.h" #include "models/models.h" @@ -88,11 +88,11 @@ namespace Controller 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(); + auto songs = oatpp::data::mapping::type::List::createShared(); std::cout << "creating object to send" << std::endl; for (auto& songDb : songsDb) { - auto song = songDto::createShared(); + auto song = Dto::songDto::createShared(); song->id = songDb.id; song->title = songDb.title.c_str(); song->artist = songDb.artist.c_str(); @@ -119,7 +119,7 @@ namespace Controller songDb = songRepo.retrieveRecord(songDb, Type::songFilter::id); - auto song = songDto::createShared(); + auto song = Dto::songDto::createShared(); song->id = songDb.id; song->title = songDb.title.c_str(); song->artist = songDb.artist.c_str(); diff --git a/src/dto/loginResultDto.hpp b/src/dto/loginResultDto.hpp deleted file mode 100644 index 935bbc7..0000000 --- a/src/dto/loginResultDto.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LOGINRESULTDTO_H_ -#define LOGINRESULTDTO_H_ - -#include "oatpp/core/data/mapping/type/Object.hpp" -#include "oatpp/core/macro/codegen.hpp" - -#include OATPP_CODEGEN_BEGIN(DTO) - -class loginResultDto : public oatpp::data::mapping::type::Object -{ - DTO_INIT(loginResultDto, Object) - - DTO_FIELD(Int32, id); - DTO_FIELD(String, username); - DTO_FIELD(String, token); - DTO_FIELD(String, token_type); - DTO_FIELD(Int32, expiration); - DTO_FIELD(String, message); -}; - -class userDto : public oatpp::data::mapping::type::Object -{ - DTO_INIT(userDto, Object) - - DTO_FIELD(String, username); - DTO_FIELD(String, password); -}; - -#include OATPP_CODEGEN_END(DTO) - -#endif diff --git a/src/dto/songDto.hpp b/src/dto/songDto.hpp deleted file mode 100644 index cc13c11..0000000 --- a/src/dto/songDto.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef SONGDTO_H_ -#define SONGDTO_H_ - -#include "oatpp/core/data/mapping/type/Object.hpp" -#include "oatpp/core/macro/codegen.hpp" - -#include OATPP_CODEGEN_BEGIN(DTO) - -class songDto : public oatpp::data::mapping::type::Object -{ - DTO_INIT(songDto, Object) - - DTO_FIELD(Int32, id); - DTO_FIELD(String, title); - DTO_FIELD(String, artist); - DTO_FIELD(String, album); - DTO_FIELD(String, genre); - DTO_FIELD(Int32, track); - DTO_FIELD(Int32, disc); - DTO_FIELD(Int32, year); - DTO_FIELD(Int32, duration); -}; - -#include OATPP_CODEGEN_END(DTO) - -#endif From ab3000c2a02518d3ab282ed5e55650c565b872c4 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 1 Sep 2019 17:13:31 -0400 Subject: [PATCH 32/36] Moved controllers to include directory --- CMakeLists.txt | 4 ++-- {src => include}/controller/loginController.hpp | 0 {src => include}/controller/songController.hpp | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename {src => include}/controller/loginController.hpp (100%) rename {src => include}/controller/songController.hpp (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80ac244..aa0aef0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,6 @@ set(CMAKE_CXX_STANDARD 17) set(SOURCES src/appComponent.hpp - src/controller/loginController.hpp - src/controller/songController.hpp src/database/albumRepository.cpp src/database/artistRepository.cpp src/database/base_repository.cpp @@ -29,6 +27,8 @@ set(SOURCES src/utilities/metadata_retriever.cpp ) set(HEADERS + include/controller/loginController.hpp + include/controller/songController.hpp include/database/albumRepository.h include/database/artistRepository.h include/database/base_repository.h diff --git a/src/controller/loginController.hpp b/include/controller/loginController.hpp similarity index 100% rename from src/controller/loginController.hpp rename to include/controller/loginController.hpp diff --git a/src/controller/songController.hpp b/include/controller/songController.hpp similarity index 100% rename from src/controller/songController.hpp rename to include/controller/songController.hpp From fafb39326bc07a45c0c457ce676696987c78c827 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sun, 1 Sep 2019 18:46:02 -0400 Subject: [PATCH 33/36] Left off at adding album record to the database and retrieving the album record to assign the album id to the song record's album id foreign key --- CMakeLists.txt | 6 +- Scripts/MySQL/create_database.sql | 42 ++++++++++- include/component/appComponent.hpp | 38 ++++++++++ include/database/albumRepository.h | 11 +++ include/managers/albumManager.h | 2 + include/managers/song_manager.h | 1 + include/models/models.h | 2 + include/types/albumFilter.h | 14 ++++ include/types/artistFilter.h | 13 ++++ include/types/genreFilter.h | 13 ++++ include/types/yearFilter.h | 13 ++++ src/appComponent.hpp | 34 --------- src/database/albumRepository.cpp | 117 +++++++++++++++++++++++++++++ src/database/songRepository.cpp | 1 + src/main.cpp | 9 +-- src/managers/albumManager.cpp | 14 ++++ src/managers/song_manager.cpp | 49 +++++++----- 17 files changed, 320 insertions(+), 59 deletions(-) create mode 100644 include/component/appComponent.hpp create mode 100644 include/types/albumFilter.h create mode 100644 include/types/artistFilter.h create mode 100644 include/types/genreFilter.h create mode 100644 include/types/yearFilter.h delete mode 100644 src/appComponent.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index aa0aef0..e86a9fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) set(SOURCES - src/appComponent.hpp src/database/albumRepository.cpp src/database/artistRepository.cpp src/database/base_repository.cpp @@ -27,6 +26,7 @@ set(SOURCES src/utilities/metadata_retriever.cpp ) set(HEADERS + include/component/appComponent.hpp include/controller/loginController.hpp include/controller/songController.hpp include/database/albumRepository.h @@ -49,9 +49,13 @@ set(HEADERS include/models/models.h include/utilities/imageFile.h include/utilities/metadata_retriever.h + include/types/albumFilter.h + include/types/artistFilter.h include/types/coverFilter.h + include/types/genreFilter.h include/types/scopes.h include/types/songFilter.h + include/types/yearFilter.h ) set (TAGLIB diff --git a/Scripts/MySQL/create_database.sql b/Scripts/MySQL/create_database.sql index 7e0d410..8594eb5 100644 --- a/Scripts/MySQL/create_database.sql +++ b/Scripts/MySQL/create_database.sql @@ -10,6 +10,34 @@ CREATE TABLE CoverArt ( PRIMARY KEY (CoverArtId) ); +CREATE TABLE Album ( + AlbumId INT NOT NULL AUTO_INCREMENT, + Title TEXT NOT NULL, + Year INT NOT NULL, + + PRIMARY KEY (AlbumId) +); + +CREATE TABLE Artist ( + ArtistId INT NOT NULL AUTO_INCREMENT, + Artist TEXT NOT NULL, + + PRIMARY KEY (ArtistId) +); + +CREATE TABLE Genre ( + GenreId INT NOT NULL AUTO_INCREMENT, + Category TEXT NOT NULL, + + PRIMARY KEY (GenreId) +); + +CREATE TABLE Year ( + YearId INT NOT NULL AUTO_INCREMENT, + + PRIMARY KEY (YearId) +); + CREATE TABLE Song ( SongId INT NOT NULL AUTO_INCREMENT, Title TEXT NOT NULL, @@ -22,13 +50,25 @@ CREATE TABLE Song ( Disc INT NOT NULL, SongPath TEXT NOT NULL, CoverArtId INT NOT NULL, + ArtistId INT NOT NULL, + AlbumId INT NOT NULL, + GenreId INT NOT NULL, + YearId INT NOT NULL, PRIMARY KEY (SongId), - CONSTRAINT FK_CoverArtId FOREIGN KEY (CoverArtId) REFERENCES CoverArt(CoverArtId) + CONSTRAINT FK_CoverArtId FOREIGN KEY (CoverArtId) REFERENCES CoverArt (CoverArtId), + CONSTRAINT FK_ArtistId FOREIGN KEY (ArtistId) REFERENCES Artist (ArtistId), + CONSTRAINT FK_AlbumId FOREIGN KEY (AlbumId) REFERENCES Album (AlbumId), + CONSTRAINT FK_GenreId FOREIGN KEY (GenreId) REFERENCES Genre (GenreId), + CONSTRAINT FK_YearId FOREIGN KEY (YearId) REFERENCES Year (YearId) ); CREATE TABLE User ( UserId INT NOT NULL AUTO_INCREMENT, + Firstname TEXT NOT NULL, + Lastname TEXT NOT NULL, + Email TEXT NOT NULL, + Phone TEXT NOT NULL, Username TEXT NOT NULL, Password TEXT NOT NULL, diff --git a/include/component/appComponent.hpp b/include/component/appComponent.hpp new file mode 100644 index 0000000..78837d3 --- /dev/null +++ b/include/component/appComponent.hpp @@ -0,0 +1,38 @@ +#ifndef APPCOMPONENT_H_ +#define APPCOMPONENT_H_ + +#include + +#include "oatpp/core/macro/component.hpp" +#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp/web/server/HttpConnectionHandler.hpp" + +namespace Component +{ + + 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, serverConnectionHandler)([] { + OATPP_COMPONENT(std::shared_ptr, router); + + return oatpp::web::server::HttpConnectionHandler::createShared(router); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { + return oatpp::parser::json::mapping::ObjectMapper::createShared(); + }()); + private: + }; +} + +#endif diff --git a/include/database/albumRepository.h b/include/database/albumRepository.h index 6525da2..d2b7be0 100644 --- a/include/database/albumRepository.h +++ b/include/database/albumRepository.h @@ -1,8 +1,11 @@ #ifndef ALBUMREPOSITORY_H_ #define ALBUMREPOSITORY_H_ +#include + #include "database/base_repository.h" #include "models/models.h" +#include "types/albumFilter.h" namespace Database { @@ -10,7 +13,15 @@ namespace Database { public: albumRepository(const Model::BinaryPath&); + + std::vector retrieveRecords(); + + Model::Album retrieveRecord(Model::Album&, Type::albumFilter); + + void saveAlbum(const Model::Album&); private: + std::vector parseRecords(MYSQL_RES*); + Model::Album parseRecord(MYSQL_RES*); }; } diff --git a/include/managers/albumManager.h b/include/managers/albumManager.h index c6a83a2..2dac3a2 100644 --- a/include/managers/albumManager.h +++ b/include/managers/albumManager.h @@ -9,6 +9,8 @@ namespace Manager { public: albumManager(const Model::BinaryPath&); + + void saveAlbum(const Model::Song&); private: Model::BinaryPath m_bConf; }; diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h index 1865b19..f49c1d8 100644 --- a/include/managers/song_manager.h +++ b/include/managers/song_manager.h @@ -22,6 +22,7 @@ namespace Manager static void printSong(const Model::Song&); private: void saveSongTemp(Model::Song&); + void saveMisc(Model::Song&); Model::BinaryPath m_bConf; std::string exe_path; diff --git a/include/models/models.h b/include/models/models.h index 2d30e01..06a1373 100644 --- a/include/models/models.h +++ b/include/models/models.h @@ -92,6 +92,8 @@ namespace Model struct BinaryPath { + BinaryPath() = default; + BinaryPath(const char *p) : path(std::move(p)) { } std::string path; }; } diff --git a/include/types/albumFilter.h b/include/types/albumFilter.h new file mode 100644 index 0000000..c9e2b83 --- /dev/null +++ b/include/types/albumFilter.h @@ -0,0 +1,14 @@ +#ifndef ALBUMFILTER_H_ +#define ALBUMFILTER_H_ + +namespace Type +{ + enum class albumFilter + { + id = 0, + title, + year + }; +} + +#endif diff --git a/include/types/artistFilter.h b/include/types/artistFilter.h new file mode 100644 index 0000000..a5243c7 --- /dev/null +++ b/include/types/artistFilter.h @@ -0,0 +1,13 @@ +#ifndef ARTISTFILTER_H_ +#define ARTISTFILTER_H_ + +namespace Type +{ + enum class artistFilter + { + id = 0, + artist + }; +} + +#endif diff --git a/include/types/genreFilter.h b/include/types/genreFilter.h new file mode 100644 index 0000000..27cf279 --- /dev/null +++ b/include/types/genreFilter.h @@ -0,0 +1,13 @@ +#ifndef GENREFILTER_H_ +#define GENREFILTER_H_ + +namespace Type +{ + enum class genreFilter + { + id = 0, + category + }; +} + +#endif diff --git a/include/types/yearFilter.h b/include/types/yearFilter.h new file mode 100644 index 0000000..6161d6c --- /dev/null +++ b/include/types/yearFilter.h @@ -0,0 +1,13 @@ +#ifndef YEARFILTER_H_ +#define YEARFILTER_H_ + +namespace Type +{ + enum class yearFilter + { + id = 0, + year + }; +} + +#endif diff --git a/src/appComponent.hpp b/src/appComponent.hpp deleted file mode 100644 index 2ddc5b7..0000000 --- a/src/appComponent.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef APPCOMPONENT_H_ -#define APPCOMPONENT_H_ - -#include - -#include "oatpp/core/macro/component.hpp" -#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" -#include "oatpp/parser/json/mapping/ObjectMapper.hpp" -#include "oatpp/web/server/HttpConnectionHandler.hpp" - -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, serverConnectionHandler)([] { - OATPP_COMPONENT(std::shared_ptr, router); - - return oatpp::web::server::HttpConnectionHandler::createShared(router); - }()); - - OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { - return oatpp::parser::json::mapping::ObjectMapper::createShared(); - }()); -private: -}; - -#endif diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp index 99d41f1..f3cebb0 100644 --- a/src/database/albumRepository.cpp +++ b/src/database/albumRepository.cpp @@ -1,5 +1,122 @@ #include "database/albumRepository.h" +#include +#include +#include +#include +#include + Database::albumRepository::albumRepository(const Model::BinaryPath& bConf) : base_repository(bConf) { } + + +// TODO: implement this later on +std::vector Database::albumRepository::retrieveRecords() +{ + std::vector albums; + + return albums; +} + +Model::Album Database::albumRepository::retrieveRecord(Model::Album& album, Type::albumFilter filter) +{ + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT alb.* FROM Album alb WHERE "; + + std::unique_ptr param; + switch (filter) { + case Type::albumFilter::id: + qry << "alb.AlbumId = " << album.id; + break; + case Type::albumFilter::title: + param = std::make_unique(new char[album.title.size()]); + mysql_real_escape_string(conn, *param, album.title.c_str(), album.title.size()); + qry << "alb.Title = '" << *param << "'"; + break; + case Type::albumFilter::year: + break; + default: + break; + } + + const std::string query = qry.str(); + auto results = perform_mysql_query(conn, query); + + album = parseRecord(results); + + mysql_close(conn); + std::cout << "done" << std::endl; + + return album; +} + +void Database::albumRepository::saveAlbum(const Model::Album& album) +{ + std::cout << "beginning to insert album record" << std::endl; + + auto conn = setup_mysql_connection(); + auto status = 0; + + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + std::string query = "INSERT INTO Album(Title, Year) VALUES(?, ?)"; + + status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[2]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)album.title.c_str(); + auto titleLength = album.title.size(); + params[0].buffer = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_LONG; + params[1].buffer = (char*)&album.year; + params[1].length = 0; + params[1].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done inserting album record" << std::endl; +} + + +// TODO: implement this +std::vector Database::albumRepository::parseRecords(MYSQL_RES* results) +{ + std::vector albums; + + return albums; +} + +Model::Album Database::albumRepository::parseRecord(MYSQL_RES* results) +{ + Model::Album album; + auto fieldNum = mysql_num_fields(results); + + auto row = mysql_fetch_row(results); + + for (auto i = 0; i != fieldNum; ++i) { + const std::string field(mysql_fetch_field(results)->name); + + if (field.compare("AlbumId") == 0) { + album.id = std::stoi(row[i]); + } + if (field.compare("Title") == 0) { + album.title = row[i]; + } + if (field.compare("Year") == 0) { + album.year = std::stoi(row[i]); + } + } + + return album; +} diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 4e9262b..026f7e7 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -74,6 +74,7 @@ void Database::songRepository::deleteRecord(const Model::Song& song) void Database::songRepository::saveRecord(const Model::Song& song) { + std::cout << "beginning to insert song record" << std::endl; auto conn = setup_mysql_connection(); auto status = 0; diff --git a/src/main.cpp b/src/main.cpp index ca0a705..6326d5b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,7 @@ #include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" #include "oatpp/web/server/HttpConnectionHandler.hpp" -#include "appComponent.hpp" +#include "component/appComponent.hpp" #include "controller/loginController.hpp" #include "controller/songController.hpp" #include "database/base_repository.h" @@ -20,7 +20,7 @@ namespace fs = std::filesystem; //void run(const std::string& working_path) void run(const Model::BinaryPath& bConf) { - appComponent component; + Component::appComponent component; OATPP_COMPONENT(std::shared_ptr, router); @@ -43,11 +43,8 @@ void run(const Model::BinaryPath& bConf) int main(int argc, char **argv) { oatpp::base::Environment::init(); - //const std::string working_path = argv[0]; - Model::BinaryPath bConf; - bConf.path = argv[0]; + Model::BinaryPath bConf(argv[0]); - //run(working_path); run(bConf); oatpp::base::Environment::destroy(); diff --git a/src/managers/albumManager.cpp b/src/managers/albumManager.cpp index 46f4d6e..af0de69 100644 --- a/src/managers/albumManager.cpp +++ b/src/managers/albumManager.cpp @@ -1,5 +1,19 @@ #include "managers/albumManager.h" +#include "database/albumRepository.h" +#include "models/models.h" + Manager::albumManager::albumManager(const Model::BinaryPath& bConf) : m_bConf(bConf) { } + + +void Manager::albumManager::saveAlbum(const Model::Song& song) +{ + Model::Album album; + album.title = song.album; + album.year = song.year; + + Database::albumRepository albRepo(m_bConf); + albRepo.saveAlbum(album); +} diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index d59100c..b49d8e0 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -8,8 +8,12 @@ #include "database/coverArtRepository.h" #include "database/songRepository.h" +#include "managers/albumManager.h" +#include "managers/artistManager.h" #include "managers/coverArtManager.h" #include "managers/directory_manager.h" +#include "managers/genreManager.h" +#include "managers/yearManager.h" #include "utilities/metadata_retriever.h" namespace fs = std::filesystem; @@ -31,25 +35,9 @@ void Manager::song_manager::saveSong(Model::Song& song) song = meta.retrieve_metadata(song.songPath); song.data = std::move(data); - coverArtManager covMgr(m_bConf); - auto pathConfigContent = Manager::directory_manager::pathConfigContent(m_bConf); - auto coverRootPath = pathConfigContent["cover_root_path"].get(); - auto musicRootPath = pathConfigContent["root_music_path"].get(); - auto stockCoverPath = Manager::directory_manager::configPath(m_bConf); - stockCoverPath.append("/CoverArt.png"); + saveMisc(song); - auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); - song.coverArtId = cov.id; - - auto songPath = Manager::directory_manager::create_directory_process(song, musicRootPath); - songPath.append(song.title); - songPath.append(".mp3"); - std::cout << "\n\ntemp path: " << song.songPath << std::endl; - std::cout << "new path: " << songPath << std::endl; - fs::copy(song.songPath, songPath); - fs::remove(song.songPath); - song.songPath = std::move(songPath); printSong(song); @@ -120,3 +108,30 @@ void Manager::song_manager::saveSongTemp(Model::Song& song) song.songPath = tmp_song; } +void Manager::song_manager::saveMisc(Model::Song& song) +{ + coverArtManager covMgr(m_bConf); + auto pathConfigContent = Manager::directory_manager::pathConfigContent(m_bConf); + auto coverRootPath = pathConfigContent["cover_root_path"].get(); + auto musicRootPath = pathConfigContent["root_music_path"].get(); + + auto stockCoverPath = Manager::directory_manager::configPath(m_bConf); + stockCoverPath.append("/CoverArt.png"); + + auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); + song.coverArtId = cov.id; + + auto songPath = Manager::directory_manager::create_directory_process(song, musicRootPath); + songPath.append(song.title); + songPath.append(".mp3"); + std::cout << "\n\ntemp path: " << song.songPath << std::endl; + std::cout << "new path: " << songPath << std::endl; + fs::copy(song.songPath, songPath); + fs::remove(song.songPath); + song.songPath = std::move(songPath); + + artistManager artMgr(m_bConf); + albumManager albMgr(m_bConf); + genreManager gnrMgr(m_bConf); + yearManager yrMgr(m_bConf); +} From 4306c174b3b1e6badf549bc008ae425f33c2a5c4 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 2 Sep 2019 13:59:49 -0400 Subject: [PATCH 34/36] Able to save and retrieve records (Artist, Album, Genre, etc.) --- Scripts/MySQL/create_database.sql | 1 + include/controller/loginController.hpp | 1 - include/database/artistRepository.h | 7 +- include/database/genreRepository.h | 6 ++ include/database/yearRepository.h | 6 ++ include/managers/albumManager.h | 5 +- include/managers/artistManager.h | 5 ++ include/managers/directory_manager.h | 6 +- include/managers/genreManager.h | 5 ++ include/managers/yearManager.h | 5 ++ include/models/models.h | 2 + src/database/albumRepository.cpp | 16 ++--- src/database/artistRepository.cpp | 96 ++++++++++++++++++++++++++ src/database/coverArtRepository.cpp | 2 - src/database/genreRepository.cpp | 94 +++++++++++++++++++++++++ src/database/songRepository.cpp | 26 ++++++- src/database/yearRepository.cpp | 92 ++++++++++++++++++++++++ src/main.cpp | 3 +- src/managers/albumManager.cpp | 23 +++++- src/managers/artistManager.cpp | 33 +++++++++ src/managers/coverArtManager.cpp | 4 +- src/managers/directory_manager.cpp | 6 ++ src/managers/genreManager.cpp | 32 +++++++++ src/managers/song_manager.cpp | 46 +++++++++--- src/managers/token_manager.cpp | 2 +- src/managers/yearManager.cpp | 32 +++++++++ 26 files changed, 522 insertions(+), 34 deletions(-) diff --git a/Scripts/MySQL/create_database.sql b/Scripts/MySQL/create_database.sql index 8594eb5..8680c54 100644 --- a/Scripts/MySQL/create_database.sql +++ b/Scripts/MySQL/create_database.sql @@ -34,6 +34,7 @@ CREATE TABLE Genre ( CREATE TABLE Year ( YearId INT NOT NULL AUTO_INCREMENT, + Year INT NOT NULL, PRIMARY KEY (YearId) ); diff --git a/include/controller/loginController.hpp b/include/controller/loginController.hpp index 1ff42ca..94301db 100644 --- a/include/controller/loginController.hpp +++ b/include/controller/loginController.hpp @@ -31,7 +31,6 @@ namespace Controller OATPP_LOGI("icarus", "logging in"); Manager::token_manager tok; - //auto token = tok.retrieve_token(exe_path); auto token = tok.retrieve_token(m_bConf); auto logRes = Dto::loginResultDto::createShared(); diff --git a/include/database/artistRepository.h b/include/database/artistRepository.h index f104a8a..f47a69d 100644 --- a/include/database/artistRepository.h +++ b/include/database/artistRepository.h @@ -3,7 +3,7 @@ #include "database/base_repository.h" #include "models/models.h" -#include "types/coverFilter.h" +#include "types/artistFilter.h" namespace Database { @@ -11,7 +11,12 @@ namespace Database { public: artistRepository(const Model::BinaryPath&); + + Model::Artist retrieveRecord(Model::Artist&, Type::artistFilter); + + void saveRecord(const Model::Artist&); private: + Model::Artist parseRecord(MYSQL_RES*); }; } diff --git a/include/database/genreRepository.h b/include/database/genreRepository.h index 50f9858..927eb3a 100644 --- a/include/database/genreRepository.h +++ b/include/database/genreRepository.h @@ -3,6 +3,7 @@ #include "database/base_repository.h" #include "models/models.h" +#include "types/genreFilter.h" namespace Database { @@ -10,7 +11,12 @@ namespace Database { public: genreRepository(const Model::BinaryPath&); + + Model::Genre retrieveRecord(Model::Genre&, Type::genreFilter); + + void saveRecord(const Model::Genre&); private: + Model::Genre parseRecord(MYSQL_RES*); }; } diff --git a/include/database/yearRepository.h b/include/database/yearRepository.h index d6157ce..da61784 100644 --- a/include/database/yearRepository.h +++ b/include/database/yearRepository.h @@ -3,6 +3,7 @@ #include "database/base_repository.h" #include "models/models.h" +#include "types/yearFilter.h" namespace Database { @@ -10,7 +11,12 @@ namespace Database { public: yearRepository(const Model::BinaryPath&); + + Model::Year retrieveRecord(Model::Year&, Type::yearFilter); + + void saveRecord(const Model::Year&); private: + Model::Year parseRecord(MYSQL_RES*); }; } diff --git a/include/managers/albumManager.h b/include/managers/albumManager.h index 2dac3a2..f487054 100644 --- a/include/managers/albumManager.h +++ b/include/managers/albumManager.h @@ -10,7 +10,10 @@ namespace Manager public: albumManager(const Model::BinaryPath&); - void saveAlbum(const Model::Song&); + Model::Album retrieveAlbum(Model::Album&); + Model::Album saveAlbum(const Model::Song&); + + static void printAlbum(const Model::Album&); private: Model::BinaryPath m_bConf; }; diff --git a/include/managers/artistManager.h b/include/managers/artistManager.h index f34db3e..42266ee 100644 --- a/include/managers/artistManager.h +++ b/include/managers/artistManager.h @@ -9,6 +9,11 @@ namespace Manager { public: artistManager(const Model::BinaryPath&); + + Model::Artist retrieveArtist(Model::Artist&); + Model::Artist saveArtist(const Model::Song&); + + static void printArtist(const Model::Artist&); private: Model::BinaryPath m_bConf; }; diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h index 2535e5a..c8ca3c8 100644 --- a/include/managers/directory_manager.h +++ b/include/managers/directory_manager.h @@ -18,11 +18,11 @@ namespace Manager static std::string configPath(const Model::BinaryPath&); static std::string contentOfPath(const std::string&); - static nlohmann::json credentialConfigContent(const std::string&); + //static nlohmann::json credentialConfigContent(const std::string&); static nlohmann::json credentialConfigContent(const Model::BinaryPath&); - static nlohmann::json databaseConfigContent(const std::string&); + //static nlohmann::json databaseConfigContent(const std::string&); static nlohmann::json databaseConfigContent(const Model::BinaryPath&); - static nlohmann::json pathConfigContent(const std::string&); + //static nlohmann::json pathConfigContent(const std::string&); static nlohmann::json pathConfigContent(const Model::BinaryPath&); void delete_cover_art_file(const std::string&, const std::string&); diff --git a/include/managers/genreManager.h b/include/managers/genreManager.h index f456e8d..35149a7 100644 --- a/include/managers/genreManager.h +++ b/include/managers/genreManager.h @@ -9,6 +9,11 @@ namespace Manager { public: genreManager(const Model::BinaryPath&); + + Model::Genre retrieveGenre(Model::Genre&); + Model::Genre saveGenre(const Model::Song&); + + static void printGenre(const Model::Genre&); private: Model::BinaryPath m_bConf; }; diff --git a/include/managers/yearManager.h b/include/managers/yearManager.h index db7fc99..c5f33e8 100644 --- a/include/managers/yearManager.h +++ b/include/managers/yearManager.h @@ -9,6 +9,11 @@ namespace Manager { public: yearManager(const Model::BinaryPath&); + + Model::Year retrieveYear(Model::Year&); + Model::Year saveYear(const Model::Song&); + + static void printYear(const Model::Year&); private: Model::BinaryPath m_bConf; }; diff --git a/include/models/models.h b/include/models/models.h index 06a1373..8ef3e1b 100644 --- a/include/models/models.h +++ b/include/models/models.h @@ -94,6 +94,8 @@ namespace Model { BinaryPath() = default; BinaryPath(const char *p) : path(std::move(p)) { } + BinaryPath(std::string& p) : path(std::move(p)) { } + BinaryPath(const std::string& p) : path(std::move(p)) { } std::string path; }; } diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp index f3cebb0..239a1ce 100644 --- a/src/database/albumRepository.cpp +++ b/src/database/albumRepository.cpp @@ -21,6 +21,7 @@ std::vector Database::albumRepository::retrieveRecords() Model::Album Database::albumRepository::retrieveRecord(Model::Album& album, Type::albumFilter filter) { + std::cout << "retrieving album record" << std::endl; std::stringstream qry; auto conn = setup_mysql_connection(); qry << "SELECT alb.* FROM Album alb WHERE "; @@ -35,12 +36,12 @@ Model::Album Database::albumRepository::retrieveRecord(Model::Album& album, Type mysql_real_escape_string(conn, *param, album.title.c_str(), album.title.size()); qry << "alb.Title = '" << *param << "'"; break; - case Type::albumFilter::year: - break; default: break; } + qry << " ORDER BY AlbumId DESC LIMIT 1"; + const std::string query = qry.str(); auto results = perform_mysql_query(conn, query); @@ -57,13 +58,11 @@ void Database::albumRepository::saveAlbum(const Model::Album& album) std::cout << "beginning to insert album record" << std::endl; auto conn = setup_mysql_connection(); - auto status = 0; - MYSQL_STMT *stmt = mysql_stmt_init(conn); - std::string query = "INSERT INTO Album(Title, Year) VALUES(?, ?)"; + const std::string query = "INSERT INTO Album(Title, Year) VALUES(?, ?)"; - status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); MYSQL_BIND params[2]; memset(params, 0, sizeof(params)); @@ -71,7 +70,7 @@ void Database::albumRepository::saveAlbum(const Model::Album& album) params[0].buffer_type = MYSQL_TYPE_STRING; params[0].buffer = (char*)album.title.c_str(); auto titleLength = album.title.size(); - params[0].buffer = &titleLength; + params[0].length= &titleLength; params[0].is_null = 0; params[1].buffer_type = MYSQL_TYPE_LONG; @@ -99,9 +98,10 @@ std::vector Database::albumRepository::parseRecords(MYSQL_RES* res Model::Album Database::albumRepository::parseRecord(MYSQL_RES* results) { + std::cout << "parsing album record" << std::endl; Model::Album album; - auto fieldNum = mysql_num_fields(results); + auto fieldNum = mysql_num_fields(results); auto row = mysql_fetch_row(results); for (auto i = 0; i != fieldNum; ++i) { diff --git a/src/database/artistRepository.cpp b/src/database/artistRepository.cpp index 4d5fb35..7aa145e 100644 --- a/src/database/artistRepository.cpp +++ b/src/database/artistRepository.cpp @@ -1,6 +1,102 @@ #include "database/artistRepository.h" +#include +#include +#include +#include +#include + Database::artistRepository::artistRepository(const Model::BinaryPath& binConf) : base_repository(binConf) { } + + +Model::Artist Database::artistRepository::retrieveRecord(Model::Artist& artist, Type::artistFilter filter) +{ + std::cout << "retrieving artist record" << std::endl; + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT art.* FROM Artist art WHERE "; + + std::unique_ptr param; + switch (filter) { + case Type::artistFilter::id: + qry << "art.ArtistId = " << artist.id; + break; + case Type::artistFilter::artist: + param = std::make_unique(new char[artist.artist.size()]); + mysql_real_escape_string(conn, *param, artist.artist.c_str(), artist.artist.size()); + qry << "art.Artist ='" << *param << "'"; + break; + default: + break; + } + + qry << " ORDER BY ArtistId DESC LIMIT 1"; + + const auto query = qry.str(); + auto results = perform_mysql_query(conn, query); + + artist = parseRecord(results); + + mysql_close(conn); + + std::cout << "retrieved record" << std::endl; + + return artist; +} + +void Database::artistRepository::saveRecord(const Model::Artist& artist) +{ + std::cout << "inserting artist record" << std::endl; + + auto conn = setup_mysql_connection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + const std::string query = "INSERT INTO Artist(Artist) VALUES(?)"; + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)artist.artist.c_str(); + auto artistLength = artist.artist.size(); + params[0].length = &artistLength; + params[0].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout<< "inserted artist record" << std::endl; +} + + +Model::Artist Database::artistRepository::parseRecord(MYSQL_RES* results) +{ + std::cout << "parsing artist record" << std::endl; + Model::Artist artist; + + auto fieldNum = mysql_num_fields(results); + auto row = mysql_fetch_row(results); + + for (auto i = 0; i != fieldNum; ++i) { + const std::string field(mysql_fetch_field(results)->name); + + if (field.compare("ArtistId") == 0) { + artist.id = std::stoi(row[i]); + } + if (field.compare("Artist") == 0) { + artist.artist = row[i]; + } + } + + std::cout << "parsed artist record" << std::endl; + + return artist; +} diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index bab5aea..f559902 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -25,13 +25,11 @@ Model::Cover Database::coverArtRepository::retrieveRecord(Model::Cover& cov, Typ case Type::coverFilter::songTitle: param = std::make_unique(new char[cov.songTitle.size()]); mysql_real_escape_string(conn, *param, cov.songTitle.c_str(), cov.songTitle.size()); - std::cout << *param << std::endl; qry << "SongTitle = '" << *param << "'"; break; case Type::coverFilter::imagePath: param = std::make_unique(new char[cov.imagePath.size()]); mysql_real_escape_string(conn, *param, cov.imagePath.c_str(), cov.imagePath.size()); - std::cout << *param << std::endl; qry << "ImagePath = '" << *param << "'"; break; } diff --git a/src/database/genreRepository.cpp b/src/database/genreRepository.cpp index 5e49c8c..b25e2cf 100644 --- a/src/database/genreRepository.cpp +++ b/src/database/genreRepository.cpp @@ -1,5 +1,99 @@ #include "database/genreRepository.h" +#include +#include +#include +#include + Database::genreRepository::genreRepository(const Model::BinaryPath& bConf) : base_repository(bConf) { } + + +Model::Genre Database::genreRepository::retrieveRecord(Model::Genre& genre, Type::genreFilter filter) +{ + std::cout << "retrieving genre record" << std::endl; + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT gnr.* FROM Genre gnr WHERE "; + + std::unique_ptr param; + switch (filter) { + case Type::genreFilter::id: + qry << "gnr.GenreId = " << genre.id; + break; + case Type::genreFilter::category: + param = std::make_unique(new char[genre.category.size()]); + mysql_real_escape_string(conn, *param, genre.category.c_str(), genre.category.size()); + qry << "gnr.Category ='" << *param << "'"; + break; + default: + break; + } + + qry << " ORDER BY GenreId DESC LIMIT 1"; + + const auto query = qry.str(); + auto results = perform_mysql_query(conn, query); + + genre = parseRecord(results); + + mysql_close(conn); + + std::cout << "retrieved record" << std::endl; + + return genre; +} + +void Database::genreRepository::saveRecord(const Model::Genre& genre) +{ + std::cout << "inserting genre record" << std::endl; + + auto conn = setup_mysql_connection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + const std::string query("INSERT INTO Genre(Category) VALUES(?)"); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)genre.category.c_str(); + auto categoryLength = genre.category.size(); + params[0].length = &categoryLength; + params[0].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "inserted record" << std::endl; +} + +Model::Genre Database::genreRepository::parseRecord(MYSQL_RES* results) +{ + std::cout << "parsing genre record" << std::endl; + Model::Genre genre; + + auto fieldNum = mysql_num_fields(results); + auto row = mysql_fetch_row(results); + + for (auto i =0; i != fieldNum; ++i) { + const std::string field(mysql_fetch_field(results)->name); + + if (field.compare("GenreId") == 0) { + genre.id = std::stoi(row[i]); + } + if (field.compare("Category") == 0) { + genre.category = row[i]; + } + } + + std::cout << "parsed genre record" << std::endl; + + return genre; +} diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 026f7e7..1536fae 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -41,7 +41,6 @@ Model::Song Database::songRepository::retrieveRecord(Model::Song& song, Type::so case Type::songFilter::title: param = std::make_unique(new char[song.title.size()]); mysql_real_escape_string(conn, *param, song.title.c_str(), song.title.size()); - std::cout << *param << std::endl; qry << "Title = '" << *param << "'"; break; default: @@ -81,11 +80,12 @@ void Database::songRepository::saveRecord(const Model::Song& song) MYSQL_STMT *stmt = mysql_stmt_init(conn); std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; - query.append("Year, Duration, Track, Disc, SongPath, CoverArtId) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + query.append("Year, Duration, Track, Disc, SongPath, CoverArtId, ArtistId, "); + query.append("AlbumId, GenreId, YearId) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); - MYSQL_BIND params[10]; + MYSQL_BIND params[14]; memset(params, 0, sizeof(params)); params[0].buffer_type = MYSQL_TYPE_STRING; @@ -142,7 +142,27 @@ void Database::songRepository::saveRecord(const Model::Song& song) params[9].buffer = (char*)&song.coverArtId; params[9].length = 0; params[9].is_null = 0; + + params[10].buffer_type = MYSQL_TYPE_LONG; + params[10].buffer = (char*)&song.artistId; + params[10].length = 0; + params[10].is_null = 0; + + params[11].buffer_type = MYSQL_TYPE_LONG; + params[11].buffer = (char*)&song.albumId; + params[11].length = 0; + params[11].is_null = 0; + params[12].buffer_type = MYSQL_TYPE_LONG; + params[12].buffer = (char*)&song.genreId; + params[12].length = 0; + params[12].is_null = 0; + + params[13].buffer_type = MYSQL_TYPE_LONG; + params[13].buffer = (char*)&song.yearId; + params[13].length = 0; + params[13].is_null = 0; + status = mysql_stmt_bind_param(stmt, params); status = mysql_stmt_execute(stmt); diff --git a/src/database/yearRepository.cpp b/src/database/yearRepository.cpp index 5e14f28..1d900c6 100644 --- a/src/database/yearRepository.cpp +++ b/src/database/yearRepository.cpp @@ -1,5 +1,97 @@ #include "database/yearRepository.h" +#include +#include +#include +#include +#include + + Database::yearRepository::yearRepository(const Model::BinaryPath& bConf) : base_repository(bConf) { } + + +Model::Year Database::yearRepository::retrieveRecord(Model::Year& year, Type::yearFilter filter) +{ + std::cout << "retrieving year record" << std::endl; + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT yr.* FROM Year yr WHERE "; + + switch (filter) { + case Type::yearFilter::id: + qry << "yr.YearId = " << year.id; + break; + case Type::yearFilter::year: + qry << "yr.Year = " << year.year; + break; + default: + break; + } + + qry << " ORDER BY yr.YearId DESC LIMIT 1"; + + const auto query = qry.str(); + auto results = perform_mysql_query(conn, query); + + year = parseRecord(results); + + mysql_close(conn); + + std::cout << "retrieved record" << std::endl; + + return year; +} + +void Database::yearRepository::saveRecord(const Model::Year& year) +{ + std::cout << "saving year record" << std::endl; + + auto conn = setup_mysql_connection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + const std::string query("INSERT INTO Year(Year) VALUES(?)"); + + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[1]; + memset(params, 0 , sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&year.year; + params[0].length = 0; + params[0].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "saved record" << std::endl; +} + +Model::Year Database::yearRepository::parseRecord(MYSQL_RES *results) +{ + std::cout << "parsing year record" << std::endl; + Model::Year year; + + auto fieldNum = mysql_num_fields(results); + auto row = mysql_fetch_row(results); + + for (auto i = 0; i != fieldNum; ++i) { + const std::string field(mysql_fetch_field(results)->name); + + if (field.compare("YearId") == 0) { + year.id= std::stoi(row[i]); + } + if (field.compare("Year") == 0) { + year.year = std::stoi(row[i]); + } + } + + std::cout << "parse year record" << std::endl; + + return year; +} diff --git a/src/main.cpp b/src/main.cpp index 6326d5b..9301bc2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,7 +43,8 @@ void run(const Model::BinaryPath& bConf) int main(int argc, char **argv) { oatpp::base::Environment::init(); - Model::BinaryPath bConf(argv[0]); + + Model::BinaryPath bConf(argv[0]); run(bConf); diff --git a/src/managers/albumManager.cpp b/src/managers/albumManager.cpp index af0de69..872204c 100644 --- a/src/managers/albumManager.cpp +++ b/src/managers/albumManager.cpp @@ -1,14 +1,25 @@ #include "managers/albumManager.h" +#include + #include "database/albumRepository.h" #include "models/models.h" +#include "types/albumFilter.h" Manager::albumManager::albumManager(const Model::BinaryPath& bConf) : m_bConf(bConf) { } -void Manager::albumManager::saveAlbum(const Model::Song& song) +Model::Album Manager::albumManager::retrieveAlbum(Model::Album& album) +{ + Database::albumRepository albRepo(m_bConf); + album = std::move(albRepo.retrieveRecord(album, Type::albumFilter::title)); + + return album; +} + +Model::Album Manager::albumManager::saveAlbum(const Model::Song& song) { Model::Album album; album.title = song.album; @@ -16,4 +27,14 @@ void Manager::albumManager::saveAlbum(const Model::Song& song) Database::albumRepository albRepo(m_bConf); albRepo.saveAlbum(album); + + return album; +} + +void Manager::albumManager::printAlbum(const Model::Album& album) +{ + std::cout << "\nalbum record" << std::endl; + std::cout << "id: " << album.id << std::endl; + std::cout << "title: " << album.title << std::endl; + std::cout << "year: " << album.year << std::endl; } diff --git a/src/managers/artistManager.cpp b/src/managers/artistManager.cpp index 1364c5c..41069a2 100644 --- a/src/managers/artistManager.cpp +++ b/src/managers/artistManager.cpp @@ -1,5 +1,38 @@ #include "managers/artistManager.h" +#include + +#include "database/artistRepository.h" +#include "types/artistFilter.h" + Manager::artistManager::artistManager(const Model::BinaryPath& bConf) : m_bConf(bConf) { } + + +Model::Artist Manager::artistManager::retrieveArtist(Model::Artist& artist) +{ + Database::artistRepository artRepo(m_bConf); + artist = artRepo.retrieveRecord(artist, Type::artistFilter::artist); + + return artist; +} + +Model::Artist Manager::artistManager::saveArtist(const Model::Song& song) +{ + Model::Artist artist; + artist.artist = song.artist; + + Database::artistRepository artRepo(m_bConf); + artRepo.saveRecord(artist); + + + return artist; +} + +void Manager::artistManager::printArtist(const Model::Artist& artist) +{ + std::cout << "\nartist record" << std::endl; + std::cout << "id: " << artist.id << std::endl; + std::cout << "artist: " << artist.artist << std::endl; +} diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index 711c3b6..c9f8a62 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -20,9 +20,9 @@ Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::s cov.songTitle = song.title; Database::coverArtRepository covRepo(m_bConf); - std::cout << "saving record to the database" << std::endl; + std::cout << "saving image record to the database" << std::endl; covRepo.saveRecord(cov); - std::cout << "retrieving record from database" << std::endl; + std::cout << "retrieving image record from database" << std::endl; cov = covRepo.retrieveRecord(cov, Type::coverFilter::songTitle); return cov; diff --git a/src/managers/directory_manager.cpp b/src/managers/directory_manager.cpp index 9702aa5..0b5647b 100644 --- a/src/managers/directory_manager.cpp +++ b/src/managers/directory_manager.cpp @@ -55,6 +55,7 @@ std::string Manager::directory_manager::contentOfPath(const std::string& path) return s.str(); } +/** nlohmann::json Manager::directory_manager::credentialConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); @@ -62,6 +63,7 @@ nlohmann::json Manager::directory_manager::credentialConfigContent(const std::st return nlohmann::json::parse(contentOfPath(path)); } +*/ nlohmann::json Manager::directory_manager::credentialConfigContent(const Model::BinaryPath& bConf) { auto path = configPath(bConf); @@ -69,6 +71,7 @@ nlohmann::json Manager::directory_manager::credentialConfigContent(const Model:: return nlohmann::json::parse(contentOfPath(path)); } +/** nlohmann::json Manager::directory_manager::databaseConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); @@ -76,6 +79,7 @@ nlohmann::json Manager::directory_manager::databaseConfigContent(const std::stri return nlohmann::json::parse(contentOfPath(path)); } +*/ nlohmann::json Manager::directory_manager::databaseConfigContent(const Model::BinaryPath& bConf) { auto path = configPath(bConf); @@ -83,6 +87,7 @@ nlohmann::json Manager::directory_manager::databaseConfigContent(const Model::Bi return nlohmann::json::parse(contentOfPath(path)); } +/** nlohmann::json Manager::directory_manager::pathConfigContent(const std::string& exe_path) { auto path = configPath(exe_path); @@ -90,6 +95,7 @@ nlohmann::json Manager::directory_manager::pathConfigContent(const std::string& return nlohmann::json::parse(contentOfPath(path)); } +*/ nlohmann::json Manager::directory_manager::pathConfigContent(const Model::BinaryPath& bConf) { auto path = configPath(bConf); diff --git a/src/managers/genreManager.cpp b/src/managers/genreManager.cpp index 2c6dc71..08cbc19 100644 --- a/src/managers/genreManager.cpp +++ b/src/managers/genreManager.cpp @@ -1,5 +1,37 @@ #include "managers/genreManager.h" +#include + +#include "database/genreRepository.h" +#include "types/genreFilter.h" + Manager::genreManager::genreManager(const Model::BinaryPath& bConf) : m_bConf(bConf) { } + + +Model::Genre Manager::genreManager::retrieveGenre(Model::Genre& genre) +{ + Database::genreRepository gnrRepo(m_bConf); + genre = gnrRepo.retrieveRecord(genre, Type::genreFilter::category); + + return genre; +} + +Model::Genre Manager::genreManager::saveGenre(const Model::Song& song) +{ + Model::Genre genre; + genre.category = song.genre; + + Database::genreRepository gnrRepo(m_bConf); + gnrRepo.saveRecord(genre); + + return genre; +} + +void Manager::genreManager::printGenre(const Model::Genre& genre) +{ + std::cout << "genre record" << std::endl; + std::cout << "id: " << genre.id << std::endl; + std::cout << "category: " << genre.category << std::endl; +} diff --git a/src/managers/song_manager.cpp b/src/managers/song_manager.cpp index b49d8e0..a61db06 100644 --- a/src/managers/song_manager.cpp +++ b/src/managers/song_manager.cpp @@ -35,10 +35,8 @@ void Manager::song_manager::saveSong(Model::Song& song) song = meta.retrieve_metadata(song.songPath); song.data = std::move(data); - saveMisc(song); - printSong(song); Database::songRepository songRepo(m_bConf); @@ -47,6 +45,9 @@ void Manager::song_manager::saveSong(Model::Song& song) void Manager::song_manager::deleteSong(Model::Song& song) { + // TODO: handle what happens to miscellanes records + // like Album, Artist, Genre, etc. when a song + // is deleted Database::coverArtRepository covRepo(m_bConf); Database::songRepository songRepo(m_bConf); @@ -75,7 +76,7 @@ void Manager::song_manager::deleteSong(Model::Song& song) void Manager::song_manager::printSong(const Model::Song& song) { - std::cout << "\n\nsong" << std::endl; + std::cout << "\nsong" << std::endl; std::cout << "title: " << song.title << std::endl; std::cout << "artist: " << song.artist << std::endl; std::cout << "album: " << song.album << std::endl; @@ -85,9 +86,11 @@ void Manager::song_manager::printSong(const Model::Song& song) std::cout << "track: " << song.track << std::endl; std::cout << "disc: " << song.disc << std::endl; std::cout << "song path: " << song.songPath << std::endl; - if (song.coverArtId != 0) { - std::cout << "cover art id: " << song.coverArtId << std::endl; - } + std::cout << "cover art id: " << song.coverArtId << std::endl; + std::cout << "album id: " << song.albumId << std::endl; + std::cout << "artist id: " << song.artistId << std::endl; + std::cout << "genre id: " << song.genreId << std::endl; + std::cout << "year id: " << song.yearId << std::endl; } void Manager::song_manager::saveSongTemp(Model::Song& song) @@ -119,19 +122,42 @@ void Manager::song_manager::saveMisc(Model::Song& song) stockCoverPath.append("/CoverArt.png"); auto cov = covMgr.saveCover(song, coverRootPath, stockCoverPath); - song.coverArtId = cov.id; auto songPath = Manager::directory_manager::create_directory_process(song, musicRootPath); songPath.append(song.title); songPath.append(".mp3"); - std::cout << "\n\ntemp path: " << song.songPath << std::endl; - std::cout << "new path: " << songPath << std::endl; + if (fs::exists(songPath)) { + std::cout << "deleting old song with the same metadata" << std::endl; + fs::remove(songPath); + } + std::cout << "copying song to the appropriate directory" << std::endl; fs::copy(song.songPath, songPath); fs::remove(song.songPath); song.songPath = std::move(songPath); - artistManager artMgr(m_bConf); albumManager albMgr(m_bConf); + auto album = albMgr.saveAlbum(song); + album = albMgr.retrieveAlbum(album); + Manager::albumManager::printAlbum(album); + + artistManager artMgr(m_bConf); + auto artist = artMgr.saveArtist(song); + artist = artMgr.retrieveArtist(artist); + Manager::artistManager::printArtist(artist); + genreManager gnrMgr(m_bConf); + auto genre = gnrMgr.saveGenre(song); + genre = gnrMgr.retrieveGenre(genre); + Manager::genreManager::printGenre(genre); + yearManager yrMgr(m_bConf); + auto year = yrMgr.saveYear(song); + year = yrMgr.retrieveYear(year); + Manager::yearManager::printYear(year); + + song.coverArtId = cov.id; + song.albumId = album.id; + song.artistId = artist.id; + song.genreId = genre.id; + song.yearId = year.id; } diff --git a/src/managers/token_manager.cpp b/src/managers/token_manager.cpp index d9f55c4..a629a2e 100644 --- a/src/managers/token_manager.cpp +++ b/src/managers/token_manager.cpp @@ -135,7 +135,7 @@ Model::auth_credentials Manager::token_manager::parse_auth_credentials(std::stri Model::auth_credentials Manager::token_manager::parse_auth_credentials(const Model::BinaryPath& bConf) { auto exePath = Manager::directory_manager::configPath(bConf); - exePath.append("/auth_credentials.json"); + exePath.append("/authcredentials.json"); auto con = Manager::directory_manager::credentialConfigContent(exePath); diff --git a/src/managers/yearManager.cpp b/src/managers/yearManager.cpp index bc6538d..5aa3f77 100644 --- a/src/managers/yearManager.cpp +++ b/src/managers/yearManager.cpp @@ -1,5 +1,37 @@ #include "managers/yearManager.h" +#include + +#include "database/yearRepository.h" +#include "types/yearFilter.h" + Manager::yearManager::yearManager(const Model::BinaryPath& bConf) : m_bConf(bConf) { } + + +Model::Year Manager::yearManager::retrieveYear(Model::Year& year) +{ + Database::yearRepository yearRepo(m_bConf); + year = yearRepo.retrieveRecord(year, Type::yearFilter::year); + + return year; +} + +Model::Year Manager::yearManager::saveYear(const Model::Song& song) +{ + Model::Year year; + year.year = song.year; + + Database::yearRepository yearRepo(m_bConf); + yearRepo.saveRecord(year); + + return year; +} + +void Manager::yearManager::printYear(const Model::Year& year) +{ + std::cout << "\nyear record" << std::endl; + std::cout << "id: " << year.id << std::endl; + std::cout << "year: " << year.year << std::endl; +} From c55d8261a2fd179d52e0d215f4cc3abf5d5ee85f Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Mon, 2 Sep 2019 20:16:30 -0400 Subject: [PATCH 35/36] Added TODO in the albumRepository.cpp on where to pick up from. Short story: duplicate related records --- include/database/albumRepository.h | 2 ++ src/database/albumRepository.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/database/albumRepository.h b/include/database/albumRepository.h index d2b7be0..e9e9dfe 100644 --- a/include/database/albumRepository.h +++ b/include/database/albumRepository.h @@ -18,6 +18,8 @@ namespace Database Model::Album retrieveRecord(Model::Album&, Type::albumFilter); + bool doesAlbumExists(const Model::Album&, Type::albumFilter); + void saveAlbum(const Model::Album&); private: std::vector parseRecords(MYSQL_RES*); diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp index 239a1ce..57b7190 100644 --- a/src/database/albumRepository.cpp +++ b/src/database/albumRepository.cpp @@ -53,6 +53,19 @@ Model::Album Database::albumRepository::retrieveRecord(Model::Album& album, Type return album; } +bool Database::albumRepository::doesAlbumExists(const Model::Album& album, Type::albumFilter filter) +{ + // TODO: continue working on this part. + // Reason: there should be a check to see if an album record already exists + // at the moment there is no check and every time a song is uploaded + // a new album record is created, even for songs that are on the + // same album. This should not happen. There should be one album + // record for songs on the same album. After fixing this, do the + // same for Artist, Genre, and Year records + + return false; +} + void Database::albumRepository::saveAlbum(const Model::Album& album) { std::cout << "beginning to insert album record" << std::endl; From 12a53ed2b1b0bf716e1072776271e5f1b224f4fe Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Tue, 3 Sep 2019 16:15:37 -0400 Subject: [PATCH 36/36] Added some TODO's. Need to switch to prepared statements for album, artist, genre, and year repositories --- database.json | 8 +- include/controller/songController.hpp | 3 + include/database/albumRepository.h | 4 + include/database/artistRepository.h | 5 + include/database/coverArtRepository.h | 5 + include/database/genreRepository.h | 5 + include/database/songRepository.h | 8 +- include/database/yearRepository.h | 5 + src/database/albumRepository.cpp | 56 +++- src/database/artistRepository.cpp | 15 + src/database/coverArtRepository.cpp | 15 + src/database/genreRepository.cpp | 15 + src/database/songRepository.cpp | 421 +++++++++++++++++++++++++- src/database/yearRepository.cpp | 15 + src/managers/albumManager.cpp | 7 +- src/managers/artistManager.cpp | 7 +- src/managers/coverArtManager.cpp | 9 +- src/managers/genreManager.cpp | 6 +- src/managers/yearManager.cpp | 6 +- 19 files changed, 589 insertions(+), 26 deletions(-) diff --git a/database.json b/database.json index 661decf..ed03ff2 100644 --- a/database.json +++ b/database.json @@ -1,7 +1,7 @@ { - "server": "server", - "database": "database", - "username": "username", - "password": "password" + "server": "localhost", + "database": "Icarus", + "username": "icarus-admin", + "password": "dreamofpeace" } diff --git a/include/controller/songController.hpp b/include/controller/songController.hpp index 54b6ee7..ca36000 100644 --- a/include/controller/songController.hpp +++ b/include/controller/songController.hpp @@ -117,6 +117,9 @@ namespace Controller Model::Song songDb; songDb.id = 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(); diff --git a/include/database/albumRepository.h b/include/database/albumRepository.h index e9e9dfe..59e0ada 100644 --- a/include/database/albumRepository.h +++ b/include/database/albumRepository.h @@ -23,7 +23,11 @@ namespace Database void saveAlbum(const Model::Album&); private: std::vector parseRecords(MYSQL_RES*); + + // TODO: after parseRecord(MYSQL_STMT*) is implemented remove + // parseRecord(MYSQL_RES*) Model::Album parseRecord(MYSQL_RES*); + Model::Album parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/artistRepository.h b/include/database/artistRepository.h index f47a69d..83b897b 100644 --- a/include/database/artistRepository.h +++ b/include/database/artistRepository.h @@ -14,9 +14,14 @@ namespace Database Model::Artist retrieveRecord(Model::Artist&, Type::artistFilter); + bool doesArtistExist(const Model::Artist&, Type::artistFilter); + void saveRecord(const Model::Artist&); private: + // TODO: After parseRecord(MYSQL_STMT*) is implemented + // remove parseRecord(MYSQL_RES*) Model::Artist parseRecord(MYSQL_RES*); + Model::Artist parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h index 115c320..c664d8f 100644 --- a/include/database/coverArtRepository.h +++ b/include/database/coverArtRepository.h @@ -16,11 +16,16 @@ namespace Database coverArtRepository(const Model::BinaryPath&); Model::Cover retrieveRecord(Model::Cover&, Type::coverFilter); + + bool doesCoverArtExist(const Model::Cover&, Type::coverFilter); void deleteRecord(const Model::Cover&); void saveRecord(const Model::Cover&); private: + // TODO: After parseRecord(MYSQL_STMT*) is implemented + // remove parseRecord(MYSQL_RES*) Model::Cover parseRecord(MYSQL_RES*); + Model::Cover parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/genreRepository.h b/include/database/genreRepository.h index 927eb3a..e495105 100644 --- a/include/database/genreRepository.h +++ b/include/database/genreRepository.h @@ -14,9 +14,14 @@ namespace Database Model::Genre retrieveRecord(Model::Genre&, Type::genreFilter); + bool doesGenreExist(const Model::Genre&, Type::genreFilter); + void saveRecord(const Model::Genre&); private: + // TODO: After parseRecord(MYSQL_STMT*) is implemented + // remove parseRecord(MYSQL_RES*) Model::Genre parseRecord(MYSQL_RES*); + Model::Genre parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/songRepository.h b/include/database/songRepository.h index 0bc05f6..a32922b 100644 --- a/include/database/songRepository.h +++ b/include/database/songRepository.h @@ -20,14 +20,18 @@ namespace Database std::vector retrieveRecords(); + bool doesSongExist(const Model::Song&, Type::songFilter); + Model::Song retrieveRecord(Model::Song&, Type::songFilter); void deleteRecord(const Model::Song&); void saveRecord(const Model::Song&); private: - std::vector parseRecords(MYSQL_RES*); + std::vector parseRecords(MYSQL_RES*); // TODO: to be removed + std::vector parseRecords(MYSQL_STMT*); - Model::Song parseRecord(MYSQL_RES*); + Model::Song parseRecord(MYSQL_RES*); // TODO: to be removed + Model::Song parseRecord(MYSQL_STMT*); }; } diff --git a/include/database/yearRepository.h b/include/database/yearRepository.h index da61784..135b98f 100644 --- a/include/database/yearRepository.h +++ b/include/database/yearRepository.h @@ -14,9 +14,14 @@ namespace Database Model::Year retrieveRecord(Model::Year&, Type::yearFilter); + bool doesYearExist(const Model::Year&, Type::yearFilter); + void saveRecord(const Model::Year&); private: + // TODO: After parseRecord(MYSQL_STMT*) is implemented + // remove parseRecord(MYSQL_RES*) Model::Year parseRecord(MYSQL_RES*); + Model::Year parseRecord(MYSQL_STMT*); }; } diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp index 57b7190..80d9f74 100644 --- a/src/database/albumRepository.cpp +++ b/src/database/albumRepository.cpp @@ -63,7 +63,53 @@ bool Database::albumRepository::doesAlbumExists(const Model::Album& album, Type: // record for songs on the same album. After fixing this, do the // same for Artist, Genre, and Year records - return false; + auto conn = setup_mysql_connection(); + auto stmt = mysql_stmt_init(conn); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + std::stringstream qry; + qry << "SELECT * FROM Album WHERE "; + + auto titleLength = album.title.size(); + switch (filter) { + case Type::albumFilter::id: + qry << "AlbumId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&album.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case Type::albumFilter::title: + qry << "Title = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)album.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const auto query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed" << std::endl; + + ::mysql_stmt_store_result(stmt); + auto rowCount = ::mysql_stmt_num_rows(stmt); + + ::mysql_stmt_close(stmt); + ::mysql_close(conn); + + return (rowCount > 0) ? true : false; } void Database::albumRepository::saveAlbum(const Model::Album& album) @@ -133,3 +179,11 @@ Model::Album Database::albumRepository::parseRecord(MYSQL_RES* results) return album; } + +Model::Album Database::albumRepository::parseRecord(MYSQL_STMT *stmt) +{ + // TODO: implement this + Model::Album album; + + return album; +} diff --git a/src/database/artistRepository.cpp b/src/database/artistRepository.cpp index 7aa145e..3eec442 100644 --- a/src/database/artistRepository.cpp +++ b/src/database/artistRepository.cpp @@ -47,6 +47,13 @@ Model::Artist Database::artistRepository::retrieveRecord(Model::Artist& artist, return artist; } +bool Database::artistRepository::doesArtistExist(const Model::Artist& artist, Type::artistFilter filter) +{ + // TODO: implement this + + return false; +} + void Database::artistRepository::saveRecord(const Model::Artist& artist) { std::cout << "inserting artist record" << std::endl; @@ -100,3 +107,11 @@ Model::Artist Database::artistRepository::parseRecord(MYSQL_RES* results) return artist; } + +Model::Artist Database::artistRepository::parseRecord(MYSQL_STMT *stmt) +{ + // TODO: implement this + Model::Artist art; + + return art; +} diff --git a/src/database/coverArtRepository.cpp b/src/database/coverArtRepository.cpp index f559902..a2edc9c 100644 --- a/src/database/coverArtRepository.cpp +++ b/src/database/coverArtRepository.cpp @@ -46,6 +46,12 @@ Model::Cover Database::coverArtRepository::retrieveRecord(Model::Cover& cov, Typ return covDb; } +bool Database::coverArtRepository::doesCoverArtExist(const Model::Cover& cover, Type::coverFilter filter) +{ + // TODO: implement this + return false; +} + void Database::coverArtRepository::deleteRecord(const Model::Cover& cov) { auto conn = setup_mysql_connection(); @@ -119,3 +125,12 @@ Model::Cover Database::coverArtRepository::parseRecord(MYSQL_RES *results) return cov; } + +Model::Cover Database::coverArtRepository::parseRecord(MYSQL_STMT *stmt) +{ + // TODO: implement this + + Model::Cover cover; + + return cover; +} diff --git a/src/database/genreRepository.cpp b/src/database/genreRepository.cpp index b25e2cf..dde767d 100644 --- a/src/database/genreRepository.cpp +++ b/src/database/genreRepository.cpp @@ -45,6 +45,13 @@ Model::Genre Database::genreRepository::retrieveRecord(Model::Genre& genre, Type return genre; } +bool Database::genreRepository::doesGenreExist(const Model::Genre& genre, Type::genreFilter filter) +{ + // TODO: implement this + + return false; +} + void Database::genreRepository::saveRecord(const Model::Genre& genre) { std::cout << "inserting genre record" << std::endl; @@ -97,3 +104,11 @@ Model::Genre Database::genreRepository::parseRecord(MYSQL_RES* results) return genre; } +Model::Genre Database::genreRepository::parseRecord(MYSQL_STMT *stmt) +{ + // TODO: implement this + + Model::Genre genre; + + return genre; +} diff --git a/src/database/songRepository.cpp b/src/database/songRepository.cpp index 1536fae..7a702bc 100644 --- a/src/database/songRepository.cpp +++ b/src/database/songRepository.cpp @@ -16,14 +16,17 @@ Database::songRepository::songRepository(const Model::BinaryPath& bConf) : base_ std::vector Database::songRepository::retrieveRecords() { auto conn = setup_mysql_connection(); + auto stmt = mysql_stmt_init(conn); const std::string query = "SELECT * FROM Song"; - auto results = perform_mysql_query(conn, query); - auto songs = parseRecords(results); + ::mysql_stmt_prepare(stmt, query.c_str(), query.size()); + ::mysql_stmt_execute(stmt); + auto songs = parseRecords(stmt); + + mysql_stmt_close(stmt); mysql_close(conn); - return songs; } @@ -31,34 +34,106 @@ Model::Song Database::songRepository::retrieveRecord(Model::Song& song, Type::so { std::stringstream qry; auto conn = setup_mysql_connection(); + auto stmt = mysql_stmt_init(conn); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + qry << "SELECT * FROM Song WHERE "; - std::unique_ptr param; + auto titleLength = song.title.size(); switch (filter) { case Type::songFilter::id: - qry << "SongId = " << song.id; + qry << "SongId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&song.id; + params[0].length = 0; + params[0].is_null = 0;; break; case Type::songFilter::title: - param = std::make_unique(new char[song.title.size()]); - mysql_real_escape_string(conn, *param, song.title.c_str(), song.title.size()); - qry << "Title = '" << *param << "'"; + qry << "Title = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; break; default: break; } + qry << " LIMIT 1"; + const std::string query = qry.str(); - auto results = perform_mysql_query(conn, query); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + std::cout << "the query has been performed" << std::endl; - song = parseRecord(results); + song = parseRecord(stmt); + mysql_stmt_close(stmt); mysql_close(conn); std::cout << "done" << std::endl; return song; } +bool Database::songRepository::doesSongExist(const Model::Song& song, Type::songFilter filter) +{ + std::cout << "checking to see if song exists" << std::endl; + std::stringstream qry; + auto conn = setup_mysql_connection(); + auto stmt = mysql_stmt_init(conn); + + MYSQL_BIND params[1]; + memset(params, 0, sizeof(params)); + + qry << "SELECT * FROM Song WHERE "; + + auto titleLength = song.title.size(); + switch (filter) { + case Type::songFilter::id: + qry << "SongId = ?"; + + params[0].buffer_type = MYSQL_TYPE_LONG; + params[0].buffer = (char*)&song.id; + params[0].length = 0; + params[0].is_null = 0; + break; + case Type::songFilter::title: + qry << "Title = ?"; + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + params[0].length = &titleLength; + params[0].is_null = 0; + break; + default: + break; + } + + qry << " LIMIT 1"; + + const std::string query = qry.str(); + auto status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + std::cout << "the query has been performed" << std::endl; + + ::mysql_stmt_store_result(stmt); + auto rowCount = ::mysql_stmt_num_rows(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + std::cout << "done" << std::endl; + + return (rowCount > 0) ? true : false; +} + void Database::songRepository::deleteRecord(const Model::Song& song) { auto conn = setup_mysql_connection(); @@ -172,6 +247,7 @@ void Database::songRepository::saveRecord(const Model::Song& song) std::cout << "done inserting song record" << std::endl; } +// TODO: delete this, not being used std::vector Database::songRepository::parseRecords(MYSQL_RES* results) { auto fieldNum = mysql_num_fields(results); @@ -184,6 +260,59 @@ std::vector Database::songRepository::parseRecords(MYSQL_RES* resul Model::Song song; for (auto i = 0; i != fieldNum; ++i) { + /** + auto field = mysql_fetch_field(results); + if (field->name == NULL) { + std::cout << "null field" << std::endl; + break; + } + */ + /** + std::string field; + if ((i + 0) == fieldNum) { + std::cout << "goodbye" << std::endl; + break; + } else { + std::cout << "still good" << std::endl; + field.assign(mysql_fetch_field(results)->name); + } + //const std::string field(row[i].field); + std::cout << field << std::endl; + + if (field.compare("SongId") == 0) { + song.id = std::stoi(row[i]); + } + if (field.compare("Title") == 0) { + song.title = row[i]; + } + if (field.compare("Artist") == 0) { + song.artist = row[i]; + } + if (field.compare("Album") == 0) { + song.album = row[i]; + } + if (field.compare("Genre") == 0) { + song.genre = row[i]; + } + if (field.compare("Year") == 0) { + song.year = std::stoi(row[i]); + } + if (field.compare("Duration") == 0) { + song.duration = std::stoi(row[i]); + } + if (field.compare("Track") == 0) { + song.track = std::stoi(row[i]); + } + if (field.compare("Disc") == 0) { + song.disc = std::stoi(row[i]); + } + if (field.compare("SongPath") == 0) { + song.songPath = row[i]; + } + if (field.compare("CoverArtId") == 0) { + song.coverArtId = std::stoi(row[i]); + } + */ switch (i) { case 0: song.id = std::stoi(row[i]); @@ -222,19 +351,163 @@ std::vector Database::songRepository::parseRecords(MYSQL_RES* resul } songs.push_back(song); + //std::cout << "added" << std::endl; + } + //std::cout << "completely" << std::endl; + + return songs; +} + +std::vector Database::songRepository::parseRecords(MYSQL_STMT *stmt) +{ + ::mysql_stmt_store_result(stmt); + auto c = ::mysql_stmt_num_rows(stmt); + std::cout << "number of results " << c << std::endl; + std::vector songs; + songs.reserve(c); + + auto status = 0; + auto time = 0; + auto valAmt = 15; + unsigned long len[valAmt]; + my_bool nullRes[valAmt]; + + while (status == 0) { + std::cout << time++ << " time" << std::endl; + std::cout << "field count " << ::mysql_stmt_field_count(stmt) << std::endl; + + if (::mysql_stmt_field_count(stmt) > 0) { + + Model::Song song; + auto res = ::mysql_stmt_result_metadata(stmt); + auto fields = ::mysql_fetch_fields(res); + auto strLen = 1024; + MYSQL_BIND val[valAmt]; + memset(val, 0, sizeof(val)); + + char title[strLen]; + char album[strLen]; + char artist[strLen]; + char genre[strLen]; + char path[strLen]; + + val[0].buffer_type = MYSQL_TYPE_LONG; + val[0].buffer = (char*)&song.id; + val[0].length = &len[0]; + val[0].is_null = &nullRes[0]; + + val[1].buffer_type = MYSQL_TYPE_STRING; + val[1].buffer = (char*)title; + val[1].buffer_length = strLen; + val[1].length = &len[1]; + val[1].is_null = &nullRes[1]; + + val[2].buffer_type = MYSQL_TYPE_STRING; + val[2].buffer = (char*)artist; + val[2].buffer_length = strLen; + val[2].length = &len[2]; + val[2].is_null = &nullRes[2]; + + val[3].buffer_type = MYSQL_TYPE_STRING; + val[3].buffer = (char*)album; + val[3].buffer_length = strLen; + val[3].length = &len[3]; + val[3].is_null = &nullRes[3]; + + val[4].buffer_type = MYSQL_TYPE_STRING; + val[4].buffer = (char*)genre; + val[4].buffer_length = strLen; + val[4].length = &len[4]; + val[4].is_null = &nullRes[4]; + + val[5].buffer_type = MYSQL_TYPE_LONG; + val[5].buffer = (char*)&song.year; + val[5].length = &len[5]; + val[5].is_null = &nullRes[5]; + + val[6].buffer_type = MYSQL_TYPE_LONG; + val[6].buffer = (char*)&song.duration; + val[6].length = &len[6]; + val[6].is_null = &nullRes[6]; + + val[7].buffer_type = MYSQL_TYPE_LONG; + val[7].buffer = (char*)&song.track; + val[7].length = &len[7]; + val[7].is_null = &nullRes[7]; + + val[8].buffer_type = MYSQL_TYPE_LONG; + val[8].buffer = (char*)&song.disc; + val[8].length = &len[8]; + val[8].is_null = &nullRes[8]; + + val[9].buffer_type = MYSQL_TYPE_STRING; + val[9].buffer = (char*)path; + val[9].buffer_length = strLen; + val[9].length = &len[9]; + val[9].is_null = &nullRes[9]; + + val[10].buffer_type = MYSQL_TYPE_LONG; + val[10].buffer = (char*)&song.coverArtId; + val[10].length = &len[10]; + val[10].is_null = &nullRes[10]; + + val[11].buffer_type = MYSQL_TYPE_LONG; + val[11].buffer = (char*)&song.artistId; + val[11].length = &len[11]; + val[11].is_null = &nullRes[11]; + + val[12].buffer_type = MYSQL_TYPE_LONG; + val[12].buffer = (char*)&song.albumId;; + val[12].length = &len[12]; + val[12].is_null = &nullRes[12]; + + val[13].buffer_type = MYSQL_TYPE_LONG; + val[13].buffer = (char*)&song.genreId; + val[13].length = &len[13]; + val[13].is_null = &nullRes[13]; + + val[14].buffer_type = MYSQL_TYPE_LONG; + val[14].buffer = (char*)&song.yearId; + val[14].length = &len[14]; + val[14].is_null = &nullRes[14]; + + status = ::mysql_stmt_bind_result(stmt, val); + + while (1) { + std::cout << "fetching statement result" << std::endl; + status = ::mysql_stmt_fetch(stmt); + + if (status == 1 || status == MYSQL_NO_DATA) { + break; + } + song.title = title; + song.album = album; + song.artist = artist; + song.genre = genre; + song.songPath = path; + + songs.push_back(song); + } + } + std::cout << "fetching next result" << std::endl; + status = ::mysql_stmt_next_result(stmt); } return songs; } + +// TODO: delete this, not being used anymore Model::Song Database::songRepository::parseRecord(MYSQL_RES* results) { Model::Song song; - auto fieldNum = mysql_num_fields(results); - MYSQL_ROW row = mysql_fetch_row(results); + auto fieldNum = mysql_num_fields(results); + auto row = mysql_fetch_row(results); for (auto i = 0; i != fieldNum; ++i) { + const std::string field(mysql_fetch_field(results)->name); + switch (i) { case 0: song.id = std::stoi(row[i]); @@ -275,3 +548,127 @@ Model::Song Database::songRepository::parseRecord(MYSQL_RES* results) return song; } + +Model::Song Database::songRepository::parseRecord(MYSQL_STMT *stmt) +{ + Model::Song song; + auto status = 0; + auto time = 0; + auto valAmt = 15; + unsigned long len[valAmt]; + my_bool nullRes[valAmt]; + + while (status == 0) { + if (::mysql_stmt_field_count(stmt) > 0) { + auto res = ::mysql_stmt_result_metadata(stmt); + auto fields = ::mysql_fetch_fields(res); + auto strLen = 1024; + MYSQL_BIND val[valAmt]; + memset(val, 0, sizeof(val)); + + char title[strLen]; + char album[strLen]; + char artist[strLen]; + char genre[strLen]; + char path[strLen]; + + val[0].buffer_type = MYSQL_TYPE_LONG; + val[0].buffer = (char*)&song.id; + val[0].length = &len[0]; + val[0].is_null = &nullRes[0]; + + val[1].buffer_type = MYSQL_TYPE_STRING; + val[1].buffer = (char*)title; + val[1].buffer_length = strLen; + val[1].length = &len[1]; + val[1].is_null = &nullRes[1]; + + val[2].buffer_type = MYSQL_TYPE_STRING; + val[2].buffer = (char*)artist; + val[2].buffer_length = strLen; + val[2].length = &len[2]; + val[2].is_null = &nullRes[2]; + + val[3].buffer_type = MYSQL_TYPE_STRING; + val[3].buffer = (char*)album; + val[3].buffer_length = strLen; + val[3].length = &len[3]; + val[3].is_null = &nullRes[3]; + + val[4].buffer_type = MYSQL_TYPE_STRING; + val[4].buffer = (char*)genre; + val[4].buffer_length = strLen; + val[4].length = &len[4]; + val[4].is_null = &nullRes[4]; + + val[5].buffer_type = MYSQL_TYPE_LONG; + val[5].buffer = (char*)&song.year; + val[5].length = &len[5]; + val[5].is_null = &nullRes[5]; + + val[6].buffer_type = MYSQL_TYPE_LONG; + val[6].buffer = (char*)&song.duration; + val[6].length = &len[6]; + val[6].is_null = &nullRes[6]; + + val[7].buffer_type = MYSQL_TYPE_LONG; + val[7].buffer = (char*)&song.track; + val[7].length = &len[7]; + val[7].is_null = &nullRes[7]; + + val[8].buffer_type = MYSQL_TYPE_LONG; + val[8].buffer = (char*)&song.disc; + val[8].length = &len[8]; + val[8].is_null = &nullRes[8]; + + val[9].buffer_type = MYSQL_TYPE_STRING; + val[9].buffer = (char*)path; + val[9].buffer_length = strLen; + val[9].length = &len[9]; + val[9].is_null = &nullRes[9]; + + val[10].buffer_type = MYSQL_TYPE_LONG; + val[10].buffer = (char*)&song.coverArtId; + val[10].length = &len[10]; + val[10].is_null = &nullRes[10]; + + val[11].buffer_type = MYSQL_TYPE_LONG; + val[11].buffer = (char*)&song.artistId; + val[11].length = &len[11]; + val[11].is_null = &nullRes[11]; + + val[12].buffer_type = MYSQL_TYPE_LONG; + val[12].buffer = (char*)&song.albumId;; + val[12].length = &len[12]; + val[12].is_null = &nullRes[12]; + + val[13].buffer_type = MYSQL_TYPE_LONG; + val[13].buffer = (char*)&song.genreId; + val[13].length = &len[13]; + val[13].is_null = &nullRes[13]; + + val[14].buffer_type = MYSQL_TYPE_LONG; + val[14].buffer = (char*)&song.yearId; + val[14].length = &len[14]; + val[14].is_null = &nullRes[14]; + + status = ::mysql_stmt_bind_result(stmt, val); + ::mysql_stmt_store_result(stmt); + + status = ::mysql_stmt_fetch(stmt); + + song.title = title; + song.album = album; + song.artist = artist; + song.genre = genre; + song.songPath = path; + + } + status = ::mysql_stmt_next_result(stmt); + } + + std::cout << "okay!!!!" << std::endl; + std::cout << "done parsing record" << std::endl; + + return song; +} diff --git a/src/database/yearRepository.cpp b/src/database/yearRepository.cpp index 1d900c6..818f0de 100644 --- a/src/database/yearRepository.cpp +++ b/src/database/yearRepository.cpp @@ -44,6 +44,13 @@ Model::Year Database::yearRepository::retrieveRecord(Model::Year& year, Type::ye return year; } +bool Database::yearRepository::doesYearExist(const Model::Year& year, Type::yearFilter filter) +{ + // TODO: implement this + + return false; +} + void Database::yearRepository::saveRecord(const Model::Year& year) { std::cout << "saving year record" << std::endl; @@ -95,3 +102,11 @@ Model::Year Database::yearRepository::parseRecord(MYSQL_RES *results) return year; } +Model::Year Database::yearRepository::parseRecord(MYSQL_STMT *stmt) +{ + // TODO: imeplement this + + Model::Year year; + + return year; +} diff --git a/src/managers/albumManager.cpp b/src/managers/albumManager.cpp index 872204c..08d1121 100644 --- a/src/managers/albumManager.cpp +++ b/src/managers/albumManager.cpp @@ -26,7 +26,12 @@ Model::Album Manager::albumManager::saveAlbum(const Model::Song& song) album.year = song.year; Database::albumRepository albRepo(m_bConf); - albRepo.saveAlbum(album); + if (!albRepo.doesAlbumExists(album, Type::albumFilter::title)) { + albRepo.saveAlbum(album); + } else { + std::cout << "album record already exists in the database" << std::endl; + } + return album; } diff --git a/src/managers/artistManager.cpp b/src/managers/artistManager.cpp index 41069a2..2cf8857 100644 --- a/src/managers/artistManager.cpp +++ b/src/managers/artistManager.cpp @@ -24,8 +24,11 @@ Model::Artist Manager::artistManager::saveArtist(const Model::Song& song) artist.artist = song.artist; Database::artistRepository artRepo(m_bConf); - artRepo.saveRecord(artist); - + if (!artRepo.doesArtistExist(artist, Type::artistFilter::artist)) { + artRepo.saveRecord(artist); + } else { + std::cout << "artist already exists" << std::endl; + } return artist; } diff --git a/src/managers/coverArtManager.cpp b/src/managers/coverArtManager.cpp index c9f8a62..3f79f64 100644 --- a/src/managers/coverArtManager.cpp +++ b/src/managers/coverArtManager.cpp @@ -20,8 +20,13 @@ Model::Cover Manager::coverArtManager::saveCover(const Model::Song& song, std::s cov.songTitle = song.title; Database::coverArtRepository covRepo(m_bConf); - std::cout << "saving image record to the database" << std::endl; - covRepo.saveRecord(cov); + if (!covRepo.doesCoverArtExist(cov, Type::coverFilter::songTitle)) { + std::cout << "saving image record to the database" << std::endl; + covRepo.saveRecord(cov); + } else { + std::cout << "cover art record already exists" << std::endl; + } + std::cout << "retrieving image record from database" << std::endl; cov = covRepo.retrieveRecord(cov, Type::coverFilter::songTitle); diff --git a/src/managers/genreManager.cpp b/src/managers/genreManager.cpp index 08cbc19..868efd7 100644 --- a/src/managers/genreManager.cpp +++ b/src/managers/genreManager.cpp @@ -24,7 +24,11 @@ Model::Genre Manager::genreManager::saveGenre(const Model::Song& song) genre.category = song.genre; Database::genreRepository gnrRepo(m_bConf); - gnrRepo.saveRecord(genre); + if (!gnrRepo.doesGenreExist(genre, Type::genreFilter::category)) { + gnrRepo.saveRecord(genre); + } else { + std::cout << "genre record already exists" << std::endl; + } return genre; } diff --git a/src/managers/yearManager.cpp b/src/managers/yearManager.cpp index 5aa3f77..f008198 100644 --- a/src/managers/yearManager.cpp +++ b/src/managers/yearManager.cpp @@ -24,7 +24,11 @@ Model::Year Manager::yearManager::saveYear(const Model::Song& song) year.year = song.year; Database::yearRepository yearRepo(m_bConf); - yearRepo.saveRecord(year); + if (!yearRepo.doesYearExist(year, Type::yearFilter::year)) { + yearRepo.saveRecord(year); + } else { + std::cout << "year record already exists in the database" << std::endl; + } return year; }