using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using StellaOps.Platform.WebService.Constants; using StellaOps.Platform.WebService.Contracts; using StellaOps.Platform.WebService.Services; using System; using System.Linq; namespace StellaOps.Platform.WebService.Endpoints; public static class ContextEndpoints { public static IEndpointRouteBuilder MapContextEndpoints(this IEndpointRouteBuilder app) { var context = app.MapGroup("/api/v2/context") .WithTags("Platform Context"); context.MapGet("/regions", async Task( HttpContext httpContext, PlatformRequestContextResolver resolver, PlatformContextService service, CancellationToken cancellationToken) => { if (!TryResolveContext(httpContext, resolver, out _, out var failure)) { return failure!; } var regions = await service.GetRegionsAsync(cancellationToken).ConfigureAwait(false); return Results.Ok(regions); }) .WithName("GetPlatformContextRegions") .WithSummary("List global regions for context selection") .RequireAuthorization(PlatformPolicies.ContextRead); context.MapGet("/environments", async Task( HttpContext httpContext, PlatformRequestContextResolver resolver, PlatformContextService service, [FromQuery(Name = "regions")] string? regions, CancellationToken cancellationToken) => { if (!TryResolveContext(httpContext, resolver, out _, out var failure)) { return failure!; } var regionFilter = ParseCsv(regions); var environments = await service.GetEnvironmentsAsync(regionFilter, cancellationToken).ConfigureAwait(false); return Results.Ok(environments); }) .WithName("GetPlatformContextEnvironments") .WithSummary("List global environments with optional region filter") .RequireAuthorization(PlatformPolicies.ContextRead); context.MapGet("/preferences", async Task( HttpContext httpContext, PlatformRequestContextResolver resolver, PlatformContextService service, CancellationToken cancellationToken) => { if (!TryResolveContext(httpContext, resolver, out var requestContext, out var failure)) { return failure!; } var preferences = await service.GetPreferencesAsync(requestContext!, cancellationToken).ConfigureAwait(false); return Results.Ok(preferences); }) .WithName("GetPlatformContextPreferences") .WithSummary("Get persisted context preferences for the current user") .RequireAuthorization(PlatformPolicies.ContextRead); context.MapPut("/preferences", async Task( HttpContext httpContext, PlatformRequestContextResolver resolver, PlatformContextService service, PlatformContextPreferencesRequest request, CancellationToken cancellationToken) => { if (!TryResolveContext(httpContext, resolver, out var requestContext, out var failure)) { return failure!; } var preferences = await service.UpsertPreferencesAsync( requestContext!, request, cancellationToken).ConfigureAwait(false); return Results.Ok(preferences); }) .WithName("UpdatePlatformContextPreferences") .WithSummary("Update persisted context preferences for the current user") .RequireAuthorization(PlatformPolicies.ContextWrite); return app; } private static string[] ParseCsv(string? value) { if (string.IsNullOrWhiteSpace(value)) { return Array.Empty(); } return value .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Where(item => !string.IsNullOrWhiteSpace(item)) .Select(item => item.Trim().ToLowerInvariant()) .Distinct(StringComparer.Ordinal) .ToArray(); } private static bool TryResolveContext( HttpContext context, PlatformRequestContextResolver resolver, out PlatformRequestContext? requestContext, out IResult? failure) { if (resolver.TryResolve(context, out requestContext, out var error)) { failure = null; return true; } failure = Results.BadRequest(new { error = error ?? "tenant_missing" }); return false; } }