Skip to content

Audit Information

Overview

The Audit Information feature tracks the creation and last modification details of entities automatically. It records:

  • Who created or updated the entity.
  • When the action occurred.

To use this feature, entities must implement one of the following interfaces based on their requirements:

  • IAuditInfo: For entities requiring both creation and modification audit information.
  • ICreatedAuditInfo: For entities requiring only creation audit information.
  • IUpdatedAuditInfo: For entities requiring only modification audit information.

Messages that need to track audit information implement either the ICreatedAuditInfoMessage or IUpdatedAuditInfoMessage interfaces.

Core Features

  • Creation Information: Tracks the user and timestamp of entity creation.
  • Modification Information: Tracks the user and timestamp of the last modification.
  • Automatic Population: Eliminates manual input through interceptors.
  • Consistency: Ensures all entities with IAuditInfo, ICreatedAuditInfo, or IUpdatedAuditInfo are audited uniformly.

How It Works

Audit tracking is handled via different interceptors and decorators depending on the interface implemented.

Entity Audit Tracking

  1. IAuditInfo Tracking:

    The AuditInfoRepositoryInterceptor<TEntity> interceptor updates audit fields automatically during create and update operations. The AuditInfoDecorator<TEntity> configures the necessary properties in the Entity Framework context.

    • On Creation:

      • CreatedBy → Current user's ID.
      • CreatedAt → Current timestamp.
      • LastUpdatedBy → Current user's ID.
      • LastUpdated → Current timestamp.
    • On Update:

      • LastUpdatedBy → Current user's ID.
      • LastUpdated → Current timestamp.
  2. ICreatedAuditInfo Tracking:

    The CreatedAuditInfoRepositoryInterceptor<TEntity> interceptor updates audit fields automatically during create operations. The CreatedAuditInfoDecorator<TEntity> configures the necessary properties in the Entity Framework context.

    • On Creation:
      • CreatedBy → Current user's ID.
      • CreatedAt → Current timestamp.
  3. IUpdatedAuditInfo Tracking:

    The UpdatedAuditInfoRepositoryInterceptor<TEntity> interceptor updates audit fields automatically during create and update operations. The UpdatedAuditInfoDecorator<TEntity> configures the necessary properties in the Entity Framework context.

    • On Creation:
      • LastUpdatedBy → Current user's ID.
      • LastUpdated → Current timestamp.
    • On Update:
      • LastUpdatedBy → Current user's ID.
      • LastUpdated → Current timestamp.

Message Audit Tracking

  1. Message Creation Information (ICreatedAuditInfoMessage):

    Messages implementing the ICreatedAuditInfoMessage interface can also track the creation details. This is useful for replicating messages. The CreatedBy and CreatedAt properties must be populated by the process responsible for creating the message (usually the consumer).

  2. Message Update Information (IUpdatedAuditInfoMessage):

    Messages implementing the IUpdatedAuditInfoMessage interface must have their LastUpdatedBy and LastUpdated properties populated by the application code. This is typically done by the process responsible for updating the message.

The interceptors uses ISuiteContext to fetch the current user's ID. If no user ID is available, an exception is thrown.

Metadata Entity Tracking

  1. IUpdatedAuditInfoMetadata Tracking:

    Entities implementing the IUpdatedAuditInfoMetadata interface must have their LastUpdatedBy and LastUpdated properties populated by the application code. This is typically done in the service or application layer when updating the metadata entity. For example:

C#
using ITsynch.Suite.Domain;
using MassTransit;
using System;
using System.Threading.Tasks;

namespace ITsynch.Suite.Settings.Abstractions;

public class SettingValueMetadata : ICorrelatedEntity, IUpdatedAuditInfoMetadata
{
    public SettingValueMetadata(
        Guid correlationId,
        string value,
        DateTime lastUpdated,
        Guid lastUpdatedBy)
    {
        this.CorrelationId = correlationId;
        this.Value = value;
        this.LastUpdated = lastUpdated;
        this.LastUpdatedBy = lastUpdatedBy;
    }

    public Guid CorrelationId { get; set; }
    public string Value { get; set; } = null!;
    public DateTime LastUpdated { get; set; }
    public Guid LastUpdatedBy { get; set; }
}

using ITsynch.Suite.Domain;
using ITsynch.Suite.MassTransit;
using ITsynch.Suite.Settings.Abstractions;
using ITsynch.Suite.Settings.Application;
using MassTransit;
using System;
using System.Threading.Tasks;

namespace ITsynch.Suite.Settings.ClientModule;

public class SettingValueConsumer(
    IRepository<Guid, SettingValueMetadata> repository)
    : IConsumer<SettingValueUpdated>
{
    public async Task Consume(ConsumeContext<SettingValueUpdated> context)
    {
        var message = context.Message;

        var settingValueMetadata = await repository.FindByIdAsync(message.CorrelationId, context.CancellationToken);

        if (settingValueMetadata is null)
        {
            settingValueMetadata = new SettingValueMetadata(message.CorrelationId)
            {
                Value = message.Value,
                LastUpdatedBy = message.LastUpdatedBy, // Set from message!
                LastUpdated = message.LastUpdated // Set from message!
            };

            await repository.CreateAsync(settingValueMetadata, context.CancellationToken);
        }
        else
        {
            settingValueMetadata.Value = message.Value;
            settingValueMetadata.LastUpdatedBy = message.LastUpdatedBy; // Set from message!
            settingValueMetadata.LastUpdated = message.LastUpdated; // Set from message!

            await repository.UpdateAsync(settingValueMetadata, context.CancellationToken);
        }
    }
}

Default Behavior

When depending on EntityFrameworkCoreModule, audit tracking is automatically applied based on the interface implemented by the entity:

  • IAuditInfo Entities: Full audit tracking is automatically enabled using AuditInfoRepositoryInterceptor<TEntity> and AuditInfoDecorator<TEntity>.
  • ICreatedAuditInfo Entities: Creation-only tracking is automatically enabled using CreatedAuditInfoRepositoryInterceptor<TEntity> and CreatedAuditInfoDecorator<TEntity>.
  • IUpdatedAuditInfo Entities: Update-only tracking is automatically enabled using UpdatedAuditInfoRepositoryInterceptor<TEntity> and UpdatedAuditInfoDecorator<TEntity>. No additional setup is required to enable these features.

Database Migrations

A database migration is necessary for entities that implement IAuditInfo, ICreatedAuditInfo, IUpdatedAuditInfo, or IUpdatedAuditInfoMetadata to have the new audit-related fields (e.g., CreatedBy, CreatedAt, LastUpdated, LastUpdatedBy) added to the database schema. Be sure to create migrations after adding the necessary interfaces to your entities.

For entities that implement IUpdatedAuditInfoMetadata, ensure that migrations are applied in all contexts where these metadata entities are used.