Browse Source

#28 Migrated old Auditing infrastructure.

pull/395/head
Halil ibrahim Kalkan 8 years ago
parent
commit
c845a612b5
  1. 1
      framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj
  2. 5
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs
  3. 55
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditInfo.cs
  4. 10
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditedAttribute.cs
  5. 39
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs
  6. 188
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs
  7. 90
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs
  8. 42
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs
  9. 21
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingOptions.cs
  10. 12
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingStoreExtensions.cs
  11. 38
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/DefaultAuditInfoProvider.cs
  12. 10
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/DisableAuditingAttribute.cs
  13. 14
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditInfoProvider.cs
  14. 7
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditSerializer.cs
  15. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAudited.cs
  16. 6
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingEnabled.cs
  17. 20
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingHelper.cs
  18. 13
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingStore.cs
  19. 11
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IClientInfoProvider.cs
  20. 26
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs
  21. 14
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/NullClientInfoProvider.cs
  22. 28
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs
  23. 11
      framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IApplicationService.cs
  24. 1
      framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj
  25. 86
      framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_Tests.cs

1
framework/src/Volo.Abp.Auditing/Volo.Abp.Auditing.csproj

@ -15,6 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Data\Volo.Abp.Data.csproj" />
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\Volo.Abp.MultiTenancy.Abstractions\Volo.Abp.MultiTenancy.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Security\Volo.Abp.Security.csproj" />
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />

5
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingModule.cs

@ -16,6 +16,11 @@ namespace Volo.Abp.Auditing
)]
public class AbpAuditingModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.OnRegistred(AuditingInterceptorRegistrar.RegisterIfNeeded);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAssemblyOf<AbpAuditingModule>();

55
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditInfo.cs

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Data;
namespace Volo.Abp.Auditing
{
public class AuditInfo : IHasExtraProperties
{
public Guid? TenantId { get; set; }
public Guid? UserId { get; set; }
public Guid? ImpersonatorUserId { get; set; }
public Guid? ImpersonatorTenantId { get; set; }
public string ServiceName { get; set; }
public string MethodName { get; set; }
public string Parameters { get; set; }
public DateTime ExecutionTime { get; set; }
public int ExecutionDuration { get; set; }
public string ClientIpAddress { get; set; }
public string ClientName { get; set; }
public string BrowserInfo { get; set; }
public Exception Exception { get; set; }
public Dictionary<string, object> ExtraProperties { get; }
public AuditInfo()
{
ExtraProperties = new Dictionary<string, object>();
}
public override string ToString()
{
var loggedUserId = UserId.HasValue
? "user " + UserId.Value
: "an anonymous user";
var exceptionOrSuccessMessage = Exception != null
? "exception: " + Exception.Message
: "succeed";
return $"AUDIT LOG: {ServiceName}.{MethodName} is executed by {loggedUserId} in {ExecutionDuration} ms from {ClientIpAddress} IP address with {exceptionOrSuccessMessage}.";
}
}
}

10
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditedAttribute.cs

@ -0,0 +1,10 @@
using System;
namespace Volo.Abp.Auditing
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]
public class AuditedAttribute : Attribute
{
}
}

39
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingContractResolver.cs

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Volo.Abp.Auditing
{
public class AuditingContractResolver : CamelCasePropertyNamesContractResolver
{
private readonly List<Type> _ignoredTypes;
public AuditingContractResolver(List<Type> ignoredTypes)
{
_ignoredTypes = ignoredTypes;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (member.IsDefined(typeof(DisableAuditingAttribute)) || member.IsDefined(typeof(JsonIgnoreAttribute)))
{
property.ShouldSerialize = instance => false;
}
foreach (var ignoredType in _ignoredTypes)
{
if (ignoredType.GetTypeInfo().IsAssignableFrom(property.PropertyType))
{
property.ShouldSerialize = instance => false;
break;
}
}
return property;
}
}
}

188
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs

