feat: 搭建审计日志模块

This commit is contained in:
陈淳
2023-12-27 18:59:26 +08:00
parent d86ee7a028
commit 8ef2ff43b0
6 changed files with 455 additions and 1 deletions

View File

@@ -0,0 +1,266 @@
//using System.Linq.Dynamic.Core;
//using System.Net;
//using Volo.Abp.Auditing;
//using Volo.Abp.Domain.Entities;
//using Yi.Framework.SqlSugarCore.Abstractions;
//using Yi.Framework.SqlSugarCore.Repositories;
//namespace Volo.Abp.AuditLogging.EntityFrameworkCore;
//public class SqlSugarCoreAuditLogRepository : SqlSugarRepository<AuditLog, Guid>, IAuditLogRepository
//{
// public SqlSugarCoreAuditLogRepository(ISugarDbContextProvider<ISqlSugarDbContext> sugarDbContextProvider) : base(sugarDbContextProvider)
// {
// }
// public virtual async Task<List<AuditLog>> GetListAsync(
// string sorting = null,
// int maxResultCount = 50,
// int skipCount = 0,
// DateTime? startTime = null,
// DateTime? endTime = null,
// string httpMethod = null,
// string url = null,
// Guid? userId = null,
// string userName = null,
// string applicationName = null,
// string clientIpAddress = null,
// string correlationId = null,
// int? maxExecutionDuration = null,
// int? minExecutionDuration = null,
// bool? hasException = null,
// HttpStatusCode? httpStatusCode = null,
// bool includeDetails = false,
// CancellationToken cancellationToken = default)
// {
// var query = await GetListQueryAsync(
// startTime,
// endTime,
// httpMethod,
// url,
// userId,
// userName,
// applicationName,
// clientIpAddress,
// correlationId,
// maxExecutionDuration,
// minExecutionDuration,
// hasException,
// httpStatusCode,
// includeDetails
// );
// var auditLogs = await query
// .OrderBy(sorting.IsNullOrWhiteSpace() ? (nameof(AuditLog.ExecutionTime) + " DESC") : sorting)
// .PageBy(skipCount, maxResultCount)
// .ToListAsync(GetCancellationToken(cancellationToken));
// return auditLogs;
// }
// public virtual async Task<long> GetCountAsync(
// DateTime? startTime = null,
// DateTime? endTime = null,
// string httpMethod = null,
// string url = null,
// Guid? userId = null,
// string userName = null,
// string applicationName = null,
// string clientIpAddress = null,
// string correlationId = null,
// int? maxExecutionDuration = null,
// int? minExecutionDuration = null,
// bool? hasException = null,
// HttpStatusCode? httpStatusCode = null,
// CancellationToken cancellationToken = default)
// {
// var query = await GetListQueryAsync(
// startTime,
// endTime,
// httpMethod,
// url,
// userId,
// userName,
// applicationName,
// clientIpAddress,
// correlationId,
// maxExecutionDuration,
// minExecutionDuration,
// hasException,
// httpStatusCode
// );
// var totalCount = await query.LongCountAsync(GetCancellationToken(cancellationToken));
// return totalCount;
// }
// protected virtual async Task<IQueryable<AuditLog>> GetListQueryAsync(
// DateTime? startTime = null,
// DateTime? endTime = null,
// string httpMethod = null,
// string url = null,
// Guid? userId = null,
// string userName = null,
// string applicationName = null,
// string clientIpAddress = null,
// string correlationId = null,
// int? maxExecutionDuration = null,
// int? minExecutionDuration = null,
// bool? hasException = null,
// HttpStatusCode? httpStatusCode = null,
// bool includeDetails = false)
// {
// var nHttpStatusCode = (int?)httpStatusCode;
// return (await GetDbSetAsync()).AsNoTracking()
// .IncludeDetails(includeDetails)
// .WhereIf(startTime.HasValue, auditLog => auditLog.ExecutionTime >= startTime)
// .WhereIf(endTime.HasValue, auditLog => auditLog.ExecutionTime <= endTime)
// .WhereIf(hasException.HasValue && hasException.Value, auditLog => auditLog.Exceptions != null && auditLog.Exceptions != "")
// .WhereIf(hasException.HasValue && !hasException.Value, auditLog => auditLog.Exceptions == null || auditLog.Exceptions == "")
// .WhereIf(httpMethod != null, auditLog => auditLog.HttpMethod == httpMethod)
// .WhereIf(url != null, auditLog => auditLog.Url != null && auditLog.Url.Contains(url))
// .WhereIf(userId != null, auditLog => auditLog.UserId == userId)
// .WhereIf(userName != null, auditLog => auditLog.UserName == userName)
// .WhereIf(applicationName != null, auditLog => auditLog.ApplicationName == applicationName)
// .WhereIf(clientIpAddress != null, auditLog => auditLog.ClientIpAddress != null && auditLog.ClientIpAddress == clientIpAddress)
// .WhereIf(correlationId != null, auditLog => auditLog.CorrelationId == correlationId)
// .WhereIf(httpStatusCode != null && httpStatusCode > 0, auditLog => auditLog.HttpStatusCode == nHttpStatusCode)
// .WhereIf(maxExecutionDuration != null && maxExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration <= maxExecutionDuration)
// .WhereIf(minExecutionDuration != null && minExecutionDuration.Value > 0, auditLog => auditLog.ExecutionDuration >= minExecutionDuration);
// }
// public virtual async Task<Dictionary<DateTime, double>> GetAverageExecutionDurationPerDayAsync(
// DateTime startDate,
// DateTime endDate,
// CancellationToken cancellationToken = default)
// {
// var result = await (await GetDbSetAsync()).AsNoTracking()
// .Where(a => a.ExecutionTime < endDate.AddDays(1) && a.ExecutionTime > startDate)
// .OrderBy(t => t.ExecutionTime)
// .GroupBy(t => new { t.ExecutionTime.Date })
// .Select(g => new { Day = g.Min(t => t.ExecutionTime), avgExecutionTime = g.Average(t => t.ExecutionDuration) })
// .ToListAsync(GetCancellationToken(cancellationToken));
// return result.ToDictionary(element => element.Day.ClearTime(), element => element.avgExecutionTime);
// }
// [Obsolete("Use WithDetailsAsync method.")]
// public override IQueryable<AuditLog> WithDetails()
// {
// return GetQueryable().IncludeDetails();
// }
// public override async Task<IQueryable<AuditLog>> WithDetailsAsync()
// {
// return (await GetQueryableAsync()).IncludeDetails();
// }
// public virtual async Task<EntityChange> GetEntityChange(
// Guid entityChangeId,
// CancellationToken cancellationToken = default)
// {
// var entityChange = await (await GetDbContextAsync()).Set<EntityChange>()
// .AsNoTracking()
// .IncludeDetails()
// .Where(x => x.Id == entityChangeId)
// .OrderBy(x => x.Id)
// .FirstOrDefaultAsync(GetCancellationToken(cancellationToken));
// if (entityChange == null)
// {
// throw new EntityNotFoundException(typeof(EntityChange));
// }
// return entityChange;
// }
// public virtual async Task<List<EntityChange>> GetEntityChangeListAsync(
// string sorting = null,
// int maxResultCount = 50,
// int skipCount = 0,
// Guid? auditLogId = null,
// DateTime? startTime = null,
// DateTime? endTime = null,
// EntityChangeType? changeType = null,
// string entityId = null,
// string entityTypeFullName = null,
// bool includeDetails = false,
// CancellationToken cancellationToken = default)
// {
// var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName, includeDetails);
// return await query.OrderBy(sorting.IsNullOrWhiteSpace() ? (nameof(EntityChange.ChangeTime) + " DESC") : sorting)
// .PageBy(skipCount, maxResultCount)
// .ToListAsync(GetCancellationToken(cancellationToken));
// }
// public virtual async Task<long> GetEntityChangeCountAsync(
// Guid? auditLogId = null,
// DateTime? startTime = null,
// DateTime? endTime = null,
// EntityChangeType? changeType = null,
// string entityId = null,
// string entityTypeFullName = null,
// CancellationToken cancellationToken = default)
// {
// var query = await GetEntityChangeListQueryAsync(auditLogId, startTime, endTime, changeType, entityId, entityTypeFullName);
// var totalCount = await query.LongCountAsync(GetCancellationToken(cancellationToken));
// return totalCount;
// }
// public virtual async Task<EntityChangeWithUsername> GetEntityChangeWithUsernameAsync(
// Guid entityChangeId,
// CancellationToken cancellationToken = default)
// {
// var auditLog = await (await GetDbSetAsync()).AsNoTracking().IncludeDetails()
// .Where(x => x.EntityChanges.Any(y => y.Id == entityChangeId)).FirstAsync(GetCancellationToken(cancellationToken));
// return new EntityChangeWithUsername()
// {
// EntityChange = auditLog.EntityChanges.First(x => x.Id == entityChangeId),
// UserName = auditLog.UserName
// };
// }
// public virtual async Task<List<EntityChangeWithUsername>> GetEntityChangesWithUsernameAsync(
// string entityId,
// string entityTypeFullName,
// CancellationToken cancellationToken = default)
// {
// var dbContext = await GetDbContextAsync();
// var query = dbContext.Set<EntityChange>()
// .AsNoTracking()
// .IncludeDetails()
// .Where(x => x.EntityId == entityId && x.EntityTypeFullName == entityTypeFullName);
// return await (from e in query
// join auditLog in dbContext.AuditLogs on e.AuditLogId equals auditLog.Id
// select new EntityChangeWithUsername { EntityChange = e, UserName = auditLog.UserName })
// .OrderByDescending(x => x.EntityChange.ChangeTime).ToListAsync(GetCancellationToken(cancellationToken));
// }
// protected virtual async Task<IQueryable<EntityChange>> GetEntityChangeListQueryAsync(
// Guid? auditLogId = null,
// DateTime? startTime = null,
// DateTime? endTime = null,
// EntityChangeType? changeType = null,
// string entityId = null,
// string entityTypeFullName = null,
// bool includeDetails = false)
// {
// return (await GetDbContextAsync())
// .Set<EntityChange>()
// .AsNoTracking()
// .IncludeDetails(includeDetails)
// .WhereIf(auditLogId.HasValue, e => e.AuditLogId == auditLogId)
// .WhereIf(startTime.HasValue, e => e.ChangeTime >= startTime)
// .WhereIf(endTime.HasValue, e => e.ChangeTime <= endTime)
// .WhereIf(changeType.HasValue, e => e.ChangeType == changeType)
// .WhereIf(!string.IsNullOrWhiteSpace(entityId), e => e.EntityId == entityId)
// .WhereIf(!string.IsNullOrWhiteSpace(entityTypeFullName), e => e.EntityTypeFullName.Contains(entityTypeFullName));
// }
//}

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AuditLogging.Domain" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\framework\Yi.Framework.SqlSugarCore\Yi.Framework.SqlSugarCore.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
using Volo.Abp.AuditLogging;
using Volo.Abp.DependencyInjection;
using Yi.Framework.SqlSugarCore;
namespace Yi.AuditLogging.SqlSugarCore
{
public class YiAuditLoggingDbContext : SqlSugarDbContext
{
public YiAuditLoggingDbContext(IAbpLazyServiceProvider lazyServiceProvider) : base(lazyServiceProvider)
{
}
protected override void EntityService(PropertyInfo property, EntityColumnInfo column)
{
base.EntityService(property, column);
column.DbTableName = AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogs";
column.IfTable<AuditLog>()
.UpdateProperty(x => x.Id,
x =>
{
x.IsPrimarykey = true;
})
.UpdateProperty(x => x.ApplicationName,
x =>
{
x.Length = AuditLogConsts.MaxApplicationNameLength;
x.DbColumnName = nameof(AuditLog.ApplicationName);
});
//builder.Entity<AuditLog>(b =>
//{
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogs", AbpAuditLoggingDbProperties.DbSchema);
// b.ConfigureByConvention();
// b.Property(x => x.ApplicationName).HasMaxLength(AuditLogConsts.MaxApplicationNameLength).HasColumnName(nameof(AuditLog.ApplicationName));
// b.Property(x => x.ClientIpAddress).HasMaxLength(AuditLogConsts.MaxClientIpAddressLength).HasColumnName(nameof(AuditLog.ClientIpAddress));
// b.Property(x => x.ClientName).HasMaxLength(AuditLogConsts.MaxClientNameLength).HasColumnName(nameof(AuditLog.ClientName));
// b.Property(x => x.ClientId).HasMaxLength(AuditLogConsts.MaxClientIdLength).HasColumnName(nameof(AuditLog.ClientId));
// b.Property(x => x.CorrelationId).HasMaxLength(AuditLogConsts.MaxCorrelationIdLength).HasColumnName(nameof(AuditLog.CorrelationId));
// b.Property(x => x.BrowserInfo).HasMaxLength(AuditLogConsts.MaxBrowserInfoLength).HasColumnName(nameof(AuditLog.BrowserInfo));
// b.Property(x => x.HttpMethod).HasMaxLength(AuditLogConsts.MaxHttpMethodLength).HasColumnName(nameof(AuditLog.HttpMethod));
// b.Property(x => x.Url).HasMaxLength(AuditLogConsts.MaxUrlLength).HasColumnName(nameof(AuditLog.Url));
// b.Property(x => x.HttpStatusCode).HasColumnName(nameof(AuditLog.HttpStatusCode));
// b.Property(x => x.Comments).HasMaxLength(AuditLogConsts.MaxCommentsLength).HasColumnName(nameof(AuditLog.Comments));
// b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLog.ExecutionDuration));
// b.Property(x => x.ImpersonatorTenantId).HasColumnName(nameof(AuditLog.ImpersonatorTenantId));
// b.Property(x => x.ImpersonatorUserId).HasColumnName(nameof(AuditLog.ImpersonatorUserId));
// b.Property(x => x.ImpersonatorTenantName).HasMaxLength(AuditLogConsts.MaxTenantNameLength).HasColumnName(nameof(AuditLog.ImpersonatorTenantName));
// b.Property(x => x.ImpersonatorUserName).HasMaxLength(AuditLogConsts.MaxUserNameLength).HasColumnName(nameof(AuditLog.ImpersonatorUserName));
// b.Property(x => x.UserId).HasColumnName(nameof(AuditLog.UserId));
// b.Property(x => x.UserName).HasMaxLength(AuditLogConsts.MaxUserNameLength).HasColumnName(nameof(AuditLog.UserName));
// b.Property(x => x.TenantId).HasColumnName(nameof(AuditLog.TenantId));
// b.Property(x => x.TenantName).HasMaxLength(AuditLogConsts.MaxTenantNameLength).HasColumnName(nameof(AuditLog.TenantName));
// b.HasMany(a => a.Actions).WithOne().HasForeignKey(x => x.AuditLogId).IsRequired();
// b.HasMany(a => a.EntityChanges).WithOne().HasForeignKey(x => x.AuditLogId).IsRequired();
// b.HasIndex(x => new { x.TenantId, x.ExecutionTime });
// b.HasIndex(x => new { x.TenantId, x.UserId, x.ExecutionTime });
// b.ApplyObjectExtensionMappings();
//});
//builder.Entity<AuditLogAction>(b =>
//{
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "AuditLogActions", AbpAuditLoggingDbProperties.DbSchema);
// b.ConfigureByConvention();
// b.Property(x => x.AuditLogId).HasColumnName(nameof(AuditLogAction.AuditLogId));
// b.Property(x => x.ServiceName).HasMaxLength(AuditLogActionConsts.MaxServiceNameLength).HasColumnName(nameof(AuditLogAction.ServiceName));
// b.Property(x => x.MethodName).HasMaxLength(AuditLogActionConsts.MaxMethodNameLength).HasColumnName(nameof(AuditLogAction.MethodName));
// b.Property(x => x.Parameters).HasMaxLength(AuditLogActionConsts.MaxParametersLength).HasColumnName(nameof(AuditLogAction.Parameters));
// b.Property(x => x.ExecutionTime).HasColumnName(nameof(AuditLogAction.ExecutionTime));
// b.Property(x => x.ExecutionDuration).HasColumnName(nameof(AuditLogAction.ExecutionDuration));
// b.HasIndex(x => new { x.AuditLogId });
// b.HasIndex(x => new { x.TenantId, x.ServiceName, x.MethodName, x.ExecutionTime });
// b.ApplyObjectExtensionMappings();
//});
//builder.Entity<EntityChange>(b =>
//{
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "EntityChanges", AbpAuditLoggingDbProperties.DbSchema);
// b.ConfigureByConvention();
// b.Property(x => x.EntityTypeFullName).HasMaxLength(EntityChangeConsts.MaxEntityTypeFullNameLength).IsRequired().HasColumnName(nameof(EntityChange.EntityTypeFullName));
// b.Property(x => x.EntityId).HasMaxLength(EntityChangeConsts.MaxEntityIdLength).IsRequired().HasColumnName(nameof(EntityChange.EntityId));
// b.Property(x => x.AuditLogId).IsRequired().HasColumnName(nameof(EntityChange.AuditLogId));
// b.Property(x => x.ChangeTime).IsRequired().HasColumnName(nameof(EntityChange.ChangeTime));
// b.Property(x => x.ChangeType).IsRequired().HasColumnName(nameof(EntityChange.ChangeType));
// b.Property(x => x.TenantId).HasColumnName(nameof(EntityChange.TenantId));
// b.HasMany(a => a.PropertyChanges).WithOne().HasForeignKey(x => x.EntityChangeId);
// b.HasIndex(x => new { x.AuditLogId });
// b.HasIndex(x => new { x.TenantId, x.EntityTypeFullName, x.EntityId });
// b.ApplyObjectExtensionMappings();
//});
//builder.Entity<EntityPropertyChange>(b =>
//{
// b.ToTable(AbpAuditLoggingDbProperties.DbTablePrefix + "EntityPropertyChanges", AbpAuditLoggingDbProperties.DbSchema);
// b.ConfigureByConvention();
// b.Property(x => x.NewValue).HasMaxLength(EntityPropertyChangeConsts.MaxNewValueLength).HasColumnName(nameof(EntityPropertyChange.NewValue));
// b.Property(x => x.PropertyName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyName));
// b.Property(x => x.PropertyTypeFullName).HasMaxLength(EntityPropertyChangeConsts.MaxPropertyTypeFullNameLength).IsRequired().HasColumnName(nameof(EntityPropertyChange.PropertyTypeFullName));
// b.Property(x => x.OriginalValue).HasMaxLength(EntityPropertyChangeConsts.MaxOriginalValueLength).HasColumnName(nameof(EntityPropertyChange.OriginalValue));
// b.HasIndex(x => new { x.EntityChangeId });
// b.ApplyObjectExtensionMappings();
//});
}
}
}

View File

@@ -0,0 +1,16 @@
using Volo.Abp.AuditLogging;
using Volo.Abp.Modularity;
using Yi.Framework.SqlSugarCore;
namespace Yi.AuditLogging.SqlSugarCore
{
[DependsOn(typeof(AbpAuditLoggingDomainModule))]
[DependsOn(typeof(YiFrameworkSqlSugarCoreModule))]
public class YiAuditLoggingSqlSugarCoreModule:AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddYiDbContext<YiAuditLoggingDbContext>();
}
}
}