using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using AutoMapper; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Retroactiune.Core.Entities; using Retroactiune.Core.Interfaces; using Retroactiune.Core.Services; using Retroactiune.DataTransferObjects; namespace Retroactiune.Controllers { [ApiController] [Route("api/v1/[controller]")] public class TokensController : ControllerBase { private readonly IFeedbackReceiversService _feedbackReceiversService; private readonly ITokensService _tokensService; private readonly IMapper _mapper; private readonly ILogger _logger; public TokensController(IFeedbackReceiversService feedbackReceiversService, ITokensService tokensService, ILogger logger, IMapper mapper) { _feedbackReceiversService = feedbackReceiversService; _tokensService = tokensService; _mapper = mapper; _logger = logger; } /// /// The list tokens controller retrieves a list of tokens. /// /// Object that holds filters for listing tokens. /// A list of tokens. /// The request is invalid. [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task ListTokens([FromQuery] ListTokensFiltersDto filtersDto) { try { var tokenFilters = _mapper.Map(filtersDto); var response = await _tokensService.FindAsync(tokenFilters); return Ok(response); } catch (GenericServiceException e) { _logger.LogError("{Message}", e.Message); return BadRequest(new BasicResponse() { Message = e.Message }); } } /// /// Creates a new batch of tokens, the tokens are tied to a FeedbackReceiver and are used by the client /// when leaving Feedback. /// /// The list of FeedbackReceivers /// A BasicResponse indicating success. /// Returns ok. /// If the items is invalid [HttpPost] [ProducesResponseType(typeof(BasicResponse), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task GenerateTokens([Required] GenerateTokensDto generateTokensDto) { var feedbackReceiverId = generateTokensDto.FeedbackReceiverId; var result = await _feedbackReceiversService.FindAsync( new[] {feedbackReceiverId}); if (!result.Any()) { return BadRequest(new BasicResponse { Message = $"Invalid FeedbackReceiverId {generateTokensDto.FeedbackReceiverId}." }); } await _tokensService.GenerateTokensAsync(generateTokensDto.NumberOfTokens, feedbackReceiverId, generateTokensDto.ExpiryTime); return Ok(new BasicResponse { Message = "Tokens generated." }); } /// /// Deletes tokens identified by ids. /// /// A list of token ids. /// The request to delete the items has been submitted. /// The request is invalid. /// [HttpDelete] [ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)] [ProducesResponseType(typeof(BasicResponse), StatusCodes.Status400BadRequest)] public async Task DeleteTokens([Required] IEnumerable tokenIds) { try { await _tokensService.DeleteTokensAsync(tokenIds); return NoContent(); } catch (GenericServiceException e) { _logger.LogError("{Message}", e.Message); return BadRequest(new BasicResponse { Message = e.Message }); } } /// /// Deletes a Token given it's guid. /// /// The guid of the item to be deleted. /// A NoContent result. /// The delete is submitted. /// The request is invalid. [HttpDelete("{guid}")] [ProducesResponseType(typeof(NoContentResult), StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task DeleteToken( [StringLength(24, ErrorMessage = "invalid guid, must be 24 characters", MinimumLength = 24)] string guid) { try { await _tokensService.DeleteTokensAsync(new[] {guid}); return NoContent(); } catch (GenericServiceException e) { _logger.LogError("{Message}", e.Message); return BadRequest(new BasicResponse { Message = e.Message }); } } /// /// Checks if a token is valid or not. /// /// The the result of the check. /// The request is invalid. [HttpGet("{guid}/check")] [ProducesResponseType(typeof(CheckTokenDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async Task CheckToken( [StringLength(24, ErrorMessage = "invalid guid, must be 24 characters", MinimumLength = 24)] string guid ) { // TODO: Unit test. var response = await _tokensService.FindAsync(new TokenListFilters { Ids = new[] {guid} }); try { var token = response.ElementAt(0); return Ok(new CheckTokenDto { IsValid = token.IsValid() }); } catch (ArgumentOutOfRangeException) { _logger.LogWarning("Invalid token {Guid}", guid); return Ok(new CheckTokenDto { IsValid = true }); } } } }