Skip to content

Commit

Permalink
Merge pull request #764 from bcgov/develop
Browse files Browse the repository at this point in the history
promote
  • Loading branch information
leewrigh authored Feb 6, 2025
2 parents 50292a4 + 490d920 commit 79632d4
Show file tree
Hide file tree
Showing 22 changed files with 190 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ public async Task<int> CreateCase(EdtCaseDto caseInfo)
/// <exception cref="EdtDisclosureServiceException"></exception>
public async Task<IEnumerable<KeyIdPair>> GetUserCases(string userIdOrKey)
{
this.logger.LogInformation($"Getting cases for user {userIdOrKey}");
this.logger.LogInformation($"Getting cases for user {userIdOrKey} org-unit {this.EdtOrgUnitId}");

var response = await this.GetAsync<IEnumerable<KeyIdPair>>($"api/v1/org-units/{this.EdtOrgUnitId}/users/{userIdOrKey}/cases");

Expand Down
36 changes: 30 additions & 6 deletions backend/webapi/Features/Parties/ProfileStatus.Model.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
namespace Pidp.Features.Parties;

using System.Security.Claims;
using Microsoft.EntityFrameworkCore;
using Pidp.Data;
using Pidp.Extensions;
using Pidp.Infrastructure.HttpClients.Claims;
using Pidp.Models;
Expand Down Expand Up @@ -451,15 +453,25 @@ protected override void SetAlertsAndStatus(ProfileStatusDto profile)

public class DefenceDelegateControls : ProfileSection
{
private readonly PidpDbContext context;

internal override string SectionName => "digitalEvidenceCounselDelegateControls";
public DefenceDelegateControls(ProfileStatusDto profile) : base(profile) { }

public DefenceDelegateControls(ProfileStatusDto profile) : base(profile)
{

}

protected override void SetAlertsAndStatus(ProfileStatusDto profile)
{
if (!profile.UserIsInLawSociety)
{
this.StatusCode = StatusCode.Hidden;
return;
}



if (profile.CompletedEnrolments.Contains(AccessTypeCode.DigitalEvidenceDefence))
{
this.StatusCode = StatusCode.Available;
Expand All @@ -472,27 +484,39 @@ protected override void SetAlertsAndStatus(ProfileStatusDto profile)
}
this.StatusCode = StatusCode.Incomplete;
}

}

public class DefenseDelegateAccess : ProfileSection
{
private readonly PidpDbContext context;

internal override string SectionName => "digitalEvidenceCounselDelegateAccess";
public DefenseDelegateAccess(ProfileStatusDto profile) : base(profile) { }
public DefenseDelegateAccess(ProfileStatusDto profile) : base(profile)
{

}



protected override void SetAlertsAndStatus(ProfileStatusDto profile)
{
if (!profile.UserIsBcServicesCardDefenseDelegate)
{
this.StatusCode = StatusCode.Hidden;
return;
}
if (profile.CompletedEnrolments.Contains(AccessTypeCode.DigitalEvidenceDefence))

if (!profile.DemographicsEntered)
{
this.StatusCode = StatusCode.Available;
this.StatusCode = StatusCode.Locked;
return;
}
if (!profile.DemographicsEntered)


if (profile.IsActiveDelegateUser)
{
this.StatusCode = StatusCode.Locked;
this.StatusCode = StatusCode.Complete;
return;
}
this.StatusCode = StatusCode.Incomplete;
Expand Down
18 changes: 15 additions & 3 deletions backend/webapi/Features/Parties/ProfileStatus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ namespace Pidp.Features.Parties;
public partial class ProfileStatus
{
private readonly PidpConfiguration configuration;
private readonly ILogger<ProfileStatus> logger;
private readonly PidpDbContext dbContext;

public ProfileStatus(PidpConfiguration configuration)
public ProfileStatus(PidpConfiguration configuration, ILogger<ProfileStatus> logger, PidpDbContext dbContext)
{
this.configuration = configuration;
this.logger = logger;
this.dbContext = dbContext;
}
private static readonly Histogram ProfileDuration = Metrics.CreateHistogram("pidp_profile_duration", "Histogram of profile duration requests.");

Expand Down Expand Up @@ -67,6 +71,7 @@ public abstract class ProfileSection
public ProfileSection(ProfileStatusDto profile) => this.SetAlertsAndStatus(profile);

protected abstract void SetAlertsAndStatus(ProfileStatusDto profile);

}


Expand Down Expand Up @@ -186,6 +191,7 @@ await this.profileUpdateService.UpdateUserProfile(new UpdatePersonContactInfoMod
: null;



// if the user is a BCPS user then we'll flag this portion as completed
if (profile.OrganizationDetailEntered && profile.OrganizationCode == OrganizationCode.CorrectionService && orgCorrectionDetail != null)
{
Expand Down Expand Up @@ -273,7 +279,11 @@ await this.profileUpdateService.UpdateUserProfile(new UpdatePersonContactInfoMod
profile.UserTypes = lookups;
}


if (profile.UserIsBcServicesCardDefenseDelegate)
{
var validDelegate = this.context.DelegateAccessRequests.Where(req => req.Party == party && req.RequestStatus == "Granted").Any();
profile.IsActiveDelegateUser = validDelegate;
}


var profileStatus = new Model
Expand All @@ -289,15 +299,16 @@ await this.profileUpdateService.UpdateUserProfile(new UpdatePersonContactInfoMod
new Model.DigitalEvidenceCaseManagement(profile),
// controls for the lawyer to manage delegates
new Model.DefenceDelegateControls(profile),
// controls for delegates to request access
new Model.DefenseDelegateAccess(profile),
// controls for delegates to request access
new Model.DefenseAndDutyCounsel(profile),
//new Model.Uci(profile),
new Model.SubmittingAgencyCaseManagement(profile),
}
.ToDictionary(section => section.SectionName, section => section)
};


// handle ordering
this.OrderProfile(command.User, profileStatus);

Expand Down Expand Up @@ -390,6 +401,7 @@ public class ProfileStatusDto
public PublicUserValidation? CodeValidations { get; set; }
public string? JusticeSectorService { get; set; }
public string? EmployeeIdentifier { get; set; }
public bool IsActiveDelegateUser { get; set; }
//public bool OrganizationDetailEntered { get; set; }
public IEnumerable<AccessTypeCode> CompletedEnrolments { get; set; } = Enumerable.Empty<AccessTypeCode>();
public IEnumerable<string> UserTypes { get; set; } = Enumerable.Empty<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ public async Task<int> HandlePendingCases()
if (longRunningCases.Count > 0)
{
logger.LogError($"*** We have {longRunningCases} that have not completed within 15 minutes ***");
}



}

// find any cases that are not complete or deleted
var cases = dbContext.SubmittingAgencyRequests.Include(r => r.Party).Where(c => c.RequestStatus != EventStatus.Complete && c.RequestStatus != EventStatus.Deleted && c.Modified <= republishTimeout).ToList();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
namespace Pidp.Features.SanityChecks.DelegateRequests;

using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using Pidp.Data;

public class DelegateAccessChecks(ILogger<DelegateAccessChecks> logger, PidpConfiguration configuration, PidpDbContext context, IClock clock) : IDelegateAccessChecks
{
public async Task<int> FlagExpiredRequestsAsync()
{
var expiredDate = clock.GetCurrentInstant().Minus(Duration.FromDays(configuration.DelegateAccessExpiryDays));
var expiredRequests = await context.DelegateAccessRequests
.Where(req => req.RequestStatus == "Submitted" && req.Created < expiredDate).ToListAsync();

foreach (var request in expiredRequests)
{
// Update request status or perform other actions
request.RequestStatus = "Expired";
request.ResponseDate = clock.GetCurrentInstant();
}

if (expiredRequests.Count > 0)
{
logger.LogInformation($"Flagged {expiredRequests.Count} expired requests");
}

return await context.SaveChangesAsync();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Pidp.Features.SanityChecks.DelegateRequests;

using Quartz;

[PersistJobDataAfterExecution]
[DisallowConcurrentExecution]
public class DelegateAccessSanityCheckTask(ILogger<DelegateAccessSanityCheckTask> logger, IDelegateAccessChecks delegateChecks) : IJob
{

public async Task Execute(IJobExecutionContext context)
{
logger.LogDebug("Delegate sanity check task started");

var updates = await delegateChecks.FlagExpiredRequestsAsync();
if (updates > 0)
{
logger.LogInformation($"Flagged {updates} expired requests");
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Pidp.Features.SanityChecks.DelegateRequests;

public interface IDelegateAccessChecks
{
public Task<int> FlagExpiredRequestsAsync();

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class SanityCheckTask(ILogger<SanityCheckTask> logger, ICaseSanityChecks

public Task Execute(IJobExecutionContext context)
{
logger.LogInformation("Sanity check task started");
logger.LogDebug("Sanity check task started");

var updates = caseSanityChecks.HandlePendingCases();

Expand Down
10 changes: 9 additions & 1 deletion backend/webapi/PidpConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class PidpConfiguration
public string ApplicationUrl { get; set; } = string.Empty;
public string CorrectionsIDP { get; set; } = "siteminder";
public int AUFToolsCaseId { get; set; }
public int DelegateAccessExpiryDays { get; set; } = 30;
public AddressAutocompleteClientConfiguration AddressAutocompleteClient { get; set; } = new();
public ConnectionStringConfiguration ConnectionStrings { get; set; } = new();
public ChesClientConfiguration ChesClient { get; set; } = new();
Expand Down Expand Up @@ -46,7 +47,7 @@ public class BackGroundServicesConfiguration
{
public DecomissionCaseAccessService DecomissionCaseAccessService { get; set; } = new DecomissionCaseAccessService();
public SyncCaseAccessService SyncCaseAccessService { get; set; } = new SyncCaseAccessService();

public DelegateAccessService DelegateAccessService { get; set; } = new DelegateAccessService();
}

public class PersonLookupType
Expand All @@ -62,6 +63,13 @@ public class SplunkConfiguration
public string CollectorToken { get; set; } = string.Empty;
}

public class DelegateAccessService
{
public int GracePeriod { get; set; }
public string PollCron { get; set; } = "0 * * * * ?";
}


public class DecomissionCaseAccessService
{
// public int PeriodicTimer { get; set; }
Expand Down
24 changes: 20 additions & 4 deletions backend/webapi/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace Pidp;
using Pidp.Features.Organization.UserTypeService;
using Pidp.Features.Parties;
using Pidp.Features.SanityChecks.CaseRequests;
using Pidp.Features.SanityChecks.DelegateRequests;
using Pidp.Features.SanityChecks.Onboarding;
using Pidp.Helpers.Middleware;
using Pidp.Infrastructure;
Expand Down Expand Up @@ -165,6 +166,8 @@ public void ConfigureServices(IServiceCollection services)
services.AddScoped<ICourtAccessService, CourtAccessService>();
services.AddScoped<IProfileUpdateService, ProfileUpdateServiceImpl>();
services.AddScoped<ICaseSanityChecks, CaseSanityChecks>();
services.AddScoped<IDelegateAccessChecks, DelegateAccessChecks>();

services.AddScoped<IDIAMAdminService, DIAMAdminService>();

services.AddSingleton(typeof(IKafkaProducer<,>), typeof(KafkaProducer<,>));
Expand Down Expand Up @@ -303,17 +306,19 @@ public void ConfigureServices(IServiceCollection services)

q.AddJob<CourtAccessScheduledJob>(opts => opts.WithIdentity(jobKey));

// add case decommision job
var decommisionJobKey = new JobKey("Decommission case access trigger");
q.AddJob<CaseAccessDecommissionJob>(opts => opts.WithIdentity(decommisionJobKey));
// add case decommission job
var decommissionJobKey = new JobKey("Decommission case access trigger");
q.AddJob<CaseAccessDecommissionJob>(opts => opts.WithIdentity(decommissionJobKey));
Log.Information($"Scheduling Case Decommission with params [{config.BackGroundServices.DecomissionCaseAccessService.PollCron}]");

// Create a trigger for the job
q.AddTrigger(opts => opts
.ForJob(decommisionJobKey) // link to the HelloWorldJob
.ForJob(decommissionJobKey) // link to the HelloWorldJob
.WithIdentity("case-decommission-trigger") // give the trigger a unique name
.WithCronSchedule(config.BackGroundServices.DecomissionCaseAccessService.PollCron));



// add case sync job
var caseAccessSyncJobKey = new JobKey("Case access sync trigger");
q.AddJob<SyncCaseAccessJob>(opts => opts.WithIdentity(caseAccessSyncJobKey));
Expand All @@ -326,6 +331,17 @@ public void ConfigureServices(IServiceCollection services)
.WithCronSchedule(config.BackGroundServices.SyncCaseAccessService.PollCron));



// add delegate access job
var delegateAccessJob = new JobKey("Delegated access sanity trigger");
q.AddJob<DelegateAccessSanityCheckTask>(opts => opts.WithIdentity(delegateAccessJob));
Log.Information($"Scheduling Delegate Sanity Check with params [{config.BackGroundServices.DecomissionCaseAccessService.PollCron}]");

// Create a trigger for the job
q.AddTrigger(opts => opts
.ForJob(delegateAccessJob) // link to the HelloWorldJob
.WithIdentity("delegate-access-trigger") // give the trigger a unique name
.WithCronSchedule(config.BackGroundServices.DelegateAccessService.PollCron));
});


Expand Down
3 changes: 3 additions & 0 deletions backend/webapi/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
"GracePeriod": 30, // 30 days,
"PollCron": "0 0 0 ? * * *"
},
"DelegateAccessService": {
"PollCron": "0 0 1 ? * * *"
},
"SyncCaseAccessService": {
"PollCron": "0 0 * ? * * *"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ <h2>Existing Disclosure Access Requests</h2>
</table>
</ng-container>
<mat-paginator
[ngClass]="{'no-background':true}"
[pageSizeOptions]="[5, 10, 25 ,50]"
[pageSize]="pageSize"
[hidePageSize]="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ button.primary {
color: white !important;
}

mat-form-field.mat-paginator-pagesize-select {
.no-background {
background-color: white !important;
}

::ng-deep.mat-paginator {
background-color: white !important;
}
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ export class DigitalEvidenceCounselDelegatePage
req.requestStatus != 'Deleted' &&
req.requestStatus != 'Rescinded' &&
req.requestStatus != 'Error' &&
req.requestStatus != 'Expired' &&
req.requestStatus != 'Denied'
);
}
Expand Down Expand Up @@ -354,7 +355,7 @@ export class DigitalEvidenceCounselDelegatePage
this.submitText = 'Submit';
this.formState.LawyerEMailAddress.disable();
this.stagingId = response.responseData['id'];
this.validationMessage = `${response.responseData['firstName']} ${response.responseData['lastName']} is a valid email address - click Submit to request delegate access`;
this.validationMessage = `EMail entered is for is for ${response.responseData['firstName']} ${response.responseData['lastName']} - click Submit to request delegate access`;
if (response.information.length === 1) {
this.toastService.openInfoToast(
response.information[0] +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
</table>
</ng-container>
<mat-paginator
[ngClass]="{'no-background':true}"
[pageSizeOptions]="[5, 10, 25,50]"
[pageSize]="pageSize"
[hidePageSize]="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ button .deny {
margin-left: 1.3rem;
}

mat-form-field.mat-paginator-pagesize-select {
.no-background {
background-color: white !important;
}

.mat-form-field::ng-deep.mat-paginator {
background-color: white !important;
}
Loading

0 comments on commit 79632d4

Please sign in to comment.