Skip to content

Commit

Permalink
Merge pull request #24 from is-tech-y24-1/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Bibletoon authored Jun 3, 2022
2 parents 8d3b650 + 4336bae commit 95a6a74
Show file tree
Hide file tree
Showing 46 changed files with 2,350 additions and 10 deletions.
43 changes: 43 additions & 0 deletions Sonar.Player/Sonar.Player.Api/Bootstraps/SwaggerConfigurator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Reflection;
using Microsoft.OpenApi.Models;

namespace Sonar.Player.Api.Bootstraps;

public static class SwaggerConfigurator
{
public static IServiceCollection AddSwaggerWithCustomAuthorization(this IServiceCollection services)
{
services.AddSwaggerGen(
options =>
{
options.CustomSchemaIds(type => type.FullName);
options.SwaggerDoc(
"v1",
new OpenApiInfo { Title = "Sonar.Player", Version = "v1" });

options.AddSecurityDefinition(
"Token",
new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Token to access resources",
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
});

string xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
}
);

return services;
}

public static IApplicationBuilder UseSwaggerWithUI(this IApplicationBuilder app)
{
app.UseSwagger();
app.UseSwaggerUI();

return app;
}
}
7 changes: 7 additions & 0 deletions Sonar.Player/Sonar.Player.Api/Controllers/Dto/TrackFormDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Sonar.Player.Api.Controllers.Dto;

public class TrackFormDto
{
public string Name { get; set; }
public IFormFile File { get; set; }
}
69 changes: 69 additions & 0 deletions Sonar.Player/Sonar.Player.Api/Controllers/FilesController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Sonar.Player.Api.Controllers.Dto;
using Sonar.Player.Application.Files.Commands;
using Sonar.Player.Application.Files.Queries;
using Sonar.Player.Application.Services;

namespace Sonar.Player.Api.Controllers;

[ApiController]
[Route("[controller]")]
public class FilesController : Controller
{
private readonly IMediator _mediator;
private readonly IUserService _userService;

public FilesController(IMediator mediator, IUserService userService)
{
_mediator = mediator;
_userService = userService;
}

[HttpPost("track")]
public async Task<ActionResult<UploadTrack.Response>> UploadTrackAsync(
[FromHeader(Name = "Token")] string token,
[FromForm] TrackFormDto form)
{
var user = await _userService.GetUserAsync(token);
await using var fileStream = form.File.OpenReadStream();

return Ok(
await _mediator.Send(
new UploadTrack.Command(
user,
form.Name,
new UploadTrack.Command.TrackFile(
form.File.FileName,
fileStream)
)));
}

[HttpGet("track-stream-info")]
public async Task<IActionResult> GetTrackStreamInfoAsync(
[FromHeader(Name = "Token")] string token,
[FromQuery(Name = "id")] Guid trackId)
{
var response = await _mediator.Send(new GetTrackStreamInfo.Query(token, trackId));
return File(response.TrackInfoStream, "application/x-mpegURL", true);
}

[HttpGet("{streamPartName}")]
public async Task<IActionResult> GetStreamPartAsync(
[FromHeader(Name = "Token")] string token,
[FromRoute] string streamPartName)
{
var user = await _userService.GetUserAsync(token);
var response = await _mediator.Send(new GetStreamPart.Query(streamPartName));
return File(response.StreamPart, "audio/MPA", true);
}

[HttpDelete("track")]
public async Task<IActionResult> DeleteTrackAsync(
[FromHeader(Name = "Token")] string token,
[FromQuery] Guid trackId)
{
await _mediator.Send(new DeleteTrack.Command(token, trackId));
return Ok();
}
}
50 changes: 50 additions & 0 deletions Sonar.Player/Sonar.Player.Api/Controllers/QueueController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Sonar.Player.Application.Queue.Commands;
using Sonar.Player.Application.Queue.Queries;

namespace Sonar.Player.Api.Controllers;

