Implement AuditLog entity and EF Core configuration for Sprint 2 Story 1 Task 1. Changes: - Created AuditLog entity with multi-tenant support - Added EF Core configuration with JSONB columns for PostgreSQL - Created composite indexes for query optimization - Generated database migration (20251104220842_AddAuditLogTable) - Updated PMDbContext with AuditLog DbSet and query filter - Updated task status to in_progress in sprint plan Technical Details: - PostgreSQL JSONB type for OldValues/NewValues (flexible schema) - Composite index on (TenantId, EntityType, EntityId) for entity history queries - Timestamp index (DESC) for recent logs queries - UserId index for user activity tracking - Multi-tenant query filter applied to AuditLog 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
81 lines
2.8 KiB
C#
81 lines
2.8 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|
using ColaFlow.Modules.ProjectManagement.Domain.Entities;
|
|
using ColaFlow.Modules.ProjectManagement.Domain.ValueObjects;
|
|
|
|
namespace ColaFlow.Modules.ProjectManagement.Infrastructure.Persistence.Configurations;
|
|
|
|
/// <summary>
|
|
/// Entity configuration for AuditLog
|
|
/// Configures multi-tenant isolation, JSONB columns, and composite indexes
|
|
/// </summary>
|
|
public class AuditLogConfiguration : IEntityTypeConfiguration<AuditLog>
|
|
{
|
|
public void Configure(EntityTypeBuilder<AuditLog> builder)
|
|
{
|
|
builder.ToTable("AuditLogs");
|
|
|
|
// Primary key
|
|
builder.HasKey(a => a.Id);
|
|
|
|
builder.Property(a => a.Id)
|
|
.IsRequired()
|
|
.ValueGeneratedNever();
|
|
|
|
// TenantId conversion (StronglyTypedId to Guid)
|
|
builder.Property(a => a.TenantId)
|
|
.HasConversion(
|
|
id => id.Value,
|
|
value => TenantId.From(value))
|
|
.IsRequired();
|
|
|
|
// EntityType - the type name of the entity being audited
|
|
builder.Property(a => a.EntityType)
|
|
.IsRequired()
|
|
.HasMaxLength(100);
|
|
|
|
// EntityId - the ID of the entity being audited
|
|
builder.Property(a => a.EntityId)
|
|
.IsRequired();
|
|
|
|
// Action - Create, Update, Delete
|
|
builder.Property(a => a.Action)
|
|
.IsRequired()
|
|
.HasMaxLength(20);
|
|
|
|
// UserId conversion (nullable StronglyTypedId to Guid)
|
|
builder.Property(a => a.UserId)
|
|
.HasConversion(
|
|
id => id != null ? id.Value : (Guid?)null,
|
|
value => value.HasValue ? UserId.From(value.Value) : null);
|
|
|
|
// Timestamp with UTC
|
|
builder.Property(a => a.Timestamp)
|
|
.IsRequired();
|
|
|
|
// OldValues as JSONB (PostgreSQL-specific)
|
|
builder.Property(a => a.OldValues)
|
|
.HasColumnType("jsonb");
|
|
|
|
// NewValues as JSONB (PostgreSQL-specific)
|
|
builder.Property(a => a.NewValues)
|
|
.HasColumnType("jsonb");
|
|
|
|
// Composite index for efficient entity history queries
|
|
// Query pattern: Get all audit logs for a specific entity within a tenant
|
|
builder.HasIndex(a => new { a.TenantId, a.EntityType, a.EntityId })
|
|
.HasDatabaseName("IX_AuditLogs_TenantId_EntityType_EntityId");
|
|
|
|
// Index for recent logs queries (DESC order for performance)
|
|
// Query pattern: Get most recent audit logs across all entities
|
|
builder.HasIndex(a => a.Timestamp)
|
|
.HasDatabaseName("IX_AuditLogs_Timestamp")
|
|
.IsDescending();
|
|
|
|
// Index for user activity tracking
|
|
// Query pattern: Get all actions performed by a specific user
|
|
builder.HasIndex(a => a.UserId)
|
|
.HasDatabaseName("IX_AuditLogs_UserId");
|
|
}
|
|
}
|