@ -0,0 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Timing;
using Volo.Abp.Users;
namespace Volo.Abp.Auditing
{
public class AuditingHelper : IAuditingHelper, ITransientDependency
{
public ILogger<AuditingHelper> Logger { get; set; }
public IAuditingStore AuditingStore { get; set; }
protected ICurrentUser CurrentUser { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IClock Clock { get; }
protected IAuditInfoProvider AuditInfoProvider;
protected AuditingOptions Options;
protected IAuditSerializer AuditSerializer;
public AuditingHelper(
IAuditInfoProvider auditInfoProvider,
IAuditSerializer auditSerializer,
IOptions<AuditingOptions> options,
ICurrentUser currentUser,
ICurrentTenant currentTenant,
IClock clock)
{
AuditInfoProvider = auditInfoProvider;
Options = options.Value;
AuditSerializer = auditSerializer;
CurrentUser = currentUser;
CurrentTenant = currentTenant;
Clock = clock;
Logger = NullLogger<AuditingHelper>.Instance;
}
public bool ShouldSaveAudit(MethodInfo methodInfo, bool defaultValue = false)
{
if (!Options.IsEnabled)
{
return false;
}
if (!Options.IsEnabledForAnonymousUsers && !CurrentUser.IsAuthenticated)
{
return false;
}
if (methodInfo == null)
{
return false;
}
if (!methodInfo.IsPublic)
{
return false;
}
if (methodInfo.IsDefined(typeof(AuditedAttribute), true))
{
return true;
}
if (methodInfo.IsDefined(typeof(DisableAuditingAttribute), true))
{
return false;
}
var classType = methodInfo.DeclaringType;
if (classType != null)
{
if (classType.IsDefined(typeof(AuditedAttribute), true))
{
return true;
}
if (classType.IsDefined(typeof(DisableAuditingAttribute), true))
{
return false;
}
if (typeof(IAuditingEnabled).IsAssignableFrom(classType))
{
return true;
}
}
return defaultValue;
}
public AuditInfo CreateAuditInfo(Type type, MethodInfo method, object[] arguments)
{
return CreateAuditInfo(type, method, CreateArgumentsDictionary(method, arguments));
}
public AuditInfo CreateAuditInfo(Type type, MethodInfo method, IDictionary<string, object> arguments)
{
var auditInfo = new AuditInfo
{
TenantId = CurrentTenant.Id,
UserId = CurrentUser.Id,
//ImpersonatorUserId = AbpSession.ImpersonatorUserId, //TODO: Impersonation system is not available yet!
//ImpersonatorTenantId = AbpSession.ImpersonatorTenantId,
ServiceName = type != null
? type.FullName
: "",
MethodName = method.Name,
Parameters = SerializeConvertArguments(arguments),
ExecutionTime = Clock.Now
};
try
{
AuditInfoProvider.Fill(auditInfo);
}
catch (Exception ex)
{
Logger.LogException(ex, LogLevel.Warning);
}
return auditInfo;
}
public void Save(AuditInfo auditInfo)
{
AuditingStore.Save(auditInfo);
}
public async Task SaveAsync(AuditInfo auditInfo)
{
await AuditingStore.SaveAsync(auditInfo);
}
private string SerializeConvertArguments(IDictionary<string, object> arguments)
{
try
{
if (arguments.IsNullOrEmpty())
{
return "{}";
}
var dictionary = new Dictionary<string, object>();
foreach (var argument in arguments)
{
if (argument.Value != null && Options.IgnoredTypes.Any(t => t.IsInstanceOfType(argument.Value)))
{
dictionary[argument.Key] = null;
}
else
{
dictionary[argument.Key] = argument.Value;
}
}
return AuditSerializer.Serialize(dictionary);
}
catch (Exception ex)
{
Logger.LogException(ex, LogLevel.Warning);
return "{}";
}
}
private static Dictionary<string, object> CreateArgumentsDictionary(MethodInfo method, object[] arguments)
{
var parameters = method.GetParameters();
var dictionary = new Dictionary<string, object>();
for (var i = 0; i < parameters.Length; i++)
{
dictionary[parameters[i].Name] = arguments[i];
}
return dictionary;
}
}
}

90
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs

@ -0,0 +1,90 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Volo.Abp.Aspects;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
namespace Volo.Abp.Auditing
{
public class AuditingInterceptor : AbpInterceptor, ITransientDependency
{
private readonly IAuditingHelper _auditingHelper;
public AuditingInterceptor(IAuditingHelper auditingHelper)
{
_auditingHelper = auditingHelper;
}
public override void Intercept(IAbpMethodInvocation invocation)
{
if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.Auditing))
{
invocation.Proceed();
return;
}
if (!_auditingHelper.ShouldSaveAudit(invocation.Method))
{
invocation.Proceed();
return;
}
var auditInfo = _auditingHelper.CreateAuditInfo(invocation.TargetObject.GetType(), invocation.Method, invocation.Arguments);
var stopwatch = Stopwatch.StartNew();
try
{
invocation.Proceed();
}
catch (Exception ex)
{
auditInfo.Exception = ex;
throw;
}
finally
{
stopwatch.Stop();
auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
_auditingHelper.Save(auditInfo);
}
}
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
//Try to reduce duplication with Intercept
if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.Auditing))
{
await invocation.ProceedAsync();
return;
}
if (!_auditingHelper.ShouldSaveAudit(invocation.Method))
{
await invocation.ProceedAsync();
return;
}
var auditInfo = _auditingHelper.CreateAuditInfo(invocation.TargetObject.GetType(), invocation.Method, invocation.Arguments);
var stopwatch = Stopwatch.StartNew();
try
{
await invocation.ProceedAsync();
}
catch (Exception ex)
{
auditInfo.Exception = ex;
}
finally
{
stopwatch.Stop();
auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
await _auditingHelper.SaveAsync(auditInfo);
}
}
}
}

