Merge pull request #11 from prtsie/9-refactor

9 refactor
This commit is contained in:
prtsie
2024-08-28 11:58:16 +03:00
committed by GitHub
9 changed files with 66 additions and 74 deletions

View File

@@ -6,7 +6,7 @@ namespace ApplicationLayer.Services.VisaApplications.Handlers;
public interface IVisaApplicationRequestsHandler
{
/// Returns all applications for approving authorities
Task<List<VisaApplicationModelForAuthority>> GetAllAsync(CancellationToken cancellationToken);
Task<List<VisaApplicationModelForAuthority>> GetPendingAsync(CancellationToken cancellationToken);
/// Returns all applications of one applicant
Task<List<VisaApplicationModelForApplicant>> GetForApplicantAsync(CancellationToken cancellationToken);

View File

@@ -19,9 +19,9 @@ public class VisaApplicationRequestsHandler(
IDateTimeProvider dateTimeProvider,
IUserIdProvider userIdProvider) : IVisaApplicationRequestsHandler
{
async Task<List<VisaApplicationModelForAuthority>> IVisaApplicationRequestsHandler.GetAllAsync(CancellationToken cancellationToken)
async Task<List<VisaApplicationModelForAuthority>> IVisaApplicationRequestsHandler.GetPendingAsync(CancellationToken cancellationToken)
{
var applicationsList = await applications.GetAllAsync(cancellationToken);
var applicationsList = await applications.GetPendingApplicationsAsync(cancellationToken);
var applicationModels = applicationsList
.Select(a => MapVisaApplicationToModelForAuthorities(a, cancellationToken).Result)

View File

@@ -10,4 +10,7 @@ public interface IVisaApplicationsRepository : IGenericRepository<VisaApplicatio
/// Get specific application of specific user
Task<VisaApplication> GetByApplicantAndApplicationIdAsync(Guid applicantId, Guid applicationId, CancellationToken cancellationToken);
/// Returns pending applications for approving authorities
Task<List<VisaApplication>> GetPendingApplicationsAsync(CancellationToken cancellationToken);
}

View File

@@ -27,4 +27,10 @@ public sealed class VisaApplicationsRepository(IGenericReader reader, IGenericWr
.SingleOrDefaultAsync(va => va.Id == applicationId && va.ApplicantId == applicantId, cancellationToken);
return result ?? throw new ApplicationNotFoundByApplicantAndApplicationIdException(applicationId);
}
async Task<List<VisaApplication>> IVisaApplicationsRepository.GetPendingApplicationsAsync(CancellationToken cancellationToken)
{
var result = LoadDomain().Where(va => va.Status == ApplicationStatus.Pending);
return await result.ToListAsync(cancellationToken);
}
}

View File

@@ -1,37 +0,0 @@
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace SchengenVisaApi.Common;
/// Adds auth for swagger
public class ConfigureSwaggerOptions : IConfigureOptions<SwaggerGenOptions>
{
void IConfigureOptions<SwaggerGenOptions>.Configure(SwaggerGenOptions options)
{
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Provide a JWT-token.",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
}
}

View File

@@ -22,12 +22,11 @@ public class UsersController(
IValidator<RegisterApplicantRequest> registerApplicantRequestValidator,
IValidator<AuthData> authDataValidator) : ControllerBase
{
/// <summary> Adds applicant with user account to DB </summary>
[HttpPost]
/// <summary> Adds applicant with user account </summary>
[HttpPost("register")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[Route("register")]
public async Task<IActionResult> Register(RegisterApplicantRequest request, CancellationToken cancellationToken)
{
await registerApplicantRequestValidator.ValidateAndThrowAsync(request, cancellationToken);
@@ -36,15 +35,14 @@ public class UsersController(
return Ok();
}
/// <summary> Adds approving authority with user account to DB </summary>
/// <summary> Adds approving authority with user account </summary>
///<remarks> Accessible only for admins </remarks>
[HttpPost]
[HttpPost("authorities")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status409Conflict)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[Route("authorities")]
[Authorize(policy: PolicyConstants.AdminPolicy)]
public async Task<IActionResult> RegisterAuthority(RegisterRequest request, CancellationToken cancellationToken)
{
@@ -55,10 +53,9 @@ public class UsersController(
}
/// <summary> Returns JWT-token for authentication </summary>
[HttpGet]
[HttpGet("login")]
[ProducesResponseType<string>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[Route("login")]
public async Task<IActionResult> Login(string email, string password, CancellationToken cancellationToken)
{
var result = await loginService.LoginAsync(email, password, cancellationToken);
@@ -67,11 +64,10 @@ public class UsersController(
/// <summary> Returns list of authority accounts </summary>
/// <remarks> Accessible only for admins </remarks>
[HttpGet]
[HttpGet("authorities")]
[ProducesResponseType<List<User>>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[Route("authorities")]
[Authorize(policy: PolicyConstants.AdminPolicy)]
public async Task<IActionResult> GetAuthorityAccounts(CancellationToken cancellationToken)
{
@@ -81,13 +77,12 @@ public class UsersController(
/// <summary> Changes authority's account authentication data </summary>
/// <remarks> Accessible only for admins </remarks>
[HttpPut]
[HttpPut("authorities/{authorityAccountId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[Route("authorities/{authorityAccountId:guid}")]
[Authorize(policy: PolicyConstants.AdminPolicy)]
public async Task<IActionResult> ChangeAuthorityAuthData(Guid authorityAccountId, AuthData authData, CancellationToken cancellationToken)
{
@@ -97,14 +92,13 @@ public class UsersController(
return Ok();
}
/// <summary> Removes authority's account authentication data </summary>
/// <summary> Removes authority's account </summary>
/// <remarks> Accessible only for admins </remarks>
[HttpDelete]
[HttpDelete("authorities/{authorityAccountId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[Route("authorities/{authorityAccountId:guid}")]
[Authorize(policy: PolicyConstants.AdminPolicy)]
public async Task<IActionResult> RemoveAuthorityAccount(Guid authorityAccountId, CancellationToken cancellationToken)
{

View File

@@ -8,42 +8,41 @@ using SchengenVisaApi.Common;
namespace SchengenVisaApi.Controllers;
/// <summary> Controller for <see cref="Domains.VisaApplicationDomain"/> </summary>
/// <summary> Controller for visa applications </summary>
[ApiController]
[Route("visaApplications")]
public class VisaApplicationController(
IVisaApplicationRequestsHandler visaApplicationRequestsHandler,
IValidator<VisaApplicationCreateRequest> visaApplicationCreateRequestValidator) : ControllerBase
{
/// <summary> Returns all applications from DB </summary>
/// <summary> Returns pending applications </summary>
/// <remarks> Accessible only for approving authorities </remarks>
[HttpGet]
[HttpGet("pending")]
[ProducesResponseType<List<VisaApplicationModelForAuthority>>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[Authorize(policy: PolicyConstants.ApprovingAuthorityPolicy)]
public async Task<IActionResult> Get(CancellationToken cancellationToken)
public async Task<IActionResult> GetPending(CancellationToken cancellationToken)
{
var result = await visaApplicationRequestsHandler.GetAllAsync(cancellationToken);
var result = await visaApplicationRequestsHandler.GetPendingAsync(cancellationToken);
return Ok(result);
}
/// <summary> Returns all applications of one applicant </summary>
/// <remarks> Returns applications of authorized applicant </remarks>
[HttpGet]
[HttpGet("ofApplicant")]
[ProducesResponseType<List<VisaApplicationModelForApplicant>>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Authorize(policy: PolicyConstants.ApplicantPolicy)]
[Route("OfApplicant")]
public async Task<IActionResult> GetForApplicant(CancellationToken cancellationToken)
{
var result = await visaApplicationRequestsHandler.GetForApplicantAsync(cancellationToken);
return Ok(result);
}
/// <summary> Adds new application to DB </summary>
/// <summary> Adds new application </summary>
/// <remarks> Adds application for authorized applicant </remarks>
[HttpPost]
[ProducesResponseType(StatusCodes.Status200OK)]
@@ -52,7 +51,7 @@ public class VisaApplicationController(
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[Authorize(policy: PolicyConstants.ApplicantPolicy)]
public async Task<IActionResult> Create(VisaApplicationCreateRequest request, CancellationToken cancellationToken)
public async Task<IActionResult> CreateApplication(VisaApplicationCreateRequest request, CancellationToken cancellationToken)
{
await visaApplicationCreateRequestValidator.ValidateAndThrowAsync(request, cancellationToken);
@@ -62,28 +61,26 @@ public class VisaApplicationController(
/// <summary> Sets application status to closed</summary>
/// <remarks> Accessible only for applicant</remarks>
[HttpPatch]
[HttpPatch("{applicationId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Authorize(policy: PolicyConstants.ApplicantPolicy)]
[Route("{applicationId:guid}")]
public async Task<IActionResult> CloseApplication(Guid applicationId, CancellationToken cancellationToken)
{
await visaApplicationRequestsHandler.HandleCloseRequestAsync(applicationId, cancellationToken);
return Ok();
}
/// <summary> Allows approving authorities approve or reject applications</summary>
/// <summary> Approve or reject applications</summary>
/// <remarks> Accessible only for authorities</remarks>
[HttpPatch]
[HttpPatch("approving/{applicationId:guid}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[Authorize(policy: PolicyConstants.ApprovingAuthorityPolicy)]
[Route("approving/{applicationId:guid}")]
public async Task<IActionResult> SetStatusFromAuthority(Guid applicationId, AuthorityRequestStatuses status, CancellationToken cancellationToken)
{
await visaApplicationRequestsHandler.SetApplicationStatusFromAuthorityAsync(applicationId, status, cancellationToken);

View File

@@ -1,14 +1,15 @@
using System.Reflection;
using System.Security.Claims;
using System.Text;
using System.Text.Json.Serialization;
using ApplicationLayer;
using Domains.Users;
using Infrastructure;
using Infrastructure.Auth;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using SchengenVisaApi.Common;
using SchengenVisaApi.ExceptionFilters;
using Swashbuckle.AspNetCore.SwaggerGen;
@@ -42,7 +43,8 @@ public static class DependencyInjection
services.AddProblemDetails();
services.AddControllers(opts => opts.Filters.Add<GlobalExceptionsFilter>());
services.AddControllers(opts => opts.Filters.Add<GlobalExceptionsFilter>())
.AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
}
/// Adds authentication, authorization and token generator
@@ -90,11 +92,38 @@ public static class DependencyInjection
/// Add swagger
private static void AddSwagger(this IServiceCollection services)
{
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
services.AddSwaggerGen(options =>
{
var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
options.CustomOperationIds(apiDescription =>
apiDescription.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null);
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Provide a JWT-token.",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});
}
}