Browse Source

Implement AbpAuditingOptions.IsEnabledForIntegrationServices

pull/12896/head
Halil İbrahim Kalkan 4 years ago
parent
commit
c8ec7d6905
  1. 10
      framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs
  2. 20
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs
  3. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs
  4. 5
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs
  5. 7
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreConsts.cs
  6. 2
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingOptions.cs
  7. 19
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs
  8. 4
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs
  9. 4
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs
  10. 9
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs
  11. 2
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingHelper.cs
  12. 2
      framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs
  13. 14
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController.cs
  14. 58
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController_Tests.cs
  15. 3
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs
  16. 24
      framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs

10
framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs

@ -43,4 +43,14 @@ public static class ActionDescriptorExtensions
{
return actionDescriptor is PageActionDescriptor;
}
public static PageActionDescriptor AsPageAction(this ActionDescriptor actionDescriptor)
{
if (!actionDescriptor.IsPageAction())
{
throw new AbpException($"{nameof(actionDescriptor)} should be type of {typeof(PageActionDescriptor).AssemblyQualifiedName}");
}
return actionDescriptor as PageActionDescriptor;
}
}

20
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs

@ -70,7 +70,9 @@ public class AbpAuditActionFilter : IAsyncActionFilter, ITransientDependency
}
var auditingHelper = context.GetRequiredService<IAuditingHelper>();
if (!auditingHelper.ShouldSaveAudit(context.ActionDescriptor.GetMethodInfo(), true))
if (!auditingHelper.ShouldSaveAudit(
context.ActionDescriptor.GetMethodInfo(),
defaultValue: GetDefaultAuditBehavior(options, context.ActionDescriptor)))
{
return false;
}
@ -85,4 +87,20 @@ public class AbpAuditActionFilter : IAsyncActionFilter, ITransientDependency
return true;
}
private static bool GetDefaultAuditBehavior(
AbpAuditingOptions abpAuditingOptions,
ActionDescriptor actionDescriptor)
{
if (!abpAuditingOptions.IsEnabledForIntegrationServices &&
actionDescriptor
.AsControllerActionDescriptor()
.ControllerTypeInfo
.IsDefined(typeof(IntegrationServiceAttribute), true))
{
return false;
}
return true;
}
}

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs

@ -75,7 +75,7 @@ public class AbpAuditPageFilter : IAsyncPageFilter, ITransientDependency
}
var auditingHelper = context.GetRequiredService<IAuditingHelper>();
if (!auditingHelper.ShouldSaveAudit(context.HandlerMethod.MethodInfo, true))
if (!auditingHelper.ShouldSaveAudit(context.HandlerMethod.MethodInfo, defaultValue: true))
{
return false;
}

5
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs

@ -4,7 +4,6 @@ using System.Reflection;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
using Microsoft.Extensions.Options;
using Volo.Abp.Application.Services;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http;
using Volo.Abp.Reflection;
@ -81,10 +80,10 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep
if (actionModel.Controller.ControllerType.IsDefined(typeof(IntegrationServiceAttribute), true))
{
return "integration-api";
return AbpAspNetCoreConsts.DefaultIntegrationServiceApiPrefix;
}
return "api";
return AbpAspNetCoreConsts.DefaultApiPrefix;
}
protected virtual string NormalizeUrlActionName(string rootPath, string controllerName, ActionModel action,

7
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Abp.AspNetCore;
public static class AbpAspNetCoreConsts
{
public const string DefaultApiPrefix = "api";
public const string DefaultIntegrationServiceApiPrefix = "integration-api";
}

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingOptions.cs

@ -10,5 +10,5 @@ public class AbpAspNetCoreAuditingOptions
/// <see cref="AbpAuditingMiddleware"/> will be disabled for URLs
/// starting with an ignored URL.
/// </summary>
public List<string> IgnoredUrls { get; } = new List<string>();
public List<string> IgnoredUrls { get; } = new();
}

19
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs

@ -94,8 +94,23 @@ public class AbpAuditingMiddleware : IMiddleware, ITransientDependency
private bool IsIgnoredUrl(HttpContext context)
{
return context.Request.Path.Value != null &&
AspNetCoreAuditingOptions.IgnoredUrls.Any(x => context.Request.Path.Value.StartsWith(x));
if (context.Request.Path.Value == null)
{
return false;
}
if (!AuditingOptions.IsEnabledForIntegrationServices &&
context.Request.Path.Value.StartsWith($"/{AbpAspNetCoreConsts.DefaultIntegrationServiceApiPrefix}/"))
{
return true;
}
if (AspNetCoreAuditingOptions.IgnoredUrls.Any(x => context.Request.Path.Value.StartsWith(x)))
{
return true;
}
return false;
}
private async Task<bool> ShouldWriteAuditLogAsync(AuditLogInfo auditLogInfo, HttpContext httpContext, bool hasError)

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

