Implemented centralised audit logging
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
namespace PostFundManagement.Domain.Abstractions;
|
||||
|
||||
public interface ITenantContextService
|
||||
{
|
||||
string? TenantName { get; }
|
||||
long TenantId { get; }
|
||||
bool IsAdmin { get; }
|
||||
bool HasTenantFilter { get; }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace PostFundManagement.Domain.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class AuditAttribute : Attribute;
|
||||
@@ -5,16 +5,19 @@ namespace PostFundManagement.Domain.Entities;
|
||||
[EntityTypeConfiguration<AuditLogConfiguration, AuditLog>]
|
||||
public class AuditLog : Models.AuditLog
|
||||
{
|
||||
public virtual User? Performer { get; set; }
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual User? Performer { get; set; }
|
||||
}
|
||||
|
||||
public sealed class AuditLogConfiguration : IEntityTypeConfiguration<Domain.Entities.AuditLog>
|
||||
public sealed class AuditLogConfiguration : IEntityTypeConfiguration<AuditLog>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Domain.Entities.AuditLog> builder)
|
||||
public void Configure(EntityTypeBuilder<AuditLog> builder)
|
||||
{
|
||||
builder.ToTable(nameof(Domain.Entities.AuditLog).Pluralize());
|
||||
builder.ToTable(nameof(AuditLog).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired(false);
|
||||
builder.Property(f => f.EntityName).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.EntityId).IsRequired();
|
||||
builder.Property(f => f.Action).IsRequired().HasMaxLength(ShortLabelLength);
|
||||
@@ -22,6 +25,12 @@ public sealed class AuditLogConfiguration : IEntityTypeConfiguration<Domain.Enti
|
||||
builder.Property(f => f.PerformedBy).IsRequired();
|
||||
builder.Property(f => f.Timestamp).IsRequired().HasDefaultValueSql("now()");
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired(false)
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Performer)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.PerformedBy)
|
||||
|
||||
@@ -9,6 +9,8 @@ public class Award : Models.Award
|
||||
|
||||
public virtual User? Approver { get; set; }
|
||||
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Organisation? Organisation { get; set; }
|
||||
|
||||
public virtual Programme? Programme { get; set; }
|
||||
@@ -27,6 +29,7 @@ public sealed class AwardConfiguration : IEntityTypeConfiguration<Award>
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.OrganisationId).IsRequired();
|
||||
builder.Property(f => f.ProgrammeId).IsRequired();
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProjectId).IsRequired(false);
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UpdatedBy).IsRequired(false);
|
||||
@@ -37,6 +40,12 @@ public sealed class AwardConfiguration : IEntityTypeConfiguration<Award>
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne(f => f.Organisation)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.OrganisationId)
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace PostFundManagement.Domain.Entities;
|
||||
[EntityTypeConfiguration<NotificationConfiguration, Notification>]
|
||||
public class Notification : Models.Notification
|
||||
{
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Organisation? Organisation { get; set; }
|
||||
|
||||
public virtual User? RecipientUser { get; set; }
|
||||
@@ -22,6 +24,7 @@ public sealed class NotificationConfiguration : IEntityTypeConfiguration<Notific
|
||||
builder.Property(f => f.SentAt).IsRequired(false);
|
||||
builder.Property(f => f.Recipient).IsRequired();
|
||||
builder.Property(f => f.OrganisationId).IsRequired();
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.Platform).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(NotificationPlatform.Email);
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
@@ -31,6 +34,12 @@ public sealed class NotificationConfiguration : IEntityTypeConfiguration<Notific
|
||||
builder.Property(f => f.Destination).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.Error).IsRequired(false);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne(f => f.Organisation)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.OrganisationId)
|
||||
|
||||
@@ -9,6 +9,8 @@ public class Portfolio : Models.Portfolio
|
||||
|
||||
public virtual User? Owner { get; set; }
|
||||
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Organisation? Organisation { get; set; }
|
||||
|
||||
public virtual ICollection<Programme> Programmes { get; set; } = [];
|
||||
@@ -21,6 +23,7 @@ public sealed class PortfolioConfiguration : IEntityTypeConfiguration<Portfolio>
|
||||
builder.ToTable(nameof(Portfolio).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.OrganisationId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.OwnedBy).IsRequired();
|
||||
@@ -28,6 +31,12 @@ public sealed class PortfolioConfiguration : IEntityTypeConfiguration<Portfolio>
|
||||
builder.Property(f => f.Name).IsRequired().HasMaxLength(LabelLength);
|
||||
builder.Property(f => f.Description).IsRequired(false).HasMaxLength(TextLength);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne(f => f.Organisation)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.OrganisationId)
|
||||
|
||||
@@ -8,6 +8,8 @@ public class Programme : Models.Programme
|
||||
public virtual User? Creator { get; set; }
|
||||
|
||||
public virtual User? Owner { get; set; }
|
||||
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Portfolio? Portfolio { get; set; }
|
||||
|
||||
@@ -27,6 +29,7 @@ public sealed class ProgrammeConfiguration : IEntityTypeConfiguration<Programme>
|
||||
builder.ToTable(nameof(Programme).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.PortfolioId).IsRequired();
|
||||
builder.Property(f => f.OwnedBy).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
@@ -37,6 +40,12 @@ public sealed class ProgrammeConfiguration : IEntityTypeConfiguration<Programme>
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.NoAction);
|
||||
|
||||
builder.HasOne(f => f.Portfolio)
|
||||
.WithMany(f => f.Programmes)
|
||||
.HasForeignKey(fk => fk.PortfolioId)
|
||||
|
||||
@@ -9,6 +9,8 @@ public class Project : Models.Project
|
||||
|
||||
public virtual User? Updator { get; set; }
|
||||
|
||||
public virtual Tenant? Tenant { get; set; }
|
||||
|
||||
public virtual Programme? Programme { get; set; }
|
||||
|
||||
public virtual ICollection<Award> Awards { get; set; } = [];
|
||||
@@ -21,6 +23,7 @@ public sealed class ProjectConfiguration : IEntityTypeConfiguration<Project>
|
||||
builder.ToTable(nameof(Project).Pluralize());
|
||||
|
||||
builder.HasKey(pk => pk.Id);
|
||||
builder.Property(f => f.TenantId).IsRequired();
|
||||
builder.Property(f => f.ProgrammeId).IsRequired();
|
||||
builder.Property(f => f.CreatedBy).IsRequired();
|
||||
builder.Property(f => f.UpdatedBy).IsRequired(false);
|
||||
@@ -37,6 +40,12 @@ public sealed class ProjectConfiguration : IEntityTypeConfiguration<Project>
|
||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>().HasDefaultValueSql("1")
|
||||
.HasSentinel(ApprovalStatus.Pending);
|
||||
|
||||
builder.HasOne(f => f.Tenant)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.TenantId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne(f => f.Programme)
|
||||
.WithMany(f => f.Projects)
|
||||
.HasForeignKey(fk => fk.ProgrammeId)
|
||||
|
||||
@@ -30,6 +30,12 @@ public sealed class TenantUserConfiguration : IEntityTypeConfiguration<TenantUse
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne(f => f.User)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.UserId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
builder.HasOne(f => f.Creator)
|
||||
.WithMany()
|
||||
.HasForeignKey(fk => fk.CreatedBy)
|
||||
|
||||
@@ -4,6 +4,37 @@ namespace PostFundManagement.Domain.Extensions;
|
||||
|
||||
public static class Mappers
|
||||
{
|
||||
public static TenantUser Map(this Entities.TenantUser entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
TenantId = entity.TenantId,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
Status = entity.Status,
|
||||
UserId = entity.UserId
|
||||
};
|
||||
|
||||
public static TenantOrganisation Map(this Entities.TenantOrganisation entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
Status = entity.Status,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
OrganisationId = entity.OrganisationId,
|
||||
TenantId = entity.TenantId
|
||||
};
|
||||
|
||||
public static Tenant Map(this Entities.Tenant entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
Name = entity.Name,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
Status = entity.Status,
|
||||
UpdatedAt = entity.UpdatedAt,
|
||||
UpdatedBy = entity.UpdatedBy
|
||||
};
|
||||
|
||||
public static Activity Map(this Entities.Activity entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
@@ -40,6 +71,7 @@ public static class Mappers
|
||||
ApprovedBy = entity.ApprovedBy,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
TenantId = entity.TenantId,
|
||||
OrganisationId = entity.OrganisationId,
|
||||
ProgrammeId = entity.ProgrammeId,
|
||||
ProjectId = entity.ProjectId,
|
||||
@@ -162,7 +194,7 @@ public static class Mappers
|
||||
AwardId = entity.AwardId,
|
||||
ContractId = entity.ContractId,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
InvitedOrganisationId = entity.InvitedOrganisationId,
|
||||
OrganisationId = entity.OrganisationId,
|
||||
Recipient = entity.Recipient,
|
||||
@@ -202,7 +234,7 @@ public static class Mappers
|
||||
public static Organisation Map(this Entities.Organisation entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
Email = entity.Email,
|
||||
Name = entity.Name,
|
||||
@@ -225,6 +257,7 @@ public static class Mappers
|
||||
{
|
||||
Id = entity.Id,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
TenantId = entity.TenantId,
|
||||
CreatedBy = entity.CreatedBy,
|
||||
Description = entity.Description,
|
||||
Name = entity.Name,
|
||||
@@ -239,6 +272,7 @@ public static class Mappers
|
||||
Destination = entity.Destination,
|
||||
Error = entity.Error,
|
||||
Message = entity.Message,
|
||||
TenantId = entity.TenantId,
|
||||
OrganisationId = entity.OrganisationId,
|
||||
Platform = entity.Platform,
|
||||
Recipient = entity.Recipient,
|
||||
@@ -255,6 +289,7 @@ public static class Mappers
|
||||
CreatedBy = entity.CreatedBy,
|
||||
Name = entity.Name,
|
||||
OwnedBy = entity.OwnedBy,
|
||||
TenantId = entity.TenantId,
|
||||
PortfolioId = entity.PortfolioId,
|
||||
Status = entity.Status,
|
||||
UpdatedAt = entity.UpdatedAt,
|
||||
@@ -269,6 +304,7 @@ public static class Mappers
|
||||
Description = entity.Description,
|
||||
EndedAt = entity.EndedAt,
|
||||
Name = entity.Name,
|
||||
TenantId = entity.TenantId,
|
||||
ProgrammeId = entity.ProgrammeId,
|
||||
StartedAt = entity.StartedAt,
|
||||
Status = entity.Status,
|
||||
|
||||
@@ -4,9 +4,11 @@ public class AuditLog
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long? TenantId { get; set; }
|
||||
|
||||
public string? EntityName { get; set; }
|
||||
|
||||
public long EntityId { get; set; }
|
||||
public string? EntityId { get; set; }
|
||||
|
||||
public string? Action { get; set; }
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ public class Award
|
||||
|
||||
public long OrganisationId { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long ProgrammeId { get; set; }
|
||||
|
||||
public long? ProjectId { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Notification
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long OrganisationId { get; set; }
|
||||
|
||||
public Guid Recipient { get; set; }
|
||||
|
||||
@@ -4,6 +4,8 @@ public class Portfolio
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public long OrganisationId { get; set; }
|
||||
|
||||
public Guid OwnedBy { get; set; }
|
||||
|
||||
@@ -6,6 +6,8 @@ public class Programme
|
||||
|
||||
public long PortfolioId { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public Guid OwnedBy { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
@@ -6,6 +6,8 @@ public class Project
|
||||
|
||||
public long ProgrammeId { get; set; }
|
||||
|
||||
public long TenantId { get; set; }
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
public Guid? UpdatedBy { get; set; }
|
||||
|
||||
@@ -8,9 +8,9 @@ public class Tenant
|
||||
|
||||
public Guid CreatedBy { get; set; }
|
||||
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
public Guid UpdatedBy { get; set; }
|
||||
public Guid? UpdatedBy { get; set; }
|
||||
|
||||
public string? Name { get; set; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user