using ApplicationLayer.Services.VisaApplications.Handlers; using ApplicationLayer.Services.VisaApplications.Models; using ApplicationLayer.Services.VisaApplications.Requests; using FluentValidation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using SchengenVisaApi.Common; namespace SchengenVisaApi.Controllers; /// Controller for visa applications [ApiController] [Route("visaApplications")] public class VisaApplicationController( IVisaApplicationRequestsHandler visaApplicationRequestsHandler, IValidator visaApplicationCreateRequestValidator) : ControllerBase { /// Returns pending applications /// Accessible only for approving authorities [HttpGet("pending")] [ProducesResponseType>(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [Authorize(policy: PolicyConstants.ApprovingAuthorityPolicy)] public async Task GetPending(CancellationToken cancellationToken) { var result = await visaApplicationRequestsHandler.GetPendingAsync(cancellationToken); return Ok(result); } /// Returns application /// Accessible only for approving authorities [HttpGet("/forAuthority/{applicationId:guid}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status409Conflict)] [Authorize(policy: PolicyConstants.ApprovingAuthorityPolicy)] public async Task GetApplicationForAuthority(Guid applicationId, CancellationToken cancellationToken) { var result = await visaApplicationRequestsHandler.GetApplicationForAuthorityAsync(applicationId, cancellationToken); return Ok(result); } /// Returns application /// Accessible only for applicant [HttpGet("/forApplicant/{applicationId:guid}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(policy: PolicyConstants.ApplicantPolicy)] public async Task GetApplicationForApplicant(Guid applicationId, CancellationToken cancellationToken) { var result = await visaApplicationRequestsHandler.GetApplicationForApplicantAsync(applicationId, cancellationToken); return Ok(result); } /// Returns all applications of one applicant /// Returns applications of authorized applicant [HttpGet("ofApplicant")] [ProducesResponseType>(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(policy: PolicyConstants.ApplicantPolicy)] public async Task GetApplicationsForApplicant(CancellationToken cancellationToken) { var result = await visaApplicationRequestsHandler.GetForApplicantAsync(cancellationToken); return Ok(result); } /// Adds new application /// Adds application for authorized applicant [HttpPost] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(policy: PolicyConstants.ApplicantPolicy)] public async Task CreateApplication(VisaApplicationCreateRequest request, CancellationToken cancellationToken) { await visaApplicationCreateRequestValidator.ValidateAndThrowAsync(request, cancellationToken); await visaApplicationRequestsHandler.HandleCreateRequestAsync(request, cancellationToken); return Ok(); } /// Sets application status to closed /// Accessible only for applicant [HttpPatch("{applicationId:guid}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(policy: PolicyConstants.ApplicantPolicy)] public async Task CloseApplication(Guid applicationId, CancellationToken cancellationToken) { await visaApplicationRequestsHandler.HandleCloseRequestAsync(applicationId, cancellationToken); return Ok(); } /// Approve or reject applications /// Accessible only for authorities [HttpPatch("approving/{applicationId:guid}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status409Conflict)] [Authorize(policy: PolicyConstants.ApprovingAuthorityPolicy)] public async Task SetStatusFromAuthority(Guid applicationId, AuthorityRequestStatuses status, CancellationToken cancellationToken) { await visaApplicationRequestsHandler.SetApplicationStatusFromAuthorityAsync(applicationId, status, cancellationToken); return Ok(); } /// Returns application /// Accessible only for applicant [HttpGet("/forApplicant/{applicationId:guid}/download")] [Produces("application/octet-stream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(policy: PolicyConstants.ApplicantPolicy)] public async Task DownloadApplicationForApplicant(Guid applicationId, CancellationToken cancellationToken) { var result = await visaApplicationRequestsHandler.ApplicationToStreamAsync(applicationId, cancellationToken); result.Position = 0; return File(result, "application/octet-stream", "Application.xlsx"); } }