diff --git a/Controllers/LoginController.cs b/Controllers/LoginController.cs index 65c013f..79da1ec 100644 --- a/Controllers/LoginController.cs +++ b/Controllers/LoginController.cs @@ -38,6 +38,12 @@ namespace Icarus.Controllers #region HTTP endpoints public IActionResult Post([FromBody] User user) { + UserStoreContext context = HttpContext + .RequestServices + .GetService(typeof(UserStoreContext)) + as UserStoreContext; + + user = context.RetrieveUser(user); Console.WriteLine($"Username: {user.Username}"); TokenManager tk = new TokenManager(_config); diff --git a/Controllers/Managers/TokenManager.cs b/Controllers/Managers/TokenManager.cs index 871004d..1cb517e 100644 --- a/Controllers/Managers/TokenManager.cs +++ b/Controllers/Managers/TokenManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; using RestSharp; using Icarus.Models; @@ -13,6 +14,11 @@ namespace Icarus.Controllers.Managers { #region Fields private IConfiguration _config; + private string _clientId; + private string _clientSecret; + private string _audience; + private string _grantType; + private string _url; #endregion @@ -32,22 +38,84 @@ namespace Icarus.Controllers.Managers #region Methods public LoginResult RetrieveLoginResult(User user) { - // TODO: Request a token from Auth0 + var client = new RestClient(_url); + var request = new RestRequest("oauth/token", Method.POST); + var tokenRequest = RetrieveTokenRequest(); + var tokenObject = JsonConvert.SerializeObject(tokenRequest); + request.AddParameter("application/json; charset=utf-8", + tokenObject, ParameterType.RequestBody); + request.RequestFormat = DataFormat.Json; + + IRestResponse response = client.Execute(request); + + + var tokenResult = JsonConvert + .DeserializeObject(response.Content); return new LoginResult { - UserId = 0, + UserId = user.Id, Username = user.Username, - Token = "gggg", - Expiration = 500 + Token = tokenResult.AccessToken, + TokenType = tokenResult.TokenType, + Expiration = tokenResult.Expiration + }; + } + + private TokenRequest RetrieveTokenRequest() + { + return new TokenRequest + { + ClientId = _clientId, + ClientSecret = _clientSecret, + Audience = _audience, + GrantType = _grantType }; } private void InitializeValues() { - // TODO: implement parse values necessary to - // retrieve a token from the appSettings using - // the _config object + _clientId = _config["Auth0:ClientId"]; + _clientSecret = _config["Auth0:ClientSecret"]; + _audience = _config["Auth0:ApiIdentifier"]; + _grantType = "client_credentials"; + _url = $"https://{_config["Auth0:Domain"]}"; + + //PrintCredentials(); + } + + // For testing purposes + private void PrintCredentials() + { + Console.WriteLine("Auth0 credentials:"); + Console.WriteLine($"Client Id: {_clientId}"); + Console.WriteLine($"Client Secret: {_clientSecret}"); + Console.WriteLine($"Audience: {_audience}"); + Console.WriteLine($"Url: {_url}"); + } + #endregion + + + #region Classes + private class TokenRequest + { + [JsonProperty("client_id")] + public string ClientId { get; set; } + [JsonProperty("client_secret")] + public string ClientSecret { get; set; } + [JsonProperty("audience")] + public string Audience { get; set; } + [JsonProperty("grant_type")] + public string GrantType { get; set; } + } + private class Token + { + [JsonProperty("access_token")] + public string AccessToken { get; set; } + [JsonProperty("expires_in")] + public int Expiration { get; set; } + [JsonProperty("token_type")] + public string TokenType { get; set; } } #endregion } diff --git a/Controllers/SongController.cs b/Controllers/SongController.cs index a51ec33..96f754c 100644 --- a/Controllers/SongController.cs +++ b/Controllers/SongController.cs @@ -4,6 +4,7 @@ using System.Configuration; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; @@ -13,81 +14,85 @@ using Icarus.Models.Context; namespace Icarus.Controllers { - [Route("api/Song")] + [Route("api/song")] [ApiController] public class SongController : ControllerBase { - #region Fields - private IConfiguration _config; - private MusicStoreContext _context; - private SongManager _songMgr; - #endregion + #region Fields + private IConfiguration _config; + private MusicStoreContext _context; + private SongManager _songMgr; + #endregion - #region Properties - #endregion + #region Properties + #endregion - #region Constructor - public SongController(IConfiguration config) - { - _config = config; - _songMgr = new SongManager(config); - } - #endregion + #region Constructor + public SongController(IConfiguration config) + { + _config = config; + _songMgr = new SongManager(config); + } + #endregion [HttpGet] + [Authorize("read:song_details")] public ActionResult> Get() { - List songs = new List(); - //songs = _songMgr.RetrieveAllSongDetails().Result; - Console.WriteLine("Attemtping to retrieve songs"); + List songs = new List(); + Console.WriteLine("Attemtping to retrieve songs"); + + MusicStoreContext context = HttpContext + .RequestServices + .GetService(typeof(MusicStoreContext)) + as MusicStoreContext; - MusicStoreContext context = HttpContext.RequestServices - .GetService(typeof(MusicStoreContext)) - as MusicStoreContext; + songs = context.GetAllSongs(); - songs = context.GetAllSongs(); - - - return songs; + return songs; } - [HttpGet("{id}")] - public ActionResult Get(int id) - { - MusicStoreContext context = HttpContext.RequestServices - .GetService(typeof(MusicStoreContext)) - as MusicStoreContext; - Song song = context.GetSong(id); + [HttpGet("{id}")] + public ActionResult Get(int id) + { + MusicStoreContext context = HttpContext + .RequestServices + .GetService(typeof(MusicStoreContext)) + as MusicStoreContext; + + Song song = context.GetSong(id); + + return song; + } - return song; - } - - [HttpPost] - public void Post([FromBody] Song song) - { - MusicStoreContext context = HttpContext.RequestServices - .GetService(typeof(MusicStoreContext)) - as MusicStoreContext; - - context.SaveSong(song); - } + [HttpPost] + public void Post([FromBody] Song song) + { + MusicStoreContext context = HttpContext + .RequestServices + .GetService(typeof(MusicStoreContext)) + as MusicStoreContext; + + context.SaveSong(song); + } [HttpPut("{id}")] public void Put(int id, [FromBody] Song song) { } - [HttpDelete("{id}")] - public void Delete(int id) - { - MusicStoreContext context = HttpContext.RequestServices - .GetService(typeof(MusicStoreContext)) - as MusicStoreContext; - - context.DeleteSong(id); + [HttpDelete("{id}")] + public void Delete(int id) + { + MusicStoreContext context = HttpContext + .RequestServices + .GetService(typeof(MusicStoreContext)) + as MusicStoreContext; + + context.DeleteSong(id); } } } diff --git a/Controllers/SongDataController.cs b/Controllers/SongDataController.cs index 2184a96..c6e3041 100644 --- a/Controllers/SongDataController.cs +++ b/Controllers/SongDataController.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; @@ -21,68 +22,71 @@ namespace Icarus.Controllers { #region Fields private IConfiguration _config; - private SongManager _songMgr; - private string _songTempDir; - #endregion + private SongManager _songMgr; + private string _songTempDir; + #endregion - #region Properties - #endregion + #region Properties + #endregion - #region Constructor - public SongDataController(IConfiguration config) - { - _config = config; - _songTempDir = _config.GetValue("TemporaryMusicPath"); - _songMgr = new SongManager(config, _songTempDir); - } - #endregion + #region Constructor + public SongDataController(IConfiguration config) + { + _config = config; + _songTempDir = _config.GetValue("TemporaryMusicPath"); + _songMgr = new SongManager(config, _songTempDir); + } + #endregion [HttpGet("{id}")] - //[Route("private-scoped")] - //[Authorize("download:songs")] + [Route("private-scoped")] + [Authorize("download:songs")] public async Task Get(int id) { - MusicStoreContext context = HttpContext.RequestServices - .GetService(typeof(MusicStoreContext)) - as MusicStoreContext; - var songMetaData = context.GetSong(id); - - SongData song = await _songMgr.RetrieveSong(songMetaData); - - return File(song.Data, "application/x-msdownload", songMetaData.Filename); - } + MusicStoreContext context = HttpContext + .RequestServices + .GetService(typeof(MusicStoreContext)) + as MusicStoreContext; + var songMetaData = context.GetSong(id); + + SongData song = await _songMgr.RetrieveSong(songMetaData); + + return File(song.Data, "application/x-msdownload", songMetaData.Filename); + } [HttpPost] + [Authorize("upload:songs")] public async Task Post([FromForm(Name = "file")] List songData) { - try - { - MusicStoreContext context = HttpContext.RequestServices - .GetService(typeof(MusicStoreContext)) - as MusicStoreContext; + try + { + MusicStoreContext context = HttpContext + .RequestServices + .GetService(typeof(MusicStoreContext)) + as MusicStoreContext; - Console.WriteLine("Uploading song..."); + Console.WriteLine("Uploading song..."); - var uploads = _songTempDir; - Console.WriteLine($"Song Root Path {uploads}"); - foreach (var sng in songData) - { - if (sng.Length > 0) { - await _songMgr.SaveSongToFileSystem(sng); - var song = _songMgr.SongDetails; - context.SaveSong(song); - Console.WriteLine("Song successfully saved"); - } + var uploads = _songTempDir; + Console.WriteLine($"Song Root Path {uploads}"); + foreach (var sng in songData) + { + if (sng.Length > 0) { + await _songMgr.SaveSongToFileSystem(sng); + var song = _songMgr.SongDetails; + context.SaveSong(song); + Console.WriteLine("Song successfully saved"); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } } - } - catch (Exception ex) - { - Console.WriteLine($"An error occurred: {ex.Message}"); - } - } [HttpPut("{id}")] public void Put(int id, [FromBody] SongData song) @@ -90,20 +94,22 @@ namespace Icarus.Controllers } [HttpDelete("{id}")] + [Authorize("delete:songs")] public void Delete(int id) { - MusicStoreContext context = HttpContext.RequestServices - .GetService(typeof(MusicStoreContext)) - as MusicStoreContext; - - var songMetaData = context.GetSong(id); - - var result = _songMgr.DeleteSongFromFileSystem(songMetaData); - - if (result) - { - context.DeleteSong(songMetaData.Id); - } - } + MusicStoreContext context = HttpContext + .RequestServices + .GetService(typeof(MusicStoreContext)) + as MusicStoreContext; + + var songMetaData = context.GetSong(id); + + var result = _songMgr.DeleteSongFromFileSystem(songMetaData); + + if (result) + { + context.DeleteSong(songMetaData.Id); + } + } } } diff --git a/Models/Context/UserStoreContext.cs b/Models/Context/UserStoreContext.cs index c3885c7..69a67dc 100644 --- a/Models/Context/UserStoreContext.cs +++ b/Models/Context/UserStoreContext.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using MySql.Data.MySqlClient; @@ -81,19 +82,25 @@ namespace Icarus.Models.Context { while (reader.Read()) { + var dateCreated = reader["DateCreated"].ToString(); + var lastLogin = reader["LastLogin"].ToString(); + var parsedC = DateTime.Parse(dateCreated); + var parsedL = DateTime.Parse(lastLogin); + user.Id = Convert.ToInt32(reader["Id"]); user.Nickname = reader["Nickname"].ToString(); user.Email = reader["Email"].ToString(); user.PhoneNumber = reader["PhoneNumber"].ToString(); - user.EmailVerified = Boolean.Parse(reader["EmailVerified"].ToString()); + user.EmailVerified = (reader["EmailVerified"].ToString()) == "1"; user.Firstname = reader["Firstname"].ToString(); user.Lastname = reader["Lastname"].ToString(); - user.DateCreated = DateTime.ParseExact(reader["DateCreated"].ToString(), "yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); - user.LastLogin = DateTime.ParseExact(reader["LastLogin"].ToString(), "yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture); + user.DateCreated = DateTime.Parse(parsedC.ToString("yyyy-MM-dd HH:mm:ss")); + user.LastLogin = DateTime.Parse(parsedL.ToString("yyyy-MM-dd HH:mm:ss")); } } } } + return user; } catch (Exception ex) { diff --git a/Models/LoginResult.cs b/Models/LoginResult.cs index 3edb3f2..bf8babb 100644 --- a/Models/LoginResult.cs +++ b/Models/LoginResult.cs @@ -12,6 +12,8 @@ namespace Icarus.Models public string Username { get; set; } [JsonProperty("token")] public string Token { get; set; } + [JsonProperty("token_type")] + public string TokenType { get; set; } [JsonProperty("expiration")] public int Expiration { get; set; } } diff --git a/Startup.cs b/Startup.cs index a9ace4c..75af88d 100644 --- a/Startup.cs +++ b/Startup.cs @@ -37,7 +37,7 @@ namespace Icarus // 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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddSingleton(Configuration); string domain = $"https://{Configuration["Auth0:Domain"]}/"; @@ -55,8 +55,24 @@ namespace Icarus services.AddAuthorization(options => { options.AddPolicy("download:songs", policy => - policy.Requirements.Add(new HasScopeRequirement - ("download:songs", domain))); + policy + .Requirements + .Add(new HasScopeRequirement("download:songs", 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))); });