Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,20 @@ namespace TrackerEnabledDbContext.Common.Configuration
{
public static class GlobalTrackingConfig
{
public static bool Enabled { get; set; } = true;
public static bool Enabled
{
get { return AdditionsEnabled || ModificationsEnabled || DeletionsEnabled; }
set
{
AdditionsEnabled = value;
ModificationsEnabled = value;
DeletionsEnabled = value;
}
}

public static bool AdditionsEnabled { get; set; } = true;
public static bool ModificationsEnabled { get; set; } = true;
public static bool DeletionsEnabled { get; set; } = true;

public static bool TrackEmptyPropertiesOnAdditionAndDeletion { get; set; } = false;

Expand Down
57 changes: 57 additions & 0 deletions TrackerEnabledDbContext.Common/CoreTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,63 @@ DbEntityEntry ent in
{
var eventType = GetEventType(ent);

AuditLog record = auditer.CreateLogRecord(userName, eventType, _context, metadata);

if (record != null)
{
var arg = new AuditLogGeneratedEventArgs(record, ent.Entity, metadata);
RaiseOnAuditLogGenerated(this, arg);
if (!arg.SkipSavingLog)
{
_context.AuditLog.Add(record);
}
}
}
}
}

public void AuditModifications(object userName, ExpandoObject metadata)
{
// Get all Modified entities (not Unmodified or Deleted or Detached or Added)
foreach (
DbEntityEntry ent in
_context.ChangeTracker.Entries()
.Where(p => p.State == EntityState.Modified))
{
using (var auditer = new LogAuditor(ent))
{
AuditLog record = auditer.CreateLogRecord(userName, EventType.Modified, _context, metadata);

if (record != null)
{
var arg = new AuditLogGeneratedEventArgs(record, ent.Entity, metadata);
RaiseOnAuditLogGenerated(this, arg);
if (!arg.SkipSavingLog)
{
_context.AuditLog.Add(record);
}
}
}
}
}

