diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs index 76a1a0e3c..a84ebdb2d 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs @@ -15,6 +15,8 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch { var configuration = context.Services.GetConfiguration(); Configure(configuration.GetSection("AuditLogging:Elasticsearch")); + + context.Services.AddHostedService(); } } } diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs index 44be008ef..76df4bd26 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs @@ -1,13 +1,17 @@ -namespace LINGYUN.Abp.AuditLogging.Elasticsearch +using Nest; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch { public class AbpAuditLoggingElasticsearchOptions { public const string DefaultIndexPrefix = "auditlogging"; public string IndexPrefix { get; set; } + public IIndexSettings IndexSettings { get; set; } public AbpAuditLoggingElasticsearchOptions() { IndexPrefix = DefaultIndexPrefix; + IndexSettings = new IndexSettings(); } } } diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs index fee2d868e..f8ae32e81 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs @@ -11,8 +11,6 @@ using System.Threading; using System.Threading.Tasks; using Volo.Abp.Auditing; using Volo.Abp.DependencyInjection; -using Volo.Abp.MultiTenancy; -using Volo.Abp; namespace LINGYUN.Abp.AuditLogging.Elasticsearch { @@ -21,27 +19,24 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch { private readonly AbpAuditingOptions _auditingOptions; private readonly AbpElasticsearchOptions _elasticsearchOptions; - private readonly AbpAuditLoggingElasticsearchOptions _options; - private readonly ICurrentTenant _currentTenant; + private readonly IIndexNameNormalizer _indexNameNormalizer; private readonly IElasticsearchClientFactory _clientFactory; private readonly IAuditLogInfoToAuditLogConverter _converter; public ILogger Logger { protected get; set; } public ElasticsearchAuditLogManager( - ICurrentTenant currentTenant, + IIndexNameNormalizer indexNameNormalizer, IOptions elasticsearchOptions, - IOptionsSnapshot options, IElasticsearchClientFactory clientFactory, IOptions auditingOptions, IAuditLogInfoToAuditLogConverter converter) { - _options = options.Value; _converter = converter; _clientFactory = clientFactory; - _currentTenant = currentTenant; _auditingOptions = auditingOptions.Value; _elasticsearchOptions = elasticsearchOptions.Value; + _indexNameNormalizer = indexNameNormalizer; Logger = NullLogger.Instance; } @@ -330,13 +325,7 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch protected virtual string CreateIndex() { - if (_currentTenant.IsAvailable) - { - return $"{_options.IndexPrefix}-audit-log-{_currentTenant.Id:N}"; - } - return _options.IndexPrefix.IsNullOrWhiteSpace() - ? "audit-log" - : $"{_options.IndexPrefix}-audit-log"; + return _indexNameNormalizer.NormalizeIndex("audit-log"); } private readonly static IDictionary _fieldMaps = new Dictionary(StringComparer.InvariantCultureIgnoreCase) diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs index 418738bc6..3905014ec 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs @@ -10,7 +10,6 @@ using System.Threading; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; -using Volo.Abp.MultiTenancy; using Volo.Abp.SecurityLog; namespace LINGYUN.Abp.AuditLogging.Elasticsearch @@ -20,25 +19,22 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch { private readonly AbpSecurityLogOptions _securityLogOptions; private readonly AbpElasticsearchOptions _elasticsearchOptions; - private readonly AbpAuditLoggingElasticsearchOptions _options; - private readonly ICurrentTenant _currentTenant; + private readonly IIndexNameNormalizer _indexNameNormalizer; private readonly IGuidGenerator _guidGenerator; private readonly IElasticsearchClientFactory _clientFactory; public ILogger Logger { protected get; set; } public ElasticsearchSecurityLogManager( - ICurrentTenant currentTenant, IGuidGenerator guidGenerator, + IIndexNameNormalizer indexNameNormalizer, IOptions securityLogOptions, IOptions elasticsearchOptions, - IOptionsSnapshot options, IElasticsearchClientFactory clientFactory) { - _options = options.Value; - _currentTenant = currentTenant; _guidGenerator = guidGenerator; _clientFactory = clientFactory; + _indexNameNormalizer = indexNameNormalizer; _securityLogOptions = securityLogOptions.Value; _elasticsearchOptions = elasticsearchOptions.Value; @@ -240,14 +236,7 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch protected virtual string CreateIndex() { - // TODO: 会出现索引很长的情况... - if (_currentTenant.IsAvailable) - { - return $"{_options.IndexPrefix}-security-log-{_currentTenant.Id:N}"; - } - return _options.IndexPrefix.IsNullOrWhiteSpace() - ? "security-log" - : $"{_options.IndexPrefix}-security-log"; + return _indexNameNormalizer.NormalizeIndex("security-log"); } private readonly static IDictionary _fieldMaps = new Dictionary(StringComparer.InvariantCultureIgnoreCase) diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexInitializer.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexInitializer.cs new file mode 100644 index 000000000..6b71bbce8 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexInitializer.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public interface IIndexInitializer + { + Task InitializeAsync(); + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexNameNormalizer.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexNameNormalizer.cs new file mode 100644 index 000000000..673e31704 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IIndexNameNormalizer.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public interface IIndexNameNormalizer + { + string NormalizeIndex(string index); + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs new file mode 100644 index 000000000..cd375483a --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs @@ -0,0 +1,106 @@ +using LINGYUN.Abp.Elasticsearch; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Nest; +using System; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public class IndexInitializer : IIndexInitializer, ISingletonDependency + { + private readonly AbpJsonOptions _jsonOptions; + private readonly AbpAuditLoggingElasticsearchOptions _elasticsearchOptions; + private readonly IIndexNameNormalizer _nameNormalizer; + private readonly IElasticsearchClientFactory _clientFactory; + + public ILogger Logger { protected get; set; } + + public IndexInitializer( + IOptions jsonOptions, + IOptions elasticsearchOptions, + IIndexNameNormalizer nameNormalizer, + IElasticsearchClientFactory clientFactory) + { + _jsonOptions = jsonOptions.Value; + _elasticsearchOptions = elasticsearchOptions.Value; + _nameNormalizer = nameNormalizer; + _clientFactory = clientFactory; + + Logger = NullLogger.Instance; + } + + public virtual async Task InitializeAsync() + { + var client = _clientFactory.Create(); + var dateTimeFormat = !_jsonOptions.DefaultDateTimeFormat.IsNullOrWhiteSpace() + ? $"{_jsonOptions.DefaultDateTimeFormat}||strict_date_optional_time||epoch_millis" + : "strict_date_optional_time||epoch_millis"; + var indexState = new IndexState + { + Settings = _elasticsearchOptions.IndexSettings, + }; + await InitlizeAuditLogIndex(client, indexState, dateTimeFormat); + await InitlizeSecurityLogIndex(client, indexState, dateTimeFormat); + } + + protected virtual async Task InitlizeAuditLogIndex(IElasticClient client, IIndexState indexState, string dateTimeFormat) + { + var indexName = _nameNormalizer.NormalizeIndex("audit-log"); + var indexExists = await client.Indices.ExistsAsync(indexName); + if (!indexExists.Exists) + { + var indexCreateResponse = await client.Indices.CreateAsync( + indexName, + dsl => dsl.InitializeUsing(indexState) + .Map(map => + map.AutoMap() + .Properties(mp => + mp.Date(p => p.Name(n => n.ExecutionTime).Format(dateTimeFormat)) + .Object(p => p.Name(n => n.ExtraProperties)) + .Nested(n => + n.AutoMap() + .Name(nameof(AuditLog.EntityChanges)) + .Properties(np => + np.Object(p => p.Name(n => n.ExtraProperties)) + .Date(p => p.Name(n => n.ChangeTime).Format(dateTimeFormat)) + .Nested(npn => npn.Name(nameof(EntityChange.PropertyChanges))))) + .Nested(n => n.Name(nameof(AuditLog.Actions)) + .AutoMap() + .Properties((np => + np.Object(p => p.Name(n => n.ExtraProperties)) + .Date(p => p.Name(n => n.ExecutionTime).Format(dateTimeFormat)))))))); + if (indexCreateResponse.IsValid) + { + Logger.LogWarning("Failed to initialize index and audit log may not be retrieved."); + Logger.LogWarning(indexCreateResponse.OriginalException.ToString()); + } + } + } + + protected virtual async Task InitlizeSecurityLogIndex(IElasticClient client, IIndexState indexState, string dateTimeFormat) + { + var indexName = _nameNormalizer.NormalizeIndex("security-log"); + var indexExists = await client.Indices.ExistsAsync(indexName); + if (!indexExists.Exists) + { + var indexCreateResponse = await client.Indices.CreateAsync( + indexName, + dsl => dsl.InitializeUsing(indexState) + .Map(map => + map.AutoMap() + .Properties(mp => + mp.Object(p => p.Name(n => n.ExtraProperties)) + .Date(p => p.Name(n => n.CreationTime).Format(dateTimeFormat))))); + if (indexCreateResponse.IsValid) + { + + } + } + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializerService.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializerService.cs new file mode 100644 index 000000000..7e0bc55ae --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializerService.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.Hosting; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public class IndexInitializerService : BackgroundService + { + private readonly IIndexInitializer _indexInitializer; + + public IndexInitializerService(IIndexInitializer indexInitializer) + { + _indexInitializer = indexInitializer; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + await _indexInitializer.InitializeAsync(); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexNameNormalizer.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexNameNormalizer.cs new file mode 100644 index 000000000..90c667dcc --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexNameNormalizer.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.Options; +using System; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public class IndexNameNormalizer : IIndexNameNormalizer, ISingletonDependency + { + private readonly ICurrentTenant _currentTenant; + private readonly AbpAuditLoggingElasticsearchOptions _options; + + public IndexNameNormalizer( + ICurrentTenant currentTenant, + IOptions options) + { + _currentTenant = currentTenant; + _options = options.Value; + } + + public string NormalizeIndex(string index) + { + if (_currentTenant.IsAvailable) + { + return $"{_options.IndexPrefix}-{index}-{_currentTenant.Id:N}"; + } + return _options.IndexPrefix.IsNullOrWhiteSpace() + ? index + : $"{_options.IndexPrefix}-{index}"; + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultEntityChangeStore.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultEntityChangeStore.cs new file mode 100644 index 000000000..7ac55ca3c --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultEntityChangeStore.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Auditing; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.AuditLogging +{ + [Dependency(TryRegister = true)] + public class DefaultEntityChangeStore : IEntityChangeStore, ISingletonDependency + { + public Task GetAsync(Guid entityChangeId, CancellationToken cancellationToken = default) + { + EntityChange entityChange = null; + return Task.FromResult(entityChange); + } + + public Task GetCountAsync(Guid? auditLogId = null, DateTime? startTime = null, DateTime? endTime = null, EntityChangeType? changeType = null, string entityId = null, string entityTypeFullName = null, CancellationToken cancellationToken = default) + { + return Task.FromResult(0L); + } + + public Task> GetListAsync(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) + { + return Task.FromResult(new List()); + } + + public Task GetWithUsernameAsync(Guid entityChangeId, CancellationToken cancellationToken = default) + { + EntityChangeWithUsername entityChange = null; + return Task.FromResult(entityChange); + } + + public Task> GetWithUsernameAsync(string entityId, string entityTypeFullName, CancellationToken cancellationToken = default) + { + return Task.FromResult(new List()); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChangeWithUsername.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChangeWithUsername.cs new file mode 100644 index 000000000..cd7a25943 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChangeWithUsername.cs @@ -0,0 +1,9 @@ +namespace LINGYUN.Abp.AuditLogging +{ + public class EntityChangeWithUsername + { + public EntityChange EntityChange { get; set; } + + public string UserName { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IEntityChangeStore.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IEntityChangeStore.cs new file mode 100644 index 000000000..3e69406b6 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IEntityChangeStore.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Auditing; + +namespace LINGYUN.Abp.AuditLogging +{ + public interface IEntityChangeStore + { + Task GetAsync( + Guid entityChangeId, + CancellationToken cancellationToken = default); + + Task GetCountAsync( + Guid? auditLogId = null, + DateTime? startTime = null, + DateTime? endTime = null, + EntityChangeType? changeType = null, + string entityId = null, + string entityTypeFullName = null, + CancellationToken cancellationToken = default); + + Task> GetListAsync( + 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); + + Task GetWithUsernameAsync( + Guid entityChangeId, + CancellationToken cancellationToken = default); + + Task> GetWithUsernameAsync( + string entityId, + string entityTypeFullName, + CancellationToken cancellationToken = default); + } +} diff --git a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/Properties/launchSettings.json index 7a6916353..f04e44238 100644 --- a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/Properties/launchSettings.json +++ b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/Properties/launchSettings.json @@ -13,7 +13,7 @@ "launchBrowser": false, "applicationUrl": "http://0.0.0.0:30010", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "ASPNETCORE_ENVIRONMENT": "Production" } } }