Added audit action filter

pull/395/head
Halil ibrahim Kalkan 8 years ago
parent c845a612b5
commit fd3091b38d

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Aspects;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
@ -11,7 +13,7 @@ using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc
{
public abstract class AbpController : Controller
public abstract class AbpController : Controller, IAvoidDuplicateCrossCuttingConcerns
{
public IUnitOfWorkManager UnitOfWorkManager { get; set; }
@ -29,6 +31,8 @@ namespace Volo.Abp.AspNetCore.Mvc
public IClock Clock { get; set; }
public List<string> AppliedCrossCuttingConcerns { get; } = new List<string>();
protected ILogger Logger => _lazyLogger.Value;
private Lazy<ILogger> _lazyLogger => new Lazy<ILogger>(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true);
}

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.Mvc.Auditing;
using Volo.Abp.AspNetCore.Mvc.Conventions;
using Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
using Volo.Abp.AspNetCore.Mvc.Uow;
@ -23,8 +24,7 @@ namespace Volo.Abp.AspNetCore.Mvc
private static void AddFilters(MvcOptions options)
{
//options.Filters.AddService(typeof(AbpAuthorizationFilter));
//options.Filters.AddService(typeof(AbpAuditActionFilter));
options.Filters.AddService(typeof(AbpAuditActionFilter));
options.Filters.AddService(typeof(AbpValidationActionFilter));
options.Filters.AddService(typeof(AbpUowActionFilter));
options.Filters.AddService(typeof(AbpExceptionFilter));

@ -0,0 +1,72 @@
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Volo.Abp.Aspects;
using Volo.Abp.Auditing;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.Mvc.Auditing
{
public class AbpAuditActionFilter : IAsyncActionFilter, ITransientDependency
{
protected AuditingOptions Options { get; }
private readonly IAuditingHelper _auditingHelper;
public AbpAuditActionFilter(IOptions<AuditingOptions> options, IAuditingHelper auditingHelper)
{
Options = options.Value;
_auditingHelper = auditingHelper;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (!ShouldSaveAudit(context))
{
await next();
return;
}
using (AbpCrossCuttingConcerns.Applying(context.Controller, AbpCrossCuttingConcerns.Auditing))
{
var auditInfo = _auditingHelper.CreateAuditInfo(
context.ActionDescriptor.AsControllerActionDescriptor().ControllerTypeInfo.AsType(),
context.ActionDescriptor.AsControllerActionDescriptor().MethodInfo,
context.ActionArguments
);
var stopwatch = Stopwatch.StartNew();
try
{
var result = await next();
if (result.Exception != null && !result.ExceptionHandled)
{
auditInfo.Exception = result.Exception;
}
}
catch (Exception ex)
{
auditInfo.Exception = ex;
throw;
}
finally
{
stopwatch.Stop();
auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
auditInfo.ServiceName = "AbpAuditActionFilter->" + auditInfo.ServiceName;
await _auditingHelper.SaveAsync(auditInfo);
}
}
}
private bool ShouldSaveAudit(ActionExecutingContext actionContext)
{
return Options.IsEnabled &&
actionContext.ActionDescriptor.IsControllerAction() &&
_auditingHelper.ShouldSaveAudit(actionContext.ActionDescriptor.GetMethodInfo(), true);
}
}
}

@ -0,0 +1,59 @@
using System;
using Castle.Core.Logging;
using Microsoft.AspNetCore.Http;
using Volo.Abp.Auditing;
namespace Volo.Abp.AspNetCore.Mvc.Auditing
{
public class HttpContextClientInfoProvider : IClientInfoProvider
{
public string BrowserInfo => GetBrowserInfo();
public string ClientIpAddress => GetClientIpAddress();
public string ComputerName => GetComputerName();
public ILogger Logger { get; set; }
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly HttpContext _httpContext;
/// <summary>
/// Creates a new <see cref="HttpContextClientInfoProvider"/>.
/// </summary>
public HttpContextClientInfoProvider(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
_httpContext = httpContextAccessor.HttpContext;
Logger = NullLogger.Instance;
}
protected virtual string GetBrowserInfo()
{
var httpContext = _httpContextAccessor.HttpContext ?? _httpContext;
return httpContext?.Request?.Headers?["User-Agent"];
}
protected virtual string GetClientIpAddress()
{
try
{
var httpContext = _httpContextAccessor.HttpContext ?? _httpContext;
return httpContext?.Connection?.RemoteIpAddress?.ToString();
}
catch (Exception ex)
{
Logger.Warn(ex.ToString());
}
return null;
}
protected virtual string GetComputerName()
{
return null; //TODO: Implement!
}
}
}

@ -47,6 +47,7 @@ namespace Volo.Abp.Auditing
{
stopwatch.Stop();
auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
auditInfo.ServiceName = "AuditingInterceptor->" + auditInfo.ServiceName;
_auditingHelper.Save(auditInfo);
}
}
@ -83,6 +84,7 @@ namespace Volo.Abp.Auditing
{
stopwatch.Stop();
auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
auditInfo.ServiceName = "AuditingInterceptor->" + auditInfo.ServiceName;
await _auditingHelper.SaveAsync(auditInfo);
}
}

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq.Expressions;
namespace Volo.Abp.Auditing
{
@ -15,7 +17,12 @@ namespace Volo.Abp.Auditing
{
IsEnabled = true;
IsEnabledForAnonymousUsers = true;
IgnoredTypes = new List<Type>();
IgnoredTypes = new List<Type>
{
typeof(Stream),
typeof(Expression)
};
}
}
}

@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Abp.Aspects;
using Volo.Abp.Authorization;
using Volo.Abp.Guids;
using Volo.Abp.MultiTenancy;
using Volo.Abp.ObjectMapping;
@ -20,9 +19,6 @@ namespace Volo.Abp.Application.Services
{
public static string[] CommonPostfixes { get; set; } = { "AppService", "ApplicationService", "Service" };
/// <summary>
/// Gets the applied cross cutting concerns.
/// </summary>
public List<string> AppliedCrossCuttingConcerns { get; } = new List<string>();
public IUnitOfWorkManager UnitOfWorkManager { get; set; }

@ -7,6 +7,7 @@
<ItemGroup>
<ProjectReference Include="..\..\..\..\modules\identity\src\Volo.Abp.Identity.Domain\Volo.Abp.Identity.Domain.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.DataAnnotations" Version="2.1.1" />
</ItemGroup>

@ -1,6 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using MyCompanyName.MyProjectName.Localization.MyProjectName;
using MyCompanyName.MyProjectName.Settings;
using Volo.Abp.Auditing;
using Volo.Abp.Identity;
using Volo.Abp.Localization;
using Volo.Abp.Localization.Resources.AbpValidation;
@ -10,7 +11,9 @@ using Volo.Abp.VirtualFileSystem;
namespace MyCompanyName.MyProjectName
{
[DependsOn(typeof(AbpIdentityDomainModule))]
[DependsOn(
typeof(AbpIdentityDomainModule),
typeof(AbpAuditingModule))] //TODO: Replace with AbpAuditLoggingDomainModule when it's done.
public class MyProjectNameDomainModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

Loading…
Cancel
Save