public void AuditDeletions(object userName, ExpandoObject metadata)
{
// Get all Deleted or Modified entities (not Unmodified or Detached or Added)
foreach (
DbEntityEntry ent in
_context.ChangeTracker.Entries()
.Where(p => p.State == EntityState.Deleted || p.State == EntityState.Modified))
{
using (var auditer = new LogAuditor(ent))
{
var eventType = GetEventType(ent);

// Skip modifications, as these are handled in the AuditModifications method
if (eventType == EventType.Modified)
{
continue;
}
AuditLog record = auditer.CreateLogRecord(userName, eventType, _context, metadata);

if (record != null)
Expand Down
3 changes: 3 additions & 0 deletions TrackerEnabledDbContext.Common/Interfaces/ITrackerContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ public interface ITrackerContext : IDbContext
DbSet<AuditLog> AuditLog { get; set; }
DbSet<AuditLogDetail> LogDetails { get; set; }
bool TrackingEnabled { get; set; }
bool AdditionTrackingEnabled { get; set; }
bool ModificationTrackingEnabled { get; set; }
bool DeletionTrackingEnabled { get; set; }

event EventHandler<AuditLogGeneratedEventArgs> OnAuditLogGenerated;

Expand Down
102 changes: 83 additions & 19 deletions TrackerEnabledDbContext.Identity/TrackerIdentityContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,59 @@ public class TrackerIdentityContext<TUser, TRole, TKey, TUserLogin, TUserRole, T
private string _defaultUsername;
private Action<dynamic> _metadataConfiguration;

private bool _trackingEnabled = true;
private bool _additionTrackingEnabled = true;
private bool _modificationTrackingEnabled = true;
private bool _deletionTrackingEnabled = true;

public bool TrackingEnabled
{
get
{
return GlobalTrackingConfig.Enabled && _trackingEnabled;
return GlobalTrackingConfig.Enabled && (_additionTrackingEnabled ||
_modificationTrackingEnabled ||
_deletionTrackingEnabled);
}
set
{
AdditionTrackingEnabled = value;
ModificationTrackingEnabled = value;
DeletionTrackingEnabled = value;
}
}

public bool AdditionTrackingEnabled
{
get
{
return GlobalTrackingConfig.AdditionsEnabled && _additionTrackingEnabled;
}
set
{
_additionTrackingEnabled = value;
}
}

public bool ModificationTrackingEnabled
{
get
{
return GlobalTrackingConfig.ModificationsEnabled && _modificationTrackingEnabled;
}
set
{
_trackingEnabled = value;
_modificationTrackingEnabled = value;
}
}

public bool DeletionTrackingEnabled
{
get
{
return GlobalTrackingConfig.DeletionsEnabled && _deletionTrackingEnabled;
}
set
{
_deletionTrackingEnabled = value;
}
}

Expand Down Expand Up @@ -122,17 +165,28 @@ public virtual int SaveChanges(object userName)
dynamic metadata = new ExpandoObject();
_metadataConfiguration?.Invoke(metadata);

_coreTracker.AuditChanges(userName, metadata);
if (ModificationTrackingEnabled) _coreTracker.AuditModifications(userName, metadata);
if (DeletionTrackingEnabled) _coreTracker.AuditDeletions(userName, metadata);

IEnumerable<DbEntityEntry> addedEntries = _coreTracker.GetAdditions();
// Call the original SaveChanges(), which will save both the changes made and the audit records...Note that added entry auditing is still remaining.
int result = base.SaveChanges();
//By now., we have got the primary keys of added entries of added entiries because of the call to savechanges.
int result;
if (AdditionTrackingEnabled)
{
IEnumerable<DbEntityEntry> addedEntries = _coreTracker.GetAdditions();
// Call the original SaveChanges(), which will save both the changes made and the audit records...Note that added entry auditing is still remaining.
result = base.SaveChanges();
//By now., we have got the primary keys of added entries of added entiries because of the call to savechanges.

_coreTracker.AuditAdditions(userName, addedEntries, metadata);

_coreTracker.AuditAdditions(userName, addedEntries, metadata);
//save changes to audit of added entries
base.SaveChanges();
}
else
{
//save changes
result = base.SaveChanges();
}

//save changes to audit of added entries
base.SaveChanges();
return result;
}

Expand Down Expand Up @@ -219,18 +273,28 @@ public virtual async Task<int> SaveChangesAsync(object userName, CancellationTok
dynamic metadata = new ExpandoObject();
_metadataConfiguration?.Invoke(metadata);

_coreTracker.AuditChanges(userName, metadata);
if (ModificationTrackingEnabled) _coreTracker.AuditModifications(userName, metadata);
if (DeletionTrackingEnabled) _coreTracker.AuditDeletions(userName, metadata);

IEnumerable<DbEntityEntry> addedEntries = _coreTracker.GetAdditions();
int result;
if (AdditionTrackingEnabled)
{
IEnumerable<DbEntityEntry> addedEntries = _coreTracker.GetAdditions();

// Call the original SaveChanges(), which will save both the changes made and the audit records...Note that added entry auditing is still remaining.
int result = await base.SaveChangesAsync(cancellationToken);
// Call the original SaveChanges(), which will save both the changes made and the audit records...Note that added entry auditing is still remaining.
result = await base.SaveChangesAsync(cancellationToken);

//By now., we have got the primary keys of added entries of added entiries because of the call to savechanges.
_coreTracker.AuditAdditions(userName, addedEntries, metadata);
//By now., we have got the primary keys of added entries of added entiries because of the call to savechanges.
_coreTracker.AuditAdditions(userName, addedEntries, metadata);

//save changes to audit of added entries
await base.SaveChangesAsync(cancellationToken);
//save changes to audit of added entries
await base.SaveChangesAsync(cancellationToken);
}
else
{
//save changes
result = await base.SaveChangesAsync(cancellationToken);
}

return result;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TrackerEnabledDbContext.Common.Configuration;
using TrackerEnabledDbContext.Common.Models;
using TrackerEnabledDbContext.Common.Testing;
using TrackerEnabledDbContext.Common.Testing.Extensions;
using TrackerEnabledDbContext.Common.Testing.Models;
Expand All @@ -12,9 +14,9 @@ namespace TrackerEnabledDbContext.IntegrationTests
public class FluentConfigurationTests : PersistanceTests<TestTrackerContext>
{
[TestMethod]
public void Can_recognise_global_tracking_indicator_when_disabled()
public void Can_recognise_global_addition_tracking_indicator_when_disabled()
{
GlobalTrackingConfig.Enabled = false;
GlobalTrackingConfig.AdditionsEnabled = false;

EntityTracker
.TrackAllProperties<POCO>()
Expand All @@ -29,7 +31,7 @@ public void Can_recognise_global_tracking_indicator_when_disabled()
}

[TestMethod]
public void Can_recognise_global_tracking_indicator_when_enabled()
public void Can_recognise_global_addition_tracking_indicator_when_enabled()
{
EntityTracker
.TrackAllProperties<POCO>();
Expand All @@ -51,6 +53,96 @@ public void Can_recognise_global_tracking_indicator_when_enabled()
x=>x.StartTime);
}

[TestMethod]
public void Can_recognise_global_change_tracking_indicator_when_disabled()
{
GlobalTrackingConfig.ModificationsEnabled = false;

EntityTracker
.TrackAllProperties<POCO>()
.Except(x => x.StartTime)
.And(x => x.Color);

POCO model = ObjectFactory.Create<POCO>();
Db.POCOs.Add(model);
Db.SaveChanges();
model.Height++;
Db.SaveChanges();

model.AssertNoLogs(Db, model.Id, Common.Models.EventType.Modified);
}

[TestMethod]
public void Can_recognise_global_change_tracking_indicator_when_enabled()
{
EntityTracker
.TrackAllProperties<POCO>();

POCO model = new POCO
{
Color = "Red",
Height = 67.4,
StartTime = new DateTime(2015, 5, 5)
};

Db.POCOs.Add(model);
Db.SaveChanges();
model.Color = "Green";
Db.SaveChanges();

model.AssertAuditForModification(Db, model.Id, null, new AuditLogDetail
{
NewValue = "Green",
OriginalValue = "Red",
PropertyName = "Color"
});
}

[TestMethod]
public void Can_recognise_global_deletion_tracking_indicator_when_disabled()
{
GlobalTrackingConfig.DeletionsEnabled = false;

EntityTracker
.TrackAllProperties<POCO>()
.Except(x => x.StartTime)
.And(x => x.Color);

POCO model = ObjectFactory.Create<POCO>();
Db.POCOs.Add(model);
Db.SaveChanges();
Db.POCOs.Remove(model);
Db.SaveChanges();

model.AssertNoLogs(Db, model.Id, Common.Models.EventType.Modified);
}

[TestMethod]
public void Can_recognise_global_deletion_tracking_indicator_when_enabled()
{
EntityTracker
.TrackAllProperties<POCO>();

POCO model = new POCO
{
Color = "Red",
Height = 67.4,
StartTime = new DateTime(2015, 5, 5)
};

Db.POCOs.Add(model);
Db.SaveChanges();
Db.POCOs.Remove(model);
Db.ChangeTracker.DetectChanges();
Db.SaveChanges();

model.AssertAuditForDeletion(Db, model.Id, null,
x => x.Id,
x => x.Color,
x => x.Height,
x => x.StartTime);
}

[TestMethod]
public async Task Can_Override_annotation_based_configuration_for_entity_skipTracking()
{
Expand Down
Loading