Merge pull request #78 from kdeng00/add_swagger_docs

Swagger docs. Close #71
This commit was merged in pull request #78.
This commit is contained in:
Kun Deng
2022-09-05 17:09:23 -04:00
committed by GitHub
15 changed files with 81 additions and 42 deletions
+2 -2
View File
@@ -39,7 +39,7 @@ namespace Icarus.Controllers.V1
#region HTTP Routes #region HTTP Routes
[HttpGet] [HttpGet]
public IActionResult Get() public IActionResult GetAlbums()
{ {
List<Album> albums = new List<Album>(); List<Album> albums = new List<Album>();
@@ -54,7 +54,7 @@ namespace Icarus.Controllers.V1
} }
[HttpGet("{id}")] [HttpGet("{id}")]
public IActionResult Get(int id) public IActionResult GetAlbum(int id)
{ {
Album album = new Album Album album = new Album
{ {
+2 -2
View File
@@ -38,7 +38,7 @@ namespace Icarus.Controllers.V1
#region HTTP Routes #region HTTP Routes
[HttpGet] [HttpGet]
public IActionResult Get() public IActionResult GetArtists()
{ {
var artistContext = new ArtistContext(_connectionString); var artistContext = new ArtistContext(_connectionString);
@@ -51,7 +51,7 @@ namespace Icarus.Controllers.V1
} }
[HttpGet("{id}")] [HttpGet("{id}")]
public IActionResult Get(int id) public IActionResult GetArtist(int id)
{ {
if (!IsTokenValid("read:artists")) if (!IsTokenValid("read:artists"))
{ {
+2
View File
@@ -17,6 +17,7 @@ namespace Icarus.Controllers.V1
#region Methods #region Methods
[ApiExplorerSettings(IgnoreApi = true)]
protected string ParseBearerTokenFromHeader() protected string ParseBearerTokenFromHeader()
{ {
var token = string.Empty; var token = string.Empty;
@@ -37,6 +38,7 @@ namespace Icarus.Controllers.V1
return token; return token;
} }
[ApiExplorerSettings(IgnoreApi = true)]
protected bool IsTokenValid(string scope) protected bool IsTokenValid(string scope)
{ {
var token = ParseBearerTokenFromHeader(); var token = ParseBearerTokenFromHeader();
+4 -3
View File
@@ -35,7 +35,8 @@ namespace Icarus.Controllers.V1
#region HTTP Routes #region HTTP Routes
public IActionResult Get() [HttpGet]
public IActionResult GetCoverArts()
{ {
var coverArtContext = new CoverArtContext(_connectionString); var coverArtContext = new CoverArtContext(_connectionString);
@@ -54,7 +55,7 @@ namespace Icarus.Controllers.V1
} }
[HttpGet("{id}")] [HttpGet("{id}")]
public async Task<IActionResult> Get(int id) public IActionResult GetCoverArt(int id)
{ {
var coverArt = new CoverArt { CoverArtID = id }; var coverArt = new CoverArt { CoverArtID = id };
@@ -65,7 +66,7 @@ namespace Icarus.Controllers.V1
if (coverArt != null) if (coverArt != null)
{ {
_logger.LogInformation("Found cover art record"); _logger.LogInformation("Found cover art record");
var coverArtBytes = await System.IO.File.ReadAllBytesAsync( var coverArtBytes = System.IO.File.ReadAllBytes(
coverArt.ImagePath); coverArt.ImagePath);
return File(coverArtBytes, "application/x-msdownload", return File(coverArtBytes, "application/x-msdownload",
+2 -2
View File
@@ -39,7 +39,7 @@ namespace Icarus.Controllers.V1
#region HTTP Routes #region HTTP Routes
[HttpGet] [HttpGet]
public IActionResult Get() public IActionResult GetGenres()
{ {
var genres = new List<Genre>(); var genres = new List<Genre>();
@@ -54,7 +54,7 @@ namespace Icarus.Controllers.V1
} }
[HttpGet("{id}")] [HttpGet("{id}")]
public IActionResult Get(int id) public IActionResult GetGenre(int id)
{ {
var genre = new Genre var genre = new Genre
{ {
+2 -1
View File
@@ -38,7 +38,8 @@ namespace Icarus.Controllers.V1
#region HTTP endpoints #region HTTP endpoints
public IActionResult Post([FromBody] User user) [HttpPost]
public IActionResult Login([FromBody] User user)
{ {
var context = new UserContext(_connectionString); var context = new UserContext(_connectionString);
+1 -1
View File
@@ -37,7 +37,7 @@ namespace Icarus.Controllers.V1
#endregion #endregion
[HttpPost] [HttpPost]
public IActionResult Post([FromBody] User user) public IActionResult RegisterUser([FromBody] User user)
{ {
PasswordEncryption pe = new PasswordEncryption(); PasswordEncryption pe = new PasswordEncryption();
user.Password = pe.HashPassword(user); user.Password = pe.HashPassword(user);
@@ -46,7 +46,7 @@ namespace Icarus.Controllers.V1
#region API Routes #region API Routes
[HttpGet("{id}")] [HttpGet("{id}")]
public async Task<IActionResult> Get(int id) public async Task<IActionResult> DownloadCompressedSong(int id)
{ {
var context = new SongContext(_connectionString); var context = new SongContext(_connectionString);
+3 -3
View File
@@ -48,7 +48,7 @@ namespace Icarus.Controllers.V1
[HttpGet] [HttpGet]
public IActionResult Get() public IActionResult GetSongs()
{ {
List<Song> songs = new List<Song>(); List<Song> songs = new List<Song>();
Console.WriteLine("Attemtping to retrieve songs"); Console.WriteLine("Attemtping to retrieve songs");
@@ -65,7 +65,7 @@ namespace Icarus.Controllers.V1
} }
[HttpGet("{id}")] [HttpGet("{id}")]
public IActionResult Get(int id) public IActionResult GetSong(int id)
{ {
var context = new SongContext(_connectionString); var context = new SongContext(_connectionString);
@@ -81,7 +81,7 @@ namespace Icarus.Controllers.V1
} }
[HttpPut("{id}")] [HttpPut("{id}")]
public IActionResult Put(int id, [FromBody] Song song) public IActionResult UpdateSong(int id, [FromBody] Song song)
{ {
var context = new SongContext(_connectionString); var context = new SongContext(_connectionString);
+15 -18
View File
@@ -48,13 +48,12 @@ namespace Icarus.Controllers.V1
[HttpGet("download/{id}")] [HttpGet("download/{id}")]
[Route("private-scoped")] public IActionResult Download(int id)
public async Task<IActionResult> Get(int id)
{ {
var songContext = new SongContext(_connectionString); var songContext = new SongContext(_connectionString);
var songMetaData = songContext.RetrieveRecord(new Song { SongID = id}); var songMetaData = songContext.RetrieveRecord(new Song { SongID = id});
var song = await _songMgr.RetrieveSong(songMetaData); var song = _songMgr.RetrieveSong(songMetaData).Result;
return File(song.Data, "application/x-msdownload", songMetaData.Filename); return File(song.Data, "application/x-msdownload", songMetaData.Filename);
} }
@@ -72,8 +71,7 @@ namespace Icarus.Controllers.V1
// Cover art // Cover art
// //
[HttpPost("upload"), DisableRequestSizeLimit] [HttpPost("upload"), DisableRequestSizeLimit]
[Route("private-scoped")] public IActionResult Upload([FromForm(Name = "file")] List<IFormFile> songData)
public IActionResult Post([FromForm(Name = "file")] List<IFormFile> songData)
{ {
try try
{ {
@@ -109,8 +107,7 @@ namespace Icarus.Controllers.V1
// as well as the cover art // as well as the cover art
// //
[HttpPost("upload/with/data")] [HttpPost("upload/with/data")]
[Route("private-scoped")] public IActionResult UploadWithData([FromForm] UploadSongWithDataForm up)
public IActionResult Post ([FromForm] UploadSongWithDataForm up)
{ {
try try
{ {
@@ -131,7 +128,7 @@ namespace Icarus.Controllers.V1
} }
[HttpDelete("delete/{id}")] [HttpDelete("delete/{id}")]
public IActionResult Delete(int id) public IActionResult DeleteSong(int id)
{ {
var songContext = new SongContext(_connectionString); var songContext = new SongContext(_connectionString);
@@ -156,15 +153,15 @@ namespace Icarus.Controllers.V1
} }
public class UploadSongWithDataForm public class UploadSongWithDataForm
{ {
[FromForm(Name = "file")] [FromForm(Name = "file")]
public IFormFile SongData { get; set; } public IFormFile SongData { get; set; }
// TODO: Think about making this optional and if it is not provided, use the stock cover art // NOTE: Think about making this optional and if it is not provided, use the stock cover art
[FromForm(Name = "cover")] [FromForm(Name = "cover")]
public IFormFile CoverArtData { get; set; } public IFormFile CoverArtData { get; set; }
[FromForm(Name = "metadata")] [FromForm(Name = "metadata")]
public string SongFile { get; set; } public string SongFile { get; set; }
} }
} }
} }
+1 -1
View File
@@ -45,7 +45,7 @@ namespace Icarus.Controllers.V1
#region HTTP endpoints #region HTTP endpoints
[HttpGet("{id}")] [HttpGet("{id}")]
public async Task<IActionResult> Get(int id) public async Task<IActionResult> StreamSong(int id)
{ {
var context = new SongContext(_config.GetConnectionString("DefaultConnection")); var context = new SongContext(_config.GetConnectionString("DefaultConnection"));
+1
View File
@@ -25,6 +25,7 @@
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" /> <PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="RestSharp" Version="106.15.0" /> <PackageReference Include="RestSharp" Version="106.15.0" />
<PackageReference Include="SevenZip" Version="19.0.0" /> <PackageReference Include="SevenZip" Version="19.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.15.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.15.0" />
<PackageReference Include="taglib" Version="2.1.0" /> <PackageReference Include="taglib" Version="2.1.0" />
</ItemGroup> </ItemGroup>
+3 -2
View File
@@ -12,7 +12,7 @@
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "api/values", "launchUrl": "swagger",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@@ -20,7 +20,8 @@
"Icarus": { "Icarus": {
"commandName": "Project", "commandName": "Project",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "api/values", "dotnetRuneMessage": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5002", "applicationUrl": "http://localhost:5002",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
+3 -6
View File
@@ -37,7 +37,9 @@ One can interface with Icarus the music server either by:
## Getting started ## Getting started
There are several things that need to be completed to properly setup and secure the API. There are several things that need to be completed to properly setup and secure the API.
#### 1. Creating RSA keys 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 1. JWT Information
2. API filesystem paths 2. API filesystem paths
3. Database connection string 3. Database connection string
@@ -138,11 +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. Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on the code of conduct, and the process for submitting pull requests to the project.
## Authors
* [kdeng00](https://github.com/kdeng00)
See also the list of [contributors](https://github.com/amazing-username/Icarus/graphs/contributors) who participated in this project.
## License ## License
+39
View File
@@ -1,15 +1,18 @@
using System; using System;
using System.Text; using System.Text;
using System.Linq;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using NLog.Web; using NLog.Web;
@@ -68,12 +71,48 @@ namespace Icarus
services.AddControllers() services.AddControllers()
.AddNewtonsoftJson(); .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. // Called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ {
// NOTE: Dev-related configuration can be done when env.IsDevelopment() evaluated to true // NOTE: Dev-related configuration can be done when env.IsDevelopment() evaluated to true
if (env.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseRouting(); app.UseRouting();
app.UseAuthentication(); app.UseAuthentication();