42
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs

@ -0,0 +1,42 @@
using System;
using System.Linq;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing
{
public static class AuditingInterceptorRegistrar
{
public static void RegisterIfNeeded(IOnServiceRegistredContext context)
{
if (ShouldIntercept(context.ImplementationType))
{
context.Interceptors.TryAdd<AuditingInterceptor>();
}
}
private static bool ShouldIntercept(Type type)
{
if (type.IsDefined(typeof(AuditedAttribute), true))
{
return true;
}
if (type.IsDefined(typeof(DisableAuditingAttribute), true))
{
return false;
}
if (typeof(IAuditingEnabled).IsAssignableFrom(type))
{
return true;
}
if (type.GetMethods().Any(m => m.IsDefined(typeof(AuditedAttribute), true)))
{
return true;
}
return false;
}
}
}

21
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingOptions.cs

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.Auditing
{
public class AuditingOptions
{
public bool IsEnabled { get; set; }
public bool IsEnabledForAnonymousUsers { get; set; }
public List<Type> IgnoredTypes { get; }
public AuditingOptions()
{
IsEnabled = true;
IsEnabledForAnonymousUsers = true;
IgnoredTypes = new List<Type>();
}
}
}

12
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingStoreExtensions.cs

@ -0,0 +1,12 @@
using Volo.Abp.Threading;
namespace Volo.Abp.Auditing
{
public static class AuditingStoreExtensions
{
public static void Save(this IAuditingStore auditingStore, AuditInfo auditInfo)
{
AsyncHelper.RunSync(() => auditingStore.SaveAsync(auditInfo));
}
}
}

38
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/DefaultAuditInfoProvider.cs

@ -0,0 +1,38 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing
{
//TODO: Implement as multiple providers can contribute!
/// <summary>
/// Default implementation of <see cref="IAuditInfoProvider" />.
/// </summary>
public class DefaultAuditInfoProvider : IAuditInfoProvider, ITransientDependency
{
protected IClientInfoProvider ClientInfoProvider { get; }
public DefaultAuditInfoProvider(IClientInfoProvider clientInfoProvider)
{
ClientInfoProvider = clientInfoProvider;
}
public virtual void Fill(AuditInfo auditInfo)
{
if (auditInfo.ClientIpAddress.IsNullOrEmpty())
{
auditInfo.ClientIpAddress = ClientInfoProvider.ClientIpAddress;
}
if (auditInfo.BrowserInfo.IsNullOrEmpty())
{
auditInfo.BrowserInfo = ClientInfoProvider.BrowserInfo;
}
if (auditInfo.ClientName.IsNullOrEmpty())
{
auditInfo.ClientName = ClientInfoProvider.ComputerName;
}
}
}
}

10
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/DisableAuditingAttribute.cs

@ -0,0 +1,10 @@
using System;
namespace Volo.Abp.Auditing
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property)]
public class DisableAuditingAttribute : Attribute
{
}
}

14
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditInfoProvider.cs

@ -0,0 +1,14 @@
namespace Volo.Abp.Auditing
{
/// <summary>
/// Provides an interface to provide audit informations in the upper layers.
/// </summary>
public interface IAuditInfoProvider
{
/// <summary>
/// Called to fill needed properties.
/// </summary>
/// <param name="auditInfo">Audit info that is partially filled</param>
void Fill(AuditInfo auditInfo);
}
}

7
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditSerializer.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.Auditing
{
public interface IAuditSerializer
{
string Serialize(object obj);
}
}

2
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAudited.cs

