using System.Reflection; using System.Runtime.CompilerServices; using System.Transactions; using Abp.Auditing; using Abp.Dependency; using Abp.Domain.Uow; using Abp.Runtime.Session; using Abp.Timing; using Castle.Core.Logging; using VberZero.Tools; using ILogger = Castle.Core.Logging.ILogger; namespace VberZero.Auditing; public class VzAuditingHelper : IAuditingHelper, ITransientDependency { private readonly IAuditInfoProvider _auditInfoProvider; private readonly IAuditingConfiguration _configuration; private readonly IUnitOfWorkManager _unitOfWorkManager; private readonly IAuditSerializer _auditSerializer; public ILogger Logger { get; set; } public IAbpSession AbpSession { get; set; } public IAuditingStore AuditingStore { get; } public VzAuditingHelper( IAuditInfoProvider auditInfoProvider, IAuditingConfiguration configuration, IUnitOfWorkManager unitOfWorkManager, IAuditSerializer auditSerializer, IAuditingStore auditingStore) { _auditInfoProvider = auditInfoProvider; _configuration = configuration; _unitOfWorkManager = unitOfWorkManager; _auditSerializer = auditSerializer; AuditingStore = auditingStore; AbpSession = NullAbpSession.Instance; Logger = NullLogger.Instance; } public bool ShouldSaveAudit(MethodInfo methodInfo, bool defaultValue = false) { if (!_configuration.IsEnabled) return false; if (!_configuration.IsEnabledForAnonymousUsers) { IAbpSession abpSession = AbpSession; if ((abpSession != null ? (!abpSession.UserId.HasValue ? 1 : 0) : 1) != 0) return false; } if (methodInfo == null || !methodInfo.IsPublic) return false; if (methodInfo.IsDefined(typeof(AuditedAttribute), true)) return true; if (methodInfo.IsDefined(typeof(DisableAuditingAttribute), true)) return false; Type classType = methodInfo.DeclaringType; if (classType != null) { if (classType.GetTypeInfo().IsDefined(typeof(AuditedAttribute), true)) return true; if (classType.GetTypeInfo().IsDefined(typeof(DisableAuditingAttribute), true)) return false; if (_configuration.Selectors.Any(selector => selector.Predicate(classType))) return true; } return defaultValue; } public AuditInfo CreateAuditInfo(Type type, MethodInfo method, object[] arguments) => CreateAuditInfo(type, method, CreateArgumentsDictionary(method, arguments)); public AuditInfo CreateAuditInfo(Type type, MethodInfo method, IDictionary arguments) { AuditInfo auditInfo = new AuditInfo() { TenantId = AbpSession.TenantId, UserId = AbpSession.UserId, ImpersonatorUserId = AbpSession.ImpersonatorUserId, ImpersonatorTenantId = AbpSession.ImpersonatorTenantId, ServiceName = type != null ? type.FullName : "", MethodName = method.Name, Parameters = ConvertArgumentsToJson(arguments), ExecutionTime = Clock.Now }; try { _auditInfoProvider.Fill(auditInfo); } catch (Exception ex) { Logger.Warn(ex.ToString(), ex); } return auditInfo; } public void Save(AuditInfo auditInfo) { using (IUnitOfWorkCompleteHandle workCompleteHandle = _unitOfWorkManager.Begin(TransactionScopeOption.Suppress)) { AuditingStore.Save(auditInfo); workCompleteHandle.Complete(); } } public async Task SaveAsync(AuditInfo auditInfo) { using (IUnitOfWorkCompleteHandle uow = _unitOfWorkManager.Begin(TransactionScopeOption.Suppress)) { ConfiguredTaskAwaitable configuredTaskAwaitable = AuditingStore.SaveAsync(auditInfo).ConfigureAwait(false); await configuredTaskAwaitable; configuredTaskAwaitable = uow.CompleteAsync().ConfigureAwait(false); await configuredTaskAwaitable; } } private string ConvertArgumentsToJson(IDictionary arguments) { try { if (arguments.IsNullOrEmpty()) return "{}"; Dictionary dictionary = new Dictionary(); foreach (KeyValuePair keyValuePair in arguments) { KeyValuePair argument = keyValuePair; dictionary[argument.Key] = argument.Value == null || !_configuration.IgnoredTypes.Any((t => t.IsInstanceOfType(argument.Value))) ? argument.Value : null; } return _auditSerializer.Serialize(dictionary); } catch (Exception ex) { Logger.Warn(ex.ToString(), ex); return "{}"; } } private static Dictionary CreateArgumentsDictionary( MethodInfo method, object[] arguments) { ParameterInfo[] parameters = method.GetParameters(); Dictionary argumentsDictionary = new Dictionary(); for (int index = 0; index < parameters.Length; ++index) { var name = parameters[index].Name; if (name != null) argumentsDictionary[name] = arguments[index]; } return argumentsDictionary; } }