[ApiController]
[Route("[controller]")]
public class QueueController : Controller
{
private readonly IMediator _mediator;

public QueueController(IMediator mediator)
{
_mediator = mediator;
}

[HttpGet]
public async Task<ActionResult<GetQueue.Response>> GetQueueAsync(
[FromHeader(Name = "Token")] string token,
CancellationToken cancellationToken = default)
{
return Ok(await _mediator.Send(new GetQueue.Query(), cancellationToken));
}

[HttpPatch("track")]
public async Task<ActionResult<AddTrackToQueue.Response>> AddTrackToQueueAsync(
[FromHeader(Name = "Token")] string token,
[FromQuery] Guid trackId, CancellationToken cancellationToken = default)
{
return Ok(await _mediator.Send(new AddTrackToQueue.Command(), cancellationToken));
}

[HttpDelete]
public async Task<ActionResult<ShuffleQueue.Response>> PurgeQueueAsync(
[FromHeader(Name = "Token")] string token,
CancellationToken cancellationToken = default)
{
return Ok(await _mediator.Send(new PurgeQueue.Command(), cancellationToken));
}

[HttpPatch("shuffle")]
public async Task<ActionResult<ShuffleQueue.Response>> ShuffleQueueAsync(
[FromHeader(Name = "Token")] string token,
CancellationToken cancellationToken = default)
{
return Ok(await _mediator.Send(new ShuffleQueue.Command(), cancellationToken));
}
}
34 changes: 34 additions & 0 deletions Sonar.Player/Sonar.Player.Api/Filters/ExceptionFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Sonar.Player.Application.Tools.Exceptions;
using Sonar.Player.Domain.Tools.Exceptions;
using ILogger = Serilog.ILogger;

namespace Sonar.Player.Api.Filters;

public class ExceptionFilter : IExceptionFilter
{
private readonly ILogger _logger;

public ExceptionFilter(ILogger logger)
{
_logger = logger;
}

public void OnException(ExceptionContext context)
{
_logger.Error(context.Exception, "");

context.Result = new JsonResult(context.Exception.Message)
{
StatusCode = context.Exception switch
{
ExternalApiException apiException => apiException.StatusCode,
NotEnoughAccessException => StatusCodes.Status403Forbidden,
EnumerationParseException => StatusCodes.Status400BadRequest,
_ => StatusCodes.Status500InternalServerError
}
};
context.ExceptionHandled = true;
}
}
44 changes: 37 additions & 7 deletions Sonar.Player/Sonar.Player.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,54 @@
using MediatR;
using Microsoft.EntityFrameworkCore;
using Serilog;
using Sonar.Player.Api.Bootstraps;
using Sonar.Player.Api.Filters;
using Sonar.Player.Application.Services;
using Sonar.Player.Application.Services.TracksStorage;
using Sonar.Player.Application.Tools;
using Sonar.Player.Data;
using Sonar.Player.Fakes.ApiClients;
using Sonar.Player.Fakes.Services;
using Sonar.UserProfile.ApiClient;
using Sonar.UserTracksManagement.ApiClient;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Host.UseSerilog((ctx, lc) => lc.WriteTo.Console());

builder.Services.AddControllers(options => options.Filters.Add<ExceptionFilter>());
builder.Services.Configure<RouteOptions>(opt => opt.LowercaseUrls = true);

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerWithCustomAuthorization();

builder.Services.AddDbContext<PlayerDbContext>(opt => opt.UseSqlite("Filename=player.db"));

builder.Services.AddMediatR(typeof(Sonar.Player.Application.IAssemblyMarker));
builder.Services.AddScoped<ITrackStorage, LocalTrackStorage>();
builder.Services.Decorate<ITrackStorage, HlsTrackProcessor>();
builder.Services.AddSingleton<ITrackPathBuilder, TrackPathBuilder>();

builder.Services.AddScoped<HttpClient>();
builder.Services.AddScoped<IUserService, UserService>();
// builder.Services.AddScoped<IUserTracksApiClient, FakeUserTracksClient>();
builder.Services.AddScoped<IUserTracksApiClient, UserTracksApiClient>(f => new UserTracksApiClient("https://localhost:7055", f.GetRequiredService<HttpClient>()));
builder.Services.AddScoped<IUserApiClient, UserApiClient>(f => new UserApiClient("https://localhost:7062", f.GetRequiredService<HttpClient>()));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
app.UseSwaggerWithUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();
app.UseCors(opt => opt.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

app.UseSerilogRequestLogging();

app.Run();
19 changes: 18 additions & 1 deletion Sonar.Player/Sonar.Player.Api/Sonar.Player.Api.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,29 @@
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<PropertyGroup>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="10.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.5" />
<PackageReference Include="Scrutor" Version="4.1.0" />
<PackageReference Include="Serilog" Version="2.11.0" />
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>

<ItemGroup>
<Folder Include="Controllers" />
<ProjectReference Include="..\Sonar.Player.Application\Sonar.Player.Application.csproj" />
<ProjectReference Include="..\Sonar.Player.DataAccess\Sonar.Player.DataAccess.csproj" />
<ProjectReference Include="..\Sonar.Player.Fakes\Sonar.Player.Fakes.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="ffmpeg.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Loading

0 comments on commit 95a6a74

Please sign in to comment.