diff --git a/.gitmodules b/.gitmodules index 06db291..03137ae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,18 @@ [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 +[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 diff --git a/Libs/cpr b/3rdparty/cpr similarity index 100% rename from Libs/cpr rename to 3rdparty/cpr diff --git a/3rdparty/jwt-cpp b/3rdparty/jwt-cpp new file mode 160000 index 0000000..27f3298 --- /dev/null +++ b/3rdparty/jwt-cpp @@ -0,0 +1 @@ +Subproject commit 27f32983fb310f4406e6da6c43700202c93bf18c 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..e86a9fe --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,115 @@ +cmake_minimum_required(VERSION 3.10) + +project(icarus) + +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) + +set(SOURCES + 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/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/component/appComponent.hpp + include/controller/loginController.hpp + include/controller/songController.hpp + 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/dto/loginResultDto.hpp + include/dto/songDto.hpp + 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 + 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 + ${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" +) + +set(JWT_CPP_INCLUDE + ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/jwt-cpp/include +) + +set (ORM_DIR + ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/ormpp +) + +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) + +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) +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}) +target_link_libraries(icarus "-lstdc++fs" tag oatpp mysqlclient ${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/directory_manager.h b/Libs/include/directory_manager.h deleted file mode 100644 index a20d29a..0000000 --- a/Libs/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/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/Libs/include/metadata_retriever.h b/Libs/include/metadata_retriever.h deleted file mode 100644 index 80e3dd4..0000000 --- a/Libs/include/metadata_retriever.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -#include "models.h" diff --git a/Libs/include/models.h b/Libs/include/models.h deleted file mode 100644 index dbc5c67..0000000 --- a/Libs/include/models.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef MODELS_H_ -#define MODELS_H_ - -struct Song -{ - int Id; - char Title[1024]; - char Artist[1024]; - char Album[1024]; - char Genre[1024]; - int Year; - int Duration; - char SongPath[1024]; -}; - -struct Cover -{ - int Id; - char SongTitle[1024]; - char ImagePath[1024]; -}; - -struct LoginRes -{ - int UserId; - char Username[1024]; - char Token[1024]; - char TokenType[1024]; - char Message[1024]; - int Expiration; -}; - -struct TokenReq -{ - char ClientId[1024]; - char ClientSecret[1024]; - char Audience[1024]; - char GrantType[1024]; - char URI[1024]; - char Endpoint[1024]; -}; - -#endif diff --git a/Libs/src/directory_manager.cpp b/Libs/src/directory_manager.cpp deleted file mode 100644 index 9f47566..0000000 --- a/Libs/src/directory_manager.cpp +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include -#include -#include -#include - -#include "directory_manager.h" - -namespace fs = std::filesystem; - -std::string create_directory_process(Song song, const char *root_path) -{ - auto curr_path = fs::path(root_path); - - if (fs::exists(curr_path)) { - std::cout<<"path exists"<(cov), - std::istreambuf_iterator(), - std::ostreambuf_iterator(buf)); - - return buf.str(); -} - -bool delete_song(Song *song) -{ - return fs::remove(song->SongPath); -} - -void copy_stock_to_root(const char *target, const std::string buff) -{ - std::cout<<"starting process"< -#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 "models.h" - - -extern "C" -{ - - -LoginRes* retrieve_token(TokenReq *tok) -{ - LoginRes *res = new LoginRes; - - nlohmann::json reqObj; - reqObj["client_id"] = tok->ClientId; - reqObj["client_secret"] = tok->ClientSecret; - reqObj["audience"] = tok->Audience; - reqObj["grant_type"] = tok->GrantType; - - std::string uri{tok->URI}; - uri.append("/"); - uri.append(tok->Endpoint); - - auto r = cpr::Post(cpr::Url{uri}, - cpr::Body{reqObj.dump()}, - cpr::Header{{"Content-Type", "application/json"}}); - - 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; -} -} 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/Scripts/MySQL/create_database.sql b/Scripts/MySQL/create_database.sql new file mode 100644 index 0000000..8680c54 --- /dev/null +++ b/Scripts/MySQL/create_database.sql @@ -0,0 +1,77 @@ +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 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, + Year INT NOT NULL, + + PRIMARY KEY (YearId) +); + +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, + Track INT NOT NULL, + 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_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, + + PRIMARY KEY (UserId) +); 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/authcredentials.json b/authcredentials.json new file mode 100644 index 0000000..f900c26 --- /dev/null +++ b/authcredentials.json @@ -0,0 +1,6 @@ +{ + "domain": "[domain].auth0.com", + "api_identifier": "https://[identifier]/api", + "client_id": "dfdfdfdf", + "client_secret": "dfdfdfdf" +} diff --git a/Libs/conanfile.txt b/conanfile.txt similarity index 100% rename from Libs/conanfile.txt rename to conanfile.txt diff --git a/database.json b/database.json new file mode 100644 index 0000000..ed03ff2 --- /dev/null +++ b/database.json @@ -0,0 +1,7 @@ + +{ + "server": "localhost", + "database": "Icarus", + "username": "icarus-admin", + "password": "dreamofpeace" +} 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/controller/loginController.hpp b/include/controller/loginController.hpp new file mode 100644 index 0000000..94301db --- /dev/null +++ b/include/controller/loginController.hpp @@ -0,0 +1,53 @@ +#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 "managers/token_manager.h" + +namespace Controller +{ + class loginController : public oatpp::web::server::api::ApiController + { + public: + loginController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), exe_path(p) + { } + loginController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + :oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) + { } + + + #include OATPP_CODEGEN_BEGIN(ApiController) + + 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(m_bConf); + + 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(); + 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/include/controller/songController.hpp b/include/controller/songController.hpp new file mode 100644 index 0000000..ca36000 --- /dev/null +++ b/include/controller/songController.hpp @@ -0,0 +1,186 @@ +#ifndef SONGCONTROLLER_H_ +#define SONGCONTROLLER_H_ + +#include +#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" +#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" +#include "types/scopes.h" +#include "types/songFilter.h" + +namespace fs = std::filesystem; + +namespace Controller +{ + class songController : public oatpp::web::server::api::ApiController + { + public: + songController(std::string p, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_exe_path(p) + { } + + songController(const Model::BinaryPath& bConf, OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), m_bConf(bConf) + { } + + #include OATPP_CODEGEN_BEGIN(ApiController) + + // endpoint for uploading a song + ENDPOINT("POST", "/api/v1/song/data", songUpload, + REQUEST(std::shared_ptr, request)) + { + 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, Type::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 = Dto::songDto::createShared(); + song->id = songDb.id; + song->title = songDb.title.c_str(); + song->artist = songDb.artist.c_str(); + song->album = songDb.album.c_str(); + song->genre = songDb.genre.c_str(); + song->year = songDb.year; + song->duration = songDb.duration; + song->track = songDb.track; + song->disc = songDb.disc; + + songs->pushBack(song); + } + + return createDtoResponse(Status::CODE_200, songs); + } + + // endpoint for retrieving song record by the song id in json format + ENDPOINT("GET", "/api/v1/song/{id}", songRecord, + PATH(Int32, id)) { + + Database::songRepository songRepo(m_bConf); + Model::Song songDb; + 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(); + song->id = songDb.id; + song->title = songDb.title.c_str(); + song->artist = songDb.artist.c_str(); + song->album = songDb.album.c_str(); + song->genre = songDb.genre.c_str(); + song->year = songDb.year; + song->duration = songDb.duration; + song->track = songDb.track; + song->disc = songDb.disc; + + return createDtoResponse(Status::CODE_200, song); + } + + ENDPOINT("GET", "/api/v1/song/data/{id}", downloadSong, + PATH(Int32, id)) { + + Database::songRepository songRepo(m_bConf); + Model::Song songDb; + songDb.id = 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); + + 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 response = createResponse(Status::CODE_200, *rawSong); + response->putHeader(Header::CONTENT_TYPE, "audio/mpeg"); + + return response; + } + + // TODO: create endpoint for updating songs + + ENDPOINT("DELETE", "api/v1/song/data/{id}", songDelete, PATH(Int32, id)) { + + Model::Song song; + song.id = id; + + Manager::song_manager sngMgr(m_bConf); + sngMgr.deleteSong(song); + + return createResponse(Status::CODE_200, "OK"); + } + + // 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/include/database/albumRepository.h b/include/database/albumRepository.h new file mode 100644 index 0000000..59e0ada --- /dev/null +++ b/include/database/albumRepository.h @@ -0,0 +1,34 @@ +#ifndef ALBUMREPOSITORY_H_ +#define ALBUMREPOSITORY_H_ + +#include + +#include "database/base_repository.h" +#include "models/models.h" +#include "types/albumFilter.h" + +namespace Database +{ + class albumRepository : public base_repository + { + public: + albumRepository(const Model::BinaryPath&); + + std::vector retrieveRecords(); + + 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*); + + // TODO: after parseRecord(MYSQL_STMT*) is implemented remove + // parseRecord(MYSQL_RES*) + Model::Album parseRecord(MYSQL_RES*); + Model::Album parseRecord(MYSQL_STMT*); + }; +} + +#endif diff --git a/include/database/artistRepository.h b/include/database/artistRepository.h new file mode 100644 index 0000000..83b897b --- /dev/null +++ b/include/database/artistRepository.h @@ -0,0 +1,28 @@ +#ifndef ARTISTREPOSITORY_H_ +#define ARTISTREPOSITORY_H_ + +#include "database/base_repository.h" +#include "models/models.h" +#include "types/artistFilter.h" + +namespace Database +{ + class artistRepository : public base_repository + { + public: + artistRepository(const Model::BinaryPath&); + + 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*); + }; +} + +#endif diff --git a/include/database/base_repository.h b/include/database/base_repository.h new file mode 100644 index 0000000..2281879 --- /dev/null +++ b/include/database/base_repository.h @@ -0,0 +1,34 @@ +#ifndef BASE_REPOSITORY_H_ +#define BASE_REPOSITORY_H_ + +#include + +#include + +#include "models/models.h" + +namespace Database +{ + class base_repository + { + public: + base_repository(); + base_repository(const std::string&); + base_repository(const Model::BinaryPath&); + protected: + MYSQL* setup_mysql_connection(); + MYSQL* setup_mysql_connection(Model::database_connection); + + MYSQL_RES* perform_mysql_query(MYSQL*, const std::string&); + + Model::database_connection details; + private: + void intitalizeDetails(); + void initializeDetails(const Model::BinaryPath&); + + std::string path; + Model::BinaryPath m_binConf; + }; +} + +#endif diff --git a/include/database/coverArtRepository.h b/include/database/coverArtRepository.h new file mode 100644 index 0000000..c664d8f --- /dev/null +++ b/include/database/coverArtRepository.h @@ -0,0 +1,32 @@ +#ifndef COVERARTREPOSITORY_H_ +#define COVERARTREPOSITORY_H_ + +#include + +#include "database/base_repository.h" +#include "models/models.h" +#include "types/coverFilter.h" + +namespace Database +{ + class coverArtRepository : public base_repository + { + public: + coverArtRepository(const std::string&); + 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*); + }; +} + +#endif diff --git a/include/database/genreRepository.h b/include/database/genreRepository.h new file mode 100644 index 0000000..e495105 --- /dev/null +++ b/include/database/genreRepository.h @@ -0,0 +1,28 @@ +#ifndef GENREREPOSITORY_H_ +#define GENREREPOSITORY_H_ + +#include "database/base_repository.h" +#include "models/models.h" +#include "types/genreFilter.h" + +namespace Database +{ + class genreRepository : public base_repository + { + public: + genreRepository(const Model::BinaryPath&); + + 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*); + }; +} + +#endif diff --git a/include/database/songRepository.h b/include/database/songRepository.h new file mode 100644 index 0000000..a32922b --- /dev/null +++ b/include/database/songRepository.h @@ -0,0 +1,38 @@ +#ifndef SONGREPOSITORY_H_ +#define SONGREPOSITORY_H_ + +#include +#include + +#include + +#include "database/base_repository.h" +#include "models/models.h" +#include "types/songFilter.h" + +namespace Database +{ + class songRepository : public base_repository + { + public: + songRepository(const std::string&); + songRepository(const Model::BinaryPath&); + + 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*); // TODO: to be removed + std::vector parseRecords(MYSQL_STMT*); + + Model::Song parseRecord(MYSQL_RES*); // TODO: to be removed + Model::Song parseRecord(MYSQL_STMT*); + }; +} + +#endif diff --git a/include/database/yearRepository.h b/include/database/yearRepository.h new file mode 100644 index 0000000..135b98f --- /dev/null +++ b/include/database/yearRepository.h @@ -0,0 +1,28 @@ +#ifndef YEARREPOSITORY_H_ +#define YEARREPOSITORY_H_ + +#include "database/base_repository.h" +#include "models/models.h" +#include "types/yearFilter.h" + +namespace Database +{ + class yearRepository : public base_repository + { + public: + yearRepository(const Model::BinaryPath&); + + 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*); + }; +} + +#endif 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/include/managers/albumManager.h b/include/managers/albumManager.h new file mode 100644 index 0000000..f487054 --- /dev/null +++ b/include/managers/albumManager.h @@ -0,0 +1,22 @@ +#ifndef ALBUMMANAGER_H_ +#define ALBUMMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class albumManager + { + public: + albumManager(const Model::BinaryPath&); + + Model::Album retrieveAlbum(Model::Album&); + Model::Album saveAlbum(const Model::Song&); + + static void printAlbum(const Model::Album&); + private: + Model::BinaryPath m_bConf; + }; +} + +#endif diff --git a/include/managers/artistManager.h b/include/managers/artistManager.h new file mode 100644 index 0000000..42266ee --- /dev/null +++ b/include/managers/artistManager.h @@ -0,0 +1,22 @@ +#ifndef ARTISTMANAGER_H_ +#define ARTISTMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class artistManager + { + 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; + }; +} + +#endif diff --git a/include/managers/coverArtManager.h b/include/managers/coverArtManager.h new file mode 100644 index 0000000..edd0831 --- /dev/null +++ b/include/managers/coverArtManager.h @@ -0,0 +1,23 @@ +#ifndef COVERARTMANAGER_H_ +#define COVERARTMANAGER_H_ + +#include + +#include "models/models.h" + +namespace Manager +{ + class coverArtManager + { + 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; + }; +} + +#endif diff --git a/include/managers/directory_manager.h b/include/managers/directory_manager.h new file mode 100644 index 0000000..c8ca3c8 --- /dev/null +++ b/include/managers/directory_manager.h @@ -0,0 +1,36 @@ +#ifndef DIRECTORY_MANAGER_H_ +#define DIRECTORY_MANAGER_H_ + +#include +#include + +#include + +#include "models/models.h" + +namespace Manager +{ + 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 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&); + + private: + void delete_song(const Model::Song); + }; +} + +#endif diff --git a/include/managers/genreManager.h b/include/managers/genreManager.h new file mode 100644 index 0000000..35149a7 --- /dev/null +++ b/include/managers/genreManager.h @@ -0,0 +1,22 @@ +#ifndef GENREMANAGER_H_ +#define GENREMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class genreManager + { + 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; + }; +} + +#endif diff --git a/include/managers/song_manager.h b/include/managers/song_manager.h new file mode 100644 index 0000000..f49c1d8 --- /dev/null +++ b/include/managers/song_manager.h @@ -0,0 +1,32 @@ +#ifndef SONGMANAGER_H_ +#define SONGMANAGER_H_ + +#include +#include + +#include + +#include "models/models.h" + +namespace Manager +{ + class song_manager + { + public: + song_manager(std::string&); + song_manager(const Model::BinaryPath&); + + void saveSong(Model::Song&); + void deleteSong(Model::Song&); + + static void printSong(const Model::Song&); + private: + void saveSongTemp(Model::Song&); + void saveMisc(Model::Song&); + + Model::BinaryPath m_bConf; + std::string exe_path; + }; +} + +#endif diff --git a/include/managers/token_manager.h b/include/managers/token_manager.h new file mode 100644 index 0000000..fc4b3f9 --- /dev/null +++ b/include/managers/token_manager.h @@ -0,0 +1,37 @@ +#ifndef TOKEN_MANAGER_H_ +#define TOKEN_MANAGER_H_ + +#include +#include +#include +#include + +#include + +#include "models/models.h" +#include "types/scopes.h" + +namespace Manager +{ + class token_manager + { + public: + token_manager(); + + Model::loginResult retrieve_token(); + Model::loginResult retrieve_token(std::string_view); + Model::loginResult retrieve_token(const Model::BinaryPath&); + + 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&); + + 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/managers/yearManager.h b/include/managers/yearManager.h new file mode 100644 index 0000000..c5f33e8 --- /dev/null +++ b/include/managers/yearManager.h @@ -0,0 +1,22 @@ +#ifndef YEARMANAGER_H_ +#define YEARMANAGER_H_ + +#include "models/models.h" + +namespace Manager +{ + class yearManager + { + 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; + }; +} + +#endif diff --git a/include/models/models.h b/include/models/models.h new file mode 100644 index 0000000..8ef3e1b --- /dev/null +++ b/include/models/models.h @@ -0,0 +1,103 @@ +#ifndef MODELS_H_ +#define MODELS_H_ + +#include +#include + +namespace Model +{ + 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; + int artistId; + int albumId; + int genreId; + int yearId; + }; + + struct Artist + { + int id; + std::string artist; + }; + + struct Album + { + int id; + std::string title; + int year; + std::vector songs; + }; + + struct Genre + { + int id; + std::string category; + + }; + + struct Year + { + int id; + int year; + }; + + 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 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 BinaryPath + { + 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; + }; +} + +#endif 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/coverFilter.h b/include/types/coverFilter.h new file mode 100644 index 0000000..0129ea8 --- /dev/null +++ b/include/types/coverFilter.h @@ -0,0 +1,14 @@ +#ifndef COVERFILTER_H_ +#define COVERFILTER_H_ + +namespace Type +{ + enum class coverFilter + { + id = 0, + songTitle, + imagePath + }; +} + +#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/scopes.h b/include/types/scopes.h new file mode 100644 index 0000000..e0fd4a6 --- /dev/null +++ b/include/types/scopes.h @@ -0,0 +1,13 @@ +#ifndef SCOPES_H_ +#define SCOPES_H_ + +namespace Type +{ + enum class Scope + { + upload = 0, + download + }; +} + +#endif diff --git a/include/types/songFilter.h b/include/types/songFilter.h new file mode 100644 index 0000000..d2d9973 --- /dev/null +++ b/include/types/songFilter.h @@ -0,0 +1,17 @@ +#ifndef SONGFILTER_H_ +#define SONGFILTER_H_ + +namespace Type +{ + enum class songFilter + { + id = 0, + title, + album, + artist, + genre, + year + }; +} + +#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/include/utilities/imageFile.h b/include/utilities/imageFile.h new file mode 100644 index 0000000..49432c6 --- /dev/null +++ b/include/utilities/imageFile.h @@ -0,0 +1,32 @@ +#ifndef IMAGEFILE_H_ +#define IMAGEFILE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Utility +{ + class imageFile : public TagLib::File + { + public: + imageFile(const char *file); + + TagLib::ByteVector data(); + + 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 new file mode 100644 index 0000000..1543143 --- /dev/null +++ b/include/utilities/metadata_retriever.h @@ -0,0 +1,22 @@ +#ifndef METADATA_RETRIEVER_H_ +#define METADATA_RETRIEVER_H_ + +#include +#include + +#include "models/models.h" + +namespace Utility +{ + 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: + }; +} + +#endif 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/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/" +} diff --git a/src/database/albumRepository.cpp b/src/database/albumRepository.cpp new file mode 100644 index 0000000..80d9f74 --- /dev/null +++ b/src/database/albumRepository.cpp @@ -0,0 +1,189 @@ +#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::cout << "retrieving album record" << std::endl; + 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; + default: + break; + } + + qry << " ORDER BY AlbumId DESC LIMIT 1"; + + 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; +} + +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 + + 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) +{ + std::cout << "beginning to insert album record" << std::endl; + + auto conn = setup_mysql_connection(); + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + const std::string query = "INSERT INTO Album(Title, Year) VALUES(?, ?)"; + + auto 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].length= &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) +{ + std::cout << "parsing album record" << std::endl; + 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; +} + +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 new file mode 100644 index 0000000..3eec442 --- /dev/null +++ b/src/database/artistRepository.cpp @@ -0,0 +1,117 @@ +#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; +} + +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; + + 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; +} + +Model::Artist Database::artistRepository::parseRecord(MYSQL_STMT *stmt) +{ + // TODO: implement this + Model::Artist art; + + return art; +} diff --git a/src/database/base_repository.cpp b/src/database/base_repository.cpp new file mode 100644 index 0000000..aa801d8 --- /dev/null +++ b/src/database/base_repository.cpp @@ -0,0 +1,73 @@ +#include "database/base_repository.h" + +#include + +#include + +#include "managers/directory_manager.h" + +Database::base_repository::base_repository() +{ } + +Database::base_repository::base_repository(const std::string& path) : path(path) +{ + intitalizeDetails(); +} +Database::base_repository::base_repository(const Model::BinaryPath& bConf) +{ + initializeDetails(bConf); +} + +MYSQL* Database::base_repository::setup_mysql_connection() +{ + MYSQL *conn = mysql_init(nullptr); + + if (!mysql_real_connect(conn, details.server.c_str(), details.username.c_str(), + details.password.c_str(), details.database.c_str(), 0, nullptr, 0)) { + std::cout << "connection error" << std::endl; + } + + return conn; +} +MYSQL* Database::base_repository::setup_mysql_connection(Model::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* 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())) + { + printf("MySQL query error : %s\n", mysql_error(conn)); + exit(1); + } + + return mysql_use_result(conn); +} + +void Database::base_repository::intitalizeDetails() +{ + auto databaseConfig = Manager::directory_manager::databaseConfigContent(path); + + details.database = databaseConfig["database"].get(); + details.password = databaseConfig["password"].get(); + 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 new file mode 100644 index 0000000..a2edc9c --- /dev/null +++ b/src/database/coverArtRepository.cpp @@ -0,0 +1,136 @@ +#include "database/coverArtRepository.h" + +#include +#include +#include +#include + +Database::coverArtRepository::coverArtRepository(const std::string& path) : base_repository(path) +{ } + +Database::coverArtRepository::coverArtRepository(const Model::BinaryPath& bConf) : base_repository(bConf) +{ } + +Model::Cover Database::coverArtRepository::retrieveRecord(Model::Cover& cov, Type::coverFilter filter = Type::coverFilter::id) +{ + std::stringstream qry; + auto conn = setup_mysql_connection(); + qry << "SELECT * FROM CoverArt WHERE "; + + std::unique_ptr param; + switch (filter) { + case Type::coverFilter::id: + qry << "CoverArtId = " << cov.id; + break; + 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()); + 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()); + qry << "ImagePath = '" << *param << "'"; + break; + } + + const std::string query = qry.str(); + 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; +} + +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(); + 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 Database::coverArtRepository::saveRecord(const Model::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; +} + +Model::Cover Database::coverArtRepository::parseRecord(MYSQL_RES *results) +{ + std::cout << "parsing record" << std::endl; + Model::Cover cov; + auto fieldNum = mysql_num_fields(results); + + MYSQL_ROW row = mysql_fetch_row(results); + + for (auto i = 0; i != fieldNum; ++i) { + switch (i) { + case 0: + cov.id = std::stoi(row[i]); + break; + case 1: + cov.songTitle = row[i]; + break; + case 2: + cov.imagePath = row[i]; + break; + } + } + std::cout << "done parsing record" << std::endl; + + return cov; +} + +Model::Cover 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 new file mode 100644 index 0000000..dde767d --- /dev/null +++ b/src/database/genreRepository.cpp @@ -0,0 +1,114 @@ +#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; +} + +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; + + 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; +} +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 new file mode 100644 index 0000000..7a702bc --- /dev/null +++ b/src/database/songRepository.cpp @@ -0,0 +1,674 @@ +#include "database/songRepository.h" + +#include +#include +#include +#include + +#include "types/songFilter.h" + +Database::songRepository::songRepository(const std::string& path) : base_repository(path) +{ } + +Database::songRepository::songRepository(const Model::BinaryPath& bConf) : base_repository(bConf) +{ } + +std::vector Database::songRepository::retrieveRecords() +{ + auto conn = setup_mysql_connection(); + auto stmt = mysql_stmt_init(conn); + const std::string query = "SELECT * FROM Song"; + + ::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; +} + +Model::Song Database::songRepository::retrieveRecord(Model::Song& song, Type::songFilter filter) +{ + 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; + + 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(); + 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 Database::songRepository::saveRecord(const Model::Song& song) +{ + std::cout << "beginning to insert song record" << std::endl; + auto conn = setup_mysql_connection(); + auto status = 0; + + MYSQL_STMT *stmt = mysql_stmt_init(conn); + + std::string query = "INSERT INTO Song(Title, Artist, Album, Genre, "; + query.append("Year, Duration, Track, Disc, SongPath, CoverArtId, ArtistId, "); + query.append("AlbumId, GenreId, YearId) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + + status = mysql_stmt_prepare(stmt, query.c_str(), query.size()); + + MYSQL_BIND params[14]; + memset(params, 0, sizeof(params)); + + params[0].buffer_type = MYSQL_TYPE_STRING; + params[0].buffer = (char*)song.title.c_str(); + auto titleLength = song.title.size(); + params[0].length = &titleLength; + params[0].is_null = 0; + + params[1].buffer_type = MYSQL_TYPE_STRING; + params[1].buffer = (char*)song.artist.c_str(); + auto artistLength = song.artist.size(); + params[1].length = &artistLength; + params[1].is_null = 0; + + params[2].buffer_type = MYSQL_TYPE_STRING; + params[2].buffer = (char*)song.album.c_str(); + auto albumLength = song.album.size(); + params[2].length = &albumLength; + params[2].is_null = 0; + + params[3].buffer_type = MYSQL_TYPE_STRING; + params[3].buffer = (char*)song.genre.c_str(); + auto genreLength = song.genre.size(); + params[3].length = &genreLength; + params[3].is_null = 0; + + params[4].buffer_type = MYSQL_TYPE_LONG; + params[4].buffer = (char*)&song.year; + params[4].length = 0; + params[4].is_null = 0; + + params[5].buffer_type = MYSQL_TYPE_LONG; + params[5].buffer = (char*)&song.duration; + params[5].length = 0; + params[5].is_null = 0; + + params[6].buffer_type = MYSQL_TYPE_LONG; + params[6].buffer = (char*)&song.track; + params[6].length = 0; + params[6].is_null = 0; + + params[7].buffer_type = MYSQL_TYPE_LONG; + params[7].buffer = (char*)&song.disc; + params[7].length = 0; + params[7].is_null = 0; + + params[8].buffer_type = MYSQL_TYPE_STRING; + params[8].buffer = (char*)song.songPath.c_str(); + auto pathLength = song.songPath.size(); + params[8].length = &pathLength; + params[8].is_null = 0; + + params[9].buffer_type = MYSQL_TYPE_LONG; + params[9].buffer = (char*)&song.coverArtId; + params[9].length = 0; + params[9].is_null = 0; + + params[10].buffer_type = MYSQL_TYPE_LONG; + params[10].buffer = (char*)&song.artistId; + params[10].length = 0; + params[10].is_null = 0; + + params[11].buffer_type = MYSQL_TYPE_LONG; + params[11].buffer = (char*)&song.albumId; + params[11].length = 0; + params[11].is_null = 0; + + params[12].buffer_type = MYSQL_TYPE_LONG; + params[12].buffer = (char*)&song.genreId; + params[12].length = 0; + params[12].is_null = 0; + + params[13].buffer_type = MYSQL_TYPE_LONG; + params[13].buffer = (char*)&song.yearId; + params[13].length = 0; + params[13].is_null = 0; + + status = mysql_stmt_bind_param(stmt, params); + status = mysql_stmt_execute(stmt); + + mysql_stmt_close(stmt); + mysql_close(conn); + + std::cout << "done inserting song record" << std::endl; +} + +// TODO: delete this, not being used +std::vector Database::songRepository::parseRecords(MYSQL_RES* results) +{ + 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; ) { + 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]); + 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.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; + } + } + + 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); + 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]); + 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.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; + } + } + std::cout << "done parsing record" << std::endl; + + 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 new file mode 100644 index 0000000..818f0de --- /dev/null +++ b/src/database/yearRepository.cpp @@ -0,0 +1,112 @@ +#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; +} + +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; + + 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; +} +Model::Year Database::yearRepository::parseRecord(MYSQL_STMT *stmt) +{ + // TODO: imeplement this + + Model::Year year; + + return year; +} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..9301bc2 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include + +#include +#include "oatpp/network/server/Server.hpp" +#include "oatpp/network/server/SimpleTCPConnectionProvider.hpp" +#include "oatpp/web/server/HttpConnectionHandler.hpp" + +#include "component/appComponent.hpp" +#include "controller/loginController.hpp" +#include "controller/songController.hpp" +#include "database/base_repository.h" +#include "models/models.h" + +namespace fs = std::filesystem; + +//void run(const std::string& working_path) +void run(const Model::BinaryPath& bConf) +{ + Component::appComponent component; + + OATPP_COMPONENT(std::shared_ptr, router); + + auto logController = std::make_shared(bConf); + auto sngController = std::make_shared(bConf); + logController->addEndpointsToRouter(router); + sngController->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(); + + Model::BinaryPath bConf(argv[0]); + + run(bConf); + + oatpp::base::Environment::destroy(); + + return 0; +} diff --git a/src/managers/albumManager.cpp b/src/managers/albumManager.cpp new file mode 100644 index 0000000..08d1121 --- /dev/null +++ b/src/managers/albumManager.cpp @@ -0,0 +1,45 @@ +#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) +{ } + + +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; + album.year = song.year; + + Database::albumRepository albRepo(m_bConf); + if (!albRepo.doesAlbumExists(album, Type::albumFilter::title)) { + albRepo.saveAlbum(album); + } else { + std::cout << "album record already exists in the database" << std::endl; + } + + + 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 new file mode 100644 index 0000000..2cf8857 --- /dev/null +++ b/src/managers/artistManager.cpp @@ -0,0 +1,41 @@ +#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); + if (!artRepo.doesArtistExist(artist, Type::artistFilter::artist)) { + artRepo.saveRecord(artist); + } else { + std::cout << "artist already exists" << std::endl; + } + + 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 new file mode 100644 index 0000000..3f79f64 --- /dev/null +++ b/src/managers/coverArtManager.cpp @@ -0,0 +1,34 @@ +#include "managers/coverArtManager.h" + +#include "database/coverArtRepository.h" +#include "types/coverFilter.h" +#include "utilities/metadata_retriever.h" + +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) +{ + Utility::metadata_retriever meta; + Model::Cover cov; + cov.imagePath = rootPath; + cov = meta.update_cover_art(song, cov, stockCoverPath); + cov.songTitle = song.title; + + Database::coverArtRepository covRepo(m_bConf); + if (!covRepo.doesCoverArtExist(cov, Type::coverFilter::songTitle)) { + std::cout << "saving image record to the database" << std::endl; + covRepo.saveRecord(cov); + } else { + std::cout << "cover art record already exists" << std::endl; + } + + std::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 new file mode 100644 index 0000000..0b5647b --- /dev/null +++ b/src/managers/directory_manager.cpp @@ -0,0 +1,155 @@ +#include +#include +#include +#include + +#include "managers/directory_manager.h" + +namespace fs = std::filesystem; + +std::string Manager::directory_manager::create_directory_process(Model::Song song, const std::string& root_path) +{ + auto curr_path = fs::path(root_path); + + if (fs::exists(curr_path)) { + std::cout<<"path exists"< + +#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); + if (!gnrRepo.doesGenreExist(genre, Type::genreFilter::category)) { + gnrRepo.saveRecord(genre); + } else { + std::cout << "genre record already exists" << std::endl; + } + + 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 new file mode 100644 index 0000000..a61db06 --- /dev/null +++ b/src/managers/song_manager.cpp @@ -0,0 +1,163 @@ +#include "managers/song_manager.h" + +#include +#include +#include + +#include + +#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; + +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) +{ + saveSongTemp(song); + Utility::metadata_retriever meta; + auto data = std::move(song.data); + song = meta.retrieve_metadata(song.songPath); + song.data = std::move(data); + + saveMisc(song); + + printSong(song); + + Database::songRepository songRepo(m_bConf); + songRepo.saveRecord(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); + + song = songRepo.retrieveRecord(song, Type::songFilter::id); + songRepo.deleteRecord(song); + + Model::Cover cov; + cov.id = song.coverArtId; + cov = covRepo.retrieveRecord(cov, Type::coverFilter::id); + covRepo.deleteRecord(cov); + + auto paths = Manager::directory_manager::pathConfigContent(m_bConf); + const auto coverArtPath = paths["cover_root_path"].get(); + std::string stockCoverArtPath = coverArtPath; + stockCoverArtPath.append("CoverArt.png"); + + if (stockCoverArtPath.compare(cov.imagePath) != 0) { + fs::remove(cov.imagePath); + std::cout << "deleting cover art" << std::endl; + } + fs::remove(song.songPath); + + Manager::directory_manager::delete_directories(song, paths["root_music_path"].get()); + Manager::directory_manager::delete_directories(song, coverArtPath); +} + +void Manager::song_manager::printSong(const Model::Song& song) +{ + std::cout << "\nsong" << std::endl; + std::cout << "title: " << song.title << std::endl; + std::cout << "artist: " << song.artist << std::endl; + std::cout << "album: " << song.album << std::endl; + std::cout << "genre: " << song.genre << std::endl; + std::cout << "duration: " << song.duration << std::endl; + std::cout << "year: " << song.year << std::endl; + std::cout << "track: " << song.track << std::endl; + std::cout << "disc: " << song.disc << std::endl; + std::cout << "song path: " << song.songPath << std::endl; + std::cout << "cover art id: " << song.coverArtId << std::endl; + std::cout << "album id: " << song.albumId << std::endl; + std::cout << "artist id: " << song.artistId << std::endl; + std::cout << "genre id: " << song.genreId << std::endl; + std::cout << "year id: " << song.yearId << std::endl; +} + +void Manager::song_manager::saveSongTemp(Model::Song& song) +{ + auto config = Manager::directory_manager::pathConfigContent(m_bConf); + + 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; +} +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); + + auto songPath = Manager::directory_manager::create_directory_process(song, musicRootPath); + songPath.append(song.title); + songPath.append(".mp3"); + 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); + + 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 new file mode 100644 index 0000000..a629a2e --- /dev/null +++ b/src/managers/token_manager.cpp @@ -0,0 +1,196 @@ +#include "managers/token_manager.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "managers/directory_manager.h" + +namespace fs = std::filesystem; + + +Manager::token_manager::token_manager() +{ +} + +Model::loginResult Manager::token_manager::retrieve_token() +{ + Model::loginResult lr; + lr.access_token = "dsfdsf"; + lr.token_type = "demo"; + + return lr; +} +Model::loginResult Manager::token_manager::retrieve_token(std::string_view path) +{ + auto cred = parse_auth_credentials(path); + + 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; +} +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, Type::Scope scope) +{ + auto authPair = fetch_auth_header(auth); + + if (!std::get<0>(authPair)) { + std::cout << "no Bearer found" << std::endl; + + return std::get<0>(authPair); + } + + auto authHeader = std::get<1>(authPair); + + auto token = authHeader.at(authHeader.size()-1); + + auto scopes = extract_scopes(jwt::decode(token)); + + switch (scope) { + case Type::Scope::upload: + return token_supports_scope(scopes, "upload:songs"); + break; + case Type::Scope::download: + return token_supports_scope(scopes, "download:songs"); + default: + break; + } + + return false; +} + +Model::auth_credentials Manager::token_manager::parse_auth_credentials(std::string_view path) +{ + auto exe_path = Manager::directory_manager::configPath(path); + exe_path.append("/authcredentials.json"); + + auto con = Manager::directory_manager::credentialConfigContent(exe_path); + + 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; +} +Model::auth_credentials Manager::token_manager::parse_auth_credentials(const Model::BinaryPath& bConf) +{ + auto exePath = Manager::directory_manager::configPath(bConf); + exePath.append("/authcredentials.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) +{ + 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> Manager::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 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) { + return (foundScope.compare(scope) == 0); + }); +} diff --git a/src/managers/yearManager.cpp b/src/managers/yearManager.cpp new file mode 100644 index 0000000..f008198 --- /dev/null +++ b/src/managers/yearManager.cpp @@ -0,0 +1,41 @@ +#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); + if (!yearRepo.doesYearExist(year, Type::yearFilter::year)) { + yearRepo.saveRecord(year); + } else { + std::cout << "year record already exists in the database" << std::endl; + } + + 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; +} diff --git a/src/utilities/imageFile.cpp b/src/utilities/imageFile.cpp new file mode 100644 index 0000000..dad7a7c --- /dev/null +++ b/src/utilities/imageFile.cpp @@ -0,0 +1,10 @@ +#include "utilities/imageFile.h" + +Utility::imageFile::imageFile(const char *file) : TagLib::File(file) +{ +} + +TagLib::ByteVector Utility::imageFile::data() +{ + return readBlock(length()); +} diff --git a/src/utilities/metadata_retriever.cpp b/src/utilities/metadata_retriever.cpp new file mode 100644 index 0000000..e10dea9 --- /dev/null +++ b/src/utilities/metadata_retriever.cpp @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "managers/directory_manager.h" +#include "utilities/imageFile.h" +#include "utilities/metadata_retriever.h" + +namespace fs = std::filesystem; + +Model::Song Utility::metadata_retriever::retrieve_metadata(std::string& song_path) +{ + TagLib::FileRef file(song_path.c_str()); + Model::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.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; +} + +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(); + auto frameList = tag->frameListMap()["APIC"]; + + if (frameList.isEmpty()) { + cov.imagePath.append("CoverArt.png"); + + if (!fs::exists(cov.imagePath)) { + std::cout << "copying stock cover path" << std::endl; + fs::copy(stockCoverPath, cov.imagePath); + } + + imageFile 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" << std::endl; + } else { + auto frame = dynamic_cast( + frameList.front()); + + 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; + + std::cout << cov.imagePath << std::endl; + + std::fstream img_save(cov.imagePath, std::ios::out | + std::ios::binary); + img_save.write(frame->picture().data(), frame->picture().size()); + img_save.close(); + std::cout << "saved to " << cov.imagePath << std::endl; + } + + return cov; +} + +void Utility::metadata_retriever::update_metadata(Model::Song sng_updated, const Model::Song sng_old) +{ + std::cout<<"updating metadata"< 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); + } + + // TODO: functionality to update the track number and disc number + + file.save(); +}