using Eis.Application.Candidate; using Eis.Infrastructure.Candidate; namespace Eis.Web.Candidate; public static class NativeCandidateEndpoints { public static IEndpointRouteBuilder MapNativeCandidateEndpoints( this IEndpointRouteBuilder endpoints, CandidateMigrationOptions options) { if (!options.NativeEnabled) { return endpoints; } endpoints.MapGet("/api/candidate/dashboard", async ( HttpContext context, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.GetDashboardAsync(SessionToken(context), cancellationToken))); endpoints.MapGet("/api/candidate/notices", async ( HttpContext context, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.GetNoticesAsync(SessionToken(context), cancellationToken))); endpoints.MapGet("/api/candidate/profile", async ( HttpContext context, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.GetProfileAsync(SessionToken(context), cancellationToken))); endpoints.MapPut("/api/candidate/profile", async ( HttpContext context, System.Text.Json.Nodes.JsonObject request, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.UpdateProfileAsync(SessionToken(context), request, cancellationToken))); endpoints.MapGet("/api/candidate/exams", async ( HttpContext context, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.GetExamsAsync(SessionToken(context), cancellationToken))); endpoints.MapGet("/api/candidate/registrations", async ( HttpContext context, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.GetRegistrationsAsync(SessionToken(context), cancellationToken))); endpoints.MapPost("/api/candidate/registrations", async ( HttpContext context, System.Text.Json.Nodes.JsonObject request, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.CreateRegistrationAsync(SessionToken(context), request, cancellationToken))); endpoints.MapGet("/api/candidate/results", async ( HttpContext context, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.GetResultsAsync( SessionToken(context), VerificationBaseUrl(context), cancellationToken))); endpoints.MapPost("/api/candidate/results/{resultId}/appeals", async ( HttpContext context, string resultId, System.Text.Json.Nodes.JsonObject request, ICandidateService service, CancellationToken cancellationToken) => ToResult( context, await service.CreateScoreAppealAsync( SessionToken(context), resultId, request, cancellationToken))); endpoints.MapGet("/api/candidate/registrations/{registrationId}/admit-card", async ( HttpContext context, string registrationId, ICandidateService service, CancellationToken cancellationToken) => ToDocumentResult( context, await service.GetAdmitCardAsync(SessionToken(context), registrationId, cancellationToken))); return endpoints; } private static string SessionToken(HttpContext context) => context.Request.Cookies.TryGetValue("hz_session", out var token) ? token : string.Empty; private static string VerificationBaseUrl(HttpContext context) { var forwarded = context.Request.Headers["X-Forwarded-Proto"].ToString(); var protocol = forwarded.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() ?? context.Request.Scheme; return $"{protocol}://{context.Request.Host.Value}"; } private static IResult ToResult(HttpContext context, CandidateEndpointResult result) { context.Response.Headers.CacheControl = "no-store"; context.Response.Headers["X-EIS-Implementation"] = "aspnet-core"; return Results.Json(result.Body, statusCode: result.StatusCode); } private static IResult ToDocumentResult(HttpContext context, CandidateDocumentResult result) { context.Response.Headers.CacheControl = "no-store"; context.Response.Headers["X-EIS-Implementation"] = "aspnet-core"; if (result.Error is not null) { return Results.Json(result.Error, statusCode: result.StatusCode); } context.Response.Headers.ContentDisposition = $"attachment; filename*=UTF-8''{Uri.EscapeDataString(result.FileName ?? "admit-card.html")}"; return Results.Content(result.Content ?? string.Empty, "text/html; charset=utf-8", statusCode: result.StatusCode); } }