using Asp.Versioning; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using TarninaHub.Application.Abstractions; using TarninaHub.Application.Dtos; using TarninaHub.Application.Security; namespace TarninaHub.Controllers; [ApiController] [ApiVersion("1.0")] [Route("api/applications")] [Authorize] public class ApplicationsController : ControllerBase { private readonly IApplicationService _applicationService; private readonly IIdeaService _ideaService; public ApplicationsController(IApplicationService applicationService, IIdeaService ideaService) { _applicationService = applicationService; _ideaService = ideaService; } [HttpPost] public async Task> Create( CreateApplicationRequest request, CancellationToken cancellationToken) { var userId = User.GetUserId(); if (string.IsNullOrWhiteSpace(userId)) { return Unauthorized(); } var result = await _applicationService.CreateAsync(userId, request, cancellationToken); return result.Outcome switch { CreateApplicationOutcome.Created when result.Application is not null => CreatedAtAction(nameof(GetById), new { applicationId = result.Application.Id }, result.Application), CreateApplicationOutcome.CallNotFound => NotFound(new ProblemDetails { Title = "Grant call not found", Status = StatusCodes.Status404NotFound, }), CreateApplicationOutcome.IdeaNotFound => NotFound(new ProblemDetails { Title = "Idea not found", Status = StatusCodes.Status404NotFound, }), _ => Conflict(new ProblemDetails { Title = "Grant call is not open", Detail = "Applications are only accepted while the call is open and within its window.", Status = StatusCodes.Status409Conflict, }), }; } [HttpGet] public async Task>> ListMine(CancellationToken cancellationToken) { var userId = User.GetUserId(); if (string.IsNullOrWhiteSpace(userId)) { return Unauthorized(); } var applications = await _applicationService.ListForAuthorAsync(userId, cancellationToken); return Ok(applications); } [HttpGet("{applicationId}")] public async Task> GetById( string applicationId, CancellationToken cancellationToken) { var application = await _applicationService.GetAsync(applicationId, cancellationToken); if (application is null) { return NotFound(); } if (!IsStaff()) { var idea = await _ideaService.GetAsync(application.IdeaId, cancellationToken); if (idea is null || !string.Equals(idea.AuthorId, User.GetUserId(), StringComparison.Ordinal)) { return Forbid(); } } return Ok(application); } private bool IsStaff() => User.IsInRole(RoleNames.Operator) || User.IsInRole(RoleNames.Manager) || User.IsInRole(RoleNames.Admin); }