@ -52,7 +52,7 @@ public class AuditingHelper : IAuditingHelper, ITransientDependency
CorrelationIdProvider = correlationIdProvider;
}
public virtual bool ShouldSaveAudit(MethodInfo methodInfo, bool defaultValue = false)
public virtual bool ShouldSaveAudit(MethodInfo methodInfo, bool defaultValue = false, bool ignoreIntegrationServiceAttribute = false)
{
if (methodInfo == null)
{
@ -77,7 +77,7 @@ public class AuditingHelper : IAuditingHelper, ITransientDependency
var classType = methodInfo.DeclaringType;
if (classType != null)
{
var shouldAudit = AuditingInterceptorRegistrar.ShouldAuditTypeByDefaultOrNull(classType);
var shouldAudit = AuditingInterceptorRegistrar.ShouldAuditTypeByDefaultOrNull(classType, ignoreIntegrationServiceAttribute);
if (shouldAudit != null)
{
return shouldAudit.Value;

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

@ -62,7 +62,9 @@ public class AuditingInterceptor : AbpInterceptor, ITransientDependency
return false;
}
if (!auditingHelper.ShouldSaveAudit(invocation.Method))
if (!auditingHelper.ShouldSaveAudit(
invocation.Method,
ignoreIntegrationServiceAttribute: options.IsEnabledForIntegrationServices))
{
return false;
}

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

@ -22,7 +22,7 @@ public static class AuditingInterceptorRegistrar
return false;
}
if (ShouldAuditTypeByDefaultOrNull(type) == true)
if (ShouldAuditTypeByDefaultOrNull(type, ignoreIntegrationServiceAttribute: true) == true)
{
return true;
}
@ -36,7 +36,7 @@ public static class AuditingInterceptorRegistrar
}
//TODO: Move to a better place
public static bool? ShouldAuditTypeByDefaultOrNull(Type type)
public static bool? ShouldAuditTypeByDefaultOrNull(Type type, bool ignoreIntegrationServiceAttribute)
{
//TODO: In an inheritance chain, it would be better to check the attributes on the top class first.
@ -52,7 +52,10 @@ public static class AuditingInterceptorRegistrar
if (typeof(IAuditingEnabled).IsAssignableFrom(type))
{
return true;
if (ignoreIntegrationServiceAttribute || !type.IsDefined(typeof(IntegrationServiceAttribute), true))
{
return true;
}
}
return null;

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

@ -7,7 +7,7 @@ namespace Volo.Abp.Auditing;
//TODO: Move ShouldSaveAudit & IsEntityHistoryEnabled and rename to IAuditingFactory
public interface IAuditingHelper
{
bool ShouldSaveAudit(MethodInfo methodInfo, bool defaultValue = false);
bool ShouldSaveAudit(MethodInfo methodInfo, bool defaultValue = false, bool ignoreIntegrationServiceAttribute = false);
bool IsEntityHistoryEnabled(Type entityType, bool defaultValue = false);

2
framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/IntegrationServiceAttribute.cs → framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs

@ -1,6 +1,6 @@
using System;
namespace Volo.Abp.Application.Services;
namespace Volo.Abp;
[AttributeUsage(AttributeTargets.Class)]
public class IntegrationServiceAttribute : Attribute

14
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController.cs

@ -0,0 +1,14 @@
using Microsoft.AspNetCore.Mvc;
namespace Volo.Abp.AspNetCore.Mvc.Auditing;
[Route("integration-api/audit-test")]
[IntegrationService]
public class AuditIntegrationServiceTestController : AbpController
{
[HttpGet]
public IActionResult Get()
{
return Ok();
}
}

58
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController_Tests.cs

@ -0,0 +1,58 @@
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using NSubstitute;
using Shouldly;
using Volo.Abp.Auditing;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Auditing;
public class AuditIntegrationServiceTestController_Tests : AspNetCoreMvcTestBase
{
private readonly AbpAuditingOptions _options;
private IAuditingStore _auditingStore;
public AuditIntegrationServiceTestController_Tests()
{
_options = ServiceProvider.GetRequiredService<IOptions<AbpAuditingOptions>>().Value;
_auditingStore = ServiceProvider.GetRequiredService<IAuditingStore>();
}
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
_auditingStore = Substitute.For<IAuditingStore>();
services.Replace(ServiceDescriptor.Singleton(_auditingStore));
base.ConfigureServices(context, services);
}
[Fact]
public async Task Should_Write_Audit_Log_For_Controllers_With_IntegrationService_Attribute_If_IsEnabledForIntegrationServices()
{
_options.IsEnabledForGetRequests = true;
_options.IsEnabledForIntegrationServices = true;
await GetResponseAsync("/integration-api/audit-test/");
await _auditingStore
.Received()
.SaveAsync(
Arg.Is<AuditLogInfo>(
x => x.Actions.Any(
a =>
a.MethodName == nameof(AuditIntegrationServiceTestController.Get) &&
a.ServiceName == typeof(AuditIntegrationServiceTestController).FullName
)
)
);
}
[Fact]
public async Task Should_Not_Write_Audit_Log_For_Controllers_With_IntegrationService_Attribute()
{
_options.IsEnabledForGetRequests = true;
await GetResponseAsync("/integration-api/audit-test/");
await _auditingStore.DidNotReceive().SaveAsync(Arg.Any<AuditLogInfo>());
}
}

3
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs

@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;

24
framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs

@ -55,6 +55,16 @@ public class Auditing_Tests : AbpAuditingTestBase
await _auditingStore.Received().SaveAsync(Arg.Any<AuditLogInfo>());
}
[Fact]
public async Task Should_Not_Write_AuditLog_For_Classes_With_IntegrationService_Attribute()
{
var myAuditedObject1 = GetRequiredService<MyNotAuditedIntegrationService1>();
await myAuditedObject1.DoItAsync(new InputObject { Value1 = "forty-two", Value2 = 42 });
await _auditingStore.DidNotReceive().SaveAsync(Arg.Any<AuditLogInfo>());
}
public interface IMyAuditedObject : ITransientDependency, IAuditingEnabled
{
@ -72,6 +82,20 @@ public class Auditing_Tests : AbpAuditingTestBase
});
}
}
/* Integration services should not be audited by default */
[IntegrationService]
public class MyNotAuditedIntegrationService1 : IMyAuditedObject
{
public virtual Task<ResultObject> DoItAsync(InputObject inputObject)
{
return Task.FromResult(new ResultObject
{
Value1 = inputObject.Value1 + "-result",
Value2 = inputObject.Value2 + 1
});
}
}
public class ResultObject
{

Loading…
Cancel
Save