Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
aritchie committed May 10, 2024
1 parent 42a713e commit 9cdd7ad
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 46 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
.idea/

# User-specific files
*.rsuser
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,14 @@
namespace Shiny.Auditing;


public abstract class AbstractAuditSaveChangesInterceptor : SaveChangesInterceptor
public class AuditSaveChangesInterceptor(IAuditInfoProvider provider) : SaveChangesInterceptor
{
public override int SavedChanges(SaveChangesCompletedEventData eventData, int result)
{
var entries = this.GetAuditEntries(eventData);

eventData.Context!.AddRange(entries);

var actualResult = base.SavedChanges(eventData, result);

// TODO: post op
// TODO: save to new dbcontext
return actualResult;
}

Expand All @@ -34,49 +32,41 @@ static DbOperation ToOperation(EntityState state)

protected virtual List<AuditEntry> GetAuditEntries(SaveChangesCompletedEventData eventData)
{
var auditInfo = this.GetAuditInfo();
// TODO: I need to tag this on entities that are changing BEFORE change tracking?

var entries = new List<AuditEntry>();
var auditInfo = provider.GetAuditInfo();
var changeTracker = eventData.Context!.ChangeTracker;
changeTracker.DetectChanges();
var entries = new List<AuditEntry>();


foreach (var entry in changeTracker.Entries())
{
// Dot not audit entities that are not tracked, not changed, or not of type IAuditable
if (entry.State == EntityState.Detached || entry.State == EntityState.Unchanged || entry.Entity is not IAuditable)
continue;

var auditEntry = new AuditEntry
if (entry.State != EntityState.Detached &&
entry.State != EntityState.Unchanged &&
entry.Entity is IAuditable)
{
Operation = ToOperation(entry.State),
EntityId = entry.Properties.Single(p => p.Metadata.IsPrimaryKey()).CurrentValue!.ToString()!,
EntityType = entry.Metadata.ClrType.Name,
Timestamp = DateTime.UtcNow,
ChangeSet = this.CalculateChangeSet(entry)

// TempProperties are properties that are only generated on save, e.g. ID's
// These properties will be set correctly after the audited entity has been saved
// TempProperties = entry.Properties.Where(p => p.IsTemporary).ToList(),
};

entries.Add(auditEntry);
var auditEntry = new AuditEntry
{
Operation = ToOperation(entry.State),
EntityId = entry.Properties.Single(p => p.Metadata.IsPrimaryKey()).CurrentValue!.ToString()!,
EntityType = entry.Metadata.ClrType.Name,
Timestamp = DateTime.UtcNow,
ChangeSet = this.CalculateChangeSet(entry),
Info = auditInfo
};
entries.Add(auditEntry);
}
}

return entries;
}

protected abstract AuditInfo GetAuditInfo();


protected virtual Dictionary<string, object> CalculateChangeSet(EntityEntry entry)
{
var dict = new Dictionary<string, object>();
foreach (var property in entry.Properties)
{
if (property.IsModified)
if (property.IsModified && property.CurrentValue is not byte[])
{
// don't track any binary or password - others?
dict.Add(property.Metadata.Name, property.OriginalValue ?? "NULL");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Shiny.Auditing;

public interface IAuditInfoProvider
{
AuditInfo GetAuditInfo();
}
35 changes: 20 additions & 15 deletions src/Shiny.Extensions.WebHosting/RegistrationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,32 @@ namespace Shiny;

public static class RegistrationExtensions
{
public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder)
public static WebApplicationBuilder AddInfrastructureForAppDomain(this WebApplicationBuilder builder, Func<string, bool>? predicate = null)
{
var assemblyFileNames = Directory
predicate ??= x => !x.StartsWith("System.");

var assemblies = Directory
.GetFiles(
AppDomain.CurrentDomain.BaseDirectory,
"BuildingOps.*.dll"
"*.dll"
)
.Where(x => !Path
.GetFileName(x)
.Equals(
"BuildingOps.WebInfrastructure.dll",
StringComparison.InvariantCultureIgnoreCase
)
)
.ToList();
.Where(x => predicate.Invoke(Path.GetFileName(x)))
.Select(x =>
{
var assembly = Assembly.LoadFrom(x);
AppDomain.CurrentDomain.Load(assembly.GetName());
return assembly;
})
.ToArray();

foreach (var assemblyFileName in assemblyFileNames)
return builder.AddInfrastructure(assemblies);
}


public static WebApplicationBuilder AddInfrastructure(this WebApplicationBuilder builder, params Assembly[] assemblies)
{
foreach (var assembly in assemblies)
{
var assembly = Assembly.LoadFrom(assemblyFileName);
AppDomain.CurrentDomain.Load(assembly.GetName());

var moduleTypes = assembly
.GetTypes()
.Where(x =>
Expand Down

0 comments on commit 9cdd7ad

Please sign in to comment.