Browse Source

Resolved #5866: Auditing interceptor should start auditing scope if auditing middleware was not added.

pull/8113/head
Halil İbrahim Kalkan 6 years ago
parent
commit
8ad7a79eec
  1. 6
      framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs
  2. 15
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreUnitOfWorkOptions.cs
  3. 42
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAuditingMiddleware.cs
  4. 0
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpAspNetCoreUnitOfWorkOptions.cs
  5. 9
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs
  6. 142
      framework/src/Volo.Abp.Auditing/Volo/Abp/Auditing/AuditingInterceptor.cs

6
framework/src/Volo.Abp.AspNetCore.Components.Server/Volo/Abp/AspNetCore/Components/Server/AbpAspNetCoreComponentsServerModule.cs

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.Uow; using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -22,6 +23,11 @@ namespace Volo.Abp.AspNetCore.Components.Server
options.IgnoredUrls.AddIfNotContains("/_blazor"); options.IgnoredUrls.AddIfNotContains("/_blazor");
}); });
Configure<AbpAspNetCoreAuditingOptions>(options =>
{
options.IgnoredUrls.AddIfNotContains("/_blazor");
});
Configure<AbpEndpointRouterOptions>(options => Configure<AbpEndpointRouterOptions>(options =>
{ {
options.EndpointConfigureActions.Add(endpointContext => options.EndpointConfigureActions.Add(endpointContext =>

15
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Auditing/AbpAspNetCoreUnitOfWorkOptions.cs

@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace Volo.Abp.AspNetCore.Auditing
{
public class AbpAspNetCoreAuditingOptions
{
/// <summary>
/// This is used to disable the <see cref="AbpAuditingMiddleware"/>,
/// app.UseAuditing(), for the specified URLs.
/// <see cref="AbpAuditingMiddleware"/> will be disabled for URLs
/// starting with an ignored URL.
/// </summary>
public List<string> IgnoredUrls { get; } = new List<string>();
}
}

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

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -12,29 +13,39 @@ namespace Volo.Abp.AspNetCore.Auditing
public class AbpAuditingMiddleware : IMiddleware, ITransientDependency public class AbpAuditingMiddleware : IMiddleware, ITransientDependency
{ {
private readonly IAuditingManager _auditingManager; private readonly IAuditingManager _auditingManager;
protected AbpAuditingOptions AuditingOptions { get; }
protected AbpAuditingOptions Options { get; } protected AbpAspNetCoreAuditingOptions AspNetCoreAuditingOptions { get; }
protected ICurrentUser CurrentUser { get; } protected ICurrentUser CurrentUser { get; }
public AbpAuditingMiddleware( public AbpAuditingMiddleware(
IAuditingManager auditingManager, IAuditingManager auditingManager,
ICurrentUser currentUser, ICurrentUser currentUser,
IOptions<AbpAuditingOptions> options) IOptions<AbpAuditingOptions> auditingOptions,
IOptions<AbpAspNetCoreAuditingOptions> aspNetCoreAuditingOptions)
{ {
_auditingManager = auditingManager; _auditingManager = auditingManager;
CurrentUser = currentUser; CurrentUser = currentUser;
Options = options.Value; AuditingOptions = auditingOptions.Value;
AspNetCoreAuditingOptions = aspNetCoreAuditingOptions.Value;
} }
public async Task InvokeAsync(HttpContext context, RequestDelegate next) public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{ {
bool hasError = false; if (!AuditingOptions.IsEnabled || IsIgnoredUrl(context))
using (var scope = _auditingManager.BeginScope()) {
await next(context);
return;
}
var hasError = false;
using (var saveHandle = _auditingManager.BeginScope())
{ {
try try
{ {
await next(context); await next(context);
Debug.Assert(_auditingManager.Current != null);
if (_auditingManager.Current.Log.Exceptions.Any()) if (_auditingManager.Current.Log.Exceptions.Any())
{ {
hasError = true; hasError = true;
@ -49,30 +60,31 @@ namespace Volo.Abp.AspNetCore.Auditing
{ {
if (ShouldWriteAuditLog(context, hasError)) if (ShouldWriteAuditLog(context, hasError))
{ {
await scope.SaveAsync(); await saveHandle.SaveAsync();
} }
} }
} }
} }
private bool ShouldWriteAuditLog(HttpContext httpContext, bool hasError = false) private bool IsIgnoredUrl(HttpContext context)
{ {
if (!Options.IsEnabled) return context.Request.Path.Value != null &&
{ AspNetCoreAuditingOptions.IgnoredUrls.Any(x => context.Request.Path.Value.StartsWith(x));
return false; }
}
if (Options.AlwaysLogOnException && hasError) private bool ShouldWriteAuditLog(HttpContext httpContext, bool hasError)
{
if (AuditingOptions.AlwaysLogOnException && hasError)
{ {
return true; return true;
} }
if (!Options.IsEnabledForAnonymousUsers && !CurrentUser.IsAuthenticated) if (!AuditingOptions.IsEnabledForAnonymousUsers && !CurrentUser.IsAuthenticated)
{ {
return false; return false;
} }
if (!Options.IsEnabledForGetRequests && if (!AuditingOptions.IsEnabledForGetRequests &&
string.Equals(httpContext.Request.Method, HttpMethods.Get, StringComparison.OrdinalIgnoreCase)) string.Equals(httpContext.Request.Method, HttpMethods.Get, StringComparison.OrdinalIgnoreCase))
{ {
return false; return false;

0
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpAspNetCoreOptions.cs → framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpAspNetCoreUnitOfWorkOptions.cs

9
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Uow/AbpUnitOfWorkMiddleware.cs

@ -22,8 +22,7 @@ namespace Volo.Abp.AspNetCore.Uow
public async Task InvokeAsync(HttpContext context, RequestDelegate next) public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{ {
if (context.Request.Path.Value != null && if (IsIgnoredUrl(context))
_options.IgnoredUrls.Any(x => context.Request.Path.Value.StartsWith(x)))
{ {
await next(context); await next(context);
return; return;
@ -35,5 +34,11 @@ namespace Volo.Abp.AspNetCore.Uow
await uow.CompleteAsync(context.RequestAborted); await uow.CompleteAsync(context.RequestAborted);
} }
} }
private bool IsIgnoredUrl(HttpContext context)
{
return context.Request.Path.Value != null &&
_options.IgnoredUrls.Any(x => context.Request.Path.Value.StartsWith(x));
}
} }
} }

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

@ -1,10 +1,13 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Aspects; using Volo.Abp.Aspects;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy; using Volo.Abp.DynamicProxy;
using Volo.Abp.Users;
namespace Volo.Abp.Auditing namespace Volo.Abp.Auditing
{ {
@ -19,12 +22,65 @@ namespace Volo.Abp.Auditing
public override async Task InterceptAsync(IAbpMethodInvocation invocation) public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{ {
if (!ShouldIntercept(invocation, out var auditLog, out var auditLogAction)) using (var serviceScope = _serviceScopeFactory.CreateScope())
{ {
await invocation.ProceedAsync(); var auditingHelper = serviceScope.ServiceProvider.GetRequiredService<IAuditingHelper>();
return; var auditingOptions = serviceScope.ServiceProvider.GetRequiredService<IOptions<AbpAuditingOptions>>().Value;
if (!ShouldIntercept(invocation, auditingOptions, auditingHelper))
{
await invocation.ProceedAsync();
return;
}
var auditingManager = serviceScope.ServiceProvider.GetRequiredService<IAuditingManager>();
if (auditingManager.Current != null)
{
await ProceedByLoggingAsync(invocation, auditingHelper, auditingManager.Current);
}
else
{
var currentUser = serviceScope.ServiceProvider.GetRequiredService<ICurrentUser>();
await ProcessWithNewAuditingScopeAsync(invocation, auditingOptions, currentUser, auditingManager, auditingHelper);
}
}
}
protected virtual bool ShouldIntercept(IAbpMethodInvocation invocation,
AbpAuditingOptions options,
IAuditingHelper auditingHelper)
{
if (!options.IsEnabled)
{
return false;
}
if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.Auditing))
{
return false;
} }
if (!auditingHelper.ShouldSaveAudit(invocation.Method))
{
return false;
}
return true;
}
private static async Task ProceedByLoggingAsync(
IAbpMethodInvocation invocation,
IAuditingHelper auditingHelper,
IAuditLogScope auditLogScope)
{
var auditLog = auditLogScope.Log;
var auditLogAction = auditingHelper.CreateAuditLogAction(
auditLog,
invocation.TargetObject.GetType(),
invocation.Method,
invocation.Arguments
);
var stopwatch = Stopwatch.StartNew(); var stopwatch = Stopwatch.StartNew();
try try
@ -43,45 +99,65 @@ namespace Volo.Abp.Auditing
auditLog.Actions.Add(auditLogAction); auditLog.Actions.Add(auditLogAction);
} }
} }
protected virtual bool ShouldIntercept( private async Task ProcessWithNewAuditingScopeAsync(
IAbpMethodInvocation invocation, IAbpMethodInvocation invocation,
out AuditLogInfo auditLog, AbpAuditingOptions options,
out AuditLogActionInfo auditLogAction) ICurrentUser currentUser,
IAuditingManager auditingManager,
IAuditingHelper auditingHelper)
{ {
auditLog = null; var hasError = false;
auditLogAction = null; using (var saveHandle = auditingManager.BeginScope())
if (AbpCrossCuttingConcerns.IsApplied(invocation.TargetObject, AbpCrossCuttingConcerns.Auditing))
{ {
return false; try
} {
await ProceedByLoggingAsync(invocation, auditingHelper, auditingManager.Current);
using (var scope = _serviceScopeFactory.CreateScope()) Debug.Assert(auditingManager.Current != null);
{ if (auditingManager.Current.Log.Exceptions.Any())
var auditingManager = scope.ServiceProvider.GetRequiredService<IAuditingManager>(); {
var auditLogScope = auditingManager.Current; hasError = true;
if (auditLogScope == null) }
}
catch (Exception)
{ {
return false; hasError = true;
throw;
} }
finally
var auditingHelper = scope.ServiceProvider.GetRequiredService<IAuditingHelper>();
if (!auditingHelper.ShouldSaveAudit(invocation.Method))
{ {
return false; if (ShouldWriteAuditLog(invocation, options, currentUser, hasError))
{
await saveHandle.SaveAsync();
}
} }
}
}
private bool ShouldWriteAuditLog(
IAbpMethodInvocation invocation,
AbpAuditingOptions options,
ICurrentUser currentUser,
bool hasError)
{
if (options.AlwaysLogOnException && hasError)
{
return true;
}
auditLog = auditLogScope.Log; if (!options.IsEnabledForAnonymousUsers && !currentUser.IsAuthenticated)
auditLogAction = auditingHelper.CreateAuditLogAction( {
auditLog, return false;
invocation.TargetObject.GetType(), }
invocation.Method,
invocation.Arguments
);
return true; if (!options.IsEnabledForGetRequests &&
invocation.Method.Name.StartsWith("Get",StringComparison.OrdinalIgnoreCase))
{
return false;
} }
return true;
} }
} }
} }
Loading…
Cancel
Save