From 16eec3e9e2ada1f0038153004cecf7c2aaf3aac2 Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 7 Mar 2025 21:54:44 -0500 Subject: [PATCH 01/14] tsk-76: Added model and context for AccessLevel --- .../Database/Contexts/AccessLevelContext.cs | 22 +++++++++++++++++++ Models/AccessLevel.cs | 14 ++++++++++++ Scripts/Migrations/Linux/AddUpdate.sh | 4 ++++ 3 files changed, 40 insertions(+) create mode 100644 Icarus/Database/Contexts/AccessLevelContext.cs create mode 100644 Models/AccessLevel.cs diff --git a/Icarus/Database/Contexts/AccessLevelContext.cs b/Icarus/Database/Contexts/AccessLevelContext.cs new file mode 100644 index 0000000..44412cd --- /dev/null +++ b/Icarus/Database/Contexts/AccessLevelContext.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore; + +using Icarus.Models; + +namespace Icarus.Database.Contexts; + + +public class AccessLevelContext : DbContext { + public DbSet AccessLevels { get; set; } + + public AccessLevelContext(string connString) : base(new DbContextOptionsBuilder() + .UseMySQL(connString).Options) + { + + } + + #region Methods + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + } + #endregion +} \ No newline at end of file diff --git a/Models/AccessLevel.cs b/Models/AccessLevel.cs new file mode 100644 index 0000000..0980895 --- /dev/null +++ b/Models/AccessLevel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace Icarus.Models; + +public class AccessLevel { + #region Properties + [Newtonsoft.Json.JsonProperty("id")] + public int Id { get; set; } + [Newtonsoft.Json.JsonProperty("level")] + public string Level { get; set; } + [Newtonsoft.Json.JsonProperty("song_id")] + public int SongId { get; set; } + #endregion +} \ No newline at end of file diff --git a/Scripts/Migrations/Linux/AddUpdate.sh b/Scripts/Migrations/Linux/AddUpdate.sh index ed4ba7b..6c8f01a 100755 --- a/Scripts/Migrations/Linux/AddUpdate.sh +++ b/Scripts/Migrations/Linux/AddUpdate.sh @@ -12,6 +12,8 @@ echo "Adding Cover art migration" dotnet dotnet-ef migrations add CoverArt --context CoverArtContext echo "Adding Song migration" dotnet dotnet-ef migrations add Song --context SongContext +echo "Adding AccessLevel migration" +dotnet dotnet-ef migrations add AccessLevel --context AccessLevelContext echo "Updating migrations.." echo "Updating User migration" @@ -26,4 +28,6 @@ echo "Updating Cover art migration" dotnet dotnet-ef database update --context CoverArtContext echo "Updating Song migration" dotnet dotnet-ef database update --context SongContext +echo "Updating AccessLevel migration" +dotnet dotnet-ef database update --context AccessLevelContext -- 2.47.3 From 40fa88fd0585ba48903270a5dda617bafd711118 Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 7 Mar 2025 21:57:08 -0500 Subject: [PATCH 02/14] Formatted code --- Icarus/Database/Contexts/AccessLevelContext.cs | 7 ++++--- Models/AccessLevel.cs | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Icarus/Database/Contexts/AccessLevelContext.cs b/Icarus/Database/Contexts/AccessLevelContext.cs index 44412cd..5249c2f 100644 --- a/Icarus/Database/Contexts/AccessLevelContext.cs +++ b/Icarus/Database/Contexts/AccessLevelContext.cs @@ -5,14 +5,15 @@ using Icarus.Models; namespace Icarus.Database.Contexts; -public class AccessLevelContext : DbContext { +public class AccessLevelContext : DbContext +{ public DbSet AccessLevels { get; set; } public AccessLevelContext(string connString) : base(new DbContextOptionsBuilder() .UseMySQL(connString).Options) - { + { - } + } #region Methods protected override void OnModelCreating(ModelBuilder modelBuilder) diff --git a/Models/AccessLevel.cs b/Models/AccessLevel.cs index 0980895..a69c5bd 100644 --- a/Models/AccessLevel.cs +++ b/Models/AccessLevel.cs @@ -2,7 +2,8 @@ using System.ComponentModel.DataAnnotations.Schema; namespace Icarus.Models; -public class AccessLevel { +public class AccessLevel +{ #region Properties [Newtonsoft.Json.JsonProperty("id")] public int Id { get; set; } -- 2.47.3 From 2e723a4bc06e0d37f80fc604c0ffb612a2beebcd Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 7 Mar 2025 22:11:43 -0500 Subject: [PATCH 03/14] AccessLevel migrations are working --- Icarus/Database/Contexts/AccessLevelContext.cs | 11 ++++++----- Icarus/Program.cs | 1 + Models/AccessLevel.cs | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Icarus/Database/Contexts/AccessLevelContext.cs b/Icarus/Database/Contexts/AccessLevelContext.cs index 5249c2f..7dd5567 100644 --- a/Icarus/Database/Contexts/AccessLevelContext.cs +++ b/Icarus/Database/Contexts/AccessLevelContext.cs @@ -1,14 +1,12 @@ using Microsoft.EntityFrameworkCore; -using Icarus.Models; - namespace Icarus.Database.Contexts; - public class AccessLevelContext : DbContext { - public DbSet AccessLevels { get; set; } + public DbSet? AccessLevels { get; set; } + public AccessLevelContext(DbContextOptions options) : base(options) { } public AccessLevelContext(string connString) : base(new DbContextOptionsBuilder() .UseMySQL(connString).Options) { @@ -18,6 +16,9 @@ public class AccessLevelContext : DbContext #region Methods protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity().ToTable("AccessLevel"); + + // modelBuilder.Entity().Property(m => m.Level).IsRequired(true); } #endregion -} \ No newline at end of file +} diff --git a/Icarus/Program.cs b/Icarus/Program.cs index 8a8377f..a9f313a 100644 --- a/Icarus/Program.cs +++ b/Icarus/Program.cs @@ -76,6 +76,7 @@ builder.Services.AddDbContext(options => options.UseMySQL(connStr builder.Services.AddDbContext(options => options.UseMySQL(connString!)); builder.Services.AddDbContext(options => options.UseMySQL(connString!)); builder.Services.AddDbContext(options => options.UseMySQL(connString!)); +builder.Services.AddDbContext(options => options.UseMySQL(connString!)); builder.Services.AddControllers() .AddNewtonsoftJson(); diff --git a/Models/AccessLevel.cs b/Models/AccessLevel.cs index a69c5bd..c85e928 100644 --- a/Models/AccessLevel.cs +++ b/Models/AccessLevel.cs @@ -8,7 +8,7 @@ public class AccessLevel [Newtonsoft.Json.JsonProperty("id")] public int Id { get; set; } [Newtonsoft.Json.JsonProperty("level")] - public string Level { get; set; } + public string? Level { get; set; } [Newtonsoft.Json.JsonProperty("song_id")] public int SongId { get; set; } #endregion -- 2.47.3 From 8054fd4d1e8a1691015a63c0cfe245ed81fbb310 Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 7 Mar 2025 22:12:55 -0500 Subject: [PATCH 04/14] minor formatting --- Icarus/Database/Contexts/AccessLevelContext.cs | 2 +- Models/AccessLevel.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Icarus/Database/Contexts/AccessLevelContext.cs b/Icarus/Database/Contexts/AccessLevelContext.cs index 7dd5567..fea0901 100644 --- a/Icarus/Database/Contexts/AccessLevelContext.cs +++ b/Icarus/Database/Contexts/AccessLevelContext.cs @@ -18,7 +18,7 @@ public class AccessLevelContext : DbContext { modelBuilder.Entity().ToTable("AccessLevel"); - // modelBuilder.Entity().Property(m => m.Level).IsRequired(true); + modelBuilder.Entity().Property(m => m.Level).IsRequired(true); } #endregion } diff --git a/Models/AccessLevel.cs b/Models/AccessLevel.cs index c85e928..645e50d 100644 --- a/Models/AccessLevel.cs +++ b/Models/AccessLevel.cs @@ -12,4 +12,4 @@ public class AccessLevel [Newtonsoft.Json.JsonProperty("song_id")] public int SongId { get; set; } #endregion -} \ No newline at end of file +} -- 2.47.3 From 4a4c021c4f0e831113cb1a3a0b75d23e2351f74c Mon Sep 17 00:00:00 2001 From: phoenix Date: Fri, 7 Mar 2025 22:41:31 -0500 Subject: [PATCH 05/14] tsk-#76: Saving AccessLevel when uploading song --- Icarus/Controllers/Managers/SongManager.cs | 26 +++++++++++++++------- Models/AccessLevel.cs | 18 +++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Icarus/Controllers/Managers/SongManager.cs b/Icarus/Controllers/Managers/SongManager.cs index 0f25270..db6c50e 100644 --- a/Icarus/Controllers/Managers/SongManager.cs +++ b/Icarus/Controllers/Managers/SongManager.cs @@ -165,7 +165,7 @@ public class SongManager : BaseManager } } - + public Song SaveFlacSongToFileSystem(IFormFile songFile, IFormFile coverArtData, Song song) { // Save temp song (Should already be saved to the filesystem by the time it gets to this method) @@ -345,10 +345,10 @@ public class SongManager : BaseManager { _logger.Info("Starting process to save the song to the database"); - var albumMgr = new AlbumManager(_config!); - var artistMgr = new ArtistManager(_config!); - var genreMgr = new GenreManager(_config!); - var coverMgr = new CoverArtManager(_config!); + var albumMgr = new AlbumManager(this._config!); + var artistMgr = new ArtistManager(this._config!); + var genreMgr = new GenreManager(this._config!); + var coverMgr = new CoverArtManager(this._config!); albumMgr.SaveAlbumToDatabase(ref song); artistMgr.SaveArtistToDatabase(ref song); genreMgr.SaveGenreToDatabase(ref song); @@ -356,10 +356,20 @@ public class SongManager : BaseManager var info = "Saving Song to DB"; _logger.Info(info); - _songContext!.Add(song); - _songContext!.SaveChanges(); + this._songContext!.Add(song); + this._songContext!.SaveChanges(); - coverMgr.SaveCoverArtToDatabase(ref song, ref cover!); + if (cover != null) + { + coverMgr.SaveCoverArtToDatabase(ref song, ref cover!); + } + + var accessLevel = Icarus.Models.AccessLevel.DefaultLevel(); + accessLevel.SongId = song.Id; + + var accessLevelContext = new AccessLevelContext(this._connectionString!); + accessLevelContext.Add(accessLevel); + accessLevelContext.SaveChanges(); } diff --git a/Models/AccessLevel.cs b/Models/AccessLevel.cs index 645e50d..0f0f4f8 100644 --- a/Models/AccessLevel.cs +++ b/Models/AccessLevel.cs @@ -12,4 +12,22 @@ public class AccessLevel [Newtonsoft.Json.JsonProperty("song_id")] public int SongId { get; set; } #endregion + + #region Methods + public static AccessLevel DefaultLevel() + { + return new AccessLevel + { + Level = "Public" + }; + } + + public static AccessLevel PrivateLevel() + { + return new AccessLevel + { + Level = "Private" + }; + } + #endregion } -- 2.47.3 From d9b942fbb3031f89683f264d7679ff3251add4fd Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 8 Mar 2025 16:24:11 -0500 Subject: [PATCH 06/14] tsk-#76: Added endpoints --- Icarus/Controllers/Managers/SongManager.cs | 5 + .../Controllers/v1/AccessLevelController.cs | 97 +++++++++++++++++++ Icarus/Controllers/v1/SongDataController.cs | 1 - 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 Icarus/Controllers/v1/AccessLevelController.cs diff --git a/Icarus/Controllers/Managers/SongManager.cs b/Icarus/Controllers/Managers/SongManager.cs index db6c50e..da81db3 100644 --- a/Icarus/Controllers/Managers/SongManager.cs +++ b/Icarus/Controllers/Managers/SongManager.cs @@ -157,6 +157,11 @@ public class SongManager : BaseManager DeleteSongFromDatabase(song); coverMgr.DeleteCoverArtFromDatabase(coverArt); + // var accessLevel = new AccessLevel{SongId = song.Id}; + var accessLevelContext = new AccessLevelContext(_config!.GetConnectionString("DefaultConnection")!); + var accessLevel = accessLevelContext.AccessLevels.FirstOrDefault(al => al.SongId == song.Id); + accessLevelContext.AccessLevels.Remove(accessLevel!); + accessLevelContext.SaveChanges(); } catch (Exception ex) { diff --git a/Icarus/Controllers/v1/AccessLevelController.cs b/Icarus/Controllers/v1/AccessLevelController.cs new file mode 100644 index 0000000..40b7fb8 --- /dev/null +++ b/Icarus/Controllers/v1/AccessLevelController.cs @@ -0,0 +1,97 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +// using I +// using Icarus.Database.Contexts; + +namespace Icarus.Controllers.V1; + +[Route("api/v1/accesslevel")] +[ApiController] +[Authorize] +public class AccessLevelController : BaseController +{ + #region Fields + private readonly ILogger? _logger; + private string? _connectionString; + #endregion + + #region Properties + #endregion + + #region Constructors + public AccessLevelController(ILogger logger, IConfiguration config) + { + this._logger = logger; + this._config = config; + _connectionString = this._config.GetConnectionString("DefaultConnection"); + } + #endregion + + #region HTTP Routes + [HttpGet] + public IActionResult GetAccessLevels([FromBody] Icarus.Models.AccessLevel accessLevel) + { + // var id = 0; + // var songId = 0; + var accLevel = new Icarus.Models.AccessLevel { Id = 0 }; + var accessLevelContext = new Icarus.Database.Contexts.AccessLevelContext(_connectionString!); + + if (accessLevel.Id != 0) + { + var id = accessLevel.Id; + accLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.Id == id); + } + else if (accessLevel.SongId != 0) + { + var songId = accessLevel.SongId; + accLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.SongId == songId); + } + + var response = new GetAccessLevelsResponse(); + var subject = ""; + + if (accLevel?.Id > 0) + { + subject = "Successful"; + response.Data = new List(); + response.Data.Add(accLevel); + } + else + { + subject = "Failure"; + } + + response.Subject = subject; + + return Ok(response); + } + + public IActionResult UpdateAccessLevel() + { + return Ok(new UpdateAccessLevelResponse()); + } + #endregion +} + +#region Responses +public class GetAccessLevelsResponse +{ + #region Properties + [Newtonsoft.Json.JsonProperty("subject")] + public string? Subject { get; set; } + [Newtonsoft.Json.JsonProperty("data")] + public List? Data { get; set; } + #endregion +} + +public class UpdateAccessLevelResponse +{ + #region Properties + [Newtonsoft.Json.JsonProperty("subject")] + public string? Subject { get; set; } + [Newtonsoft.Json.JsonProperty("data")] + public List? Data { get; set; } + #endregion +} +#endregion diff --git a/Icarus/Controllers/v1/SongDataController.cs b/Icarus/Controllers/v1/SongDataController.cs index 7626853..b929886 100644 --- a/Icarus/Controllers/v1/SongDataController.cs +++ b/Icarus/Controllers/v1/SongDataController.cs @@ -179,7 +179,6 @@ public class SongDataController : BaseController return Ok(songMetaData); } - } public class UploadSongWithDataForm -- 2.47.3 From 86864bcd8f6021b29f206e86416cd71d73bf5c99 Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 8 Mar 2025 16:28:39 -0500 Subject: [PATCH 07/14] tsk-#76: Warning fix --- Icarus/Controllers/Managers/SongManager.cs | 5 ++--- Icarus/Controllers/v1/AccessLevelController.cs | 9 ++------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Icarus/Controllers/Managers/SongManager.cs b/Icarus/Controllers/Managers/SongManager.cs index da81db3..6e0dcd7 100644 --- a/Icarus/Controllers/Managers/SongManager.cs +++ b/Icarus/Controllers/Managers/SongManager.cs @@ -157,10 +157,9 @@ public class SongManager : BaseManager DeleteSongFromDatabase(song); coverMgr.DeleteCoverArtFromDatabase(coverArt); - // var accessLevel = new AccessLevel{SongId = song.Id}; var accessLevelContext = new AccessLevelContext(_config!.GetConnectionString("DefaultConnection")!); - var accessLevel = accessLevelContext.AccessLevels.FirstOrDefault(al => al.SongId == song.Id); - accessLevelContext.AccessLevels.Remove(accessLevel!); + var accessLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.SongId == song.Id); + accessLevelContext.AccessLevels!.Remove(accessLevel!); accessLevelContext.SaveChanges(); } catch (Exception ex) diff --git a/Icarus/Controllers/v1/AccessLevelController.cs b/Icarus/Controllers/v1/AccessLevelController.cs index 40b7fb8..ded6acf 100644 --- a/Icarus/Controllers/v1/AccessLevelController.cs +++ b/Icarus/Controllers/v1/AccessLevelController.cs @@ -32,8 +32,6 @@ public class AccessLevelController : BaseController [HttpGet] public IActionResult GetAccessLevels([FromBody] Icarus.Models.AccessLevel accessLevel) { - // var id = 0; - // var songId = 0; var accLevel = new Icarus.Models.AccessLevel { Id = 0 }; var accessLevelContext = new Icarus.Database.Contexts.AccessLevelContext(_connectionString!); @@ -49,21 +47,18 @@ public class AccessLevelController : BaseController } var response = new GetAccessLevelsResponse(); - var subject = ""; if (accLevel?.Id > 0) { - subject = "Successful"; + response.Subject = "Successful"; response.Data = new List(); response.Data.Add(accLevel); } else { - subject = "Failure"; + response.Subject = "Failure"; } - response.Subject = subject; - return Ok(response); } -- 2.47.3 From 5d82051ab39581da5d74d333684fef1b08caae4c Mon Sep 17 00:00:00 2001 From: phoenix Date: Sat, 8 Mar 2025 16:47:36 -0500 Subject: [PATCH 08/14] tsk-#76: Adding more controller code --- Icarus/Controllers/v1/AccessLevelController.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Icarus/Controllers/v1/AccessLevelController.cs b/Icarus/Controllers/v1/AccessLevelController.cs index ded6acf..01523d2 100644 --- a/Icarus/Controllers/v1/AccessLevelController.cs +++ b/Icarus/Controllers/v1/AccessLevelController.cs @@ -1,9 +1,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -// using I -// using Icarus.Database.Contexts; - namespace Icarus.Controllers.V1; [Route("api/v1/accesslevel")] @@ -53,18 +50,22 @@ public class AccessLevelController : BaseController response.Subject = "Successful"; response.Data = new List(); response.Data.Add(accLevel); + return Ok(response); } else { response.Subject = "Failure"; + return BadRequest(response); } - - return Ok(response); } - public IActionResult UpdateAccessLevel() + [HttpPatch("{id}")] + public IActionResult UpdateAccessLevel(int id, [FromBody] Icarus.Models.AccessLevel accessLevel) { - return Ok(new UpdateAccessLevelResponse()); + var response = new UpdateAccessLevelResponse(); + var accessLevelContext = new Icarus.Database.Contexts.AccessLevelContext(this._connectionString!); + + return Ok(response); } #endregion } -- 2.47.3 From f9162fc69cb11742c43613ddcb9b4b05529a8169 Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 10 Mar 2025 19:56:33 -0400 Subject: [PATCH 09/14] Functionality to modify access levels is operational --- Icarus/Controllers/Managers/TokenManager.cs | 27 ++++++++-- .../Controllers/v1/AccessLevelController.cs | 52 +++++++++++++++---- Icarus/Controllers/v1/SongDataController.cs | 4 +- Models/AccessLevel.cs | 14 +++++ 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/Icarus/Controllers/Managers/TokenManager.cs b/Icarus/Controllers/Managers/TokenManager.cs index dfa1f2e..ef6e0f2 100644 --- a/Icarus/Controllers/Managers/TokenManager.cs +++ b/Icarus/Controllers/Managers/TokenManager.cs @@ -121,7 +121,23 @@ public class TokenManager : BaseManager }; } - public int RetrieveUserIdFromToken(string token) + // TODO: Make this call to whenver media is being accessed or modified - cover art, genre, + // album, song, et cetera + public bool CanAccessSong(string token, Song song, AccessLevel accessLevel) + { + if (accessLevel!.Level!.Equals(Models.AccessLevel.DefaultLevel().Level)) { + return true; + } + var tokenUserId = this.RetrieveUserIdFromToken(token); + if (tokenUserId == null) + { + return false; + } + + return tokenUserId.Value == song.UserId; + } + + public int? RetrieveUserIdFromToken(string token) { if (this.ContainsBearer(token)) { @@ -130,18 +146,19 @@ public class TokenManager : BaseManager var tokenHandler = new JwtSecurityTokenHandler(); var readTok = tokenHandler.ReadJwtToken(token); - var userId = -1; + // var userId = -1; foreach (var item in readTok.Payload) { if (item.Key == "user_id") { - userId = Convert.ToInt32(item.Value); - break; + // userId = + return Convert.ToInt32(item.Value); + // break; } } - return userId; + return null; } private string StripBearer(string token) diff --git a/Icarus/Controllers/v1/AccessLevelController.cs b/Icarus/Controllers/v1/AccessLevelController.cs index 01523d2..25bcb8d 100644 --- a/Icarus/Controllers/v1/AccessLevelController.cs +++ b/Icarus/Controllers/v1/AccessLevelController.cs @@ -27,28 +27,25 @@ public class AccessLevelController : BaseController #region HTTP Routes [HttpGet] - public IActionResult GetAccessLevels([FromBody] Icarus.Models.AccessLevel accessLevel) + public IActionResult GetAccessLevels(int? id, int? songId) { var accLevel = new Icarus.Models.AccessLevel { Id = 0 }; var accessLevelContext = new Icarus.Database.Contexts.AccessLevelContext(_connectionString!); - if (accessLevel.Id != 0) + if (id != null) { - var id = accessLevel.Id; accLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.Id == id); } - else if (accessLevel.SongId != 0) + else if (songId != null) { - var songId = accessLevel.SongId; accLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.SongId == songId); } - var response = new GetAccessLevelsResponse(); + var response = new GetAccessLevelsResponse{ Data = new List()}; if (accLevel?.Id > 0) { response.Subject = "Successful"; - response.Data = new List(); response.Data.Add(accLevel); return Ok(response); } @@ -60,12 +57,45 @@ public class AccessLevelController : BaseController } [HttpPatch("{id}")] - public IActionResult UpdateAccessLevel(int id, [FromBody] Icarus.Models.AccessLevel accessLevel) + public IActionResult UpdateAccessLevel(int id, [FromBody] Models.AccessLevel accessLevel) { - var response = new UpdateAccessLevelResponse(); - var accessLevelContext = new Icarus.Database.Contexts.AccessLevelContext(this._connectionString!); + var response = new UpdateAccessLevelResponse{ Data = new List()}; + var targetLevel = accessLevel.Level; + if (targetLevel == null) { + response.Subject = "No level provided"; + return BadRequest(response); + } else { + if (!Models.AccessLevel.IsAccessLevelValid(targetLevel)) { + response.Subject = "Invalid level"; + return BadRequest(response); + } + } - return Ok(response); + var accessLevelContext = new Database.Contexts.AccessLevelContext(this._connectionString!); + + var fetchedAccLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.Id == id); + + if (fetchedAccLevel == null) { + response.Subject = "Nothing found"; + return NotFound(response); + } + + var fetchedLevel = fetchedAccLevel!.Level; + + if (fetchedLevel!.Equals(targetLevel)) { + // No change + response.Subject = "No change"; + response.Data.Add(fetchedAccLevel); + return Ok(response); + } else { + fetchedAccLevel.Level = targetLevel; + response.Subject = "Successful"; + accessLevelContext.Update(fetchedAccLevel); + accessLevelContext.SaveChanges(); + + response.Data.Add(fetchedAccLevel); + return Ok(response); + } } #endregion } diff --git a/Icarus/Controllers/v1/SongDataController.cs b/Icarus/Controllers/v1/SongDataController.cs index b929886..9eb14af 100644 --- a/Icarus/Controllers/v1/SongDataController.cs +++ b/Icarus/Controllers/v1/SongDataController.cs @@ -116,9 +116,9 @@ public class SongDataController : BaseController var accessToken = Request.Headers["Authorization"]; var userId = tokMgr.RetrieveUserIdFromToken(accessToken!); - if (userId != -1) + if (userId != null) { - song!.UserId = userId; + song!.UserId = userId.Value; } _logger!.LogInformation($"Song title: {song!.Title}"); diff --git a/Models/AccessLevel.cs b/Models/AccessLevel.cs index 0f0f4f8..a734ae0 100644 --- a/Models/AccessLevel.cs +++ b/Models/AccessLevel.cs @@ -29,5 +29,19 @@ public class AccessLevel Level = "Private" }; } + +public static bool IsAccessLevelValid(string level) { + if (level.Equals(DefaultLevel().Level)) { + return true; + } + else if (level.Equals(PrivateLevel().Level)) { + return true; + } + else { + return false; + } +} #endregion } + + -- 2.47.3 From f2aeeb1af448b476584e9d920c34d3cada3af62a Mon Sep 17 00:00:00 2001 From: phoenix Date: Mon, 10 Mar 2025 19:57:20 -0400 Subject: [PATCH 10/14] Formatting --- Icarus/Controllers/Managers/TokenManager.cs | 3 +- .../Controllers/v1/AccessLevelController.cs | 34 ++++++++++++------- Models/AccessLevel.cs | 24 +++++++------ 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/Icarus/Controllers/Managers/TokenManager.cs b/Icarus/Controllers/Managers/TokenManager.cs index ef6e0f2..42cda59 100644 --- a/Icarus/Controllers/Managers/TokenManager.cs +++ b/Icarus/Controllers/Managers/TokenManager.cs @@ -125,7 +125,8 @@ public class TokenManager : BaseManager // album, song, et cetera public bool CanAccessSong(string token, Song song, AccessLevel accessLevel) { - if (accessLevel!.Level!.Equals(Models.AccessLevel.DefaultLevel().Level)) { + if (accessLevel!.Level!.Equals(Models.AccessLevel.DefaultLevel().Level)) + { return true; } var tokenUserId = this.RetrieveUserIdFromToken(token); diff --git a/Icarus/Controllers/v1/AccessLevelController.cs b/Icarus/Controllers/v1/AccessLevelController.cs index 25bcb8d..1209df8 100644 --- a/Icarus/Controllers/v1/AccessLevelController.cs +++ b/Icarus/Controllers/v1/AccessLevelController.cs @@ -27,7 +27,7 @@ public class AccessLevelController : BaseController #region HTTP Routes [HttpGet] - public IActionResult GetAccessLevels(int? id, int? songId) + public IActionResult GetAccessLevels(int? id, int? songId) { var accLevel = new Icarus.Models.AccessLevel { Id = 0 }; var accessLevelContext = new Icarus.Database.Contexts.AccessLevelContext(_connectionString!); @@ -41,7 +41,7 @@ public class AccessLevelController : BaseController accLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.SongId == songId); } - var response = new GetAccessLevelsResponse{ Data = new List()}; + var response = new GetAccessLevelsResponse { Data = new List() }; if (accLevel?.Id > 0) { @@ -59,13 +59,17 @@ public class AccessLevelController : BaseController [HttpPatch("{id}")] public IActionResult UpdateAccessLevel(int id, [FromBody] Models.AccessLevel accessLevel) { - var response = new UpdateAccessLevelResponse{ Data = new List()}; + var response = new UpdateAccessLevelResponse { Data = new List() }; var targetLevel = accessLevel.Level; - if (targetLevel == null) { + if (targetLevel == null) + { response.Subject = "No level provided"; return BadRequest(response); - } else { - if (!Models.AccessLevel.IsAccessLevelValid(targetLevel)) { + } + else + { + if (!Models.AccessLevel.IsAccessLevelValid(targetLevel)) + { response.Subject = "Invalid level"; return BadRequest(response); } @@ -73,21 +77,25 @@ public class AccessLevelController : BaseController var accessLevelContext = new Database.Contexts.AccessLevelContext(this._connectionString!); - var fetchedAccLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.Id == id); + var fetchedAccLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.Id == id); - if (fetchedAccLevel == null) { - response.Subject = "Nothing found"; - return NotFound(response); - } + if (fetchedAccLevel == null) + { + response.Subject = "Nothing found"; + return NotFound(response); + } var fetchedLevel = fetchedAccLevel!.Level; - if (fetchedLevel!.Equals(targetLevel)) { + if (fetchedLevel!.Equals(targetLevel)) + { // No change response.Subject = "No change"; response.Data.Add(fetchedAccLevel); return Ok(response); - } else { + } + else + { fetchedAccLevel.Level = targetLevel; response.Subject = "Successful"; accessLevelContext.Update(fetchedAccLevel); diff --git a/Models/AccessLevel.cs b/Models/AccessLevel.cs index a734ae0..d983b31 100644 --- a/Models/AccessLevel.cs +++ b/Models/AccessLevel.cs @@ -30,17 +30,21 @@ public class AccessLevel }; } -public static bool IsAccessLevelValid(string level) { - if (level.Equals(DefaultLevel().Level)) { - return true; - } - else if (level.Equals(PrivateLevel().Level)) { - return true; - } - else { - return false; + public static bool IsAccessLevelValid(string level) + { + if (level.Equals(DefaultLevel().Level)) + { + return true; + } + else if (level.Equals(PrivateLevel().Level)) + { + return true; + } + else + { + return false; + } } -} #endregion } -- 2.47.3 From eafaa5d9d2922431761e8eb72342bdeed5dc2920 Mon Sep 17 00:00:00 2001 From: phoenix Date: Tue, 11 Mar 2025 20:02:14 -0400 Subject: [PATCH 11/14] tsk-#76: Added functionality --- Icarus/Controllers/Managers/TokenManager.cs | 20 ++++++++++++------- Icarus/Controllers/v1/SongDataController.cs | 15 +++++++++++++- .../Database/Contexts/AccessLevelContext.cs | 19 ++++++++++++++---- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/Icarus/Controllers/Managers/TokenManager.cs b/Icarus/Controllers/Managers/TokenManager.cs index 42cda59..4eb02fa 100644 --- a/Icarus/Controllers/Managers/TokenManager.cs +++ b/Icarus/Controllers/Managers/TokenManager.cs @@ -138,24 +138,30 @@ public class TokenManager : BaseManager return tokenUserId.Value == song.UserId; } - public int? RetrieveUserIdFromToken(string token) + public string? GetBearerToken(HttpContext context) { - if (this.ContainsBearer(token)) + string authorizationHeader = context.Request.Headers["Authorization"]!; + + if (!authorizationHeader.IsNullOrEmpty() && authorizationHeader.StartsWith("Bearer", StringComparison.OrdinalIgnoreCase)) { - token = this.StripBearer(token); + string token = authorizationHeader.Substring("Bearer ".Length).Trim(); + return token; } + return null; + } + + public int? RetrieveUserIdFromToken(string token) + { + var parsedToken = this.ContainsBearer(token) ? this.StripBearer(token) : token; var tokenHandler = new JwtSecurityTokenHandler(); - var readTok = tokenHandler.ReadJwtToken(token); - // var userId = -1; + var readTok = tokenHandler.ReadJwtToken(parsedToken); foreach (var item in readTok.Payload) { if (item.Key == "user_id") { - // userId = return Convert.ToInt32(item.Value); - // break; } } diff --git a/Icarus/Controllers/v1/SongDataController.cs b/Icarus/Controllers/v1/SongDataController.cs index 9eb14af..0876ef7 100644 --- a/Icarus/Controllers/v1/SongDataController.cs +++ b/Icarus/Controllers/v1/SongDataController.cs @@ -38,11 +38,23 @@ public class SongDataController : BaseController #endregion + [HttpGet("download/{id}")] public IActionResult Download(int id, [FromQuery] bool? randomizeFilename) { - var songContext = new SongContext(_connectionString!); + var tokenManager = new TokenManager(this._config!); + var songContext = new SongContext(this._connectionString!); + var accLvlContext = new AccessLevelContext(this._connectionString!); var songMetaData = songContext.RetrieveRecord(new Song { Id = id }); + var accessLevel = accLvlContext.GetAccessLevel(songMetaData.Id); + var token = tokenManager.GetBearerToken(HttpContext); + if (token == null || accessLevel == null) { + return BadRequest(); + } + + if (!tokenManager.CanAccessSong(token, songMetaData, accessLevel)) { + return BadRequest(); + } var song = _songMgr!.RetrieveSong(songMetaData).Result; string filename; @@ -66,6 +78,7 @@ public class SongDataController : BaseController return File(song.Data!, "application/x-msdownload", filename); } + // NOTE: No longer being used // Assumes that the song already has metadata such as // Title // Artist diff --git a/Icarus/Database/Contexts/AccessLevelContext.cs b/Icarus/Database/Contexts/AccessLevelContext.cs index fea0901..78edbbc 100644 --- a/Icarus/Database/Contexts/AccessLevelContext.cs +++ b/Icarus/Database/Contexts/AccessLevelContext.cs @@ -4,21 +4,32 @@ namespace Icarus.Database.Contexts; public class AccessLevelContext : DbContext { - public DbSet? AccessLevels { get; set; } + #region Properties + public DbSet? AccessLevels { get; set; } + #endregion + #region Constructors public AccessLevelContext(DbContextOptions options) : base(options) { } public AccessLevelContext(string connString) : base(new DbContextOptionsBuilder() .UseMySQL(connString).Options) { - + if (this.AccessLevels == null) + { + } } + #endregion #region Methods + public Models.AccessLevel? GetAccessLevel(int songId) { + var accessLevel = this.AccessLevels!.FirstOrDefault(acc => acc.SongId == songId); + return accessLevel; + } + protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity().ToTable("AccessLevel"); + modelBuilder.Entity().ToTable("AccessLevel"); - modelBuilder.Entity().Property(m => m.Level).IsRequired(true); + modelBuilder.Entity().Property(m => m.Level).IsRequired(true); } #endregion } -- 2.47.3 From bccb0f649194a9b9f25b404fd8b3cbfc12469ed4 Mon Sep 17 00:00:00 2001 From: phoenix Date: Tue, 11 Mar 2025 20:03:15 -0400 Subject: [PATCH 12/14] tsk-#76: Formatting code --- Icarus/Controllers/Managers/TokenManager.cs | 2 +- Icarus/Controllers/v1/SongDataController.cs | 6 ++++-- Icarus/Database/Contexts/AccessLevelContext.cs | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Icarus/Controllers/Managers/TokenManager.cs b/Icarus/Controllers/Managers/TokenManager.cs index 4eb02fa..8a48157 100644 --- a/Icarus/Controllers/Managers/TokenManager.cs +++ b/Icarus/Controllers/Managers/TokenManager.cs @@ -153,7 +153,7 @@ public class TokenManager : BaseManager public int? RetrieveUserIdFromToken(string token) { - var parsedToken = this.ContainsBearer(token) ? this.StripBearer(token) : token; + var parsedToken = this.ContainsBearer(token) ? this.StripBearer(token) : token; var tokenHandler = new JwtSecurityTokenHandler(); var readTok = tokenHandler.ReadJwtToken(parsedToken); diff --git a/Icarus/Controllers/v1/SongDataController.cs b/Icarus/Controllers/v1/SongDataController.cs index 0876ef7..15dff68 100644 --- a/Icarus/Controllers/v1/SongDataController.cs +++ b/Icarus/Controllers/v1/SongDataController.cs @@ -48,11 +48,13 @@ public class SongDataController : BaseController var songMetaData = songContext.RetrieveRecord(new Song { Id = id }); var accessLevel = accLvlContext.GetAccessLevel(songMetaData.Id); var token = tokenManager.GetBearerToken(HttpContext); - if (token == null || accessLevel == null) { + if (token == null || accessLevel == null) + { return BadRequest(); } - if (!tokenManager.CanAccessSong(token, songMetaData, accessLevel)) { + if (!tokenManager.CanAccessSong(token, songMetaData, accessLevel)) + { return BadRequest(); } diff --git a/Icarus/Database/Contexts/AccessLevelContext.cs b/Icarus/Database/Contexts/AccessLevelContext.cs index 78edbbc..ac8a5ea 100644 --- a/Icarus/Database/Contexts/AccessLevelContext.cs +++ b/Icarus/Database/Contexts/AccessLevelContext.cs @@ -20,7 +20,8 @@ public class AccessLevelContext : DbContext #endregion #region Methods - public Models.AccessLevel? GetAccessLevel(int songId) { + public Models.AccessLevel? GetAccessLevel(int songId) + { var accessLevel = this.AccessLevels!.FirstOrDefault(acc => acc.SongId == songId); return accessLevel; } -- 2.47.3 From 0677a4ddbccb91e38f39c0872ffec460c686eb30 Mon Sep 17 00:00:00 2001 From: phoenix Date: Tue, 11 Mar 2025 21:41:44 -0400 Subject: [PATCH 13/14] tsk-#76: Adding more code --- Icarus/Controllers/Managers/TokenManager.cs | 2 -- .../Controllers/v1/AccessLevelController.cs | 12 +++++----- .../v1/SongCompressedDataControllers.cs | 14 ++++++++++++ Icarus/Controllers/v1/SongController.cs | 14 ++++++++++++ Icarus/Controllers/v1/SongDataController.cs | 16 +++++++++++--- Icarus/Controllers/v1/SongStreamController.cs | 22 +++++++++++++++++-- 6 files changed, 67 insertions(+), 13 deletions(-) diff --git a/Icarus/Controllers/Managers/TokenManager.cs b/Icarus/Controllers/Managers/TokenManager.cs index 8a48157..bbb79e7 100644 --- a/Icarus/Controllers/Managers/TokenManager.cs +++ b/Icarus/Controllers/Managers/TokenManager.cs @@ -121,8 +121,6 @@ public class TokenManager : BaseManager }; } - // TODO: Make this call to whenver media is being accessed or modified - cover art, genre, - // album, song, et cetera public bool CanAccessSong(string token, Song song, AccessLevel accessLevel) { if (accessLevel!.Level!.Equals(Models.AccessLevel.DefaultLevel().Level)) diff --git a/Icarus/Controllers/v1/AccessLevelController.cs b/Icarus/Controllers/v1/AccessLevelController.cs index 1209df8..1d74488 100644 --- a/Icarus/Controllers/v1/AccessLevelController.cs +++ b/Icarus/Controllers/v1/AccessLevelController.cs @@ -21,7 +21,7 @@ public class AccessLevelController : BaseController { this._logger = logger; this._config = config; - _connectionString = this._config.GetConnectionString("DefaultConnection"); + this._connectionString = this._config.GetConnectionString("DefaultConnection"); } #endregion @@ -29,8 +29,8 @@ public class AccessLevelController : BaseController [HttpGet] public IActionResult GetAccessLevels(int? id, int? songId) { - var accLevel = new Icarus.Models.AccessLevel { Id = 0 }; - var accessLevelContext = new Icarus.Database.Contexts.AccessLevelContext(_connectionString!); + var accLevel = new Models.AccessLevel { Id = 0 }; + var accessLevelContext = new Database.Contexts.AccessLevelContext(_connectionString!); if (id != null) { @@ -38,7 +38,7 @@ public class AccessLevelController : BaseController } else if (songId != null) { - accLevel = accessLevelContext.AccessLevels!.FirstOrDefault(al => al.SongId == songId); + accLevel = accessLevelContext.GetAccessLevel(songId.Value); } var response = new GetAccessLevelsResponse { Data = new List() }; @@ -115,7 +115,7 @@ public class GetAccessLevelsResponse [Newtonsoft.Json.JsonProperty("subject")] public string? Subject { get; set; } [Newtonsoft.Json.JsonProperty("data")] - public List? Data { get; set; } + public List? Data { get; set; } #endregion } @@ -125,7 +125,7 @@ public class UpdateAccessLevelResponse [Newtonsoft.Json.JsonProperty("subject")] public string? Subject { get; set; } [Newtonsoft.Json.JsonProperty("data")] - public List? Data { get; set; } + public List? Data { get; set; } #endregion } #endregion diff --git a/Icarus/Controllers/v1/SongCompressedDataControllers.cs b/Icarus/Controllers/v1/SongCompressedDataControllers.cs index 57dd630..d82864b 100644 --- a/Icarus/Controllers/v1/SongCompressedDataControllers.cs +++ b/Icarus/Controllers/v1/SongCompressedDataControllers.cs @@ -47,6 +47,20 @@ public class SongCompressedDataController : BaseController Console.WriteLine("Starting process of retrieving comrpessed song"); var sng = context.RetrieveRecord(new Song { Id = id }); + + var tokenManager = new TokenManager(this._config!); + var accLvlContext = new AccessLevelContext(this._connectionString!); + var accessLevel = accLvlContext.GetAccessLevel(sng.Id); + var token = tokenManager.GetBearerToken(HttpContext); + if (token == null || accessLevel == null) + { + return BadRequest(); + } + + if (!tokenManager.CanAccessSong(token, sng, accessLevel)) + { + return BadRequest(); + } SongData song = await cmp.RetrieveCompressedSong(sng); var filename = DirectoryManager.GenerateDownloadFilename(10, Constants.FileExtensions.ZIP_EXTENSION, sng.Title!, randomizeFilename); diff --git a/Icarus/Controllers/v1/SongController.cs b/Icarus/Controllers/v1/SongController.cs index 6011260..f59a0c9 100644 --- a/Icarus/Controllers/v1/SongController.cs +++ b/Icarus/Controllers/v1/SongController.cs @@ -86,6 +86,20 @@ public class SongController : BaseController }); } + var tokenManager = new TokenManager(this._config!); + var accLvlContext = new AccessLevelContext(this._connectionString!); + var accessLevel = accLvlContext.GetAccessLevel(song.Id); + var token = tokenManager.GetBearerToken(HttpContext); + if (token == null || accessLevel == null) + { + return BadRequest(); + } + + if (!tokenManager.CanAccessSong(token, song, accessLevel)) + { + return BadRequest(); + } + var songRes = _songMgr.UpdateSong(song); return Ok(songRes); diff --git a/Icarus/Controllers/v1/SongDataController.cs b/Icarus/Controllers/v1/SongDataController.cs index 15dff68..4cbd4b4 100644 --- a/Icarus/Controllers/v1/SongDataController.cs +++ b/Icarus/Controllers/v1/SongDataController.cs @@ -175,11 +175,21 @@ public class SongDataController : BaseController public IActionResult DeleteSong(int id) { var songContext = new SongContext(_connectionString!); + var songMetaData = songContext.RetrieveRecord(new Song { Id = id }); - var songMetaData = new Song { Id = id }; - Console.WriteLine($"Id {songMetaData.Id}"); + var tokenManager = new TokenManager(this._config!); + var accLvlContext = new AccessLevelContext(this._connectionString!); + var accessLevel = accLvlContext.GetAccessLevel(songMetaData.Id); + var token = tokenManager.GetBearerToken(HttpContext); + if (token == null || accessLevel == null) + { + return BadRequest(); + } - songMetaData = songContext.RetrieveRecord(songMetaData); + if (!tokenManager.CanAccessSong(token, songMetaData, accessLevel)) + { + return BadRequest(); + } if (string.IsNullOrEmpty(songMetaData.Title)) { diff --git a/Icarus/Controllers/v1/SongStreamController.cs b/Icarus/Controllers/v1/SongStreamController.cs index 7a347bb..af8fcec 100644 --- a/Icarus/Controllers/v1/SongStreamController.cs +++ b/Icarus/Controllers/v1/SongStreamController.cs @@ -11,6 +11,7 @@ namespace Icarus.Controllers.V1; public class SongStreamController : BaseController { #region Fields + private string? _connectionString; private ILogger? _logger; #endregion @@ -22,8 +23,9 @@ public class SongStreamController : BaseController #region Constructor public SongStreamController(ILogger logger, IConfiguration config) { - _logger = logger; - _config = config; + this._logger = logger; + this._config = config; + this._connectionString = this._config.GetConnectionString("DefaultConnection"); } #endregion @@ -35,6 +37,22 @@ public class SongStreamController : BaseController var context = new SongContext(_config!.GetConnectionString("DefaultConnection")!); var song = context.Songs!.FirstOrDefault(sng => sng.Id == id); + if (song == null) { + return BadRequest(); + } + var tokenManager = new Managers.TokenManager(this._config!); + var accLvlContext = new AccessLevelContext(this._connectionString!); + var accessLevel = accLvlContext.GetAccessLevel(song.Id); + var token = tokenManager.GetBearerToken(HttpContext); + if (token == null || accessLevel == null) + { + return BadRequest(); + } + + if (!tokenManager.CanAccessSong(token, song, accessLevel)) + { + return BadRequest(); + } var stream = new FileStream(song!.SongPath(), FileMode.Open, FileAccess.Read); stream.Position = 0; -- 2.47.3 From 6f1e918f2f6a9b8e43f8b603309b88f51fa263e6 Mon Sep 17 00:00:00 2001 From: phoenix Date: Tue, 11 Mar 2025 21:42:25 -0400 Subject: [PATCH 14/14] tsk-#76: Formatting --- Icarus/Controllers/v1/SongStreamController.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Icarus/Controllers/v1/SongStreamController.cs b/Icarus/Controllers/v1/SongStreamController.cs index af8fcec..f38a966 100644 --- a/Icarus/Controllers/v1/SongStreamController.cs +++ b/Icarus/Controllers/v1/SongStreamController.cs @@ -37,7 +37,8 @@ public class SongStreamController : BaseController var context = new SongContext(_config!.GetConnectionString("DefaultConnection")!); var song = context.Songs!.FirstOrDefault(sng => sng.Id == id); - if (song == null) { + if (song == null) + { return BadRequest(); } var tokenManager = new Managers.TokenManager(this._config!); -- 2.47.3