Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 80628292e2 | |||
| 57f4ec1261 | |||
| c191d7ee7a | |||
| 73bfff3940 | |||
| 38c056cc99 | |||
| 640971dea8 | |||
| 664b0d520b | |||
| 11fe1f29e1 | |||
| 05b5de0939 | |||
| d5944c470b | |||
| 00ef8d0242 | |||
| 77c6ee00ea | |||
| 1bfd0a4931 | |||
| 6c3ce69873 | |||
| a423e6e220 | |||
| f8ec65fd29 | |||
| 665407aac5 | |||
| e5bea187f4 | |||
| fd0f487615 | |||
| d48716a54f | |||
| 2cc13ac9bb | |||
| 467a9d7e0f | |||
| f0551a4801 | |||
| 2cd8c83e28 | |||
| 9797897b76 | |||
| 27cc80d114 | |||
| 27ee3d6ba5 | |||
| 1b6e70ce12 | |||
| 5669cdbdd0 | |||
| 3a6e0f64bc | |||
| aa0a1ab5fe | |||
| b529731c95 | |||
| 64e6f33d7c | |||
| 023298c6f8 | |||
| f8d9c8e4a7 | |||
| 471fa71789 | |||
| edaea68296 | |||
| 8600d9b6bc | |||
| 922e527819 | |||
| 46f0da4a5f | |||
| 16839b9bf8 | |||
| 552d5dcd25 | |||
| cadcf33ed6 | |||
| 4f46f2ed94 | |||
| 560773bfff | |||
| 43623d07c3 | |||
| b93d436c29 |
@@ -3,6 +3,9 @@
|
||||
################################################################################
|
||||
|
||||
/.vs/Icarus
|
||||
/bin/*
|
||||
/bin/Debug/netcoreapp2.2
|
||||
/Migrations
|
||||
/obj
|
||||
/obj/*
|
||||
/Icarus.txt
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
|
||||
|
||||
namespace Icarus.Certs
|
||||
{
|
||||
public class SigningIssuerCertificate : IDisposable
|
||||
{
|
||||
private readonly RSACryptoServiceProvider _rsa;
|
||||
|
||||
public SigningIssuerCertificate()
|
||||
{
|
||||
_rsa = new RSACryptoServiceProvider();
|
||||
}
|
||||
|
||||
public RsaSecurityKey GetIssuerSigningKey(string publicKeyPath)
|
||||
{
|
||||
var file = publicKeyPath;
|
||||
var publicKey = System.IO.File.ReadAllText(file);
|
||||
|
||||
using (var reader = System.IO.File.OpenText(file))
|
||||
{
|
||||
var pem = new PemReader(reader);
|
||||
var o = (RsaKeyParameters)pem.ReadObject();
|
||||
var parameters = new RSAParameters();
|
||||
parameters.Modulus = o.Modulus.ToByteArray();
|
||||
parameters.Exponent = o.Exponent.ToByteArray();
|
||||
_rsa.ImportParameters(parameters);
|
||||
}
|
||||
|
||||
return new RsaSecurityKey(_rsa);
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_rsa?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SigningAudienceCertificate : IDisposable
|
||||
{
|
||||
private readonly RSACryptoServiceProvider _rsa;
|
||||
|
||||
public SigningAudienceCertificate()
|
||||
{
|
||||
_rsa = new RSACryptoServiceProvider();
|
||||
}
|
||||
|
||||
public SigningCredentials GetAudienceSigningKey(string keyPath)
|
||||
{
|
||||
var file = keyPath;
|
||||
var publicKey = System.IO.File.ReadAllText(file);
|
||||
|
||||
using (var reader = System.IO.File.OpenText(file))
|
||||
{
|
||||
var pem = new PemReader(reader);
|
||||
var o = (RsaKeyParameters)pem.ReadObject();
|
||||
var parameters = new RSAParameters();
|
||||
parameters.Modulus = o.Modulus.ToByteArray();
|
||||
parameters.Exponent = o.Exponent.ToByteArray();
|
||||
_rsa.ImportParameters(parameters);
|
||||
}
|
||||
|
||||
return new SigningCredentials(
|
||||
key: new RsaSecurityKey(_rsa),
|
||||
algorithm: SecurityAlgorithms.RsaSha256);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_rsa?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
@@ -11,6 +14,7 @@ namespace Icarus.Controllers.Managers
|
||||
public class AlbumManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private AlbumContext _albumContext;
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -19,10 +23,133 @@ namespace Icarus.Controllers.Managers
|
||||
|
||||
|
||||
#region Constructors
|
||||
public AlbumManager(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
_albumContext = new AlbumContext(_connectionString);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public void SaveAlbumToDatabase(ref Song song)
|
||||
{
|
||||
_logger.Info("Starting process to save the album record of the song to the database");
|
||||
|
||||
var album = new Album();
|
||||
|
||||
album.Title = song.AlbumTitle;
|
||||
album.AlbumArtist = song.Artist;
|
||||
album.Year = song.Year.Value;
|
||||
var albumTitle = song.AlbumTitle;
|
||||
var albumArtist = song.Artist;
|
||||
|
||||
var albumRetrieved = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(albumTitle) && alb.AlbumArtist.Equals(albumArtist));
|
||||
|
||||
if (albumRetrieved == null)
|
||||
{
|
||||
album.SongCount = 1;
|
||||
_albumContext.Add(album);
|
||||
_albumContext.SaveChanges();
|
||||
|
||||
Console.WriteLine($"Album Id {album.AlbumID}");
|
||||
}
|
||||
else
|
||||
{
|
||||
album.AlbumID = albumRetrieved.AlbumID;
|
||||
}
|
||||
|
||||
song.AlbumID = album.AlbumID;
|
||||
}
|
||||
|
||||
|
||||
public void DeleteAlbumFromDatabase(Song song)
|
||||
{
|
||||
var album = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(song.AlbumTitle));
|
||||
|
||||
if (album == null)
|
||||
{
|
||||
_logger.Info("Cannot delete the album record because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
DeleteAlbumFromDb(album);
|
||||
}
|
||||
|
||||
|
||||
public Album UpdateAlbumInDatabase(Song oldSong, Song newSong)
|
||||
{
|
||||
var albumRecord = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(oldSong.AlbumTitle));
|
||||
var oldAlbumTitle = oldSong.AlbumTitle;
|
||||
var oldAlbumArtist = oldSong.Artist;
|
||||
var newAlbumTitle = newSong.AlbumTitle;
|
||||
var newAlbumArtist = newSong.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);
|
||||
|
||||
var existingAlbumRecord = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(oldSong.AlbumTitle));
|
||||
if (existingAlbumRecord == null)
|
||||
{
|
||||
_logger.Info("Creating new album record");
|
||||
|
||||
var newAlbumRecord = new Album
|
||||
{
|
||||
Title = newAlbumTitle,
|
||||
AlbumArtist = newAlbumArtist,
|
||||
Year = newSong.Year.Value
|
||||
};
|
||||
|
||||
_albumContext.Add(newAlbumRecord);
|
||||
_albumContext.SaveChanges();
|
||||
|
||||
return newAlbumRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Updating existing album record");
|
||||
|
||||
existingAlbumRecord = _albumContext.Albums.FirstOrDefault(alb => alb.Title.Equals(newSong.AlbumTitle));
|
||||
existingAlbumRecord.AlbumArtist = newAlbumArtist;
|
||||
|
||||
_albumContext.Update(existingAlbumRecord);
|
||||
_albumContext.SaveChanges();
|
||||
|
||||
return existingAlbumRecord;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeleteAlbumFromDb(Album album)
|
||||
{
|
||||
if (SongsInAlbum(album) <= 1)
|
||||
{
|
||||
_albumContext.Remove(album);
|
||||
_albumContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
private int SongsInAlbum(Album album)
|
||||
{
|
||||
var sngContext = new SongContext(_connectionString);
|
||||
var songs = sngContext.Songs.Where(sng => sng.AlbumID == album.AlbumID).ToList();
|
||||
|
||||
return songs.Count;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
@@ -11,6 +14,7 @@ namespace Icarus.Controllers.Managers
|
||||
public class ArtistManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private ArtistContext _artistContext;
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -19,10 +23,115 @@ namespace Icarus.Controllers.Managers
|
||||
|
||||
|
||||
#region Constructors
|
||||
public ArtistManager(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
_artistContext = new ArtistContext(_connectionString);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public void SaveArtistToDatabase(ref Song song)
|
||||
{
|
||||
_logger.Info("Starting process to save the artist record of the song to the database");
|
||||
|
||||
var artist = new Artist();
|
||||
|
||||
artist.Name = song.Artist;
|
||||
artist.SongCount = 1;
|
||||
var artistTitle = artist.Name;
|
||||
|
||||
var artistRetrieved = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artistTitle));
|
||||
|
||||
if (artistRetrieved == null)
|
||||
{
|
||||
artist.SongCount = 1;
|
||||
_artistContext.Add(artist);
|
||||
_artistContext.SaveChanges();
|
||||
}
|
||||
else
|
||||
{
|
||||
artist.ArtistID = artistRetrieved.ArtistID;
|
||||
}
|
||||
|
||||
song.ArtistID = artist.ArtistID;
|
||||
}
|
||||
|
||||
public Artist UpdateArtistInDatabase(Song oldSongRecord, Song newSongRecord)
|
||||
{
|
||||
var oldArtistRecord = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(oldSongRecord.AlbumTitle));
|
||||
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");
|
||||
|
||||
_artistContext.Remove(oldArtistRecord);
|
||||
_artistContext.SaveChanges();
|
||||
}
|
||||
|
||||
if (!(_artistContext.Artists.FirstOrDefault(art => art.Name.Equals(oldSongRecord.AlbumTitle)) != null))
|
||||
{
|
||||
_logger.Info("Creating new artist record");
|
||||
|
||||
var newArtistRecord = new Artist
|
||||
{
|
||||
Name = newArtistName
|
||||
};
|
||||
|
||||
_artistContext.Add(newArtistRecord);
|
||||
_artistContext.SaveChanges();
|
||||
|
||||
return newArtistRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Updating existing artist record");
|
||||
|
||||
var existingArtistRecord = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(newSongRecord.AlbumTitle));
|
||||
|
||||
_artistContext.Update(existingArtistRecord);
|
||||
_artistContext.SaveChanges();
|
||||
|
||||
return existingArtistRecord;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteArtistFromDatabase(Song song)
|
||||
{
|
||||
if (!(_artistContext.Artists.FirstOrDefault(art => art.Name.Equals(song.Artist)) != null))
|
||||
{
|
||||
_logger.Info("Cannot delete the artist record because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
var artist = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(song.Artist));
|
||||
|
||||
if (SongsOfArtist(artist) <= 1)
|
||||
{
|
||||
_artistContext.Remove(artist);
|
||||
_artistContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
private int SongsOfArtist(Artist artist)
|
||||
{
|
||||
var sngContext = new SongContext(_connectionString);
|
||||
var songs = sngContext.Songs.Where(sng => sng.ArtistID == artist.ArtistID).ToList();
|
||||
|
||||
return songs.Count;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using NLog;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
@@ -8,6 +9,8 @@ namespace Icarus.Controllers.Managers
|
||||
{
|
||||
#region Fields
|
||||
protected static Logger _logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
|
||||
protected IConfiguration _config;
|
||||
protected string _connectionString;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Constants;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
using Icarus.Models;
|
||||
using Icarus.Types;
|
||||
|
||||
@@ -14,36 +18,37 @@ namespace Icarus.Controllers.Managers
|
||||
{
|
||||
#region Fields
|
||||
private string _rootCoverArtPath;
|
||||
private CoverArtContext _coverArtContext;
|
||||
private byte[] _stockCoverArt = null;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public CoverArtManager(string rootPath)
|
||||
public CoverArtManager(IConfiguration config)
|
||||
{
|
||||
_rootCoverArtPath = rootPath;
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
_rootCoverArtPath = _config.GetValue<string>("CoverArtPath");
|
||||
Initialize();
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public void SaveCoverArtToDatabase(ref Song song, ref CoverArt coverArt,
|
||||
CoverArtRepository coverArtRepository)
|
||||
public void SaveCoverArtToDatabase(ref Song song, ref CoverArt coverArt)
|
||||
{
|
||||
_logger.Info("Saving cover art record to the database");
|
||||
coverArtRepository.SaveCoverArt(coverArt);
|
||||
_coverArtContext.Add(coverArt);
|
||||
_coverArtContext.SaveChanges();
|
||||
|
||||
coverArt = coverArtRepository.GetCoverArt(CoverArtField.SongTitle,
|
||||
coverArt);
|
||||
|
||||
song.CoverArtId = coverArt.CoverArtId;
|
||||
song.CoverArtID = coverArt.CoverArtID;
|
||||
}
|
||||
public void DeleteCoverArtFromDatabase(CoverArt coverArt,
|
||||
CoverArtRepository coverArtRepository)
|
||||
public void DeleteCoverArtFromDatabase(CoverArt coverArt)
|
||||
{
|
||||
_logger.Info("Attempting to delete cover art from the database");
|
||||
coverArtRepository.DeleteCoverArt(coverArt);
|
||||
|
||||
_coverArtContext.Remove(coverArt);
|
||||
_coverArtContext.SaveChanges();
|
||||
}
|
||||
public void DeleteCoverArt(CoverArt coverArt)
|
||||
{
|
||||
@@ -75,14 +80,19 @@ namespace Icarus.Controllers.Managers
|
||||
try
|
||||
{
|
||||
var dirMgr = new DirectoryManager(_rootCoverArtPath);
|
||||
var defaultExtension = ".png";
|
||||
dirMgr.CreateDirectory(song);
|
||||
var imagePath = dirMgr.SongDirectory + song.Title + ".png";
|
||||
|
||||
var coverArt = new CoverArt
|
||||
{
|
||||
SongTitle = song.Title,
|
||||
ImagePath = imagePath
|
||||
SongTitle = song.Title
|
||||
};
|
||||
|
||||
var segment = coverArt.GenerateFilename(0);
|
||||
var imagePath = dirMgr.SongDirectory + segment + defaultExtension;
|
||||
|
||||
coverArt.ImagePath = imagePath;
|
||||
|
||||
var metaData = new MetadataRetriever();
|
||||
var imgBytes = metaData.RetrieveCoverArtBytes(song);
|
||||
|
||||
@@ -94,7 +104,7 @@ namespace Icarus.Controllers.Managers
|
||||
else
|
||||
{
|
||||
_logger.Info("Song has no cover art, applying stock cover art");
|
||||
coverArt.ImagePath = _rootCoverArtPath + "CoverArt.png";
|
||||
coverArt.ImagePath = _rootCoverArtPath + $"{segment}{defaultExtension}";
|
||||
metaData.UpdateCoverArt(song, coverArt);
|
||||
File.WriteAllBytes(coverArt.ImagePath, _stockCoverArt);
|
||||
}
|
||||
@@ -110,8 +120,43 @@ namespace Icarus.Controllers.Managers
|
||||
return null;
|
||||
}
|
||||
|
||||
public CoverArt SaveCoverArt(IFormFile data, Song song)
|
||||
{
|
||||
var cover = new CoverArt { SongTitle = song.Title };
|
||||
|
||||
try
|
||||
{
|
||||
var dirMgr = new DirectoryManager(_rootCoverArtPath);
|
||||
var defaultExtension = ".png";
|
||||
dirMgr.CreateDirectory(song);
|
||||
|
||||
var segment = cover.GenerateFilename(0);
|
||||
var imagePath = dirMgr.SongDirectory + segment + defaultExtension;
|
||||
|
||||
cover.ImagePath = imagePath;
|
||||
|
||||
using (var fileStream = new FileStream(imagePath, FileMode.Create))
|
||||
{
|
||||
data.CopyTo(fileStream);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex.Message, "An error occurred");
|
||||
}
|
||||
|
||||
return cover;
|
||||
}
|
||||
|
||||
public CoverArt GetCoverArt(Song song)
|
||||
{
|
||||
return _coverArtContext.CoverArtImages.FirstOrDefault(cov => cov.SongTitle.Equals(song.Title));
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
_coverArtContext = new CoverArtContext(_connectionString);
|
||||
|
||||
if (System.IO.File.Exists(DirectoryPaths.CoverArtPath))
|
||||
_stockCoverArt = File.ReadAllBytes(DirectoryPaths.CoverArtPath);
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ using Icarus.Types;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
// NOTE: Do not use metadata for the song's metadata
|
||||
public class DirectoryManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
private Song _song;
|
||||
private string _rootSongDirectory;
|
||||
private string _songDirectory;
|
||||
@@ -50,24 +50,7 @@ namespace Icarus.Controllers.Managers
|
||||
#region Methods
|
||||
public void CreateDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
_songDirectory = AlbumDirectory();
|
||||
|
||||
if (!Directory.Exists(_songDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(_songDirectory);
|
||||
Console.WriteLine("The directory has been created");
|
||||
}
|
||||
|
||||
|
||||
Console.WriteLine($"The song will be saved in the following" +
|
||||
$" directory: {_songDirectory}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"An error occurred {ex.Message}");
|
||||
}
|
||||
CreateDirectory(_song);
|
||||
}
|
||||
public void CreateDirectory(Song song)
|
||||
{
|
||||
@@ -158,6 +141,7 @@ namespace Icarus.Controllers.Managers
|
||||
|
||||
return artistPath;
|
||||
}
|
||||
|
||||
public string GenerateSongPath(Song song)
|
||||
{
|
||||
_logger.Info("Generating song path");
|
||||
@@ -208,34 +192,41 @@ namespace Icarus.Controllers.Managers
|
||||
|
||||
private string AlbumDirectory()
|
||||
{
|
||||
string directory = _rootSongDirectory;
|
||||
directory += $@"{_song.Artist}/{_song.AlbumTitle}/";
|
||||
|
||||
return directory;
|
||||
return AlbumDirectory(_song);
|
||||
}
|
||||
private string AlbumDirectory(Song song)
|
||||
{
|
||||
var directory = _rootSongDirectory;
|
||||
directory += $@"{song.Artist}/{song.AlbumTitle}/";
|
||||
var directory = ArtistDirectory(song);
|
||||
var segment = SerializeValue(song.AlbumTitle);
|
||||
directory += $@"{segment}/";
|
||||
Console.WriteLine($"Album directory {directory}");
|
||||
|
||||
return directory;
|
||||
}
|
||||
private string ArtistDirectory()
|
||||
{
|
||||
var directory = _rootSongDirectory;
|
||||
directory += $@"{_song.Artist}/";
|
||||
|
||||
return directory;
|
||||
return ArtistDirectory(_song);
|
||||
}
|
||||
private string ArtistDirectory(Song song)
|
||||
{
|
||||
var directory = _rootSongDirectory;
|
||||
directory += $@"{song.Artist}/";
|
||||
var segment = SerializeValue(song.Artist);
|
||||
directory += $@"{segment}/";
|
||||
Console.WriteLine($"Artist directory {directory}");
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
private string SerializeValue(string value)
|
||||
{
|
||||
const int length = 15;
|
||||
const string chars = "ABCDEF0123456789";
|
||||
var random = new Random();
|
||||
var output = new string(Enumerable.Repeat(chars, length).Select(s =>
|
||||
s[random.Next(s.Length)]).ToArray());
|
||||
|
||||
return output;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
@@ -11,6 +14,7 @@ namespace Icarus.Controllers.Managers
|
||||
public class GenreManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private GenreContext _genreContext;
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -19,10 +23,115 @@ namespace Icarus.Controllers.Managers
|
||||
|
||||
|
||||
#region Constructors
|
||||
public GenreManager(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
_genreContext = new GenreContext(_connectionString);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public void SaveGenreToDatabase(ref Song song)
|
||||
{
|
||||
_logger.Info("Starting process to save the genre record of the song to the database");
|
||||
|
||||
var genre = new Genre
|
||||
{
|
||||
GenreName = song.Genre,
|
||||
SongCount = 1
|
||||
};
|
||||
|
||||
var genreName = song.Genre;
|
||||
var genreRetrieved = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(genreName));
|
||||
|
||||
if (genreRetrieved == null)
|
||||
{
|
||||
_genreContext.Add(genre);
|
||||
_genreContext.SaveChanges();
|
||||
}
|
||||
else
|
||||
{
|
||||
genre.GenreID = genreRetrieved.GenreID;
|
||||
}
|
||||
|
||||
song.GenreID = genre.GenreID;
|
||||
}
|
||||
|
||||
public Genre UpdateGenreInDatabase(Song oldSongRecord, Song newSongRecord)
|
||||
{
|
||||
var oldGenreRecord = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(oldSongRecord.Genre));
|
||||
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");
|
||||
|
||||
_genreContext.Remove(oldGenreRecord);
|
||||
_genreContext.SaveChanges();
|
||||
}
|
||||
|
||||
if (!(_genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(oldSongRecord.Genre)) != null))
|
||||
{
|
||||
_logger.Info("Creating new genre record");
|
||||
|
||||
var newGenreRecord = new Genre
|
||||
{
|
||||
GenreName = newGenreName
|
||||
};
|
||||
|
||||
_genreContext.Add(newGenreRecord);
|
||||
_genreContext.SaveChanges();
|
||||
|
||||
return newGenreRecord;
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info("Updating existing genre record");
|
||||
|
||||
var existingGenreRecord = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(oldGenreRecord.GenreName));
|
||||
|
||||
_genreContext.Update(existingGenreRecord);
|
||||
_genreContext.SaveChanges();
|
||||
|
||||
return existingGenreRecord;
|
||||
}
|
||||
}
|
||||
|
||||
public void DeleteGenreFromDatabase(Song song)
|
||||
{
|
||||
if (!(_genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(song.Genre)) != null))
|
||||
{
|
||||
_logger.Info("Cannot delete the genre record because it does not exist");
|
||||
return;
|
||||
}
|
||||
|
||||
var genre = _genreContext.Genres.FirstOrDefault(gnr => gnr.GenreName.Equals(song.Genre));
|
||||
|
||||
if (SongsInGenre(genre) <= 1)
|
||||
{
|
||||
_genreContext.Remove(genre);
|
||||
_genreContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
private int SongsInGenre(Genre genre)
|
||||
{
|
||||
var sngContext = new SongContext(_connectionString);
|
||||
var songs = sngContext.Songs.Where(sng => sng.GenreID == genre.GenreID).ToList();
|
||||
|
||||
return songs.Count;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
+161
-877
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
|
||||
using JWT;
|
||||
using JWT.Serializers;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Newtonsoft.Json;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
using RestSharp;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
#region Classes
|
||||
public class TokenManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
private string _clientId;
|
||||
private string _clientSecret;
|
||||
private string _privateKeyPath;
|
||||
private string _privateKey;
|
||||
private string _publicKeyPath;
|
||||
private string _publicKey;
|
||||
private string _audience;
|
||||
private string _grantType;
|
||||
private string _url;
|
||||
@@ -59,17 +77,270 @@ namespace Icarus.Controllers.Managers
|
||||
|
||||
_logger.Info("Deserializing response");
|
||||
var tokenResult = JsonConvert
|
||||
.DeserializeObject<Token>(response.Content);
|
||||
.DeserializeObject<TokenTierOne>(response.Content);
|
||||
_logger.Info("Response deserialized");
|
||||
|
||||
return new LoginResult
|
||||
{
|
||||
UserId = user.Id, Username = user.Username, Token = tokenResult.AccessToken,
|
||||
UserID = user.UserID, Username = user.Username, Token = tokenResult.AccessToken,
|
||||
TokenType = tokenResult.TokenType, Expiration = tokenResult.Expiration,
|
||||
Message = "Successfully retrieved token"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public LoginResult LogIn(User user)
|
||||
{
|
||||
var tokenResult = new TokenTierOne();
|
||||
tokenResult.TokenType = "Jwt";
|
||||
|
||||
var privateKey = ReadKeyContent(_privateKeyPath).Result;
|
||||
var publicKey = ReadKeyContent(_publicKeyPath).Result;
|
||||
|
||||
var payload = Payload();
|
||||
|
||||
var token = CreateToken(payload, privateKey);
|
||||
tokenResult.AccessToken = token;
|
||||
|
||||
var expClaim = payload.FirstOrDefault(cl =>
|
||||
{
|
||||
return cl.Type.Equals("exp");
|
||||
});
|
||||
|
||||
tokenResult.Expiration = System.Convert.ToInt32(expClaim.Value);
|
||||
|
||||
return new LoginResult
|
||||
{
|
||||
UserID = user.UserID, Username = user.Username, Token = tokenResult.AccessToken,
|
||||
TokenType = tokenResult.TokenType, Expiration = tokenResult.Expiration,
|
||||
Message = "Successfully retrieved token"
|
||||
};
|
||||
}
|
||||
|
||||
public LoginResult LoginSymmetric(User user)
|
||||
{
|
||||
var tokenResult = new TokenTierOne();
|
||||
tokenResult.TokenType = "Jwt";
|
||||
|
||||
var payload = Payload();
|
||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JWT:Secret"]));
|
||||
var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||
var token = new JwtSecurityToken(
|
||||
_config["JWT:Issuer"],
|
||||
_config["JWT:Audience"],
|
||||
payload,
|
||||
expires: DateTime.UtcNow.AddMinutes(30),
|
||||
signingCredentials: signIn);
|
||||
|
||||
tokenResult.AccessToken = new JwtSecurityTokenHandler().WriteToken(token);
|
||||
|
||||
var expClaim = payload.FirstOrDefault(cl =>
|
||||
{
|
||||
return cl.Type.Equals("exp");
|
||||
});
|
||||
|
||||
var expiredDate = DateTime.Parse(expClaim.Value);
|
||||
var exp = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds);
|
||||
tokenResult.Expiration = Convert.ToInt32(exp);
|
||||
|
||||
return new LoginResult
|
||||
{
|
||||
UserID = user.UserID, Username = user.Username, Token = tokenResult.AccessToken,
|
||||
TokenType = tokenResult.TokenType, Expiration = tokenResult.Expiration,
|
||||
Message = "Successfully retrieved token"
|
||||
};
|
||||
}
|
||||
|
||||
public bool IsTokenValid(string scope, string accessToken)
|
||||
{
|
||||
var result = false;
|
||||
var token = DecodeToken(accessToken);
|
||||
|
||||
if (token == null || token.Erroneous())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = (!token.TokenExpired() && token.ContainsScope(scope)) ? true : false;
|
||||
|
||||
// What would make a token valid?
|
||||
// 1. The expiration date must be before the current date
|
||||
// 2. The desired scope must be part of the scopes within the access token
|
||||
// 3. Must be able to be decoded
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Token? DecodeToken(string accessToken)
|
||||
{
|
||||
var rsaParams = GetRSAPublic(_publicKey);
|
||||
Token tok = null;
|
||||
|
||||
try
|
||||
{
|
||||
using (var rsa = new RSACryptoServiceProvider())
|
||||
{
|
||||
rsa.ImportParameters(rsaParams);
|
||||
|
||||
IJsonSerializer serializer = new JsonNetSerializer();
|
||||
IDateTimeProvider provider = new UtcDateTimeProvider();
|
||||
IJwtValidator validator = new JwtValidator(serializer, provider);
|
||||
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
|
||||
var algorithm = new JWT.Algorithms.RS256Algorithm(rsa);
|
||||
IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
|
||||
|
||||
var json = decoder.Decode(accessToken);
|
||||
tok = JsonConvert.DeserializeObject<Token>(json);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error("An error occurred: {0}", ex.Message);
|
||||
}
|
||||
|
||||
|
||||
return tok;
|
||||
}
|
||||
|
||||
|
||||
private string AllScopes()
|
||||
{
|
||||
var allScopes = new List<String>()
|
||||
{
|
||||
"download:songs",
|
||||
"read:song_details",
|
||||
"upload:songs",
|
||||
"delete:songs",
|
||||
"read:albums",
|
||||
"read:artists",
|
||||
"update:songs",
|
||||
"stream:songs",
|
||||
"read:genre",
|
||||
"read:year",
|
||||
"download:cover_art"
|
||||
};
|
||||
|
||||
var scopes = string.Empty;
|
||||
|
||||
for (var i = 0; i < allScopes.Count; i++)
|
||||
{
|
||||
if (i == allScopes.Count - 1)
|
||||
{
|
||||
scopes += allScopes[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
scopes += allScopes[i] + " ";
|
||||
}
|
||||
}
|
||||
|
||||
return scopes;
|
||||
}
|
||||
|
||||
private List<Claim> Payload()
|
||||
{
|
||||
var expLimit = 30;
|
||||
var currentDate = DateTime.Now;
|
||||
var expiredDate = currentDate.AddMinutes(expLimit);
|
||||
var issued = Math.Floor((currentDate - DateTime.UnixEpoch).TotalSeconds);
|
||||
var expires = Math.Floor((expiredDate - DateTime.UnixEpoch).TotalSeconds);
|
||||
var issuer = "https://soaricarus.auth0.com";
|
||||
issuer = "http://localhost:5002";
|
||||
var audience = "https://icarus/api";
|
||||
audience = "http://localhost:5002";
|
||||
var subject = _config["JWT:Subject"];
|
||||
|
||||
var claim = new List<System.Security.Claims.Claim>()
|
||||
{
|
||||
new System.Security.Claims.Claim("scope", AllScopes(), "string"),
|
||||
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Exp, expiredDate.ToString()),
|
||||
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Aud, audience),
|
||||
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Iss, issuer),
|
||||
new Claim(JwtRegisteredClaimNames.Sub, subject),
|
||||
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Iat, currentDate.ToString())
|
||||
};
|
||||
|
||||
return claim;
|
||||
}
|
||||
|
||||
private string CreateToken(List<Claim> claims, string privateKey)
|
||||
{
|
||||
var token = string.Empty;
|
||||
|
||||
if (string.IsNullOrEmpty(privateKey))
|
||||
{
|
||||
privateKey = ReadKeyContent(_privateKeyPath).Result;
|
||||
}
|
||||
|
||||
RSAParameters rsaParams;
|
||||
using (var tr = new System.IO.StringReader(privateKey))
|
||||
{
|
||||
var pemReader = new PemReader(tr);
|
||||
var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair;
|
||||
if (keyPair == null)
|
||||
{
|
||||
throw new Exception("Could not read RSA private key");
|
||||
}
|
||||
var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters;
|
||||
rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams);
|
||||
}
|
||||
|
||||
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
|
||||
{
|
||||
var rsaParamsPublic = GetRSAPublic(ReadKeyContent(_publicKeyPath).Result);
|
||||
var rsaPublic = new RSACryptoServiceProvider();
|
||||
|
||||
rsa.ImportParameters(rsaParams);
|
||||
rsaPublic.ImportParameters(rsaParamsPublic);
|
||||
|
||||
Dictionary<string, object> payload = new Dictionary<string, object>();
|
||||
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
var type = claim.Type;
|
||||
var val = Int32.TryParse(claim.Value, out _);
|
||||
|
||||
if (val)
|
||||
{
|
||||
payload.Add(type, Convert.ToInt32(claim.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
payload.Add(type, claim.Value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var algorithm = new JWT.Algorithms.RS256Algorithm(rsaPublic, rsa);
|
||||
IJsonSerializer serializer = new JsonNetSerializer();
|
||||
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
|
||||
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
|
||||
|
||||
token = encoder.Encode(payload, privateKey);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
private RSAParameters GetRSAPublic(string publicKey)
|
||||
{
|
||||
using (var tr = new System.IO.StringReader(publicKey))
|
||||
{
|
||||
var pemReader = new PemReader(tr);
|
||||
var publicKeyParams = pemReader.ReadObject() as RsaKeyParameters;
|
||||
if (publicKeyParams == null)
|
||||
{
|
||||
throw new Exception("Could not read RSA public key");
|
||||
}
|
||||
return DotNetUtilities.ToRSAParameters(publicKeyParams);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> ReadKeyContent(string filepath)
|
||||
{
|
||||
return await System.IO.File.ReadAllTextAsync(filepath);
|
||||
}
|
||||
|
||||
private TokenRequest RetrieveTokenRequest()
|
||||
{
|
||||
_logger.Info("Retrieving token object");
|
||||
@@ -90,6 +361,10 @@ namespace Icarus.Controllers.Managers
|
||||
_audience = _config["Auth0:ApiIdentifier"];
|
||||
_grantType = "client_credentials";
|
||||
_url = $"https://{_config["Auth0:Domain"]}";
|
||||
_privateKeyPath = _config["RSAKeys:PrivateKeyPath"];
|
||||
_publicKeyPath = _config["RSAKeys:PublicKeyPath"];
|
||||
_privateKey = System.IO.File.ReadAllText(_privateKeyPath);
|
||||
_publicKey = System.IO.File.ReadAllText(_publicKeyPath);
|
||||
|
||||
PrintCredentials();
|
||||
}
|
||||
@@ -120,7 +395,7 @@ namespace Icarus.Controllers.Managers
|
||||
[JsonProperty("grant_type")]
|
||||
public string GrantType { get; set; }
|
||||
}
|
||||
private class Token
|
||||
private class TokenTierOne
|
||||
{
|
||||
[JsonProperty("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
@@ -131,4 +406,5 @@ namespace Icarus.Controllers.Managers
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.Managers
|
||||
{
|
||||
public class YearManager : BaseManager
|
||||
{
|
||||
#region Fields
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -46,18 +46,17 @@ namespace Icarus.Controllers.Utilities
|
||||
public static void PrintMetadata(Song song)
|
||||
{
|
||||
Console.WriteLine("\n\nMetadata of the song:");
|
||||
Console.WriteLine($"Id: {song.Id}");
|
||||
Console.WriteLine($"ID: {song.SongID}");
|
||||
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($"AlbumID: {song.AlbumID}");
|
||||
Console.WriteLine($"ArtistID: {song.ArtistID}");
|
||||
Console.WriteLine($"GenreID: {song.GenreID}");
|
||||
Console.WriteLine($"Song Path: {song.SongPath()}");
|
||||
Console.WriteLine($"Filename: {song.Filename}");
|
||||
Console.WriteLine("\n");
|
||||
|
||||
@@ -82,13 +81,21 @@ namespace Icarus.Controllers.Utilities
|
||||
_genre = string.Join("", fileTag.Tag.Genres);
|
||||
_year = (int)fileTag.Tag.Year;
|
||||
_duration = (int)fileTag.Properties.Duration.TotalSeconds;
|
||||
var albumArtist = string.Join("", fileTag.Tag.AlbumArtists);
|
||||
var track = (int)fileTag.Tag.Track;
|
||||
var disc = (int)fileTag.Tag.Disc;
|
||||
|
||||
song.Title = _title;
|
||||
song.Artist = _artist;
|
||||
song.AlbumTitle = _album;
|
||||
song.AlbumArtist = albumArtist;
|
||||
song.Genre = _genre;
|
||||
song.Year = _year;
|
||||
song.Duration = _duration;
|
||||
song.Track = track;
|
||||
song.Disc = disc;
|
||||
song.TrackCount = (int)fileTag.Tag.TrackCount;
|
||||
song.DiscCount = (int)fileTag.Tag.DiscCount;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -101,12 +108,21 @@ namespace Icarus.Controllers.Utilities
|
||||
return song;
|
||||
}
|
||||
|
||||
public int RetrieveSongDuration(string filepath)
|
||||
{
|
||||
var duration = 0;
|
||||
var fileTag = TagLib.File.Create(filepath);
|
||||
duration = (int)fileTag.Properties.Duration.TotalSeconds;
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
public byte[] RetrieveCoverArtBytes(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Fetching image");
|
||||
var tag = TagLib.File.Create(song.SongPath);
|
||||
var tag = TagLib.File.Create(song.SongPath());
|
||||
byte[] imgBytes = tag.Tag.Pictures[0].Data.Data;
|
||||
|
||||
return imgBytes;
|
||||
@@ -120,28 +136,7 @@ namespace Icarus.Controllers.Utilities
|
||||
return null;
|
||||
}
|
||||
|
||||
public void UpdateMetadata(Song song)
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Updating song metadata");
|
||||
_logger.Info("Updating song metadata");
|
||||
var filePath = song.SongPath;
|
||||
TagLib.File fileTag = TagLib.File.Create(filePath);
|
||||
fileTag.Tag.Title = song.Title;
|
||||
fileTag.Tag.Genres = new []{song.Genre};
|
||||
fileTag.Save();
|
||||
Console.WriteLine("Song metadata updated");
|
||||
_logger.Info("Song metadata updated");
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
Console.WriteLine($"An error occurred: \n{msg}");
|
||||
_logger.Error(msg, "An error occurred");
|
||||
}
|
||||
}
|
||||
public void UpdateMetadata(Song updatedSong, Song oldSong)
|
||||
{
|
||||
try
|
||||
@@ -163,7 +158,7 @@ namespace Icarus.Controllers.Utilities
|
||||
{
|
||||
Console.WriteLine("Updating song's cover art");
|
||||
|
||||
var tag = TagLib.File.Create(song.SongPath);
|
||||
var tag = TagLib.File.Create(song.SongPath());
|
||||
var pics = tag.Tag.Pictures;
|
||||
Array.Resize(ref pics, 1);
|
||||
|
||||
@@ -178,13 +173,19 @@ namespace Icarus.Controllers.Utilities
|
||||
|
||||
private void PerformUpdate(Song updatedSong, SortedDictionary<string, bool> checkedValues)
|
||||
{
|
||||
var filePath = updatedSong.SongPath;
|
||||
var filePath = updatedSong.SongPath();
|
||||
var title = updatedSong.Title;
|
||||
var artist = updatedSong.Artist;
|
||||
var album = updatedSong.AlbumTitle;
|
||||
var genre = updatedSong.Genre;
|
||||
var year = updatedSong.Year;
|
||||
var albumArtist = updatedSong.AlbumArtist;
|
||||
var track = updatedSong.Track;
|
||||
var trackCount = updatedSong.TrackCount;
|
||||
var disc = updatedSong.Disc;
|
||||
var discCount = updatedSong.DiscCount;
|
||||
TagLib.File fileTag = TagLib.File.Create(filePath);
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine($"Updating metadata of {title}");
|
||||
@@ -194,7 +195,6 @@ namespace Icarus.Controllers.Utilities
|
||||
{
|
||||
bool result = checkedValues[key];
|
||||
|
||||
|
||||
if (!result)
|
||||
switch (key.ToLower())
|
||||
{
|
||||
@@ -218,6 +218,26 @@ namespace Icarus.Controllers.Utilities
|
||||
_updatedSong.Year = year;
|
||||
fileTag.Tag.Year = (uint)year;
|
||||
break;
|
||||
case "albumartist":
|
||||
_updatedSong.AlbumArtist = albumArtist;
|
||||
fileTag.Tag.AlbumArtists = new []{albumArtist};
|
||||
break;
|
||||
case "track":
|
||||
_updatedSong.Track = track;
|
||||
fileTag.Tag.Track = (uint)(track);
|
||||
break;
|
||||
case "trackcount":
|
||||
_updatedSong.TrackCount = trackCount;
|
||||
fileTag.Tag.TrackCount = (uint)(trackCount);
|
||||
break;
|
||||
case "disc":
|
||||
_updatedSong.Disc = disc;
|
||||
fileTag.Tag.Disc = (uint)(disc);
|
||||
break;
|
||||
case "disccount":
|
||||
_updatedSong.DiscCount = discCount;
|
||||
fileTag.Tag.DiscCount = (uint)(discCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,18 +255,7 @@ namespace Icarus.Controllers.Utilities
|
||||
}
|
||||
private void InitializeUpdatedSong(Song song)
|
||||
{
|
||||
_updatedSong = new Song
|
||||
{
|
||||
Id = song.Id,
|
||||
Title = song.Title,
|
||||
AlbumTitle = song.AlbumTitle,
|
||||
Artist = song.Artist,
|
||||
Genre = song.Genre,
|
||||
Year = song.Year,
|
||||
Duration = song.Duration,
|
||||
Filename = song.Filename,
|
||||
SongPath = song.SongPath
|
||||
};
|
||||
_updatedSong = song;
|
||||
}
|
||||
private void PrintMetadata()
|
||||
{
|
||||
@@ -271,7 +280,7 @@ namespace Icarus.Controllers.Utilities
|
||||
Console.WriteLine($"\n\n{message}");
|
||||
Console.WriteLine($"Title: {song.Title}");
|
||||
Console.WriteLine($"Artist: {song.Artist}");
|
||||
Console.WriteLine($"Album: {song.Album}");
|
||||
Console.WriteLine($"Album: {song.AlbumTitle}");
|
||||
Console.WriteLine($"Genre: {song.Genre}");
|
||||
Console.WriteLine($"Year: {song.Year}");
|
||||
Console.WriteLine($"Duration: {song.Duration}\n\n");
|
||||
@@ -290,19 +299,20 @@ namespace Icarus.Controllers.Utilities
|
||||
var songValues = new SortedDictionary<string, bool>();
|
||||
Console.WriteLine("Checking for null data");
|
||||
_logger.Info("Checking for null data");
|
||||
|
||||
try
|
||||
{
|
||||
songValues["Title"] = String.IsNullOrEmpty(song.Title);
|
||||
songValues["Artists"] = String.IsNullOrEmpty(song.Artist);
|
||||
songValues["Album"] = String.IsNullOrEmpty(song.AlbumTitle);
|
||||
songValues["Genre"] = String.IsNullOrEmpty(song.Genre);
|
||||
songValues["AlbumArtist"] = String.IsNullOrEmpty(song.AlbumArtist);
|
||||
|
||||
if (song.Year == null)
|
||||
songValues["Year"] = true;
|
||||
else if (song.Year==0)
|
||||
songValues["Year"] = true;
|
||||
else
|
||||
songValues["Year"] = false;
|
||||
songValues["Year"] = CheckIntField(song.Year);
|
||||
songValues["Track"] = CheckIntField(song.Track);
|
||||
songValues["TrackCount"] = CheckIntField(song.TrackCount);
|
||||
songValues["Disc"] = CheckIntField(song.Disc);
|
||||
songValues["DiscCount"] = CheckIntField(song.Disc);
|
||||
|
||||
Console.WriteLine("Checking for null data completed");
|
||||
_logger.Info("Checking for null data completed");
|
||||
@@ -316,6 +326,20 @@ namespace Icarus.Controllers.Utilities
|
||||
|
||||
return songValues;
|
||||
}
|
||||
|
||||
private bool CheckIntField(int? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (value == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Icarus.Controllers.Utilities
|
||||
var archivePath = RetrieveCompressesSongPath(song);
|
||||
Console.WriteLine($"Compressed song saved to: {archivePath}");
|
||||
|
||||
songData.Data = System.IO.File.ReadAllBytes(archivePath);
|
||||
songData.Data = await System.IO.File.ReadAllBytesAsync(archivePath);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
@@ -71,9 +71,10 @@ namespace Icarus.Controllers.Utilities
|
||||
{
|
||||
using (ZipFile zip = new ZipFile())
|
||||
{
|
||||
zip.AddFile(songDetails.SongPath);
|
||||
zip.AddFile(songDetails.SongPath());
|
||||
zip.Save(tmpZipFilePath);
|
||||
}
|
||||
|
||||
Console.WriteLine("Successfully compressed");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -8,16 +8,18 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/album")]
|
||||
[ApiController]
|
||||
public class AlbumController : ControllerBase
|
||||
[Authorize]
|
||||
public class AlbumController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<AlbumController> _logger;
|
||||
private string _connectionString;
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -26,24 +28,24 @@ namespace Icarus.Controllers.V1
|
||||
|
||||
|
||||
#region Constructors
|
||||
public AlbumController(ILogger<AlbumController> logger)
|
||||
public AlbumController(ILogger<AlbumController> logger, IConfiguration config)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:albums")]
|
||||
public IActionResult Get()
|
||||
public IActionResult GetAlbums()
|
||||
{
|
||||
List<Album> albums = new List<Album>();
|
||||
|
||||
AlbumRepository albumStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(AlbumRepository)) as AlbumRepository;
|
||||
var albumContext = new AlbumContext(_connectionString);
|
||||
|
||||
albums = albumStoreContext.GetAlbums();
|
||||
albums = albumContext.Albums.ToList();
|
||||
|
||||
if (albums.Count > 0)
|
||||
return Ok(albums);
|
||||
@@ -52,20 +54,18 @@ namespace Icarus.Controllers.V1
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:albums")]
|
||||
public IActionResult Get(int id)
|
||||
public IActionResult GetAlbum(int id)
|
||||
{
|
||||
Album album = new Album
|
||||
{
|
||||
AlbumId = id
|
||||
AlbumID = id
|
||||
};
|
||||
|
||||
AlbumRepository albumStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(AlbumRepository)) as AlbumRepository;
|
||||
var albumContext = new AlbumContext(_connectionString);
|
||||
|
||||
if (albumStoreContext.DoesAlbumExist(album))
|
||||
if (albumContext.DoesRecordExist(album))
|
||||
{
|
||||
album = albumStoreContext.GetAlbum(album);
|
||||
album = albumContext.RetrieveRecord(album);
|
||||
|
||||
return Ok(album);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -9,16 +7,18 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/artist")]
|
||||
[ApiController]
|
||||
public class ArtistController : ControllerBase
|
||||
[Authorize]
|
||||
public class ArtistController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<ArtistController> _logger;
|
||||
private string _connectionString;
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -27,22 +27,22 @@ namespace Icarus.Controllers.V1
|
||||
|
||||
|
||||
#region Constructors
|
||||
public ArtistController(ILogger<ArtistController> logger)
|
||||
public ArtistController(ILogger<ArtistController> logger, IConfiguration config)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:artists")]
|
||||
public IActionResult Get()
|
||||
public IActionResult GetArtists()
|
||||
{
|
||||
ArtistRepository artistStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(ArtistRepository)) as ArtistRepository;
|
||||
var artistContext = new ArtistContext(_connectionString);
|
||||
|
||||
var artists = artistStoreContext.GetArtists();
|
||||
var artists = artistContext.Artists.ToList();
|
||||
|
||||
if (artists.Count > 0)
|
||||
return Ok(artists);
|
||||
@@ -51,20 +51,23 @@ namespace Icarus.Controllers.V1
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:artists")]
|
||||
public IActionResult Get(int id)
|
||||
public IActionResult GetArtist(int id)
|
||||
{
|
||||
if (!IsTokenValid("read:artists"))
|
||||
{
|
||||
return StatusCode(401, "Not allowed");
|
||||
}
|
||||
|
||||
Artist artist = new Artist
|
||||
{
|
||||
ArtistId = id
|
||||
ArtistID = id
|
||||
};
|
||||
|
||||
ArtistRepository artistStoreContext = HttpContext.RequestServices
|
||||
.GetService(typeof(ArtistRepository)) as ArtistRepository;
|
||||
var artistContext = new ArtistContext(_connectionString);
|
||||
|
||||
if (artistStoreContext.DoesArtistExist(artist))
|
||||
if (artistContext.DoesRecordExist(artist))
|
||||
{
|
||||
artist = artistStoreContext.GetArtist(artist);
|
||||
artist = artistContext.RetrieveRecord(artist);
|
||||
|
||||
return Ok(artist);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
public class BaseController : ControllerBase
|
||||
{
|
||||
#region Fiends
|
||||
protected IConfiguration _config;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
protected string ParseBearerTokenFromHeader()
|
||||
{
|
||||
var token = string.Empty;
|
||||
const string tokenType = "Bearer";
|
||||
const string otherTokenType = "Jwt";
|
||||
|
||||
var req = Request;
|
||||
var auth = req.Headers.Authorization;
|
||||
var val = auth.ToString();
|
||||
|
||||
if ((val.Contains(tokenType) || val.Contains(otherTokenType)) && val.Split(" ").Count() > 1)
|
||||
{
|
||||
var split = val.Split(" ");
|
||||
token = split[1];
|
||||
}
|
||||
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
protected bool IsTokenValid(string scope)
|
||||
{
|
||||
var token = ParseBearerTokenFromHeader();
|
||||
var tokMgr = new TokenManager(_config);
|
||||
|
||||
return tokMgr.IsTokenValid(scope, token);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -9,37 +8,39 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/coverart")]
|
||||
[ApiController]
|
||||
public class CoverArtController : ControllerBase
|
||||
[Authorize]
|
||||
public class CoverArtController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<CoverArtController> _logger;
|
||||
private string _connectionString;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public CoverArtController(ILogger<CoverArtController> logger)
|
||||
public CoverArtController(ILogger<CoverArtController> logger, IConfiguration config)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
public async Task<IActionResult> Get()
|
||||
[HttpGet]
|
||||
public IActionResult GetCoverArts()
|
||||
{
|
||||
var coverArtRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(
|
||||
typeof(CoverArtRepository)) as CoverArtRepository;
|
||||
var coverArtContext = new CoverArtContext(_connectionString);
|
||||
|
||||
var coverArtRecords = coverArtRepository.GetCoverArtRecords();
|
||||
var coverArtRecords = coverArtContext.CoverArtImages.ToList();
|
||||
|
||||
if (coverArtRecords == null)
|
||||
{
|
||||
@@ -51,21 +52,16 @@ namespace Icarus.Controllers.V1
|
||||
_logger.LogInformation("Found cover art records");
|
||||
return Ok(coverArtRecords);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("download:cover_art")]
|
||||
public async Task<IActionResult> Get(int id)
|
||||
public IActionResult GetCoverArt(int id)
|
||||
{
|
||||
var coverArt = new CoverArt { CoverArtId = id };
|
||||
var coverArt = new CoverArt { CoverArtID = id };
|
||||
|
||||
var coverArtRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService(
|
||||
typeof(CoverArtRepository)) as CoverArtRepository;
|
||||
var coverArtContext = new CoverArtContext(_connectionString);
|
||||
|
||||
coverArt = coverArtRepository.GetCoverArt(coverArt);
|
||||
coverArt = coverArtContext.RetrieveRecord(coverArt);
|
||||
|
||||
if (coverArt != null)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@@ -7,16 +8,18 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/genre")]
|
||||
[ApiController]
|
||||
public class GenreController : ControllerBase
|
||||
[Authorize]
|
||||
public class GenreController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<GenreController> _logger;
|
||||
private string _connectionString;
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -25,24 +28,24 @@ namespace Icarus.Controllers.V1
|
||||
|
||||
|
||||
#region Constructors
|
||||
public GenreController(ILogger<GenreController> logger)
|
||||
public GenreController(ILogger<GenreController> logger, IConfiguration config)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:genre")]
|
||||
public IActionResult Get()
|
||||
public IActionResult GetGenres()
|
||||
{
|
||||
var genres = new List<Genre>();
|
||||
|
||||
var genreStore = HttpContext.RequestServices
|
||||
.GetService(typeof(GenreRepository)) as GenreRepository;
|
||||
var genreStore = new GenreContext(_connectionString);
|
||||
|
||||
genres = genreStore.GetGenres();
|
||||
genres = genreStore.Genres.ToList();
|
||||
|
||||
if (genres.Count > 0)
|
||||
return Ok(genres);
|
||||
@@ -51,20 +54,18 @@ namespace Icarus.Controllers.V1
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:genre")]
|
||||
public IActionResult Get(int id)
|
||||
public IActionResult GetGenre(int id)
|
||||
{
|
||||
var genre = new Genre
|
||||
{
|
||||
GenreId = id
|
||||
GenreID = id
|
||||
};
|
||||
|
||||
var genreStore = HttpContext.RequestServices
|
||||
.GetService(typeof(GenreRepository)) as GenreRepository;
|
||||
var genreStore = new GenreContext(_connectionString);
|
||||
|
||||
if (genreStore.DoesGenreExist(genre))
|
||||
if (genreStore.DoesRecordExist(genre))
|
||||
{
|
||||
genre = genreStore.GetGenre(genre);
|
||||
genre = genreStore.RetrieveRecord(genre);
|
||||
|
||||
return Ok(genre);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@@ -11,7 +8,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
@@ -20,6 +17,7 @@ namespace Icarus.Controllers.V1
|
||||
public class LoginController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private string _connectionString;
|
||||
private IConfiguration _config;
|
||||
private ILogger<LoginController> _logger;
|
||||
#endregion
|
||||
@@ -32,17 +30,18 @@ namespace Icarus.Controllers.V1
|
||||
#region Contructors
|
||||
public LoginController(IConfiguration config, ILogger<LoginController> logger)
|
||||
{
|
||||
_config = config;
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP endpoints
|
||||
public IActionResult Post([FromBody] User user)
|
||||
[HttpPost]
|
||||
public IActionResult Login([FromBody] User user)
|
||||
{
|
||||
UserRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(UserRepository)) as UserRepository;
|
||||
var context = new UserContext(_connectionString);
|
||||
|
||||
_logger.LogInformation("Starting process of validating credentials");
|
||||
|
||||
@@ -54,9 +53,11 @@ namespace Icarus.Controllers.V1
|
||||
Username = user.Username
|
||||
};
|
||||
|
||||
if (context.DoesUserExist(user))
|
||||
try
|
||||
{
|
||||
user = context.RetrieveUser(user);
|
||||
if (context.Users.FirstOrDefault(usr => usr.Username.Equals(user.Username)) != null)
|
||||
{
|
||||
user = context.Users.FirstOrDefault(usr => usr.Username.Equals(user.Username));
|
||||
|
||||
var validatePass = new PasswordEncryption();
|
||||
var validated = validatePass.VerifyPassword(user, password);
|
||||
@@ -72,7 +73,7 @@ namespace Icarus.Controllers.V1
|
||||
|
||||
TokenManager tk = new TokenManager(_config);
|
||||
|
||||
loginRes = tk.RetrieveLoginResult(user);
|
||||
loginRes = tk.LoginSymmetric(user);
|
||||
|
||||
return Ok(loginRes);
|
||||
}
|
||||
@@ -83,6 +84,14 @@ namespace Icarus.Controllers.V1
|
||||
return NotFound(loginRes);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("An error occurred: {0}", ex.Message);
|
||||
_logger.LogError("Inner Exception: {0}", ex.InnerException.Message);
|
||||
}
|
||||
|
||||
return NotFound(loginRes);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ using Microsoft.Extensions.Configuration;
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
@@ -19,6 +19,7 @@ namespace Icarus.Controllers.V1
|
||||
public class RegisterController : ControllerBase
|
||||
{
|
||||
#region Fields
|
||||
private string _connectionString;
|
||||
private IConfiguration _config;
|
||||
#endregion
|
||||
|
||||
@@ -31,27 +32,41 @@ namespace Icarus.Controllers.V1
|
||||
public RegisterController(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Post([FromBody] User user)
|
||||
public IActionResult RegisterUser([FromBody] User user)
|
||||
{
|
||||
PasswordEncryption pe = new PasswordEncryption();
|
||||
user.Password = pe.HashPassword(user);
|
||||
user.EmailVerified = false;
|
||||
user.Status = "Registered";
|
||||
user.DateCreated = DateTime.Now;
|
||||
|
||||
UserRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(UserRepository)) as UserRepository;
|
||||
UserContext context = null;
|
||||
|
||||
context.SaveUser(user);
|
||||
try
|
||||
{
|
||||
context = new UserContext(_config.GetConnectionString("DefaultConnection"));
|
||||
context.Add(user);
|
||||
context.SaveChanges();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
var stackTrace = ex.StackTrace;
|
||||
|
||||
Console.WriteLine($"An error occurred: {msg}");
|
||||
}
|
||||
|
||||
var registerResult = new RegisterResult
|
||||
{
|
||||
Username = user.Username
|
||||
};
|
||||
|
||||
if (context.DoesUserExist(user))
|
||||
if (context.Users.FirstOrDefault(sng => sng.Username.Equals(user.Username)) != null)
|
||||
{
|
||||
registerResult.Message = "Successful registration";
|
||||
registerResult.SuccessfullyRegistered = true;
|
||||
|
||||
@@ -13,16 +13,17 @@ using Microsoft.Extensions.Configuration;
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/song/compressed/data")]
|
||||
[ApiController]
|
||||
public class SongCompressedDataController : ControllerBase
|
||||
[Authorize]
|
||||
public class SongCompressedDataController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private IConfiguration _config;
|
||||
private string _connectionString;
|
||||
private string _songTempDir;
|
||||
private string _archiveDir;
|
||||
#endregion
|
||||
@@ -35,27 +36,26 @@ namespace Icarus.Controllers.V1
|
||||
#region Constructor
|
||||
public SongCompressedDataController(IConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_songTempDir = _config.GetValue<string>("TemporaryMusicPath");
|
||||
_archiveDir = _config.GetValue<string>("ArchivePath");
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region API Routes
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("download:songs")]
|
||||
public async Task<IActionResult> Get(int id)
|
||||
public async Task<IActionResult> DownloadCompressedSong(int id)
|
||||
{
|
||||
SongRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
var context = new SongContext(_connectionString);
|
||||
|
||||
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));
|
||||
SongData song = await cmp.RetrieveCompressedSong(context.RetrieveRecord(new Song{ SongID = id }));
|
||||
|
||||
return File(song.Data, "application/x-msdownload", cmp.CompressedSongFilename);
|
||||
}
|
||||
|
||||
@@ -12,17 +12,18 @@ using Microsoft.Extensions.Logging;
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Controllers.Utilities;
|
||||
using Icarus.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/song")]
|
||||
[ApiController]
|
||||
public class SongController : ControllerBase
|
||||
[Authorize]
|
||||
public class SongController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private readonly ILogger<SongController> _logger;
|
||||
private IConfiguration _config;
|
||||
private string _connectionString;
|
||||
private SongManager _songMgr;
|
||||
#endregion
|
||||
|
||||
@@ -35,24 +36,27 @@ namespace Icarus.Controllers.V1
|
||||
public SongController(IConfiguration config, ILogger<SongController> logger)
|
||||
{
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
_logger = logger;
|
||||
_songMgr = new SongManager(config);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
#region HTTP Endpoints
|
||||
|
||||
|
||||
[HttpGet]
|
||||
[Authorize("read:song_details")]
|
||||
public IActionResult Get()
|
||||
public IActionResult GetSongs()
|
||||
{
|
||||
List<Song> songs = new List<Song>();
|
||||
Console.WriteLine("Attemtping to retrieve songs");
|
||||
_logger.LogInformation("Attempting to retrieve songs");
|
||||
|
||||
SongRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
var context = new SongContext(_connectionString);
|
||||
|
||||
songs = context.GetAllSongs();
|
||||
songs = context.Songs.ToList();
|
||||
|
||||
if (songs.Count > 0)
|
||||
return Ok(songs);
|
||||
@@ -61,56 +65,43 @@ namespace Icarus.Controllers.V1
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("read:song_details")]
|
||||
public IActionResult Get(int id)
|
||||
public IActionResult GetSong(int id)
|
||||
{
|
||||
SongRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
var context = new SongContext(_connectionString);
|
||||
|
||||
Song song = new Song { Id = id };
|
||||
song = context.GetSong(song);
|
||||
Song song = new Song { SongID = id };
|
||||
song = context.RetrieveRecord(song);
|
||||
|
||||
Console.WriteLine("Here");
|
||||
|
||||
if (song.Id != 0)
|
||||
if (song.SongID != 0)
|
||||
return Ok(song);
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[Authorize("update:songs")]
|
||||
[HttpPut("{id}")]
|
||||
public IActionResult Put(int id, [FromBody] Song song)
|
||||
public IActionResult UpdateSong(int id, [FromBody] Song song)
|
||||
{
|
||||
SongRepository context = HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
var context = new SongContext(_connectionString);
|
||||
|
||||
ArtistRepository artistStore = HttpContext.RequestServices
|
||||
.GetService(typeof(ArtistRepository)) as ArtistRepository;
|
||||
|
||||
AlbumRepository albumStore = HttpContext.RequestServices
|
||||
.GetService(typeof(AlbumRepository)) as AlbumRepository;
|
||||
|
||||
GenreRepository genreStore = HttpContext.RequestServices
|
||||
.GetService(typeof(GenreRepository)) as GenreRepository;
|
||||
|
||||
YearRepository yearStore = HttpContext.RequestServices
|
||||
.GetService(typeof(YearRepository)) as YearRepository;
|
||||
|
||||
song.Id = id;
|
||||
song.SongID = id;
|
||||
Console.WriteLine("Retrieving filepath of song");
|
||||
_logger.LogInformation("Retrieving filepath of song");
|
||||
|
||||
if (!context.DoesSongExist(song))
|
||||
if (!_songMgr.DoesSongExist(song))
|
||||
{
|
||||
return NotFound(new SongResult
|
||||
{
|
||||
Message = "Song does not exist"
|
||||
});
|
||||
}
|
||||
|
||||
var songRes = _songMgr.UpdateSong(song, context, albumStore, artistStore, genreStore,
|
||||
yearStore);
|
||||
var songRes = _songMgr.UpdateSong(song);
|
||||
|
||||
return Ok(songRes);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,26 +10,21 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
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
|
||||
[Authorize]
|
||||
public class SongDataController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private SongRepository _songRepository;
|
||||
private AlbumRepository _albumRepository;
|
||||
private ArtistRepository _artistRepository;
|
||||
private GenreRepository _genreRepository;
|
||||
private YearRepository _yearRepository;
|
||||
private CoverArtRepository _coverArtRepository;
|
||||
private IConfiguration _config;
|
||||
private string _connectionString;
|
||||
private ILogger<SongDataController> _logger;
|
||||
private SongManager _songMgr;
|
||||
private string _songTempDir;
|
||||
@@ -44,94 +39,103 @@ namespace Icarus.Controllers.V1
|
||||
public SongDataController(IConfiguration config, ILogger<SongDataController> logger)
|
||||
{
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
_logger = logger;
|
||||
_songTempDir = _config.GetValue<string>("TemporaryMusicPath");
|
||||
_songMgr = new SongManager(config, _songTempDir);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private void Initialize()
|
||||
|
||||
[HttpGet("download/{id}")]
|
||||
public IActionResult Download(int id)
|
||||
{
|
||||
_songRepository = HttpContext
|
||||
.RequestServices
|
||||
.GetService
|
||||
(typeof(SongRepository)) as SongRepository;
|
||||
var songContext = new SongContext(_connectionString);
|
||||
var songMetaData = songContext.RetrieveRecord(new Song { SongID = id});
|
||||
|
||||
_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<IActionResult> Get(int id)
|
||||
{
|
||||
Initialize();
|
||||
var songMetaData = _songRepository.GetSong(id);
|
||||
|
||||
SongData song = await _songMgr.RetrieveSong(songMetaData);
|
||||
var song = _songMgr.RetrieveSong(songMetaData).Result;
|
||||
|
||||
return File(song.Data, "application/x-msdownload", songMetaData.Filename);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize("upload:songs")]
|
||||
public async Task Post([FromForm(Name = "file")] List<IFormFile> songData)
|
||||
// Assumes that the song already has metadata such as
|
||||
// Title
|
||||
// Artist
|
||||
// Album
|
||||
// Genre
|
||||
// Year
|
||||
// Track
|
||||
// Track count
|
||||
// Disc
|
||||
// Disc count
|
||||
// Cover art
|
||||
//
|
||||
[HttpPost("upload"), DisableRequestSizeLimit]
|
||||
public IActionResult Upload([FromForm(Name = "file")] List<IFormFile> songData)
|
||||
{
|
||||
try
|
||||
{
|
||||
Initialize();
|
||||
|
||||
Console.WriteLine("Uploading song...");
|
||||
// Console.WriteLine("Uploading song...");
|
||||
_logger.LogInformation("Uploading song...");
|
||||
|
||||
var uploads = _songTempDir;
|
||||
Console.WriteLine($"Song Root Path {uploads}");
|
||||
// Console.WriteLine($"Song Root Path {uploads}");
|
||||
_logger.LogInformation($"Song root path {uploads}");
|
||||
|
||||
foreach (var sng in songData)
|
||||
if (sng.Length > 0) {
|
||||
Console.WriteLine($"Song filename {sng.FileName}");
|
||||
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);
|
||||
_songMgr.SaveSongToFileSystem(sng).Wait();
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var msg = ex.Message;
|
||||
_logger.LogError(msg, "An error occurred");
|
||||
}
|
||||
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
[Authorize("delete:songs")]
|
||||
public IActionResult Delete(int id)
|
||||
// The client is expected to send the file, metadata, and cover art separately.
|
||||
// Any metadata already on the file will be overwritten with values from the metadata
|
||||
// as well as the cover art
|
||||
//
|
||||
[HttpPost("upload/with/data")]
|
||||
public IActionResult UploadWithData([FromForm] UploadSongWithDataForm up)
|
||||
{
|
||||
Initialize();
|
||||
try
|
||||
{
|
||||
if (up.SongData.Length > 0 && up.CoverArtData.Length > 0 && !string.IsNullOrEmpty(up.SongFile))
|
||||
{
|
||||
var song = Newtonsoft.Json.JsonConvert.DeserializeObject<Song>(up.SongFile);
|
||||
_logger.LogInformation($"Song title: {song.Title}");
|
||||
|
||||
var songMetaData = new Song{ Id = id };
|
||||
Console.WriteLine($"Id {songMetaData.Id}");
|
||||
songMetaData = _songRepository.GetSong(songMetaData);
|
||||
_songMgr.SaveSongToFileSystem(up.SongData, up.CoverArtData, song);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message, "An error occurred");
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[HttpDelete("delete/{id}")]
|
||||
public IActionResult DeleteSong(int id)
|
||||
{
|
||||
var songContext = new SongContext(_connectionString);
|
||||
|
||||
var songMetaData = new Song{ SongID = id };
|
||||
Console.WriteLine($"Id {songMetaData.SongID}");
|
||||
|
||||
songMetaData = songContext.RetrieveRecord(songMetaData);
|
||||
|
||||
if (string.IsNullOrEmpty(songMetaData.Title))
|
||||
{
|
||||
@@ -142,13 +146,22 @@ namespace Icarus.Controllers.V1
|
||||
{
|
||||
_logger.LogInformation("Starting process of deleting song from the filesystem and database");
|
||||
|
||||
_songMgr.DeleteSong(songMetaData, _songRepository,
|
||||
_albumRepository, _artistRepository,
|
||||
_genreRepository, _yearRepository,
|
||||
_coverArtRepository);
|
||||
_songMgr.DeleteSong(songMetaData);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class UploadSongWithDataForm
|
||||
{
|
||||
[FromForm(Name = "file")]
|
||||
public IFormFile SongData { get; set; }
|
||||
// NOTE: Think about making this optional and if it is not provided, use the stock cover art
|
||||
[FromForm(Name = "cover")]
|
||||
public IFormFile CoverArtData { get; set; }
|
||||
[FromForm(Name = "metadata")]
|
||||
public string SongFile { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,19 +9,23 @@ 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.Models;
|
||||
using Icarus.Database.Repositories;
|
||||
using Icarus.Controllers.Managers;
|
||||
using Icarus.Database.Contexts;
|
||||
|
||||
namespace Icarus.Controllers.V1
|
||||
{
|
||||
[Route("api/v1/song/stream")]
|
||||
[ApiController]
|
||||
public class SongStreamController : ControllerBase
|
||||
[Authorize]
|
||||
public class SongStreamController : BaseController
|
||||
{
|
||||
#region Fields
|
||||
private ILogger<SongStreamController> _logger;
|
||||
private string _connectionString;
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -30,31 +34,35 @@ namespace Icarus.Controllers.V1
|
||||
|
||||
|
||||
#region Constructor
|
||||
public SongStreamController(ILogger<SongStreamController> logger)
|
||||
public SongStreamController(ILogger<SongStreamController> logger, IConfiguration config)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_connectionString = _config.GetConnectionString("DefaultConnection");
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP endpoints
|
||||
[HttpGet("{id}")]
|
||||
[Authorize("stream:songs")]
|
||||
public async Task<IActionResult> Get(int id)
|
||||
public async Task<IActionResult> StreamSong(int id)
|
||||
{
|
||||
var songStore= HttpContext.RequestServices
|
||||
.GetService(typeof(SongRepository)) as SongRepository;
|
||||
var context = new SongContext(_config.GetConnectionString("DefaultConnection"));
|
||||
|
||||
var song = songStore.GetSong(new Song { Id = id });
|
||||
var song = context.Songs.FirstOrDefault(sng => sng.SongID == id);
|
||||
|
||||
var stream = new FileStream(song.SongPath, FileMode.Open, FileAccess.Read);
|
||||
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...");
|
||||
|
||||
var file = await Task.Run(() => {
|
||||
return File(stream, "application/octet-stream", filename);
|
||||
});
|
||||
|
||||
return file;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -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<YearController> _logger;
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#region Constructors
|
||||
public YearController(ILogger<YearController> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region HTTP Routes
|
||||
[HttpGet]
|
||||
[Authorize("read:year")]
|
||||
public IActionResult Get()
|
||||
{
|
||||
var yearValues = new List<Year>();
|
||||
|
||||
var yearStore = HttpContext.RequestServices
|
||||
.GetService(typeof(YearRepository)) as YearRepository;
|
||||
|
||||
yearValues = yearStore.GetSongYears();
|
||||
|
||||
if (yearValues.Count > 0)
|
||||
return Ok(yearValues);
|
||||
else
|
||||
return NotFound(new List<Year>());
|
||||
}
|
||||
|
||||
[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
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
@@ -15,11 +13,25 @@ namespace Icarus.Database.Contexts
|
||||
public DbSet<Album> Albums { get; set; }
|
||||
|
||||
public AlbumContext(DbContextOptions<AlbumContext> options) : base(options) { }
|
||||
public AlbumContext(string connString) : base(new DbContextOptionsBuilder<AlbumContext>()
|
||||
.UseMySQL(connString).Options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Album>()
|
||||
.ToTable("Album");
|
||||
}
|
||||
|
||||
public Album RetrieveRecord(Album album)
|
||||
{
|
||||
return Albums.FirstOrDefault(alb => alb.AlbumID == album.AlbumID);
|
||||
}
|
||||
|
||||
public bool DoesRecordExist(Album album)
|
||||
{
|
||||
return Albums.FirstOrDefault(alb => alb.AlbumID == album.AlbumID) != null ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
@@ -15,11 +13,27 @@ namespace Icarus.Database.Contexts
|
||||
public DbSet<Artist> Artists { get; set; }
|
||||
|
||||
public ArtistContext(DbContextOptions<ArtistContext> options) : base (options) { }
|
||||
public ArtistContext(string connString) : base(new DbContextOptionsBuilder<ArtistContext>()
|
||||
.UseMySQL(connString).Options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Artist>()
|
||||
.ToTable("Artist");
|
||||
}
|
||||
|
||||
public Artist RetrieveRecord(Artist artist)
|
||||
{
|
||||
|
||||
return Artists.FirstOrDefault(arst => arst.ArtistID == artist.ArtistID);
|
||||
}
|
||||
|
||||
|
||||
public bool DoesRecordExist(Artist artist)
|
||||
{
|
||||
return Artists.FirstOrDefault(arst => arst.ArtistID == artist.ArtistID) != null ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
@@ -15,11 +13,25 @@ namespace Icarus.Database.Contexts
|
||||
public DbSet<CoverArt> CoverArtImages { get; set; }
|
||||
|
||||
public CoverArtContext(DbContextOptions<CoverArtContext> options) : base(options) { }
|
||||
public CoverArtContext(string connString) : base(new DbContextOptionsBuilder<CoverArtContext>()
|
||||
.UseMySQL(connString).Options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<CoverArt>()
|
||||
.ToTable("CoverArt");
|
||||
}
|
||||
|
||||
public CoverArt RetrieveRecord(CoverArt cover)
|
||||
{
|
||||
return CoverArtImages.FirstOrDefault(cov => cov.CoverArtID == cover.CoverArtID);
|
||||
}
|
||||
|
||||
public bool DoesRecordExist(CoverArt cover)
|
||||
{
|
||||
return CoverArtImages.FirstOrDefault(cov => cov.CoverArtID == cover.CoverArtID) != null ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
@@ -14,11 +12,26 @@ namespace Icarus.Database.Contexts
|
||||
{
|
||||
public DbSet<Genre> Genres { get; set; }
|
||||
public GenreContext(DbContextOptions<GenreContext> options) : base(options) { }
|
||||
public GenreContext(string connString) : base(new DbContextOptionsBuilder<GenreContext>()
|
||||
.UseMySQL(connString).Options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Genre>()
|
||||
.ToTable("Genre");
|
||||
}
|
||||
|
||||
|
||||
public Genre RetrieveRecord(Genre genre)
|
||||
{
|
||||
return Genres.FirstOrDefault(gnr => gnr.GenreID == genre.GenreID);
|
||||
}
|
||||
|
||||
public bool DoesRecordExist(Genre genre)
|
||||
{
|
||||
return Genres.FirstOrDefault(gnr => gnr.GenreID == genre.GenreID) != null ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
@@ -14,6 +12,11 @@ namespace Icarus.Database.Contexts
|
||||
{
|
||||
public DbSet<Song> Songs { get; set; }
|
||||
|
||||
public SongContext(string connString) : base(new DbContextOptionsBuilder<SongContext>()
|
||||
.UseMySQL(connString).Options)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public SongContext(DbContextOptions<SongContext> options) : base(options) { }
|
||||
|
||||
@@ -22,54 +25,65 @@ namespace Icarus.Database.Contexts
|
||||
modelBuilder.Entity<Song>()
|
||||
.ToTable("Song");
|
||||
|
||||
/**
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.Album)
|
||||
.WithMany(al => al.Songs)
|
||||
.HasForeignKey(s => s.AlbumId)
|
||||
.HasForeignKey(s => s.AlbumID)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(sa => sa.SongArtist)
|
||||
.WithMany(ar => ar.Songs)
|
||||
.HasForeignKey(s => s.ArtistId)
|
||||
.HasForeignKey(s => s.ArtistID)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.SongGenre)
|
||||
.WithMany(gnr => gnr.Songs)
|
||||
.HasForeignKey(s => s.GenreId)
|
||||
.HasForeignKey(s => s.GenreID)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.SongYear)
|
||||
.WithMany(yr => yr.Songs)
|
||||
.HasForeignKey(s => s.YearId)
|
||||
.HasForeignKey(s => s.YearID)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.HasOne(s => s.SongCoverArt)
|
||||
.WithMany(ca => ca.Songs)
|
||||
.HasForeignKey(s => s.CoverArtId)
|
||||
.HasForeignKey(s => s.CoverArtID)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
*/
|
||||
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.Year)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.YearId)
|
||||
.Property(s => s.GenreID)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.GenreId)
|
||||
.Property(s => s.ArtistID)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.ArtistId)
|
||||
.Property(s => s.AlbumID)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.AlbumId)
|
||||
.IsRequired(false);
|
||||
modelBuilder.Entity<Song>()
|
||||
.Property(s => s.CoverArtId)
|
||||
.Property(s => s.CoverArtID)
|
||||
.IsRequired(false);
|
||||
}
|
||||
|
||||
|
||||
public Song RetrieveRecord(Song song)
|
||||
{
|
||||
return Songs.FirstOrDefault(sng => sng.SongID == song.SongID);
|
||||
}
|
||||
|
||||
|
||||
public bool DoesRecordExist(Song song)
|
||||
{
|
||||
return Songs.FirstOrDefault(sng => sng.SongID == song.SongID) != null ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
// using MySql.Data.EntityFrameworkCore;
|
||||
// using MySql.Data;
|
||||
// using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
// using MySql.Data.Entity;
|
||||
// using MySql.Data.MySqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
@@ -15,7 +19,15 @@ namespace Icarus.Database.Contexts
|
||||
public DbSet<User> Users { get; set; }
|
||||
|
||||
|
||||
#region Constructors
|
||||
public UserContext(DbContextOptions<UserContext> options) : base(options) { }
|
||||
[ActivatorUtilitiesConstructor]
|
||||
public UserContext(string connString) : base(new DbContextOptionsBuilder<UserContext>()
|
||||
.UseMySQL(connString).Options)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -26,5 +38,16 @@ namespace Icarus.Database.Contexts
|
||||
modelBuilder.Entity<User>()
|
||||
.Property(u => u.DateCreated).HasDefaultValue(DateTime.Now);
|
||||
}
|
||||
|
||||
|
||||
public User RetrieveRecord(User user)
|
||||
{
|
||||
return Users.FirstOrDefault(usr => usr.UserID == user.UserID);
|
||||
}
|
||||
|
||||
public bool DoesRecordExist(User user)
|
||||
{
|
||||
return Users.FirstOrDefault(usr => usr.UserID == user.UserID) != null ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Year> YearValues { get; set; }
|
||||
|
||||
public YearContext(DbContextOptions<YearContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<Year>()
|
||||
.ToTable("Year");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,385 +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<Album> GetAlbumWithoutCount()
|
||||
{
|
||||
var albums = new List<Album>();
|
||||
|
||||
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<Album> GetAlbums()
|
||||
{
|
||||
List<Album> albums = new List<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=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);
|
||||
|
||||
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<Album> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
List<Album> albums = new List<Album>();
|
||||
_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<Album>();
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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<Artist> GetArtists()
|
||||
{
|
||||
List<Artist> artists = new List<Artist>();
|
||||
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<Artist> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
List<Artist> artists = new List<Artist>();
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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<CoverArt> 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<CoverArt> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
if (reader.HasRows)
|
||||
{
|
||||
var coverArtList = new List<CoverArt>();
|
||||
_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
|
||||
}
|
||||
}
|
||||
@@ -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<Genre> GetGenresWithoutCount()
|
||||
{
|
||||
_logger.Info("Retrieving all genre records without song counts");
|
||||
|
||||
var genres = new List<Genre>();
|
||||
|
||||
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<Genre> GetGenres()
|
||||
{
|
||||
_logger.Info("Retrieving Genre records");
|
||||
|
||||
var genres = new List<Genre>();
|
||||
|
||||
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<Genre> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
var genres = new List<Genre>();
|
||||
_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
|
||||
}
|
||||
}
|
||||
@@ -1,324 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
using Icarus.Models;
|
||||
|
||||
namespace Icarus.Database.Repositories
|
||||
{
|
||||
public class SongRepository : BaseRepository
|
||||
{
|
||||
#region Fields
|
||||
#endregion
|
||||
|
||||
|
||||
#region Properties
|
||||
#endregion
|
||||
|
||||
|
||||
#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<Song> GetAllSongs()
|
||||
{
|
||||
List<Song> songs = new List<Song>();
|
||||
|
||||
try
|
||||
{
|
||||
_logger.Info("Retrieving songs from the database");
|
||||
using (MySqlConnection conn = GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
var query = "SELECT * FROM Song";
|
||||
Console.WriteLine("ffff");
|
||||
MySqlCommand 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<Song> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
|
||||
List<Song> songs = new List<Song>();
|
||||
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)
|
||||
{
|
||||
Song 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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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<Year> GetSongYears()
|
||||
{
|
||||
_logger.Info("Retrieving Year records");
|
||||
|
||||
var yearValues = new List<Year>();
|
||||
|
||||
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<Year> ParseData(MySqlDataReader reader)
|
||||
{
|
||||
var yearValues = new List<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());
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
+17
-16
@@ -1,31 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<TargetFramework>net6</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
<Version>0.1.10</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="3.1.3" />
|
||||
<PackageReference Include="DotNetZip" Version="1.13.3" />
|
||||
<PackageReference Include="EntityFramework" Version="6.2.0" />
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.2" />
|
||||
<PackageReference Include="DotNetZip" Version="1.15.0" />
|
||||
<PackageReference Include="EntityFramework" Version="6.4.4" />
|
||||
<PackageReference Include="ID3" Version="0.6.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.2.3">
|
||||
<PackageReference Include="JWT" Version="9.0.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.8" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.8">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="mysql.data" Version="8.0.15" />
|
||||
<PackageReference Include="MySql.Data.Entity" Version="7.0.7-m61" />
|
||||
<PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.15" />
|
||||
<PackageReference Include="MySql.Data.EntityFrameworkCore.Design" Version="8.0.15" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="4.8.1" />
|
||||
<PackageReference Include="RestSharp" Version="106.6.9" />
|
||||
<PackageReference Include="MySql.EntityFrameworkCore" Version="5.0.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
|
||||
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||
<PackageReference Include="RestSharp" Version="106.15.0" />
|
||||
<PackageReference Include="SevenZip" Version="19.0.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.4.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.15.0" />
|
||||
<PackageReference Include="taglib" Version="2.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ActiveDebugProfile>Icarus</ActiveDebugProfile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
+12
-21
@@ -1,34 +1,25 @@
|
||||
|
||||
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}"
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32616.157
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Icarus", "Icarus.csproj", "{66389DAC-0D3C-4271-BBAE-AF27FCFD28B7}"
|
||||
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(ProjectConfigurationPlatforms) = postSolution
|
||||
{66389DAC-0D3C-4271-BBAE-AF27FCFD28B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{66389DAC-0D3C-4271-BBAE-AF27FCFD28B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{66389DAC-0D3C-4271-BBAE-AF27FCFD28B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{66389DAC-0D3C-4271-BBAE-AF27FCFD28B7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
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
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0BE61157-7A0C-41CF-B097-71178A3F6755}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
-313
@@ -1,313 +0,0 @@
|
||||
2019-05-23 20:25:46.2420 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:25:46.2666 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:25:46.3926 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:25:46.4144 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:25:46.4351 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:25:46.4703 Info Found 45 configuration items
|
||||
2019-05-23 20:26:13.6466 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:26:13.6651 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:26:13.8165 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:26:13.8351 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:26:13.8552 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:26:13.8939 Info Found 45 configuration items
|
||||
2019-05-23 20:33:39.8295 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:33:39.8438 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:33:39.9198 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:33:39.9238 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:33:39.9238 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:33:39.9871 Info Found 45 configuration items
|
||||
2019-05-23 20:33:40.2458 Info Configuration initialized.
|
||||
2019-05-23 20:33:40.2602 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:33:42.2086 Info Shutting down logging...
|
||||
2019-05-23 20:33:42.2458 Info Logger has been shut down.
|
||||
2019-05-23 20:34:06.6746 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:34:06.6896 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:34:06.7827 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:34:06.7827 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:34:06.8010 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:34:06.8321 Info Found 45 configuration items
|
||||
2019-05-23 20:34:06.8673 Info Configuration initialized.
|
||||
2019-05-23 20:34:06.8673 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:34:07.7083 Info Shutting down logging...
|
||||
2019-05-23 20:34:07.7346 Info Logger has been shut down.
|
||||
2019-05-23 20:35:03.8649 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:35:03.8783 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:35:03.9596 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:35:03.9596 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:35:03.9745 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:35:03.9958 Info Found 45 configuration items
|
||||
2019-05-23 20:35:04.0200 Info Configuration initialized.
|
||||
2019-05-23 20:35:04.0200 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:35:04.5747 Info Shutting down logging...
|
||||
2019-05-23 20:35:04.6042 Info Logger has been shut down.
|
||||
2019-05-23 20:35:41.2884 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:35:41.3011 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:35:41.3629 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:35:41.3629 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:35:41.3755 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:35:41.3973 Info Found 45 configuration items
|
||||
2019-05-23 20:35:41.4257 Info Configuration initialized.
|
||||
2019-05-23 20:35:41.4257 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:35:42.0181 Info Shutting down logging...
|
||||
2019-05-23 20:35:42.0437 Info Logger has been shut down.
|
||||
2019-05-23 20:36:03.3664 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:36:03.3803 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:36:03.4469 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:36:03.4469 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:36:03.4634 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:36:03.4897 Info Found 45 configuration items
|
||||
2019-05-23 20:36:03.5214 Info Configuration initialized.
|
||||
2019-05-23 20:36:03.5214 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:36:04.0862 Info Shutting down logging...
|
||||
2019-05-23 20:36:04.1162 Info Logger has been shut down.
|
||||
2019-05-23 20:37:13.4449 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:37:13.4578 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:37:13.5222 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:37:13.5222 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:37:13.5349 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:37:13.5575 Info Found 45 configuration items
|
||||
2019-05-23 20:37:13.5870 Info Configuration initialized.
|
||||
2019-05-23 20:37:13.5870 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:37:14.1141 Info Shutting down logging...
|
||||
2019-05-23 20:37:14.1395 Info Logger has been shut down.
|
||||
2019-05-23 20:37:38.9373 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:37:38.9373 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:37:39.0239 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:37:39.0239 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:37:39.0371 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:37:39.0624 Info Found 45 configuration items
|
||||
2019-05-23 20:37:39.0916 Info Configuration initialized.
|
||||
2019-05-23 20:37:39.0984 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:37:39.2254 Info Shutting down logging...
|
||||
2019-05-23 20:37:39.2461 Info Logger has been shut down.
|
||||
2019-05-23 20:38:15.2217 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:38:15.2426 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:38:15.3307 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:38:15.3307 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:38:15.3434 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:38:15.3733 Info Found 45 configuration items
|
||||
2019-05-23 20:38:15.4046 Info Configuration initialized.
|
||||
2019-05-23 20:38:15.4103 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:38:16.3887 Info Shutting down logging...
|
||||
2019-05-23 20:38:16.4170 Info Logger has been shut down.
|
||||
2019-05-23 20:38:56.3096 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:38:56.3228 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:38:56.3991 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:38:56.3991 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:38:56.4137 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:38:56.4412 Info Found 45 configuration items
|
||||
2019-05-23 20:38:56.4662 Info Configuration initialized.
|
||||
2019-05-23 20:38:56.4711 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:38:57.5659 Info Shutting down logging...
|
||||
2019-05-23 20:38:57.5921 Info Logger has been shut down.
|
||||
2019-05-23 20:39:33.6137 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:39:33.6328 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:39:33.7158 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:39:33.7209 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:39:33.7349 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\NLog.config...
|
||||
2019-05-23 20:39:33.7661 Info Found 45 configuration items
|
||||
2019-05-23 20:39:33.7984 Info Configuration initialized.
|
||||
2019-05-23 20:39:33.7984 Info NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c. File version: 4.5.11.8645. Product version: 4.5.11.
|
||||
2019-05-23 20:39:35.3535 Info Shutting down logging...
|
||||
2019-05-23 20:39:35.3853 Info Logger has been shut down.
|
||||
2019-05-23 20:41:03.9531 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:41:04.0224 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:41:04.2489 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:41:04.2638 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:41:04.2801 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:41:04.3178 Info Found 45 configuration items
|
||||
2019-05-23 20:42:20.8771 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:42:20.8771 Info Found 45 configuration items
|
||||
2019-05-23 20:42:20.8771 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:42:20.8771 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:42:20.8771 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:42:20.8771 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:42:20.8912 Info Closing old configuration.
|
||||
2019-05-23 20:42:20.9264 Info Found 45 configuration items
|
||||
2019-05-23 20:44:09.2436 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:44:09.2625 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:44:09.5033 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:44:09.5221 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:44:09.5436 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:44:09.5955 Info Found 45 configuration items
|
||||
2019-05-23 20:44:22.9386 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:44:22.9386 Info Found 45 configuration items
|
||||
2019-05-23 20:44:22.9386 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:44:22.9525 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:44:22.9525 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:44:22.9525 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:44:22.9525 Info Closing old configuration.
|
||||
2019-05-23 20:44:22.9920 Info Found 45 configuration items
|
||||
2019-05-23 20:45:56.3589 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:45:56.3781 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:45:56.5714 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:45:56.5830 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:45:56.5944 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:45:56.6232 Info Found 45 configuration items
|
||||
2019-05-23 20:46:59.8334 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:46:59.8559 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:47:00.0588 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:47:00.0756 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:47:00.1007 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:47:00.1455 Info Found 45 configuration items
|
||||
2019-05-23 20:48:14.1040 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:48:14.1282 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:48:14.2899 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:48:14.3059 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:48:14.3273 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:48:14.3764 Info Found 45 configuration items
|
||||
2019-05-23 20:49:07.1970 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:49:07.2494 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:49:07.4433 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:49:07.4565 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:49:07.4760 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:49:07.5338 Info Found 45 configuration items
|
||||
2019-05-23 20:49:20.7109 Info Message Template Auto Format enabled
|
||||
2019-05-23 20:49:20.7109 Info Found 45 configuration items
|
||||
2019-05-23 20:49:20.7109 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 20:49:20.7184 Info Adding target File Target[allfile]
|
||||
2019-05-23 20:49:20.7184 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 20:49:20.7184 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 20:49:20.7184 Info Closing old configuration.
|
||||
2019-05-23 20:49:20.7514 Info Found 45 configuration items
|
||||
2019-05-23 21:24:18.4464 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:24:18.4889 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:24:18.7399 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:24:18.7604 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:24:18.7838 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:24:18.8238 Info Found 45 configuration items
|
||||
2019-05-23 21:25:06.3861 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:25:06.3904 Info Found 45 configuration items
|
||||
2019-05-23 21:25:06.3904 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:25:06.4052 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:25:06.4052 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:25:06.4052 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:25:06.4243 Info Closing old configuration.
|
||||
2019-05-23 21:25:06.4727 Info Found 45 configuration items
|
||||
2019-05-23 21:26:26.1707 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:26:26.1964 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:26:26.3688 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:26:26.3866 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:26:26.4195 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:26:26.4805 Info Found 45 configuration items
|
||||
2019-05-23 21:27:58.0534 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:27:58.0751 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:27:58.2630 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:27:58.2786 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:27:58.2977 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:27:58.3440 Info Found 45 configuration items
|
||||
2019-05-23 21:28:30.3852 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:28:30.3901 Info Found 45 configuration items
|
||||
2019-05-23 21:28:30.3901 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:28:30.4094 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:28:30.4094 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:28:30.4094 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:28:30.4256 Info Closing old configuration.
|
||||
2019-05-23 21:28:30.4744 Info Found 45 configuration items
|
||||
2019-05-23 21:28:35.1110 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:28:35.1110 Info Found 45 configuration items
|
||||
2019-05-23 21:28:35.1110 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:28:35.1110 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:28:35.1110 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:28:35.1110 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:28:35.1110 Info Closing old configuration.
|
||||
2019-05-23 21:28:35.1110 Info Found 45 configuration items
|
||||
2019-05-23 21:33:27.3097 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:33:27.3317 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:33:27.6071 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:33:27.6230 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:33:27.6409 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:33:27.6860 Info Found 45 configuration items
|
||||
2019-05-23 21:34:21.2749 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:34:21.2749 Info Found 45 configuration items
|
||||
2019-05-23 21:34:21.2822 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:34:21.2822 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:34:21.2977 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:34:21.2977 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:34:21.2977 Info Closing old configuration.
|
||||
2019-05-23 21:34:21.3496 Info Found 45 configuration items
|
||||
2019-05-23 21:34:44.8361 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:34:44.8361 Info Found 45 configuration items
|
||||
2019-05-23 21:34:44.8361 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:34:44.8475 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:34:44.8475 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:34:44.8475 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:34:44.8475 Info Closing old configuration.
|
||||
2019-05-23 21:34:49.8402 Info Found 45 configuration items
|
||||
2019-05-23 21:36:39.6643 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:36:39.6956 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:36:39.9527 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:36:39.9527 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:36:39.9854 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:36:40.0214 Info Found 45 configuration items
|
||||
2019-05-23 21:37:11.5126 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:37:11.5149 Info Found 45 configuration items
|
||||
2019-05-23 21:37:11.5149 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:37:11.5149 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:37:11.5149 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:37:11.5149 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:37:11.5149 Info Closing old configuration.
|
||||
2019-05-23 21:37:11.5688 Info Found 45 configuration items
|
||||
2019-05-23 21:37:55.3893 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:37:55.3912 Info Found 45 configuration items
|
||||
2019-05-23 21:37:55.3912 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:37:55.3912 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:37:55.4088 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:37:55.4088 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:37:55.4088 Info Closing old configuration.
|
||||
2019-05-23 21:37:55.4088 Info Found 45 configuration items
|
||||
2019-05-23 21:44:40.0208 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:44:40.0474 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:44:40.2073 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:44:40.2186 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:44:40.2186 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:44:40.2868 Info Found 45 configuration items
|
||||
2019-05-23 21:45:19.6595 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:45:19.6595 Info Found 45 configuration items
|
||||
2019-05-23 21:45:19.6595 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:45:19.6595 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:45:19.6595 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:45:19.6595 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:45:19.6740 Info Closing old configuration.
|
||||
2019-05-23 21:45:19.7116 Info Found 45 configuration items
|
||||
2019-05-23 21:51:00.1698 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:51:00.1840 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:51:00.2721 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:51:00.2721 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:51:00.2920 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:51:00.3152 Info Found 45 configuration items
|
||||
2019-05-23 21:51:25.1256 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:51:25.1256 Info Found 45 configuration items
|
||||
2019-05-23 21:51:25.1256 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:51:25.1256 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:51:25.1256 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:51:25.1256 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:51:25.1412 Info Closing old configuration.
|
||||
2019-05-23 21:51:25.1648 Info Found 45 configuration items
|
||||
2019-05-23 21:51:25.2103 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:51:25.2103 Info Found 45 configuration items
|
||||
2019-05-23 21:51:25.2103 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:51:25.2103 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:51:25.2103 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:51:25.2103 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:51:25.2103 Info Closing old configuration.
|
||||
2019-05-23 21:51:25.2182 Info Found 45 configuration items
|
||||
2019-05-23 21:53:11.2368 Info Logger closing down...
|
||||
2019-05-23 21:53:11.2368 Info Closing old configuration.
|
||||
2019-05-23 21:53:11.2368 Info Logger has been closed down.
|
||||
2019-05-23 21:53:11.2368 Info Shutting down logging...
|
||||
2019-05-23 21:53:11.2555 Info Logger has been shut down.
|
||||
2019-05-23 21:54:25.6441 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:54:25.6761 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:54:25.9546 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:54:25.9757 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:54:25.9951 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:54:26.0361 Info Found 45 configuration items
|
||||
2019-05-23 21:54:55.6086 Info Message Template Auto Format enabled
|
||||
2019-05-23 21:54:55.6086 Info Found 45 configuration items
|
||||
2019-05-23 21:54:55.6086 Info Loading assembly: NLog.Web.AspNetCore
|
||||
2019-05-23 21:54:55.6086 Info Adding target File Target[allfile]
|
||||
2019-05-23 21:54:55.6086 Info Adding target File Target[ownFile-web]
|
||||
2019-05-23 21:54:55.6086 Info Configured from an XML element in C:\Users\user0\Programming\C#\Icarus\bin\Debug\netcoreapp2.2\nlog.config...
|
||||
2019-05-23 21:54:55.6280 Info Closing old configuration.
|
||||
2019-05-23 21:54:55.6926 Info Found 45 configuration items
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Kun Deng
|
||||
Copyright (c) 2021 Kun Deng
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+6
-2
@@ -8,17 +8,21 @@ namespace Icarus.Models
|
||||
{
|
||||
public class Album
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int AlbumId { get; set; }
|
||||
[JsonProperty("album_id")]
|
||||
public int AlbumID { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("album_artist")]
|
||||
[Column("Artist")]
|
||||
public string AlbumArtist { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
[NotMapped]
|
||||
public int SongCount { get; set; }
|
||||
[JsonProperty("year")]
|
||||
public int Year { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[NotMapped]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -8,15 +8,17 @@ namespace Icarus.Models
|
||||
{
|
||||
public class Artist
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int ArtistId { get; set; }
|
||||
[JsonProperty("artist_id")]
|
||||
public int ArtistID { get; set; }
|
||||
[JsonProperty("name")]
|
||||
[Column("Artist")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
[NotMapped]
|
||||
public int SongCount { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[NotMapped]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
+25
-4
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
@@ -8,15 +10,34 @@ namespace Icarus.Models
|
||||
{
|
||||
public class CoverArt
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int CoverArtId { get; set; }
|
||||
#region Properties
|
||||
[JsonProperty("cover_art_id")]
|
||||
public int CoverArtID { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string SongTitle { get; set; }
|
||||
[JsonIgnore]
|
||||
public string ImagePath { get; set; }
|
||||
[JsonProperty("song_id")]
|
||||
public int SongId { get; set; }
|
||||
[JsonIgnore]
|
||||
[NotMapped]
|
||||
public int SongID { get; set; }
|
||||
[JsonIgnore]
|
||||
[NotMapped]
|
||||
public List<Song> Songs { get; set; }
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public string GenerateFilename(int flag)
|
||||
{
|
||||
const int length = 25;
|
||||
const string chars = "ABCDEF0123456789";
|
||||
var random = new Random();
|
||||
var filename = new string(Enumerable.Repeat(chars, length).Select(s =>
|
||||
s[random.Next(s.Length)]).ToArray());
|
||||
var extension = ".mp3";
|
||||
|
||||
return (flag == 0) ? filename : $"{filename}{extension}";
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -8,15 +8,16 @@ namespace Icarus.Models
|
||||
{
|
||||
public class Genre
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int GenreId { get; set; }
|
||||
[JsonProperty("genre_id")]
|
||||
public int GenreID { get; set; }
|
||||
[JsonProperty("genre")]
|
||||
[Column("Category")]
|
||||
public string GenreName { get; set; }
|
||||
[JsonProperty("song_count")]
|
||||
[NotMapped]
|
||||
public int SongCount { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[NotMapped]
|
||||
public List<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace Icarus.Models
|
||||
{
|
||||
public class LoginResult : BaseResult
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int UserId { get; set; }
|
||||
[JsonProperty("user_id")]
|
||||
public int UserID { get; set; }
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; set; }
|
||||
[JsonProperty("token")]
|
||||
|
||||
+72
-24
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@@ -7,14 +9,18 @@ namespace Icarus.Models
|
||||
{
|
||||
public class Song
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int Id { get; set; }
|
||||
#region Properties
|
||||
[JsonProperty("song_id")]
|
||||
public int SongID { get; set; }
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
[JsonProperty("album")]
|
||||
[Column("Album")]
|
||||
public string AlbumTitle { get; set; }
|
||||
[JsonProperty("artist")]
|
||||
public string Artist { get; set; }
|
||||
[JsonProperty("album_artist")]
|
||||
public string AlbumArtist { get; set; }
|
||||
[JsonProperty("year")]
|
||||
public int? Year { get; set; }
|
||||
[JsonProperty("genre")]
|
||||
@@ -23,32 +29,74 @@ namespace Icarus.Models
|
||||
public int Duration { get; set; }
|
||||
[JsonProperty("filename")]
|
||||
public string Filename { get; set; }
|
||||
[JsonProperty("song_path")]
|
||||
public string SongPath { get; set; }
|
||||
[JsonIgnore]
|
||||
public string SongDirectory { get; set; }
|
||||
[JsonProperty("track")]
|
||||
public int Track { get; set; } = 0;
|
||||
[JsonProperty("track_count")]
|
||||
public int TrackCount { get; set; } = 0;
|
||||
[JsonProperty("disc")]
|
||||
public int Disc { get; set; } = 0;
|
||||
[JsonProperty("disc_count")]
|
||||
public int DiscCount { get; set; } = 0;
|
||||
[JsonIgnore]
|
||||
public int? AlbumID { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? ArtistID { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? GenreID { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? CoverArtID { get; set; }
|
||||
[JsonProperty("date_created")]
|
||||
public DateTime DateCreated { get; set; }
|
||||
#endregion
|
||||
|
||||
[JsonIgnore]
|
||||
public Album Album { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? AlbumId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Artist SongArtist { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? ArtistId { get; set; }
|
||||
#region Constructors
|
||||
#endregion
|
||||
|
||||
[JsonIgnore]
|
||||
public Genre SongGenre { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? GenreId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Year SongYear { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? YearId { get; set; }
|
||||
#region Methods
|
||||
public string SongPath()
|
||||
{
|
||||
var fullPath = SongDirectory;
|
||||
|
||||
[JsonIgnore]
|
||||
public CoverArt SongCoverArt { get; set; }
|
||||
[JsonIgnore]
|
||||
public int? CoverArtId { get; set; }
|
||||
if (fullPath[fullPath.Length -1] != '/')
|
||||
{
|
||||
fullPath += "/";
|
||||
}
|
||||
|
||||
fullPath += Filename;
|
||||
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
public string GenerateFilename(int flag = 0)
|
||||
{
|
||||
const int length = 25;
|
||||
const string chars = "ABCDEF0123456789";
|
||||
var random = new Random();
|
||||
var filename = new string(Enumerable.Repeat(chars, length).Select(s =>
|
||||
s[random.Next(s.Length)]).ToArray());
|
||||
var extension = ".mp3";
|
||||
|
||||
return flag == 0 ? filename : $"{filename}{extension}";
|
||||
}
|
||||
public async Task<string> GenerateFilenameAsync(int flag = 0)
|
||||
{
|
||||
const int length = 25;
|
||||
const string chars = "ABCDEF0123456789";
|
||||
var extension = ".mp3";
|
||||
var random = new Random();
|
||||
var filename = await Task.Run(() =>
|
||||
{
|
||||
return new string(Enumerable.Repeat(chars, length).Select(s =>
|
||||
s[random.Next(s.Length)]).ToArray());
|
||||
});
|
||||
|
||||
|
||||
return flag == 0 ? filename : $"{filename}{extension}";
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@ namespace Icarus.Models
|
||||
{
|
||||
public class SongData
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int ID { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
public int SongId { get; set; }
|
||||
public int SongID { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
public class Token
|
||||
{
|
||||
#region Properties
|
||||
[JsonProperty("scope")]
|
||||
public string Scope { get; set; }
|
||||
[JsonProperty("exp")]
|
||||
public int Expiration { get; set; }
|
||||
[JsonProperty("aud")]
|
||||
public string Audience { get; set; }
|
||||
[JsonProperty("iss")]
|
||||
public string Issuer { get; set; }
|
||||
[JsonProperty("iat")]
|
||||
public int Issued { get; set; }
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
public bool TokenExpired()
|
||||
{
|
||||
var result = false;
|
||||
var currentDate = DateTime.Now;
|
||||
|
||||
var currentDateInSeconds = Math.Floor((currentDate - DateTime.UnixEpoch).TotalSeconds);
|
||||
|
||||
result = (currentDateInSeconds >= Expiration) ? true : false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool ContainsScope(string desiredScope)
|
||||
{
|
||||
var result = false;
|
||||
result = Scope.Contains(desiredScope);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool Erroneous()
|
||||
{
|
||||
var result = true;
|
||||
Func<string, bool> isEmpty = a => string.IsNullOrEmpty(a);
|
||||
result = (!isEmpty(Scope) && !isEmpty(Audience) && !isEmpty(Issuer) &&
|
||||
Expiration > 0 && Issued > 0) ? false : true;
|
||||
|
||||
return result;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+33
-8
@@ -1,32 +1,57 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Icarus.Models
|
||||
{
|
||||
[Table("User")]
|
||||
public class User
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int Id { get; set; }
|
||||
#region Properties
|
||||
[JsonProperty("user_id")]
|
||||
[Column("UserID")]
|
||||
[Key]
|
||||
public int UserID { 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")]
|
||||
[JsonProperty("phone")]
|
||||
[Column("Phone")]
|
||||
public string Phone { get; set; }
|
||||
[JsonProperty("firstname")]
|
||||
public string Firstname { get; set; }
|
||||
[JsonProperty("last_name")]
|
||||
[JsonProperty("lastname")]
|
||||
public string Lastname { get; set; }
|
||||
[JsonProperty("email_verified")]
|
||||
[NotMapped]
|
||||
public bool EmailVerified { get; set; }
|
||||
[JsonProperty("date_created")]
|
||||
public DateTime DateCreated { get; set; }
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
[JsonProperty("last_login")]
|
||||
public DateTime? LastLogin { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
[NotMapped]
|
||||
public System.Collections.Generic.IEnumerable<string> Roles { get; set; }
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
public System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> Claims()
|
||||
{
|
||||
var claims = new System.Collections.Generic.List<System.Security.Claims.Claim> { new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Name, Username) };
|
||||
claims.AddRange(Roles.Select(role => new System.Security.Claims.Claim(System.Security.Claims.ClaimTypes.Role, role)));
|
||||
|
||||
return claims;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Song> Songs { get; set; }
|
||||
}
|
||||
}
|
||||
+8
-9
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog.Web;
|
||||
|
||||
@@ -21,7 +22,8 @@ namespace Icarus
|
||||
try
|
||||
{
|
||||
logger.Debug("init main");
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -34,14 +36,11 @@ namespace Icarus
|
||||
}
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args).UseStartup<Startup>()
|
||||
.UseUrls("http://localhost:5002")
|
||||
.ConfigureLogging(logging =>
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
logging.ClearProviders();
|
||||
logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
|
||||
})
|
||||
.UseNLog();
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
@@ -20,7 +20,8 @@
|
||||
"Icarus": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"dotnetRuneMessage": true,
|
||||
"launchUrl": "swagger",
|
||||
"applicationUrl": "http://localhost:5002",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
|
||||
@@ -10,38 +10,57 @@ One can interface with Icarus the music server either by:
|
||||
* [IcarusDownloadManager](https://github.com/amazing-username/IcarusDownloadManager)
|
||||
|
||||
|
||||
|
||||
## Built With
|
||||
|
||||
|
||||
* C#
|
||||
* [.NET Core](https://dotnet.microsoft.com/) 2.2
|
||||
* .NET Web RESTful API
|
||||
* C# [.NET](https://dotnet.microsoft.com/) 6
|
||||
* [MySql](https://www.nuget.org/packages/MySql.Data/)
|
||||
* OpenSSL
|
||||
* BCrypt.Net-Next
|
||||
* DotNetZip
|
||||
* ID3
|
||||
* JWT
|
||||
* Microsoft.AspNetCore.Authentication.JwtBearer
|
||||
* Microsoft.AspNetCore.Mvc.NewtonsoftJson
|
||||
* Microsoft.EntityFrameworkCore
|
||||
* Microsoft.EntityFrameworkCore.Tools
|
||||
* MySql.EntityFrameworkCore
|
||||
* [Newtonsoft.Json](https://www.newtonsoft.com/json)
|
||||
* NLog.Web.AspNetCpre
|
||||
* Portable.BouncyCastle
|
||||
* RestSharp
|
||||
* SevenZip
|
||||
* System.IdentityModel.Tokens.Jwt
|
||||
* [TagLib#](https://github.com/mono/taglib-sharp)
|
||||
|
||||

|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
There are several things that need to be completed to properly setup and secure the API.
|
||||
1. Auth0 API configuration
|
||||
This API uses OpenAPI Specification 3.0. After configuring the API, launch the software
|
||||
and navigate your browser to https://localhost:5001/swagger to view the endpoints.
|
||||
|
||||
1. JWT Information
|
||||
2. API filesystem paths
|
||||
3. Database connection string
|
||||
4. Migrations
|
||||
|
||||
### Auth0 API configuration
|
||||
|
||||
Securing Icarus is required, preventing the API from being publicly accessible. To do so, create an Auth0 account (it's free), for the sake of this section of the documentation, I will not go over how to create an Auth0 account. Once created, create a tentant and proceed to create an API
|
||||
<h1 align=center>
|
||||
<img src="Images/Configuration/create_api.png" width=100%>
|
||||
</h1>
|
||||
### JWT Information
|
||||
|
||||
Create the API and enter an approrpiate name and identified. For the identified, append **api** like in the example
|
||||
<h1 align="center">
|
||||
<img src="Images/Configuration/enter_api_info.png" width=100%>
|
||||
</h1>
|
||||
Replace [domain] with the domain name of the created tenant. This can be found in the Default App from the Application menu. Replace [identifier] with the identifer root name in the appsettings environment file. Not the friendly name but the root name of the identifier, omitting the http protocol and the *api* path.
|
||||
Configure JWT information. Notably the Secret
|
||||
|
||||
```Json
|
||||
"JWT": {
|
||||
"Issuer": "IcarusAPI",
|
||||
"Audience": "IcarusAPIClient",
|
||||
"Secret": "Manaiswhatyouthinkitis",
|
||||
"Subject": "Authorization"
|
||||
},
|
||||
```
|
||||
|
||||
|
||||
Replace [domain] with the domain name that represent's your domain. Replace [identifier] with the identifer root name in the appsettings environment file. Not the friendly name but the root name of the identifier, omitting the http protocol and the *api* path.
|
||||
|
||||
```Json
|
||||
"Auth0": {
|
||||
@@ -50,37 +69,8 @@ Replace [domain] with the domain name of the created tenant. This can be found i
|
||||
},
|
||||
```
|
||||
|
||||
For the sake of this section, I will not go over configuring the API to accept the signing algorithm since it has already been configured in the [Startip](Startup.cs).cs file. Click on permissions to create the permissions for the API.
|
||||
<h1 align "center">
|
||||
<img src="Images/Configuration/configure_api.png" width=100%>
|
||||
</h1>
|
||||
**Note**: The Auth0 section is likely to be changed or removed in future releases.
|
||||
|
||||
The permissions ensure that a validated user can interact with the API with a token that has not expired. Ensure that the permissions match, the description can change but the permission identifier must match.
|
||||
<h1 align="center">
|
||||
<img src="Images/Configuration/permissions.png" width=100%>
|
||||
</h1>
|
||||
|
||||
On the left side, click on Application and create a new Application. Choose the Machine to Machine Application
|
||||
<h1 align="center">
|
||||
<img src="Images/Configuration/create_m2m.png" width=100%>
|
||||
</h1>
|
||||
|
||||
With the grant permissions you created from the API, enable all the permissions. This is important because if they are not enabled then even with a valid token the request will return 403 (unauthorized)
|
||||
<h1 align="center">
|
||||
<img src="Images/Configuration/authorize_app.png" width=100%>
|
||||
</h1>
|
||||
|
||||
From the Application page, copy the client id and client secret. These values will be used for the API to interact with API.
|
||||
<h1 align="center">
|
||||
<img src="Images/Configuration/api_cred.png" width=100%>
|
||||
</h1>
|
||||
Enter the information in the corresponding appsettings json file
|
||||
```Json
|
||||
"Auth0": {
|
||||
"ClientId":"",
|
||||
"ClientSecret":""
|
||||
},
|
||||
```
|
||||
|
||||
### API filesystem paths
|
||||
|
||||
@@ -89,12 +79,14 @@ For the purposes of properly uploading, downloading, updating, deleting, and str
|
||||
{
|
||||
"RootMusicPath": "/home/dev/null/music/",
|
||||
"TemporaryMusicPath": "/home/dev/null/music/temp/",
|
||||
"ArchivePath": "/home/dev/null/music/archive/"
|
||||
"ArchivePath": "/home/dev/null/music/archive/",
|
||||
"CoverArtPath": "/home/dev/null/music/coverart/"
|
||||
}
|
||||
```
|
||||
* RootMusicPath - Where music will be stored in the following convention: *`Artist/Album/Songs`*
|
||||
* TemporaryMusicPath - Where music will be stored when uploding songs to the server until the metadata has been fully parsed and entered into the database. Upon completion the files will be deleted and moved to the appropriate path in the `RootMusicPath`
|
||||
* ArchivePath - When downloading compressed songs this is the path where songs will be compressed prior to dataa being read into memory, deleting the compressed file, and sending the compressed file from memory to the client
|
||||
* CoverArtPath - Root directory where cover art will be saved to
|
||||
|
||||
|
||||
**Note**: The `TemporaryMusic` or `ArchivePath` does not have to be located in the `RootMusicPath`. Ensure that the permissions are properly set for all of the paths.
|
||||
@@ -102,15 +94,15 @@ For the purposes of properly uploading, downloading, updating, deleting, and str
|
||||
### Database connection string
|
||||
|
||||
In order for Database functionality to be operable, there must be a valid connection string and credentials with appropriate permissions. **At the moment there is only support for MySQL**. Depending on your environment `Release` or `Debug` you will need to edit the appsettings.json or appsettings.Development.json accordingly. An example of the fields to change are below:
|
||||
|
||||
```Json
|
||||
{
|
||||
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=localhost;Database=my_db;Uid=admin;Pwd=toughpassword;"
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
* Server - The address or domain name of the MySQL server
|
||||
* Database - The database name
|
||||
* Uid - Username
|
||||
@@ -148,15 +140,6 @@ From this point the database has been successfully configured. Metadata and song
|
||||
|
||||
Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduct, and the process for submitting pull requests to the project.
|
||||
|
||||
## Versioning
|
||||
|
||||
* [v0.1](https://github.com/amazing-username/Icarus/releases/tag/v0.1)
|
||||
|
||||
## Authors
|
||||
|
||||
* **Kun Deng** - [amazing-username](https://github.com/amazing-username)
|
||||
|
||||
See also the list of [contributors](https://github.com/amazing-username/Icarus/graphs/contributors) who participated in this project.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
Executable → Regular
@@ -0,0 +1,99 @@
|
||||
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,
|
||||
Artist 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 Song (
|
||||
SongID INT NOT NULL AUTO_INCREMENT,
|
||||
Title TEXT NOT NULL,
|
||||
Artist TEXT NOT NULL,
|
||||
Album TEXT NOT NULL,
|
||||
AlbumArtist TEXT NOT NULL,
|
||||
Genre TEXT NOT NULL,
|
||||
Year INT NOT NULL,
|
||||
Duration INT NOT NULL,
|
||||
Track INT NOT NULL,
|
||||
TrackCount INT NOT NULL,
|
||||
Disc INT NOT NULL,
|
||||
DiscCount INT NOT NULL,
|
||||
SongDirectory TEXT NOT NULL,
|
||||
Filename TEXT NOT NULL,
|
||||
CoverArtID INT NOT NULL,
|
||||
ArtistID INT NOT NULL,
|
||||
AlbumID INT NOT NULL,
|
||||
GenreID INT NOT NULL,
|
||||
DateCreated DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
PRIMARY KEY (SongID),
|
||||
CONSTRAINT FK_Song_CoverArtID FOREIGN KEY (CoverArtID) REFERENCES CoverArt (CoverArtID),
|
||||
CONSTRAINT FK_Song_ArtistID FOREIGN KEY (ArtistID) REFERENCES Artist (ArtistID),
|
||||
CONSTRAINT FK_Song_AlbumID FOREIGN KEY (AlbumID) REFERENCES Album (AlbumID),
|
||||
CONSTRAINT FK_Song_GenreID FOREIGN KEY (GenreID) REFERENCES Genre (GenreID)
|
||||
);
|
||||
|
||||
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,
|
||||
DateCreated DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
Status TEXT DEFAULT 'Active',
|
||||
LastLogin DATETIME NULL,
|
||||
|
||||
PRIMARY KEY (UserID)
|
||||
);
|
||||
|
||||
CREATE TABLE Salt (
|
||||
SaltID INT NOT NULL AUTO_INCREMENT,
|
||||
Salt TEXT NOT NULL,
|
||||
UserID INT NOT NULL,
|
||||
|
||||
PRIMARY KEY (SaltID),
|
||||
CONSTRAINT FK_Salt_UserID FOREIGN KEY (UserID) REFERENCES User (UserID)
|
||||
);
|
||||
|
||||
CREATE TABLE Token (
|
||||
TokenID INT NOT NULL AUTO_INCREMENT,
|
||||
AccessToken TEXT NOT NULL,
|
||||
TokenType TEXT NOT NULL,
|
||||
Expires DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
Issued DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
UserID INT NOT NULL,
|
||||
|
||||
PRIMARY KEY (TokenID),
|
||||
CONSTRAINT FK_Token_UserID FOREIGN KEY (UserID) REFERENCES User (UserID)
|
||||
);
|
||||
@@ -2,5 +2,4 @@ delete from Song;
|
||||
delete from Album;
|
||||
delete from Artist;
|
||||
delete from Genre;
|
||||
delete from Year;
|
||||
delete from CoverArt;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
drop database Icarus;
|
||||
+76
-106
@@ -1,157 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
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.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySql.Data;
|
||||
using MySql.Data.EntityFrameworkCore.Extensions;
|
||||
using MySql.Data.MySqlClient;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Newtonsoft.Json;
|
||||
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
|
||||
{
|
||||
#region Constructors
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public IConfiguration Configuration { get; }
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
// 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<IConfiguration>(Configuration);
|
||||
services.AddControllers();
|
||||
|
||||
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<IAuthorizationHandler, HasScopeHandler>();
|
||||
var auth_id = Configuration["Auth0:Domain"];
|
||||
var domain = $"https://{auth_id}/";
|
||||
var audience = Configuration["Auth0:ApiIdentifier"];
|
||||
|
||||
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.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
|
||||
{
|
||||
options.RequireHttpsMetadata = false;
|
||||
options.SaveToken = true;
|
||||
options.TokenValidationParameters = new TokenValidationParameters()
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidAudience = Configuration["JWT:Audience"],
|
||||
ValidIssuer = Configuration["JWT:Issuer"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]))
|
||||
};
|
||||
});
|
||||
|
||||
services.AddDbContext<SongContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<AlbumContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<ArtistContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<UserContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<GenreContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<YearContext>(options => options.UseMySQL(connString));
|
||||
services.AddDbContext<CoverArtContext>(options => options.UseMySQL(connString));
|
||||
|
||||
services.AddControllers()
|
||||
.AddNewtonsoftJson();
|
||||
|
||||
services.AddEndpointsApiExplorer();
|
||||
services.AddSwaggerGen(c =>
|
||||
{
|
||||
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
|
||||
|
||||
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Icarus", Version = "v1" });
|
||||
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
|
||||
{
|
||||
Name = "Authorization",
|
||||
Scheme = "Bearer",
|
||||
BearerFormat = "JWT",
|
||||
Type = SecuritySchemeType.ApiKey,
|
||||
In = ParameterLocation.Header,
|
||||
Description = "Bearer *Auth Token*",
|
||||
});
|
||||
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
new string[] {}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
// NOTE: Dev-related configuration can be done when env.IsDevelopment() evaluated to true
|
||||
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.UseSwagger();
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseRouting();
|
||||
app.UseAuthentication();
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseMvc();
|
||||
}
|
||||
app.UseAuthorization();
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
});
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,16 @@
|
||||
"ClientId": "",
|
||||
"ClientSecret": ""
|
||||
},
|
||||
"RSAKeys": {
|
||||
"PrivateKeyPath": "",
|
||||
"PublicKeyPath": ""
|
||||
},
|
||||
"JWT": {
|
||||
"Issuer": "",
|
||||
"Audience": "",
|
||||
"Secret": "",
|
||||
"Subject": ""
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=;Database=;Uid=;Pwd=;"
|
||||
},
|
||||
|
||||
@@ -12,6 +12,16 @@
|
||||
"ClientId": "",
|
||||
"ClientSecret": ""
|
||||
},
|
||||
"RSAKeys": {
|
||||
"PrivateKeyPath": "",
|
||||
"PublicKeyPath": ""
|
||||
},
|
||||
"JWT": {
|
||||
"Issuer": "",
|
||||
"Audience": "",
|
||||
"Secret": "",
|
||||
"Subject": ""
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=;Database=;Uid=;Pwd=;"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user