#74: Add UserID to the Song model (#98)

* #74: Add UserID to the Song model

* #74: Added functionality to retrieve user id from the token

* #74: Songs will now contain the User Id when uploading

* Updated Readme and script to add migrations

* #74: Some cleanup
This commit was merged in pull request #98.
This commit is contained in:
Kun Deng
2024-06-19 15:41:55 -04:00
committed by GitHub
parent ebb15b7cdb
commit 562bc87822
25 changed files with 117 additions and 164 deletions
+6 -6
View File
@@ -29,13 +29,13 @@ public class ArtistManager : BaseManager
{
_logger.Info("Starting process to save the artist record of the song to the database");
var artist = new Artist();
var artist = new Artist
{
Name = song.Artist,
SongCount = 1
};
artist.Name = song.Artist;
artist.SongCount = 1;
var artistTitle = artist.Name;
var artistRetrieved = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artistTitle));
var artistRetrieved = _artistContext.Artists.FirstOrDefault(art => art.Name.Equals(artist.Name));
if (artistRetrieved == null)
{
+1 -1
View File
@@ -97,7 +97,7 @@ public class CoverArtManager : BaseManager
else
{
_logger.Info("Song has no cover art, applying stock cover art");
// coverArt.ImagePath = _rootCoverArtPath + $"{segment}{defaultExtension}";
var coverArtFilePath = _rootCoverArtPath + $"{segment}{defaultExtension}";
coverArt.ImagePath = DirectoryPaths.CoverArtPath;
metaData.UpdateCoverArt(song, coverArt);
+1 -1
View File
@@ -107,7 +107,7 @@ public class SongManager : BaseManager
try
{
var songPath = songMetaData.SongPath();
System.IO.File.Delete(songPath);
File.Delete(songPath);
successful = true;
DirectoryManager dirMgr = new DirectoryManager(_config, songMetaData);
dirMgr.DeleteEmptyDirectories();
+50 -18
View File
@@ -7,6 +7,7 @@ using Newtonsoft.Json;
using RestSharp;
using Icarus.Models;
using Microsoft.VisualBasic;
namespace Icarus.Controllers.Managers;
@@ -77,11 +78,10 @@ public class TokenManager : BaseManager
public LoginResult LoginSymmetric(User user)
{
var tokenResult = new TokenTierOne();
tokenResult.TokenType = "Jwt";
var tokenResult = new TokenTierOne{ TokenType = "JWT" };
var payload = Payload();
payload.Add(new System.Security.Claims.Claim("user_id", user.UserID.ToString(), ClaimValueTypes.Integer));
payload.Add(new Claim("user_id", user.UserID.ToString(), ClaimValueTypes.Integer));
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_config["JWT:Secret"]);
@@ -98,10 +98,7 @@ public class TokenManager : BaseManager
Audience = _config["Jwt:Audience"]
};
var token = tokenHandler.CreateToken(tokenDescriptor);
tokenResult.AccessToken = tokenHandler.WriteToken(token);
tokenResult.AccessToken = tokenHandler.WriteToken(tokenHandler.CreateToken(tokenDescriptor));
var expClaim = payload.FirstOrDefault(cl =>
{
@@ -120,6 +117,42 @@ public class TokenManager : BaseManager
};
}
public int RetrieveUserIdFromToken(string token)
{
if (this.ContainsBearer(token))
{
token = this.StripBearer(token);
}
var tokenHandler = new JwtSecurityTokenHandler();
var readTok = tokenHandler.ReadJwtToken(token);
var userId = -1;
foreach (var item in readTok.Payload)
{
if (item.Key == "user_id")
{
userId = Convert.ToInt32(item.Value);
break;
}
}
return userId;
}
private string StripBearer(string token)
{
var start = 6;
var strippedToken = token.Substring(start);
return Strings.Trim(strippedToken);
}
private bool ContainsBearer(string token)
{
return token.Contains("Bearer");
}
private string AllScopes()
{
@@ -157,30 +190,28 @@ public class TokenManager : BaseManager
private List<Claim> Payload()
{
// TODO: Remove this hard coding
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 issuer = "http://localhost:5002";
var 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("scope", AllScopes(), "string"),
new Claim(JwtRegisteredClaimNames.Exp, expiredDate.ToString()),
new Claim(JwtRegisteredClaimNames.Aud, audience),
new Claim(JwtRegisteredClaimNames.Iss, issuer),
new Claim(JwtRegisteredClaimNames.Sub, subject),
new System.Security.Claims.Claim(JwtRegisteredClaimNames.Iat, currentDate.ToString())
new Claim(JwtRegisteredClaimNames.Iat, currentDate.ToString())
};
return claim;
}
[Obsolete("Deprecated function")]
private async Task<string> ReadKeyContent(string filepath)
{
return await System.IO.File.ReadAllTextAsync(filepath);
@@ -234,6 +265,7 @@ public class TokenManager : BaseManager
[JsonProperty("grant_type")]
public string GrantType { get; set; }
}
private class TokenTierOne
{
[JsonProperty("access_token")]
-5
View File
@@ -1,9 +1,4 @@
using System;
using System.IO;
using System.Threading.Tasks;
using Ionic.Zip;
using Microsoft.AspNetCore.Http;
using Icarus.Models;
+2 -13
View File
@@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Icarus.Models;
using Icarus.Database.Contexts;
@@ -41,11 +35,9 @@ public class AlbumController : BaseController
[HttpGet]
public IActionResult GetAlbums()
{
List<Album> albums = new List<Album>();
var albumContext = new AlbumContext(_connectionString);
albums = albumContext.Albums.ToList();
var albums = albumContext.Albums.ToList();
if (albums.Count > 0)
return Ok(albums);
@@ -56,10 +48,7 @@ public class AlbumController : BaseController
[HttpGet("{id}")]
public IActionResult GetAlbum(int id)
{
Album album = new Album
{
AlbumID = id
};
Album album = new Album{ AlbumID = id };
var albumContext = new AlbumContext(_connectionString);
+2 -5
View File
@@ -1,10 +1,5 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Icarus.Models;
using Icarus.Database.Contexts;
@@ -67,7 +62,9 @@ public class ArtistController : BaseController
return Ok(artist);
}
else
{
return NotFound();
}
}
#endregion
}
-4
View File
@@ -1,8 +1,4 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
namespace Icarus.Controllers.V1;
+8 -13
View File
@@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Icarus.Models;
using Icarus.Database.Contexts;
@@ -41,25 +35,24 @@ public class GenreController : BaseController
[HttpGet]
public IActionResult GetGenres()
{
var genres = new List<Genre>();
var genreStore = new GenreContext(_connectionString);
genres = genreStore.Genres.ToList();
var genres = genreStore.Genres.ToList();
if (genres.Count > 0)
{
return Ok(genres);
}
else
{
return NotFound(new List<Genre>());
}
}
[HttpGet("{id}")]
public IActionResult GetGenre(int id)
{
var genre = new Genre
{
GenreID = id
};
var genre = new Genre{ GenreID = id };
var genreStore = new GenreContext(_connectionString);
@@ -70,7 +63,9 @@ public class GenreController : BaseController
return Ok(genre);
}
else
{
return NotFound(new Genre());
}
}
#endregion
}
View File
-10
View File
@@ -1,13 +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;
using Icarus.Controllers.Managers;
using Icarus.Controllers.Utilities;
using Icarus.Models;
using Icarus.Database.Contexts;
@@ -19,7 +11,6 @@ namespace Icarus.Controllers.V1;
public class RegisterController : ControllerBase
{
#region Fields
private string _connectionString;
private IConfiguration _config;
#endregion
@@ -32,7 +23,6 @@ public class RegisterController : ControllerBase
public RegisterController(IConfiguration config)
{
_config = config;
_connectionString = _config.GetConnectionString("DefaultConnection");
}
#endregion
@@ -42,7 +42,6 @@ public class SongCompressedDataController : BaseController
var context = new SongContext(_connectionString);
SongCompression cmp = new SongCompression(_archiveDir);
Console.WriteLine($"Archive directory root: {_archiveDir}");
+8 -19
View File
@@ -1,16 +1,7 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Icarus.Controllers.Managers;
using Icarus.Controllers.Utilities;
using Icarus.Models;
using Icarus.Database.Contexts;
@@ -36,8 +27,8 @@ public class SongController : BaseController
public SongController(IConfiguration config, ILogger<SongController> logger)
{
_config = config;
_connectionString = _config.GetConnectionString("DefaultConnection");
_logger = logger;
_connectionString = _config.GetConnectionString("DefaultConnection");
_songMgr = new SongManager(config);
}
#endregion
@@ -45,23 +36,24 @@ public class SongController : BaseController
#region Methods
#region HTTP Endpoints
[HttpGet]
public IActionResult GetSongs()
{
List<Song> songs = new List<Song>();
Console.WriteLine("Attemtping to retrieve songs");
_logger.LogInformation("Attempting to retrieve songs");
var context = new SongContext(_connectionString);
songs = context.Songs.ToList();
var songs = context.Songs.ToList();
if (songs.Count > 0)
{
return Ok(songs);
}
else
{
return NotFound();
}
}
[HttpGet("{id}")]
@@ -69,8 +61,7 @@ public class SongController : BaseController
{
var context = new SongContext(_connectionString);
Song song = new Song { SongID = id };
song = context.RetrieveRecord(song);
var song = context.RetrieveRecord(new Song{ SongID = id });
Console.WriteLine("Here");
@@ -83,8 +74,6 @@ public class SongController : BaseController
[HttpPut("{id}")]
public IActionResult UpdateSong(int id, [FromBody] Song song)
{
var context = new SongContext(_connectionString);
song.SongID = id;
Console.WriteLine("Retrieving filepath of song");
_logger.LogInformation("Retrieving filepath of song");
+9
View File
@@ -104,6 +104,15 @@ public class SongDataController : BaseController
if (up.SongData.Length > 0 && up.CoverArtData.Length > 0 && !string.IsNullOrEmpty(up.SongFile))
{
var song = Newtonsoft.Json.JsonConvert.DeserializeObject<Song>(up.SongFile);
var tokMgr = new TokenManager(this._config);
var accessToken = Request.Headers["Authorization"];
var userId = tokMgr.RetrieveUserIdFromToken(accessToken);
if (userId != -1)
{
song.UserID = userId;
}
_logger.LogInformation($"Song title: {song.Title}");
_songMgr.SaveSongToFileSystem(up.SongData, up.CoverArtData, song);
+2 -19
View File
@@ -1,19 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Icarus.Models;
using Icarus.Controllers.Managers;
using Icarus.Database.Contexts;
namespace Icarus.Controllers.V1;
@@ -25,7 +12,6 @@ public class SongStreamController : BaseController
{
#region Fields
private ILogger<SongStreamController> _logger;
private string _connectionString;
#endregion
@@ -38,7 +24,6 @@ public class SongStreamController : BaseController
{
_logger = logger;
_config = config;
_connectionString = _config.GetConnectionString("DefaultConnection");
}
#endregion
@@ -63,11 +48,9 @@ public class SongStreamController : BaseController
_logger.LogInformation("Starting to stream song...>");
Console.WriteLine("Starting to streamsong...");
var file = await Task.Run(() => {
return await Task.Run(() => {
return File(stream, "application/octet-stream", filename);
});
return file;
}
#endregion
}