@ -1,5 +1,7 @@
namespace Volo.Abp.Auditing
{
//TODO: Rename IAudited to IAuditedObject (also for ICreationAudited, IDeletionAudited... and so on)
/// <summary>
/// This interface can be implemented to add standard auditing properties to a class.
/// </summary>

6
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingEnabled.cs

@ -0,0 +1,6 @@
namespace Volo.Abp.Auditing
{
public interface IAuditingEnabled
{
}
}

20
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingHelper.cs

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
namespace Volo.Abp.Auditing
{
public interface IAuditingHelper
{
bool ShouldSaveAudit(MethodInfo methodInfo, bool defaultValue = false);
AuditInfo CreateAuditInfo(Type type, MethodInfo method, object[] arguments);
AuditInfo CreateAuditInfo(Type type, MethodInfo method, IDictionary<string, object> arguments);
void Save(AuditInfo auditInfo);
Task SaveAsync(AuditInfo auditInfo);
}
}

13
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingStore.cs

@ -0,0 +1,13 @@
using System.Threading.Tasks;
namespace Volo.Abp.Auditing
{
public interface IAuditingStore
{
/// <summary>
/// Should save audits to a persistent store.
/// </summary>
/// <param name="auditInfo">Audit informations</param>
Task SaveAsync(AuditInfo auditInfo);
}
}

11
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IClientInfoProvider.cs

@ -0,0 +1,11 @@
namespace Volo.Abp.Auditing
{
public interface IClientInfoProvider
{
string BrowserInfo { get; }
string ClientIpAddress { get; }
string ComputerName { get; }
}
}

26
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/JsonNetAuditSerializer.cs

@ -0,0 +1,26 @@
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing
{
public class JsonNetAuditSerializer : IAuditSerializer, ITransientDependency
{
protected AuditingOptions Options;
public JsonNetAuditSerializer(IOptions<AuditingOptions> options)
{
Options = options.Value;
}
public string Serialize(object obj)
{
var options = new JsonSerializerSettings
{
ContractResolver = new AuditingContractResolver(Options.IgnoredTypes)
};
return JsonConvert.SerializeObject(obj, options);
}
}
}

14
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/NullClientInfoProvider.cs

@ -0,0 +1,14 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing
{
//TODO: Implement on aspnet core layer
public class NullClientInfoProvider : IClientInfoProvider, ISingletonDependency
{
public static NullClientInfoProvider Instance { get; } = new NullClientInfoProvider();
public string BrowserInfo => null;
public string ClientIpAddress => null;
public string ComputerName => null;
}
}

28
framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/SimpleLogAuditingStore.cs

@ -0,0 +1,28 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Auditing
{
[Dependency(TryRegister = true)]
public class SimpleLogAuditingStore : IAuditingStore, ISingletonDependency
{
public ILogger<SimpleLogAuditingStore> Logger { get; set; }
public SimpleLogAuditingStore()
{
Logger = NullLogger<SimpleLogAuditingStore>.Instance;
}
public Task SaveAsync(AuditInfo auditInfo)
{
Logger.LogWithLevel(
auditInfo.Exception == null ? LogLevel.Information : LogLevel.Warning,
auditInfo.ToString()
);
return Task.FromResult(0);
}
}
}

11
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IApplicationService.cs

@ -1,4 +1,5 @@
using Volo.Abp.Authorization;
using Volo.Abp.Auditing;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Uow;
using Volo.Abp.Validation;
@ -8,7 +9,13 @@ namespace Volo.Abp.Application.Services
/// <summary>
/// This interface must be implemented by all application services to register and identify them by convention.
/// </summary>
public interface IApplicationService : ITransientDependency, IRemoteService, IUnitOfWorkEnabled, IValidationEnabled, IAuthorizationEnabled
public interface IApplicationService :
ITransientDependency,
IRemoteService,
IUnitOfWorkEnabled,
IValidationEnabled,
IAuthorizationEnabled,
IAuditingEnabled
{
}

1
framework/test/Volo.Abp.Auditing.Tests/Volo.Abp.Auditing.Tests.csproj

@ -14,6 +14,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
</ItemGroup>

86
framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/AuditingInterceptor_Tests.cs

@ -0,0 +1,86 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using NSubstitute;
using Volo.Abp.Autofac;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Modularity;
using Xunit;
namespace Volo.Abp.Auditing
{
public class AuditingInterceptor_Tests : AbpIntegratedTest<AuditingInterceptor_Tests.TestModule>
{
private IAuditingStore _auditingStore;
public AuditingInterceptor_Tests()
{
}
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
protected override void AfterAddApplication(IServiceCollection services)
{
_auditingStore = Substitute.For<IAuditingStore>();
services.Replace(ServiceDescriptor.Singleton(_auditingStore));
}
[Fact]
public async Task Should_Write_AuditLog_For_Classes_That_Implement_IAuditingEnabled()
{
var myAuditedObject1 = GetRequiredService<MyAuditedObject1>();
await myAuditedObject1.DoItAsync(new InputObject {Value1 = "fourty-two", Value2 = 42});
#pragma warning disable 4014
_auditingStore.Received().SaveAsync(Arg.Any<AuditInfo>());
#pragma warning restore 4014
}
[DependsOn(
typeof(AbpAuditingModule),
typeof(AbpAutofacModule)
)]
public class TestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddType<MyAuditedObject1>();
}
}
public interface IMyAuditedObject : ITransientDependency, IAuditingEnabled
{
}
public class MyAuditedObject1 : IMyAuditedObject
{
public async virtual Task<ResultObject> DoItAsync(InputObject inputObject)
{
return new ResultObject
{
Value1 = inputObject.Value1 + "-result",
Value2 = inputObject.Value2 + 1
};
}
}
public class ResultObject
{
public string Value1 { get; set; }
public int Value2 { get; set; }
}
public class InputObject
{
public string Value1 { get; set; }
public int Value2 { get; set; }
}
}
}
Loading…
Cancel
Save