-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #195 from bcgov/BCPSDEMS-1174-hold-non-matching-VC…
…-accounts Bcpsdems 1174 hold non matching vc accounts
- Loading branch information
Showing
194 changed files
with
27,244 additions
and
71 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net6.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Version>1.0.0</Version> | ||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<ProjectReference Include="..\common\Common.csproj" /> | ||
</ItemGroup> | ||
|
||
<ItemGroup> | ||
<Folder Include="Data\Migrations\" /> | ||
</ItemGroup> | ||
|
||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
namespace ApprovalFlow; | ||
using common.Constants.Auth; | ||
|
||
public class ApprovalFlowConfiguration | ||
{ | ||
public static bool IsProduction() => EnvironmentName == Environments.Production; | ||
public static bool IsDevelopment() => EnvironmentName == Environments.Development; | ||
private static readonly string? EnvironmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); | ||
|
||
public ConnectionStringConfiguration ConnectionStrings { get; set; } = new(); | ||
public KafkaClusterConfiguration KafkaCluster { get; set; } = new(); | ||
public ApprovalConfiguration ApprovalConfig { get; set; } = new(); | ||
public KeycloakConfiguration Keycloak { get; set; } = new(); | ||
|
||
public SchemaRegistryConfiguration SchemaRegistry { get; set; } = new(); | ||
public TelemeteryConfiguration Telemetry { get; set; } = new TelemeteryConfiguration(); | ||
public SplunkConfiguration SplunkConfig { get; set; } = new SplunkConfiguration(); | ||
|
||
|
||
public class SplunkConfiguration | ||
{ | ||
public string Host { get; set; } = string.Empty; | ||
public string CollectorToken { get; set; } = string.Empty; | ||
} | ||
|
||
public class ApprovalConfiguration | ||
{ | ||
public string NotifyEmail { get; set; } = string.Empty; | ||
public string Subject { get; set; } = string.Empty; | ||
} | ||
|
||
// ------- Configuration Objects ------- | ||
|
||
public class TelemeteryConfiguration | ||
{ | ||
public string CollectorUrl { get; set; } = string.Empty; | ||
public string AzureConnectionString { get; set; } = string.Empty; | ||
public bool LogToConsole { get; set; } | ||
|
||
} | ||
|
||
|
||
public class ConnectionStringConfiguration | ||
{ | ||
public string ApprovalFlowDataStore { get; set; } = string.Empty; | ||
} | ||
|
||
public class KeycloakConfiguration | ||
{ | ||
public string RealmUrl { get; set; } = string.Empty; | ||
public string WellKnownConfig => KeycloakUrls.WellKnownConfig(this.RealmUrl); | ||
public string TokenUrl => KeycloakUrls.Token(this.RealmUrl); | ||
public string AdministrationUrl { get; set; } = string.Empty; | ||
public string AdministrationClientId { get; set; } = string.Empty; | ||
public string AdministrationClientSecret { get; set; } = string.Empty; | ||
public string HcimClientId { get; set; } = string.Empty; | ||
} | ||
|
||
|
||
|
||
public class SchemaRegistryConfiguration | ||
{ | ||
public string Url { get; set; } = string.Empty; | ||
public string ClientId { get; set; } = string.Empty; | ||
public string ClientSecret { get; set; } = string.Empty; | ||
|
||
} | ||
|
||
|
||
public class KafkaClusterConfiguration | ||
{ | ||
public string Url { get; set; } = string.Empty; | ||
public string BootstrapServers { get; set; } = string.Empty; | ||
public string SaslOauthbearerTokenEndpointUrl { get; set; } = string.Empty; | ||
public string IncomingApprovalCreationTopic { get; set; } = string.Empty; | ||
public string ApprovalResponseTopic { get; set; } = string.Empty; | ||
public string NotificationTopic { get;set; } = string.Empty; | ||
|
||
public string SaslOauthbearerProducerClientId { get; set; } = string.Empty; | ||
public string SaslOauthbearerProducerClientSecret { get; set; } = string.Empty; | ||
public string SaslOauthbearerConsumerClientId { get; set; } = string.Empty; | ||
public string SaslOauthbearerConsumerClientSecret { get; set; } = string.Empty; | ||
public string SslCaLocation { get; set; } = string.Empty; | ||
public string SslCertificateLocation { get; set; } = string.Empty; | ||
public string SslKeyLocation { get; set; } = string.Empty; | ||
public string Scope { get; set; } = "openid"; | ||
public string ConsumerGroupId { get; set; } = "approval-consumer-group"; | ||
|
||
|
||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
namespace ApprovalFlow.Data.Approval; | ||
|
||
using System.ComponentModel.DataAnnotations; | ||
using System.ComponentModel.DataAnnotations.Schema; | ||
using Common.Models.Approval; | ||
using DIAM.Common.Models; | ||
using NodaTime; | ||
|
||
[Table(nameof(ApprovalHistory))] | ||
public class ApprovalHistory : BaseAuditable | ||
{ | ||
[Key] | ||
public int Id { get; set; } | ||
public string DecisionNote { get; set; } = string.Empty; | ||
public string Approver { get; set; } = string.Empty; | ||
public int RequestId { get; set; } | ||
public Request AccessRequest { get; set; } | ||
public Instant? Deleted { get; set; } | ||
public ApprovalStatus Status { get; set; } = ApprovalStatus.PENDING; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
namespace ApprovalFlow.Data.Approval; | ||
|
||
using NodaTime; | ||
using System.ComponentModel.DataAnnotations.Schema; | ||
using System.ComponentModel.DataAnnotations; | ||
using DIAM.Common.Models; | ||
|
||
[Table(nameof(ApprovalRequest))] | ||
public class ApprovalRequest : BaseAuditable | ||
{ | ||
[Key] | ||
public int Id { get; set; } | ||
public string Reason { get; set; } = string.Empty; | ||
[Required] | ||
public string MessageKey { get; set; } = string.Empty; | ||
public string UserId { get; set; } = string.Empty; | ||
public string IdentityProvider { get; set; } = string.Empty; | ||
public int NoOfApprovalsRequired { get; set; } | ||
public string RequiredAccess { get; set; } = string.Empty; | ||
public Instant? Approved { get; set; } | ||
public Instant? Completed { get; set; } | ||
public ICollection<Request> Requests { get; set; } = new List<Request>(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
namespace ApprovalFlow.Data.Approval; | ||
|
||
using AutoMapper; | ||
using Common.Models.Approval; | ||
|
||
public class MappingProfile : Profile | ||
{ | ||
public MappingProfile() | ||
{ | ||
this.CreateMap<ApprovalRequest, ApprovalModel>(); | ||
this.CreateMap<Request, RequestModel>(); | ||
this.CreateMap<ApprovalHistory, ApprovalHistoryModel>(); | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
namespace ApprovalFlow.Data.Approval; | ||
|
||
using System.ComponentModel.DataAnnotations; | ||
using System.ComponentModel.DataAnnotations.Schema; | ||
using DIAM.Common.Models; | ||
|
||
/// <summary> | ||
/// An ApprovalRequest can contain one or more requests, this allows us to group requests for a user | ||
/// together. E.g. a lawyer might be requesting to be a participant in core and user in disclosure. | ||
/// Or in future a user may request to have access to something and also change their email address | ||
/// </summary> | ||
[Table(nameof(Request))] | ||
public class Request : BaseAuditable | ||
{ | ||
[Key] | ||
public int Id { get; set; } | ||
[Required] | ||
public int ApprovalRequestId { get; set; } | ||
public ApprovalRequest? ApprovalRequest { get; set; } // navigation property | ||
public int RequestId { get; set; } | ||
|
||
public ApprovalType ApprovalType { get; set; } = ApprovalType.AccessRequest; | ||
public string RequestType { get; set; } = string.Empty; | ||
public ICollection<ApprovalHistory> History { get; set; } | ||
|
||
} | ||
|
||
public enum ApprovalType | ||
{ | ||
AccessRequest, | ||
AccountChange | ||
} |
87 changes: 87 additions & 0 deletions
87
backend/ApprovalFlow/Data/ApprovalFlowDataStoreDbContext.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
namespace ApprovalFlow.Data; | ||
|
||
using ApprovalFlow.Data.Approval; | ||
using ApprovalFlow.Models; | ||
using DIAM.Common.Models; | ||
using Microsoft.EntityFrameworkCore; | ||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion; | ||
using NodaTime; | ||
|
||
public class ApprovalFlowDataStoreDbContext : DbContext | ||
{ | ||
private readonly IClock clock; | ||
|
||
public ApprovalFlowDataStoreDbContext(DbContextOptions<ApprovalFlowDataStoreDbContext> options, IClock clock) : base(options) => this.clock = clock; | ||
public DbSet<IdempotentConsumer> IdempotentConsumers { get; set; } = default!; | ||
public DbSet<ApprovalRequest> ApprovalRequests { get; set; } = default!; | ||
public DbSet<Request> Requests { get; set; } = default!; | ||
public DbSet<ApprovalHistory> ApprovalHistories { get; set; } = default!; | ||
|
||
|
||
|
||
public override int SaveChanges() | ||
{ | ||
this.ApplyAudits(); | ||
|
||
return base.SaveChanges(); | ||
} | ||
|
||
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) | ||
{ | ||
this.ApplyAudits(); | ||
|
||
return await base.SaveChangesAsync(cancellationToken); | ||
} | ||
|
||
protected override void OnModelCreating(ModelBuilder modelBuilder) | ||
{ | ||
modelBuilder.HasDefaultSchema("approvalflow"); | ||
base.OnModelCreating(modelBuilder); | ||
|
||
modelBuilder | ||
.Entity<Request>() | ||
.Property(d => d.ApprovalType) | ||
.HasConversion(new EnumToStringConverter<ApprovalType>()); | ||
|
||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(ApprovalFlowDataStoreDbContext).Assembly); | ||
} | ||
|
||
private void ApplyAudits() | ||
{ | ||
this.ChangeTracker.DetectChanges(); | ||
var updated = this.ChangeTracker.Entries() | ||
.Where(x => x.Entity is BaseAuditable | ||
&& (x.State == EntityState.Added || x.State == EntityState.Modified)); | ||
|
||
var currentInstant = this.clock.GetCurrentInstant(); | ||
|
||
foreach (var entry in updated) | ||
{ | ||
entry.CurrentValues[nameof(BaseAuditable.Modified)] = currentInstant; | ||
|
||
if (entry.State == EntityState.Added) | ||
{ | ||
entry.CurrentValues[nameof(BaseAuditable.Created)] = currentInstant; | ||
} | ||
else | ||
{ | ||
entry.Property(nameof(BaseAuditable.Created)).IsModified = false; | ||
} | ||
} | ||
} | ||
|
||
public async Task IdempotentConsumer(string messageId, string consumer, Instant consumeDate) | ||
{ | ||
await this.IdempotentConsumers.AddAsync(new IdempotentConsumer | ||
{ | ||
MessageId = messageId, | ||
Consumer = consumer, | ||
ConsumeDate = consumeDate | ||
}); | ||
await this.SaveChangesAsync(); | ||
} | ||
|
||
public async Task<bool> HasBeenProcessed(string messageId, string consumer) => await this.IdempotentConsumers.AnyAsync(x => x.MessageId == messageId && x.Consumer == consumer); | ||
|
||
|
||
} |
Oops, something went wrong.