Skip to content

Commit

Permalink
Add the calling app's name to TRN allocation tasks (#1684)
Browse files Browse the repository at this point in the history
  • Loading branch information
gunndabad authored Nov 18, 2024
1 parent 4d2806c commit 9365553
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public static IServiceCollection AddRateLimiting(
{
var rateLimiterOptions = httpContext.RequestServices.GetRequiredService<IOptions<ClientIdRateLimiterOptions>>().Value;
var connectionMultiplexerFactory = () => httpContext.RequestServices.GetRequiredService<IConnectionMultiplexer>();
var partitionKey = ClaimsPrincipalCurrentUserProvider.TryGetCurrentClientIdFromHttpContext(httpContext, out var userId) ? userId.ToString() : UnknownUserPartitionKey;
var partitionKey = ClaimsPrincipalCurrentUserProvider.TryGetCurrentApplicationUserFromHttpContext(httpContext, out var userId) ? userId.ToString() : UnknownUserPartitionKey;
var clientRateLimit = rateLimiterOptions.ClientRateLimits.TryGetValue(partitionKey, out var windowOptions) ? windowOptions : rateLimiterOptions.DefaultRateLimit;

// Window isn't available via RateLimitMetadata so stash it on the HttpContext instead
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,30 @@ namespace TeachingRecordSystem.Api.Infrastructure.Security;

public class ClaimsPrincipalCurrentUserProvider(IHttpContextAccessor httpContextAccessor) : ICurrentUserProvider
{
public static bool TryGetCurrentClientIdFromHttpContext(HttpContext httpContext, out Guid userId)
public static bool TryGetCurrentApplicationUserFromHttpContext(HttpContext httpContext, out (Guid UserId, string Name) user)
{
var userIdStr = httpContext.User.FindFirstValue("sub");
var name = httpContext.User.FindFirstValue(ClaimTypes.Name);

if (userIdStr is null)
if (userIdStr is null || !Guid.TryParse(userIdStr, out var userId) || name is null)
{
userId = default;
user = default;
return false;
}

return Guid.TryParse(userIdStr, out userId);
user = (UserId: userId, Name: name);
return true;
}

public Guid GetCurrentApplicationUserId()
public (Guid UserId, string Name) GetCurrentApplicationUser()
{
var httpContext = httpContextAccessor.HttpContext ?? throw new Exception("No HttpContext.");

if (!TryGetCurrentClientIdFromHttpContext(httpContext, out var userId))
if (!TryGetCurrentApplicationUserFromHttpContext(httpContext, out var user))
{
throw new Exception("Current user has no 'sub' claim.");
throw new Exception("No current user.");
}

return userId;
return user;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ namespace TeachingRecordSystem.Api.Infrastructure.Security;

public interface ICurrentUserProvider
{
Guid GetCurrentApplicationUserId();
(Guid UserId, string Name) GetCurrentApplicationUser();
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public GetOrCreateTrnRequestHandler(

public async Task<TrnRequestInfo> Handle(GetOrCreateTrnRequest request, CancellationToken cancellationToken)
{
var currentApplicationUserId = _currentUserProvider.GetCurrentApplicationUserId();
var (currentApplicationUserId, _) = _currentUserProvider.GetCurrentApplicationUser();

await using var requestIdLock = await _distributedLockProvider.AcquireLockAsync(
DistributedLockKeys.TrnRequestId(currentApplicationUserId, request.RequestId),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public GetTrnRequestHandler(

public async Task<TrnRequestInfo> Handle(GetTrnRequest request, CancellationToken cancellationToken)
{
var currentApplicationUserId = _currentUserProvider.GetCurrentApplicationUserId();
var (currentApplicationUserId, _) = _currentUserProvider.GetCurrentApplicationUser();

var trnRequest = await _trnRequestHelper.GetTrnRequestInfo(currentApplicationUserId, request.RequestId);
if (trnRequest == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class CreateTrnRequestHandler(
{
public async Task<TrnRequestInfo> Handle(CreateTrnRequestCommand command)
{
var currentApplicationUserId = currentUserProvider.GetCurrentApplicationUserId();
var (currentApplicationUserId, currentApplicationUserName) = currentUserProvider.GetCurrentApplicationUser();

var trnRequest = await trnRequestHelper.GetTrnRequestInfo(currentApplicationUserId, command.RequestId);
if (trnRequest is not null)
Expand Down Expand Up @@ -147,6 +147,7 @@ await crmQueryDispatcher.ExecuteQuery(new CreateContactQuery()
EmailAddress = emailAddress,
NationalInsuranceNumber = NationalInsuranceNumberHelper.Normalize(command.NationalInsuranceNumber),
PotentialDuplicates = potentialDuplicates.Select(d => (Duplicate: d, HasActiveAlert: resultsWithActiveAlerts.Contains(d.ContactId))).ToArray(),
ApplicationUserName = currentApplicationUserName,
Trn = trn,
TrnRequestId = TrnRequestHelper.GetCrmTrnRequestId(currentApplicationUserId, command.RequestId),
OutboxMessages = outboxMessages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class GetTrnRequestHandler(TrnRequestHelper trnRequestHelper, ICurrentUse
{
public async Task<TrnRequestInfo?> Handle(GetTrnRequestCommand command)
{
var currentApplicationUserId = currentUserProvider.GetCurrentApplicationUserId();
var (currentApplicationUserId, _) = currentUserProvider.GetCurrentApplicationUser();

var trnRequest = await trnRequestHelper.GetTrnRequestInfo(currentApplicationUserId, command.RequestId);
if (trnRequest is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class CreateContactQuery : ICrmQuery<Guid>
public required string? EmailAddress { get; init; }
public required string? NationalInsuranceNumber { get; init; }
public required IReadOnlyCollection<(FindPotentialDuplicateContactsResult Duplicate, bool HasActiveAlert)> PotentialDuplicates { get; init; }
public required string ApplicationUserName { get; init; }
public required string? Trn { get; init; }
public required string? TrnRequestId { get; init; }
public required IEnumerable<dfeta_TrsOutboxMessage> OutboxMessages { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,17 @@ public async Task<Guid> Execute(CreateContactQuery query, IOrganizationServiceAs
dfeta_TRN = query.Trn
};

if (query.Trn is null)
{
// CRM plug-in explodes if TRN is specified but is null
contact.Attributes.Remove(Contact.Fields.dfeta_TRN);
}

requestBuilder.AddRequest(new CreateRequest() { Target = contact });

foreach (var (duplicate, hasActiveAlert) in query.PotentialDuplicates)
{
var task = CreateDuplicateReviewTaskEntity(duplicate, contactId, hasActiveAlert);
var task = CreateDuplicateReviewTaskEntity(duplicate, hasActiveAlert);
requestBuilder.AddRequest(new CreateRequest() { Target = task });
}

Expand All @@ -49,66 +55,66 @@ public async Task<Guid> Execute(CreateContactQuery query, IOrganizationServiceAs
await requestBuilder.Execute();

return contactId;
}

private CrmTask CreateDuplicateReviewTaskEntity(FindPotentialDuplicateContactsResult duplicate, Guid contactId, bool hasActiveAlert)
{
var description = GetDescription();

var category = "DMSImportTrn";

return new CrmTask()
CrmTask CreateDuplicateReviewTaskEntity(FindPotentialDuplicateContactsResult duplicate, bool hasActiveAlert)
{
RegardingObjectId = contactId.ToEntityReference(Contact.EntityLogicalName),
dfeta_potentialduplicateid = duplicate.ContactId.ToEntityReference(Contact.EntityLogicalName),
Category = category,
Subject = "Notification for QTS Unit Team",
Description = description
};
var description = GetDescription();

string GetDescription()
{
var sb = new StringBuilder();
sb.AppendLine("Potential duplicate");
sb.AppendLine("Matched on");
var category = $"TRN request from {query.ApplicationUserName}";

foreach (var matchedAttribute in duplicate.MatchedAttributes)
return new CrmTask()
{
sb.AppendLine(matchedAttribute switch
{
Contact.Fields.FirstName => $" - First name: '{duplicate.FirstName}'",
Contact.Fields.MiddleName => $" - Middle name: '{duplicate.MiddleName}'",
Contact.Fields.LastName => $" - Last name: '{duplicate.LastName}'",
Contact.Fields.BirthDate => $" - Date of birth: '{duplicate.DateOfBirth:dd/MM/yyyy}'",
Contact.Fields.dfeta_NINumber => $" - National Insurance number: '{duplicate.NationalInsuranceNumber}'",
Contact.Fields.EMailAddress1 => $" - Email address: '{duplicate.EmailAddress}'",
_ => throw new Exception($"Unknown matched field: '{matchedAttribute}'.")
});
}
RegardingObjectId = contactId.ToEntityReference(Contact.EntityLogicalName),
dfeta_potentialduplicateid = duplicate.ContactId.ToEntityReference(Contact.EntityLogicalName),
Category = category,
Subject = "Notification for QTS Unit Team",
Description = description
};

string GetDescription()
{
var sb = new StringBuilder();
sb.AppendLine("Potential duplicate");
sb.AppendLine("Matched on");

var additionalFlags = new List<string>();
foreach (var matchedAttribute in duplicate.MatchedAttributes)
{
sb.AppendLine(matchedAttribute switch
{
Contact.Fields.FirstName => $" - First name: '{duplicate.FirstName}'",
Contact.Fields.MiddleName => $" - Middle name: '{duplicate.MiddleName}'",
Contact.Fields.LastName => $" - Last name: '{duplicate.LastName}'",
Contact.Fields.BirthDate => $" - Date of birth: '{duplicate.DateOfBirth:dd/MM/yyyy}'",
Contact.Fields.dfeta_NINumber => $" - National Insurance number: '{duplicate.NationalInsuranceNumber}'",
Contact.Fields.EMailAddress1 => $" - Email address: '{duplicate.EmailAddress}'",
_ => throw new Exception($"Unknown matched field: '{matchedAttribute}'.")
});
}

var additionalFlags = new List<string>();

if (hasActiveAlert)
{
additionalFlags.Add("active sanctions");
}

if (hasActiveAlert)
{
additionalFlags.Add("active sanctions");
}
if (duplicate.HasQtsDate)
{
additionalFlags.Add("QTS date");
}

if (duplicate.HasQtsDate)
{
additionalFlags.Add("QTS date");
}
if (duplicate.HasEytsDate)
{
additionalFlags.Add("EYTS date");
}

if (duplicate.HasEytsDate)
{
additionalFlags.Add("EYTS date");
}
if (additionalFlags.Count > 0)
{
sb.AppendLine($"Matched record has {string.Join(" & ", additionalFlags)}");
}

if (additionalFlags.Count > 0)
{
sb.AppendLine($"Matched record has {string.Join(" & ", additionalFlags)}");
return sb.ToString();
}

return sb.ToString();
}
}
}
Loading

0 comments on commit 9365553

Please sign in to comment.