diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs index 4bc4673860..24c9b071bd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Microsoft/AspNetCore/Mvc/Abstractions/ActionDescriptorExtensions.cs +++ b/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; + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs index 47ed4c4614..dfffeea5b4 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditActionFilter.cs +++ b/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(); - 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; + } } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs index 2abfd477db..1f347decf7 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Auditing/AbpAuditPageFilter.cs +++ b/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(); - if (!auditingHelper.ShouldSaveAudit(context.HandlerMethod.MethodInfo, true)) + if (!auditingHelper.ShouldSaveAudit(context.HandlerMethod.MethodInfo, defaultValue: true)) { return false; } diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs index 3891827c0f..0906d46006 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Conventions/ConventionalRouteBuilder.cs @@ -26,9 +26,11 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep string httpMethod, [CanBeNull] ConventionalControllerSetting configuration) { - var controllerNameInUrl = NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration); + var apiRoutePrefix = GetApiRoutePrefix(action, configuration); + var controllerNameInUrl = + NormalizeUrlControllerName(rootPath, controllerName, action, httpMethod, configuration); - var url = $"api/{rootPath}/{NormalizeControllerNameCase(controllerNameInUrl, configuration)}"; + var url = $"{apiRoutePrefix}/{rootPath}/{NormalizeControllerNameCase(controllerNameInUrl, configuration)}"; //Add {id} path if needed var idParameterModel = action.Parameters.FirstOrDefault(p => p.ParameterName == "id"); @@ -69,6 +71,16 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep return url; } + protected virtual string GetApiRoutePrefix(ActionModel actionModel, ConventionalControllerSetting configuration) + { + if (actionModel.Controller.ControllerType.IsDefined(typeof(IntegrationServiceAttribute), true)) + { + return AbpAspNetCoreConsts.DefaultIntegrationServiceApiPrefix; + } + + return AbpAspNetCoreConsts.DefaultApiPrefix; + } + protected virtual string NormalizeUrlActionName(string rootPath, string controllerName, ActionModel action, string httpMethod, [CanBeNull] ConventionalControllerSetting configuration) { @@ -108,7 +120,8 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep ); } - protected virtual string NormalizeControllerNameCase(string controllerName, [CanBeNull] ConventionalControllerSetting configuration) + protected virtual string NormalizeControllerNameCase(string controllerName, + [CanBeNull] ConventionalControllerSetting configuration) { if (configuration?.UseV3UrlStyle ?? Options.UseV3UrlStyle) { @@ -120,7 +133,8 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep } } - protected virtual string NormalizeActionNameCase(string actionName, [CanBeNull] ConventionalControllerSetting configuration) + protected virtual string NormalizeActionNameCase(string actionName, + [CanBeNull] ConventionalControllerSetting configuration) { if (configuration?.UseV3UrlStyle ?? Options.UseV3UrlStyle) { @@ -132,13 +146,15 @@ public class ConventionalRouteBuilder : IConventionalRouteBuilder, ITransientDep } } - protected virtual string NormalizeIdPropertyNameCase(PropertyInfo property, [CanBeNull] ConventionalControllerSetting configuration) + protected virtual string NormalizeIdPropertyNameCase(PropertyInfo property, + [CanBeNull] ConventionalControllerSetting configuration) { return property.Name; } - protected virtual string NormalizeSecondaryIdNameCase(ParameterModel secondaryId, [CanBeNull] ConventionalControllerSetting configuration) + protected virtual string NormalizeSecondaryIdNameCase(ParameterModel secondaryId, + [CanBeNull] ConventionalControllerSetting configuration) { return secondaryId.ParameterName; } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreConsts.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreConsts.cs new file mode 100644 index 0000000000..dff987b6b3 --- /dev/null +++ b/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"; +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingOptions.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingOptions.cs index 7977205096..693945e903 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingOptions.cs +++ b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreAuditingOptions.cs @@ -10,5 +10,5 @@ public class AbpAspNetCoreAuditingOptions /// will be disabled for URLs /// starting with an ignored URL. /// - public List IgnoredUrls { get; } = new List(); + public List IgnoredUrls { get; } = new(); } diff --git a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs b/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs index 9cae64501a..83deaef26a 100644 --- a/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs +++ b/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 ShouldWriteAuditLogAsync(AuditLogInfo auditLogInfo, HttpContext httpContext, bool hasError) diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs index b3c6aeb051..441cd8ef23 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs +++ b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AbpAuditingOptions.cs @@ -37,6 +37,12 @@ public class AbpAuditingOptions /// Default: true. /// public bool AlwaysLogOnException { get; set; } + + /// + /// Disables/enables audit logging for integration services. + /// Default: false. + /// + public bool IsEnabledForIntegrationServices { get; set; } public List>> AlwaysLogSelectors { get; } diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs index 1f3c6b433c..7468f10986 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingHelper.cs +++ b/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; diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs index 63c38ef3c3..78de793b6c 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs +++ b/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; } diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs index 45af44ef91..db5d44cec5 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptorRegistrar.cs +++ b/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; diff --git a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingHelper.cs b/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingHelper.cs index 915d2fcfc1..5a2878d1b0 100644 --- a/framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/IAuditingHelper.cs +++ b/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); diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IRemoteService.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IRemoteService.cs index f17a0619dc..613781629c 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/IRemoteService.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IRemoteService.cs @@ -1,5 +1,5 @@ namespace Volo.Abp; -public interface IRemoteService //TODO: Can we move this to another package? +public interface IRemoteService { } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs b/framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs new file mode 100644 index 0000000000..016a7a49c7 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/IntegrationServiceAttribute.cs @@ -0,0 +1,9 @@ +using System; + +namespace Volo.Abp; + +[AttributeUsage(AttributeTargets.Class)] +public class IntegrationServiceAttribute : Attribute +{ + +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Services/IApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Services/IApplicationService.cs index 34fe187f81..ce59e46832 100644 --- a/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Services/IApplicationService.cs +++ b/framework/src/Volo.Abp.Ddd.Application.Contracts/Volo/Abp/Application/Services/IApplicationService.cs @@ -3,8 +3,7 @@ /// /// This interface must be implemented by all application services to register and identify them by convention. /// -public interface IApplicationService : - IRemoteService +public interface IApplicationService : IRemoteService { -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs index 38a7efdb2e..bef608a6ff 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/AbpDddApplicationModule.cs @@ -1,5 +1,7 @@ using System.Collections.Generic; using Volo.Abp.Application.Services; +using Volo.Abp.Aspects; +using Volo.Abp.Auditing; using Volo.Abp.Authorization; using Volo.Abp.Domain; using Volo.Abp.Features; @@ -33,10 +35,12 @@ public class AbpDddApplicationModule : AbpModule { Configure(options => { - //TODO: Should we move related items to their own projects? - options.IgnoredInterfaces.AddIfNotContains(typeof(IRemoteService)); + options.IgnoredInterfaces.AddIfNotContains(typeof(IRemoteService)); options.IgnoredInterfaces.AddIfNotContains(typeof(IApplicationService)); options.IgnoredInterfaces.AddIfNotContains(typeof(IUnitOfWorkEnabled)); + options.IgnoredInterfaces.AddIfNotContains(typeof(IAuditingEnabled)); + options.IgnoredInterfaces.AddIfNotContains(typeof(IValidationEnabled)); + options.IgnoredInterfaces.AddIfNotContains(typeof(IGlobalFeatureCheckingEnabled)); }); } } diff --git a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs index 03b2857ddc..b24e4b2900 100644 --- a/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs +++ b/framework/src/Volo.Abp.Ddd.Application/Volo/Abp/Application/Services/ApplicationService.cs @@ -41,9 +41,9 @@ public abstract class ApplicationService : [Obsolete("Use LazyServiceProvider instead.")] public IServiceProvider ServiceProvider { get; set; } - public static string[] CommonPostfixes { get; set; } = { "AppService", "ApplicationService", "Service" }; + public static string[] CommonPostfixes { get; set; } = { "AppService", "ApplicationService", "IntService", "IntegrationService", "Service" }; - public List AppliedCrossCuttingConcerns { get; } = new List(); + public List AppliedCrossCuttingConcerns { get; } = new(); protected IUnitOfWorkManager UnitOfWorkManager => LazyServiceProvider.LazyGetRequiredService(); diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController.cs new file mode 100644 index 0000000000..6e14e04d32 --- /dev/null +++ b/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(); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditIntegrationServiceTestController_Tests.cs new file mode 100644 index 0000000000..129035f406 --- /dev/null +++ b/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>().Value; + _auditingStore = ServiceProvider.GetRequiredService(); + } + + protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services) + { + _auditingStore = Substitute.For(); + 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( + 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()); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs index d36b5a5723..886df9a0ac 100644 --- a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Auditing/AuditTestController_Tests.cs +++ b/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; diff --git a/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PeopleIntegrationService_Tests.cs b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PeopleIntegrationService_Tests.cs new file mode 100644 index 0000000000..850eb12862 --- /dev/null +++ b/framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/PeopleIntegrationService_Tests.cs @@ -0,0 +1,15 @@ +using System.Threading.Tasks; +using Shouldly; +using Xunit; + +namespace Volo.Abp.AspNetCore.Mvc; + +public class PeopleIntegrationService_Tests : AspNetCoreMvcTestBase +{ + [Fact] + public async Task GetValueAsync() + { + var result = await GetResponseAsStringAsync("/integration-api/app/people/value"); + result.ShouldBe("42"); + } +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs b/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs index e40fdd8b59..49d92d2776 100644 --- a/framework/test/Volo.Abp.Auditing.Tests/Volo/Abp/Auditing/Auditing_Tests.cs +++ b/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()); } + + [Fact] + public async Task Should_Not_Write_AuditLog_For_Classes_With_IntegrationService_Attribute() + { + var myAuditedObject1 = GetRequiredService(); + + await myAuditedObject1.DoItAsync(new InputObject { Value1 = "forty-two", Value2 = 42 }); + + await _auditingStore.DidNotReceive().SaveAsync(Arg.Any()); + } 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 DoItAsync(InputObject inputObject) + { + return Task.FromResult(new ResultObject + { + Value1 = inputObject.Value1 + "-result", + Value2 = inputObject.Value2 + 1 + }); + } + } public class ResultObject { diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPeopleIntegrationService.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPeopleIntegrationService.cs new file mode 100644 index 0000000000..7e4c76daaa --- /dev/null +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/IPeopleIntegrationService.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace Volo.Abp.TestApp.Application; + +public interface IPeopleIntegrationService : IApplicationService +{ + Task GetValueAsync(); +} \ No newline at end of file diff --git a/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleIntegrationService.cs b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleIntegrationService.cs new file mode 100644 index 0000000000..4501fdb16f --- /dev/null +++ b/framework/test/Volo.Abp.TestApp/Volo/Abp/TestApp/Application/PeopleIntegrationService.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace Volo.Abp.TestApp.Application; + +[IntegrationService] +public class PeopleIntegrationService : ApplicationService, IPeopleIntegrationService +{ + public async Task GetValueAsync() + { + return "42"; + } +} \ No newline at end of file