Skip to content

Commit

Permalink
Access requests for in-custody
Browse files Browse the repository at this point in the history
  • Loading branch information
Lee Wright authored and Lee Wright committed Jul 16, 2024
1 parent c9f50a4 commit de2371f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 23 deletions.
2 changes: 1 addition & 1 deletion backend/ApprovalFlow/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ private static void CreateLogger(
Console.WriteLine("Creating the logging directory failed: {0}", e.ToString());
}


var name = Assembly.GetExecutingAssembly().GetName();
var outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}";

var loggerConfiguration = new LoggerConfiguration()
.MinimumLevel.Information()
.Filter.ByExcluding("RequestPath like '/health%'")
.Filter.ByExcluding("RequestPath like '/metrics%'")
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("Microsoft.Hosting.Lifetime", LogEventLevel.Information)
.MinimumLevel.Override("System", LogEventLevel.Warning)
Expand Down
23 changes: 23 additions & 0 deletions backend/common/Logging/CorrelationIdMiddleware.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Http.Extensions;

namespace Common.Logging;

using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Serilog.Context;

public class CorrelationIdMiddleware(RequestDelegate next, ILogger<CorrelationIdMiddleware> logger)
{
public const string CorrelationIdHeader = "X-Correlation-ID";
public async Task InvokeAsync(HttpContext context)
{
var correlationId = context.Request.Headers[CorrelationIdHeader].FirstOrDefault() ?? Guid.NewGuid().ToString();
context.Items["CorrelationId"] = correlationId;
context.Response.Headers.Append(CorrelationIdHeader, correlationId);
using (LogContext.PushProperty(CorrelationIdHeader, correlationId))
{
logger.LogInformation($"CorrelationId: {correlationId} {context.Request.GetEncodedUrl}");
await next(context);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Pidp.Kafka.Consumer.InCustodyProvisioning;
using Pidp.Models;
using Pidp.Models.Lookups;

public class InCustodyService(IClock clock, PidpDbContext context, ILogger<InCustodyService> logger, IKafkaProducer<string, AccessRequest> producer, IEdtCoreClient coreClient, IKeycloakAdministrationClient keycloakAdministrationClient, PidpConfiguration pidpConfiguration) : IInCustodyService
public class InCustodyService(IClock clock, PidpDbContext context, ILogger<InCustodyService> logger, IKafkaProducer<string, EdtDisclosureUserProvisioning> producer, IEdtCoreClient coreClient, IKeycloakAdministrationClient keycloakAdministrationClient, PidpConfiguration pidpConfiguration) : IInCustodyService
{

public async Task<Task> ProcessInCustodySubmissionMessage(InCustodyParticipantModel value)
Expand Down Expand Up @@ -129,34 +129,49 @@ private async Task<ExtendedUserRepresentation> AddOrUpdateKeycloakUserAsync(InCu

private async Task<AccessRequest> CreateInCustodyAccessRequest(ExtendedUserRepresentation keycloakUser, InCustodyParticipantModel value)
{
var party = context.Parties.Where(p => p.Jpdid == keycloakUser.Username).FirstOrDefault();


var party = new Party
if (party != null)
{
UserId = keycloakUser.Id,
Jpdid = keycloakUser.Username,
FirstName = keycloakUser.FirstName!,
LastName = keycloakUser.LastName!,
Email = keycloakUser.Username
};

context.Parties.Add(party);

logger.LogPartyAlreadyPresent(party.Jpdid);
}
else
{
party = new Party
{
UserId = keycloakUser.Id,
Jpdid = keycloakUser.Username,
FirstName = keycloakUser.FirstName!,
LastName = keycloakUser.LastName!,
Email = keycloakUser.Username
};

var partyAdded = await context.SaveChangesAsync();
context.Parties.Add(party);
await context.SaveChangesAsync();
party = context.Parties.Where(p => p.Jpdid == keycloakUser.Username).FirstOrDefault();
}

if (partyAdded > 0)
if (party != null)
{
var accessRequest = new AccessRequest
var accessRequest = context.AccessRequests.Where(req => req.PartyId == party.Id && req.AccessTypeCode == AccessTypeCode.DigitalEvidenceDisclosure).FirstOrDefault();

if (accessRequest != null)
{
Party = party,
AccessTypeCode = AccessTypeCode.DigitalEvidenceDisclosure,
RequestedOn = clock.GetCurrentInstant()
};
logger.LogAccessRequestAlreadyPresent(party.Jpdid, accessRequest.Id);
}
else
{
accessRequest = new AccessRequest
{
Party = party,
AccessTypeCode = AccessTypeCode.DigitalEvidenceDisclosure,
RequestedOn = clock.GetCurrentInstant()
};

context.AccessRequests.Add(accessRequest);
context.AccessRequests.Add(accessRequest);

await context.SaveChangesAsync();
await context.SaveChangesAsync();
}

return accessRequest;
}
Expand All @@ -169,6 +184,7 @@ private async Task<AccessRequest> CreateInCustodyAccessRequest(ExtendedUserRepre
}



/// <summary>
/// Publish a message to tell disclosure service that a new user should be created
/// This will be with the username for corrections users
Expand All @@ -180,7 +196,7 @@ public async Task<Task> PublishDisclosurePortalMessage(AccessRequest accessReque

var msgId = Guid.NewGuid().ToString();
// publish to the topic for disclosure portal to handle provisioning
var delivered = await producer.ProduceAsync(pidpConfiguration.KafkaCluster.DisclosurePublicUserCreationTopic, msgId, accessRequest);
var delivered = await producer.ProduceAsync(pidpConfiguration.KafkaCluster.DisclosurePublicUserCreationTopic, msgId, GetInCustoryDisclosureUserModel(accessRequest, value));

if (delivered.Status == Confluent.Kafka.PersistenceStatus.Persisted)
{
Expand All @@ -193,6 +209,26 @@ public async Task<Task> PublishDisclosurePortalMessage(AccessRequest accessReque

return Task.CompletedTask;
}


private static EdtDisclosureUserProvisioning GetInCustoryDisclosureUserModel(AccessRequest accessRequest, InCustodyParticipantModel model)
{

return new EdtDisclosureUserProvisioning
{
Key = $"{model.ParticipantId}",
UserName = accessRequest.Party.Jpdid,
Email = accessRequest.Party.Email,
FullName = $"{accessRequest.Party.FirstName} {accessRequest.Party.LastName}",
AccountType = "Saml",
Role = "User",
SystemName = AccessTypeCode.DigitalEvidenceDisclosure.ToString(),
AccessRequestId = accessRequest.Id,
OrganizationType = "In-custody",
OrganizationName = "Public",
PersonKey = model.ParticipantId
};
}
}

public static partial class InCustodyServiceLoggingExtensions
Expand All @@ -219,6 +255,10 @@ public static partial class InCustodyServiceLoggingExtensions
public static partial void LogIDPNotFound(this ILogger logger, string realm, string idp);
[LoggerMessage(11, LogLevel.Error, "Failed to complete in-custody onboarding {msg}")]
public static partial void LogInCustodyServiceException(this ILogger logger, string msg, Exception ex);
[LoggerMessage(12, LogLevel.Information, "Party already present {party}")]
public static partial void LogPartyAlreadyPresent(this ILogger logger, string party);
[LoggerMessage(13, LogLevel.Information, "Access request {accessRequestId} already present for party {party}")]
public static partial void LogAccessRequestAlreadyPresent(this ILogger logger, string party, int accessRequestId);

}

Expand Down
2 changes: 2 additions & 0 deletions backend/webapi/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace Pidp;
using System.Reflection;
using System.Text.Json;
using Common.Kafka;
using Common.Logging;
using Common.Utils;
using FluentValidation.AspNetCore;
using MicroElements.Swashbuckle.FluentValidation.AspNetCore;
Expand Down Expand Up @@ -362,6 +363,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
// For example: 200, 201, 203 -> 2xx
options.ReduceStatusCodeCardinality();
});
app.UseMiddleware<CorrelationIdMiddleware>();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
Expand Down

0 comments on commit de2371f

Please sign in to comment.