Files
pfm/PostFundManagement.Api/Endpoints/Evidence/UploadEvidenceFilesEndpoint.cs
2026-08-25 17:52:44 +02:00

79 lines
3.4 KiB
C#

using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Api;
using PostFundManagement.Domain.Extensions;
using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Api.Endpoints.Evidence;
[ApiVersionTarget(1)]
public class UploadEvidenceFilesEndpoint : IEndpoint
{
public void Map(IEndpointRouteBuilder builder)
{
builder.MapPost("api/evidence/files", async (HttpRequest request, ClaimsPrincipal principal, IDbContextFactory<ApplicationDbContext> contextFactory,
[FromKeyedServices(Constants.EvidenceS3SettingsSection)] IS3Service s3Service, CancellationToken cancellationToken = default) =>
{
var sidClaim = principal.FindFirst("sid")?.Value ?? principal.FindFirst(ClaimTypes.Sid)?.Value;
if (!Guid.TryParse(sidClaim, out var userId))
return Results.BadRequest("Missing or invalid 'sid' claim.");
if (!request.HasFormContentType)
return Results.BadRequest("Request must be a multipart form.");
var form = await request.ReadFormAsync(cancellationToken);
var file = form.Files.GetFile("file");
if (file == null || file.Length == 0)
return Results.BadRequest("No file uploaded or file is empty.");
_ = long.TryParse(form["projectId"], out var projectId);
_ = long.TryParse(form["milestoneId"], out var milestoneId);
_ = long.TryParse(form["indicatorId"], out var indicatorId);
_ = long.TryParse(form["activityId"], out var activityId);
_ = Enum.TryParse<EvidenceType>(form["type"], out var type);
using var stream = file.OpenReadStream();
var uploadResult = await s3Service.UploadFileAsync(file.FileName, stream, file.ContentType, cancellationToken);
if (uploadResult.IsFailed)
return Results.BadRequest(uploadResult.Errors.FirstOrDefault()?.Message ?? "File upload failed.");
var documentUrl = uploadResult.Value;
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var evidence = new Domain.Entities.Evidence
{
ProjectId = projectId,
MilestoneId = milestoneId,
IndicatorId = indicatorId,
ActivityId = activityId,
CreatedBy = userId,
CreatedAt = DateTime.UtcNow,
Version = 1,
Type = type,
DocumentUrl = documentUrl,
Status = ApprovalStatus.Pending
};
context.Evidences.Add(evidence);
return await context.SaveChangesAsync(cancellationToken) > 0
? Results.Created($"api/evidence/files/{evidence.Id}", evidence)
: Results.BadRequest("Evidence upload failed");
})
.RequireAuthorization()
.DisableAntiforgery()
.WithDescription("Upload supporting evidence file to S3 and register metadata (M14)")
.WithName(typeof(UploadEvidenceFilesEndpoint).ToEndpointName())
.MapToApiVersion(new ApiVersion(1))
.Produces<PostFundManagement.Domain.Entities.Evidence>(StatusCodes.Status201Created)
.Produces(StatusCodes.Status400BadRequest)
.Produces(StatusCodes.Status401Unauthorized)
.WithTags(EndpointTags.Evidence);
}
}