using FluentResults; using IdentityShroud.Api.Mappers; using IdentityShroud.Core.Contracts; using IdentityShroud.Core.Model; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; namespace IdentityShroud.Api.Apis; /// /// The part of the api below realms/{slug}/clients /// public static class ClientApi { public const string ClientGetRouteName = "ClientGet"; public static void MapEndpoints(this IEndpointRouteBuilder erp) { RouteGroupBuilder clientsGroup = erp.MapGroup("clients"); clientsGroup.MapPost("", ClientCreate) .Produces(StatusCodes.Status201Created) .Validate() .WithName("ClientCreate"); var clientIdGroup = clientsGroup.MapGroup("{clientId}") .AddEndpointFilter(); clientIdGroup.MapGet("", ClientGet) .WithName(ClientGetRouteName); } private static Ok ClientGet( Guid realmId, int clientId, HttpContext context) { Client client = (Client)context.Items["ClientEntity"]!; return TypedResults.Ok(new ClientMapper().ToDto(client)); } private static async Task, InternalServerError>> ClientCreate( Guid realmId, ClientCreateRequest request, [FromServices] IClientService service, [FromServices] IDataEncryptionService cryptor, HttpContext context, CancellationToken cancellationToken) { Realm realm = context.GetValidatedRealm(); Result result = await service.Create(realm.Id, request, cancellationToken); if (result.IsFailed) { throw new NotImplementedException(); } Client client = result.Value; ClientRepresentation clientRepresentation = new ClientMapper().ToDto(client); var secret = SelectBestSecret(client.Secrets); if (secret is {} s) clientRepresentation.Secret = cryptor.DecryptUtf8ToString(realm.DataEncryptionKeys, s.Secret); return TypedResults.CreatedAtRoute( clientRepresentation, ClientGetRouteName, new RouteValueDictionary() { ["realmId"] = realm.Id, ["clientId"] = client.Id, }); } private static ClientSecret? SelectBestSecret(List clientSecrets) { ClientSecret? result = null; foreach (var cs in clientSecrets) { if (cs.RevokedAt is null && (!cs.Expires.HasValue || cs.Expires.Value > DateTime.UtcNow)) { if (result is null) { result = cs; } else { int d = (cs.Expires ?? DateTime.MaxValue).CompareTo(result.Expires ?? DateTime.MaxValue); if (d > 0 || (d == 0 && cs.CreatedAt > result.CreatedAt)) result = cs; } } } return result; } }