From 04a300e9653332a227f19f44b4e06e5783a73d0f Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Thu, 28 Oct 2021 22:52:45 +0800 Subject: [PATCH] feat(elasticsearch): support elasticsearch and migrate logs to es. --- .gitignore | 1 - .../LINGYUN.MicroService.BackendAdmin.sln | 48 +++ aspnet-core/LINGYUN.MicroService.Common.sln | 51 +++ ...GYUN.Abp.AuditLogging.Elasticsearch.csproj | 19 + .../AbpAuditLoggingElasticsearchModule.cs | 20 + .../AbpAuditLoggingElasticsearchOptions.cs | 13 + .../AuditLogInfoToAuditLogConverter.cs | 93 +++++ .../ElasticsearchAuditLogManager.cs | 347 ++++++++++++++++++ .../ElasticsearchSecurityLogManager.cs | 249 +++++++++++++ .../IAuditLogInfoToAuditLogConverter.cs | 10 + ...bp.AuditLogging.EntityFrameworkCore.csproj | 20 + ...bpAuditLoggingEntityFrameworkCoreModule.cs | 25 ++ .../AbpAuditingMapperProfile.cs | 21 ++ .../EntityFrameworkCore/AuditLogManager.cs | 177 +++++++++ .../EntityFrameworkCore/SecurityLogManager.cs | 144 ++++++++ .../LINGYUN.Abp.AuditLogging.csproj | 16 + .../Abp/AuditLogging/AbpAuditLoggingModule.cs | 15 + .../LINGYUN/Abp/AuditLogging/AuditLog.cs | 115 ++++++ .../Abp/AuditLogging/AuditLogAction.cs | 47 +++ .../LINGYUN/Abp/AuditLogging/AuditingStore.cs | 23 ++ .../AuditLogging/DefaultAuditLogManager.cs | 96 +++++ .../AuditLogging/DefaultSecurityLogManager.cs | 87 +++++ .../LINGYUN/Abp/AuditLogging/EntityChange.cs | 69 ++++ .../Abp/AuditLogging/EntityPropertyChange.cs | 43 +++ .../Abp/AuditLogging/IAuditLogManager.cs | 64 ++++ .../Abp/AuditLogging/ISecurityLogManager.cs | 56 +++ .../LINGYUN/Abp/AuditLogging/SecurityLog.cs | 72 ++++ .../Abp/AuditLogging/SecurityLogStore.cs | 23 ++ ....Abp.Auditing.Application.Contracts.csproj | 3 +- .../AbpAuditingApplicationContractsModule.cs | 70 ++-- .../AuditLogActionDto.cs | 36 +- .../{Logging => AuditLogs}/AuditLogDto.cs | 110 +++--- .../AuditLogGetByPagedDto.cs | 4 +- .../{Logging => AuditLogs}/EntityChangeDto.cs | 50 +-- .../EntityPropertyChangeDto.cs | 32 +- .../IAuditLogAppService.cs | 32 +- .../Abp/Auditing/Logging/Dto/LogDto.cs | 15 + .../Auditing/Logging/Dto/LogExceptionDto.cs | 13 + .../Abp/Auditing/Logging/Dto/LogFieldDto.cs | 17 + .../Auditing/Logging/Dto/LogGetByPagedDto.cs | 18 + .../Abp/Auditing/Logging/ILogAppService.cs | 14 + .../ISecurityLogAppService.cs | 32 +- .../SecurityLogDto.cs | 60 +-- .../SecurityLogGetByPagedDto.cs | 36 +- .../LINGYUN.Abp.Auditing.Application.csproj | 6 +- .../Auditing/AbpAuditingApplicationModule.cs | 48 +-- .../Abp/Auditing/AbpAuditingMapperProfile.cs | 55 +-- .../AuditLogAppService.cs | 27 +- .../Abp/Auditing/Logging/LogAppService.cs | 44 +++ .../SecurityLogAppService.cs | 115 +++--- .../AuditLogController.cs | 86 ++--- .../Abp/Auditing/Logging/LogController.cs | 35 ++ .../SecurityLogController.cs | 86 ++--- .../LINGYUN.Abp.Elasticsearch.csproj | 15 + .../Elasticsearch/AbpElasticsearchModule.cs | 14 + .../Elasticsearch/AbpElasticsearchOptions.cs | 69 ++++ .../ElasticsearchClientFactory.cs | 32 ++ .../IElasticsearchClientFactory.cs | 9 + ...N.Abp.Logging.Serilog.Elasticsearch.csproj | 19 + ...oggingSerilogElasticsearchMapperProfile.cs | 14 + .../AbpLoggingSerilogElasticsearchModule.cs | 33 ++ .../AbpLoggingSerilogElasticsearchOptions.cs | 12 + .../SerilogElasticsearchLoggingManager.cs | 265 +++++++++++++ .../Serilog/Elasticsearch/SerilogException.cs | 26 ++ .../Serilog/Elasticsearch/SerilogField.cs | 38 ++ .../Serilog/Elasticsearch/SerilogInfo.cs | 26 ++ .../LINGYUN.Abp.Logging.csproj | 14 + .../Abp/AuditLogging/AbpLoggingModule.cs | 9 + .../Abp/AuditLogging/DefaultLoggingManager.cs | 41 +++ .../Abp/AuditLogging/ILoggingManager.cs | 42 +++ .../LINGYUN/Abp/AuditLogging/LogException.cs | 13 + .../LINGYUN/Abp/AuditLogging/LogField.cs | 17 + .../LINGYUN/Abp/AuditLogging/LogInfo.cs | 15 + ....Abp.OssManagement.Application.csproj.user | 6 + .../.gitignore | 3 +- .../BackendAdminHostModule.cs | 9 +- ...NGYUN.Abp.BackendAdmin.HttpApi.Host.csproj | 7 +- ...bp.AuditLogging.Elasticsearch.Tests.csproj | 18 + .../AbpAuditLoggingElasticsearchTestBase.cs | 15 + .../AbpAuditLoggingElasticsearchTestModule.cs | 39 ++ .../Elasticsearch/AuditLogManagerTests.cs | 121 ++++++ 81 files changed, 3500 insertions(+), 449 deletions(-) create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN.Abp.AuditLogging.Elasticsearch.csproj create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLogInfoToAuditLogConverter.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreModule.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditingMapperProfile.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AuditLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/SecurityLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN.Abp.AuditLogging.csproj create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AbpAuditLoggingModule.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLogAction.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultAuditLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultSecurityLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityPropertyChange.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IAuditLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/ISecurityLogManager.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLog.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLogStore.cs rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/AuditLogActionDto.cs (86%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/AuditLogDto.cs (93%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/AuditLogGetByPagedDto.cs (82%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/EntityChangeDto.cs (90%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/EntityPropertyChangeDto.cs (85%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/IAuditLogAppService.cs (86%) create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogDto.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogExceptionDto.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogFieldDto.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogGetByPagedDto.cs create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/ILogAppService.cs rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Security => SecurityLogs}/ISecurityLogAppService.cs (86%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Security => SecurityLogs}/SecurityLogDto.cs (89%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/{Security => SecurityLogs}/SecurityLogGetByPagedDto.cs (90%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/AuditLogAppService.cs (68%) create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Logging/LogAppService.cs rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/{Security => SecurityLogs}/SecurityLogAppService.cs (63%) rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/{Logging => AuditLogs}/AuditLogController.cs (93%) create mode 100644 aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Logging/LogController.cs rename aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/{Security => SecurityLogs}/SecurityLogController.cs (93%) create mode 100644 aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN.Abp.Elasticsearch.csproj create mode 100644 aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchModule.cs create mode 100644 aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchOptions.cs create mode 100644 aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/ElasticsearchClientFactory.cs create mode 100644 aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/IElasticsearchClientFactory.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchMapperProfile.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchModule.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchOptions.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogElasticsearchLoggingManager.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogException.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogField.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogInfo.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN.Abp.Logging.csproj create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/AbpLoggingModule.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/DefaultLoggingManager.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/ILoggingManager.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogException.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogField.cs create mode 100644 aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogInfo.cs create mode 100644 aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj.user create mode 100644 aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests.csproj create mode 100644 aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestBase.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestModule.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogManagerTests.cs diff --git a/.gitignore b/.gitignore index 553381f99..a939b365f 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ appsettings.*.json tempkey.jwk .vs Publish -Modules /tests/e2e/videos/ /tests/e2e/screenshots/ diff --git a/aspnet-core/LINGYUN.MicroService.BackendAdmin.sln b/aspnet-core/LINGYUN.MicroService.BackendAdmin.sln index 3fbd590e8..ab4a7bff9 100644 --- a/aspnet-core/LINGYUN.MicroService.BackendAdmin.sln +++ b/aspnet-core/LINGYUN.MicroService.BackendAdmin.sln @@ -71,6 +71,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.OssManagement.A EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy", "modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj", "{360B5928-DD64-42AA-8C99-07EFC5224C24}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "elasticsearch", "elasticsearch", "{0A75BBE9-6757-4319-9C5A-D6315945E8A5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elasticsearch", "modules\elasticsearch\LINGYUN.Abp.Elasticsearch\LINGYUN.Abp.Elasticsearch.csproj", "{96940212-429F-4BF0-BB41-ADEE3D2DE4C0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging", "modules\auditing\LINGYUN.Abp.AuditLogging\LINGYUN.Abp.AuditLogging.csproj", "{CB71A69A-1C9A-4019-8FFE-42CA9663968E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging.Elasticsearch", "modules\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj", "{C92AE96D-9106-492C-901C-722282CF23E3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging.EntityFrameworkCore", "modules\auditing\LINGYUN.Abp.AuditLogging.EntityFrameworkCore\LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj", "{4F105408-B884-4796-B273-53734485D591}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logging", "logging", "{FC5C41DC-3E6E-4775-A6A2-D5B5B490B13D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Logging", "modules\logging\LINGYUN.Abp.Logging\LINGYUN.Abp.Logging.csproj", "{0C800A57-2658-4640-99A1-A02805EE6E99}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Logging.Serilog.Elasticsearch", "modules\logging\LINGYUN.Abp.Logging.Serilog.Elasticsearch\LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj", "{EBDD5D30-7F82-46EB-A4E9-213932D14047}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -173,6 +189,30 @@ Global {360B5928-DD64-42AA-8C99-07EFC5224C24}.Debug|Any CPU.Build.0 = Debug|Any CPU {360B5928-DD64-42AA-8C99-07EFC5224C24}.Release|Any CPU.ActiveCfg = Release|Any CPU {360B5928-DD64-42AA-8C99-07EFC5224C24}.Release|Any CPU.Build.0 = Release|Any CPU + {96940212-429F-4BF0-BB41-ADEE3D2DE4C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96940212-429F-4BF0-BB41-ADEE3D2DE4C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96940212-429F-4BF0-BB41-ADEE3D2DE4C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96940212-429F-4BF0-BB41-ADEE3D2DE4C0}.Release|Any CPU.Build.0 = Release|Any CPU + {CB71A69A-1C9A-4019-8FFE-42CA9663968E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB71A69A-1C9A-4019-8FFE-42CA9663968E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB71A69A-1C9A-4019-8FFE-42CA9663968E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB71A69A-1C9A-4019-8FFE-42CA9663968E}.Release|Any CPU.Build.0 = Release|Any CPU + {C92AE96D-9106-492C-901C-722282CF23E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C92AE96D-9106-492C-901C-722282CF23E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C92AE96D-9106-492C-901C-722282CF23E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C92AE96D-9106-492C-901C-722282CF23E3}.Release|Any CPU.Build.0 = Release|Any CPU + {4F105408-B884-4796-B273-53734485D591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F105408-B884-4796-B273-53734485D591}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F105408-B884-4796-B273-53734485D591}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F105408-B884-4796-B273-53734485D591}.Release|Any CPU.Build.0 = Release|Any CPU + {0C800A57-2658-4640-99A1-A02805EE6E99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C800A57-2658-4640-99A1-A02805EE6E99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C800A57-2658-4640-99A1-A02805EE6E99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C800A57-2658-4640-99A1-A02805EE6E99}.Release|Any CPU.Build.0 = Release|Any CPU + {EBDD5D30-7F82-46EB-A4E9-213932D14047}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EBDD5D30-7F82-46EB-A4E9-213932D14047}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EBDD5D30-7F82-46EB-A4E9-213932D14047}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EBDD5D30-7F82-46EB-A4E9-213932D14047}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -210,6 +250,14 @@ Global {3FD9C35C-3A8D-49F5-B7C5-4828AA3407AB} = {B36F627B-FD7D-4357-A623-F01AFF78B80D} {5C3D0A48-4EE3-4968-9826-5F52ADDC22C4} = {8F972C8E-F047-4883-A4BF-3423A2BAED36} {360B5928-DD64-42AA-8C99-07EFC5224C24} = {CB1A2EB0-34D4-41C4-BF01-C99EFBBF09EE} + {0A75BBE9-6757-4319-9C5A-D6315945E8A5} = {ED23B2F3-87C1-44B6-8906-9DE739422C2C} + {96940212-429F-4BF0-BB41-ADEE3D2DE4C0} = {0A75BBE9-6757-4319-9C5A-D6315945E8A5} + {CB71A69A-1C9A-4019-8FFE-42CA9663968E} = {709E77F9-DABF-47D3-A86E-40CD5448B1E5} + {C92AE96D-9106-492C-901C-722282CF23E3} = {709E77F9-DABF-47D3-A86E-40CD5448B1E5} + {4F105408-B884-4796-B273-53734485D591} = {709E77F9-DABF-47D3-A86E-40CD5448B1E5} + {FC5C41DC-3E6E-4775-A6A2-D5B5B490B13D} = {ED23B2F3-87C1-44B6-8906-9DE739422C2C} + {0C800A57-2658-4640-99A1-A02805EE6E99} = {FC5C41DC-3E6E-4775-A6A2-D5B5B490B13D} + {EBDD5D30-7F82-46EB-A4E9-213932D14047} = {FC5C41DC-3E6E-4775-A6A2-D5B5B490B13D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {1573B900-87BA-4AD3-B785-6DD78127ADEF} diff --git a/aspnet-core/LINGYUN.MicroService.Common.sln b/aspnet-core/LINGYUN.MicroService.Common.sln index f4e3cc8ba..b54788b9f 100644 --- a/aspnet-core/LINGYUN.MicroService.Common.sln +++ b/aspnet-core/LINGYUN.MicroService.Common.sln @@ -158,6 +158,24 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM.SignalR", "m EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.WeChat", "modules\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj", "{00F1D30E-A6F6-464F-A80B-D423CFAA79A3}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "elasticsearch", "elasticsearch", "{358A4FB1-F5DF-433C-9DA7-D27401155AD7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Elasticsearch", "modules\elasticsearch\LINGYUN.Abp.Elasticsearch\LINGYUN.Abp.Elasticsearch.csproj", "{2584D823-53A7-4184-8295-719A41E5B440}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "auditing", "auditing", "{6271EBC0-78F2-4E4F-A646-BBD15BCB0F84}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging", "modules\auditing\LINGYUN.Abp.AuditLogging\LINGYUN.Abp.AuditLogging.csproj", "{C1A91534-E84F-4A98-9A78-135988030646}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging.Elasticsearch", "modules\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj", "{0CC508D7-480C-4409-842A-A6C10E11ACFD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AuditLogging.Elasticsearch.Tests", "tests\LINGYUN.Abp.AuditLogging.Elasticsearch.Tests\LINGYUN.Abp.AuditLogging.Elasticsearch.Tests.csproj", "{F8330A1E-6CC3-4E90-8B5C-DCD8FA00CF5C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "logging", "logging", "{23F4260D-87C1-4AA6-A302-0A8A76D53BA1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Logging", "modules\logging\LINGYUN.Abp.Logging\LINGYUN.Abp.Logging.csproj", "{CE7E525F-8628-4076-8A2E-B615B944D140}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Logging.Serilog.Elasticsearch", "modules\logging\LINGYUN.Abp.Logging.Serilog.Elasticsearch\LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj", "{CD556F2A-A96B-43A2-8BB3-6C0EBA27EB02}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -412,6 +430,30 @@ Global {00F1D30E-A6F6-464F-A80B-D423CFAA79A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {00F1D30E-A6F6-464F-A80B-D423CFAA79A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {00F1D30E-A6F6-464F-A80B-D423CFAA79A3}.Release|Any CPU.Build.0 = Release|Any CPU + {2584D823-53A7-4184-8295-719A41E5B440}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2584D823-53A7-4184-8295-719A41E5B440}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2584D823-53A7-4184-8295-719A41E5B440}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2584D823-53A7-4184-8295-719A41E5B440}.Release|Any CPU.Build.0 = Release|Any CPU + {C1A91534-E84F-4A98-9A78-135988030646}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C1A91534-E84F-4A98-9A78-135988030646}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C1A91534-E84F-4A98-9A78-135988030646}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C1A91534-E84F-4A98-9A78-135988030646}.Release|Any CPU.Build.0 = Release|Any CPU + {0CC508D7-480C-4409-842A-A6C10E11ACFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0CC508D7-480C-4409-842A-A6C10E11ACFD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0CC508D7-480C-4409-842A-A6C10E11ACFD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0CC508D7-480C-4409-842A-A6C10E11ACFD}.Release|Any CPU.Build.0 = Release|Any CPU + {F8330A1E-6CC3-4E90-8B5C-DCD8FA00CF5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8330A1E-6CC3-4E90-8B5C-DCD8FA00CF5C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8330A1E-6CC3-4E90-8B5C-DCD8FA00CF5C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8330A1E-6CC3-4E90-8B5C-DCD8FA00CF5C}.Release|Any CPU.Build.0 = Release|Any CPU + {CE7E525F-8628-4076-8A2E-B615B944D140}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE7E525F-8628-4076-8A2E-B615B944D140}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE7E525F-8628-4076-8A2E-B615B944D140}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE7E525F-8628-4076-8A2E-B615B944D140}.Release|Any CPU.Build.0 = Release|Any CPU + {CD556F2A-A96B-43A2-8BB3-6C0EBA27EB02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD556F2A-A96B-43A2-8BB3-6C0EBA27EB02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD556F2A-A96B-43A2-8BB3-6C0EBA27EB02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD556F2A-A96B-43A2-8BB3-6C0EBA27EB02}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -491,6 +533,15 @@ Global {191BB108-546E-4E70-978E-D6A8149C319C} = {086BE5BE-8594-4DA7-8819-935FEF76DABD} {DEB98AD7-9630-4F32-89E6-C1A118D1D18C} = {B91F26C5-B148-4094-B5F1-71E5F945DBED} {00F1D30E-A6F6-464F-A80B-D423CFAA79A3} = {22C61434-D29A-4376-AD56-F5089F3E617A} + {358A4FB1-F5DF-433C-9DA7-D27401155AD7} = {02EA4E78-5891-43BC-944F-3E52FEE032E4} + {2584D823-53A7-4184-8295-719A41E5B440} = {358A4FB1-F5DF-433C-9DA7-D27401155AD7} + {6271EBC0-78F2-4E4F-A646-BBD15BCB0F84} = {02EA4E78-5891-43BC-944F-3E52FEE032E4} + {C1A91534-E84F-4A98-9A78-135988030646} = {6271EBC0-78F2-4E4F-A646-BBD15BCB0F84} + {0CC508D7-480C-4409-842A-A6C10E11ACFD} = {6271EBC0-78F2-4E4F-A646-BBD15BCB0F84} + {F8330A1E-6CC3-4E90-8B5C-DCD8FA00CF5C} = {B86C21A4-73B7-471E-B73A-B4B905EC9435} + {23F4260D-87C1-4AA6-A302-0A8A76D53BA1} = {02EA4E78-5891-43BC-944F-3E52FEE032E4} + {CE7E525F-8628-4076-8A2E-B615B944D140} = {23F4260D-87C1-4AA6-A302-0A8A76D53BA1} + {CD556F2A-A96B-43A2-8BB3-6C0EBA27EB02} = {23F4260D-87C1-4AA6-A302-0A8A76D53BA1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {06C707C6-02C0-411A-AD3B-2D0E13787CB8} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN.Abp.AuditLogging.Elasticsearch.csproj b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN.Abp.AuditLogging.Elasticsearch.csproj new file mode 100644 index 000000000..a56fd715b --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN.Abp.AuditLogging.Elasticsearch.csproj @@ -0,0 +1,19 @@ + + + + + + netstandard2.0 + + + + + + + + + + + + + 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 new file mode 100644 index 000000000..76a1a0e3c --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchModule.cs @@ -0,0 +1,20 @@ +using LINGYUN.Abp.Elasticsearch; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Json; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + [DependsOn( + typeof(AbpAuditLoggingModule), + typeof(AbpElasticsearchModule), + typeof(AbpJsonModule))] + public class AbpAuditLoggingElasticsearchModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + Configure(configuration.GetSection("AuditLogging:Elasticsearch")); + } + } +} 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 new file mode 100644 index 000000000..44be008ef --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchOptions.cs @@ -0,0 +1,13 @@ +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public class AbpAuditLoggingElasticsearchOptions + { + public const string DefaultIndexPrefix = "auditlogging"; + public string IndexPrefix { get; set; } + + public AbpAuditLoggingElasticsearchOptions() + { + IndexPrefix = DefaultIndexPrefix; + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs new file mode 100644 index 000000000..4b57fda8c --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.Auditing; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Http; +using Volo.Abp.Json; + +namespace LINGYUN.Abp.AuditLogging +{ + public class AuditLogInfoToAuditLogConverter : IAuditLogInfoToAuditLogConverter, ITransientDependency + { + protected IGuidGenerator GuidGenerator { get; } + protected IExceptionToErrorInfoConverter ExceptionToErrorInfoConverter { get; } + protected IJsonSerializer JsonSerializer { get; } + + public AuditLogInfoToAuditLogConverter(IGuidGenerator guidGenerator, IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, IJsonSerializer jsonSerializer) + { + GuidGenerator = guidGenerator; + ExceptionToErrorInfoConverter = exceptionToErrorInfoConverter; + JsonSerializer = jsonSerializer; + } + + public virtual Task ConvertAsync(AuditLogInfo auditLogInfo) + { + var auditLogId = GuidGenerator.Create(); + + var extraProperties = new ExtraPropertyDictionary(); + if (auditLogInfo.ExtraProperties != null) + { + foreach (var pair in auditLogInfo.ExtraProperties) + { + extraProperties.Add(pair.Key, pair.Value); + } + } + + var entityChanges = auditLogInfo + .EntityChanges? + .Select(entityChangeInfo => new EntityChange(GuidGenerator, auditLogId, entityChangeInfo, tenantId: auditLogInfo.TenantId)) + .ToList() + ?? new List(); + + var actions = auditLogInfo + .Actions? + .Select(auditLogActionInfo => new AuditLogAction(GuidGenerator.Create(), auditLogId, auditLogActionInfo, tenantId: auditLogInfo.TenantId)) + .ToList() + ?? new List(); + + var remoteServiceErrorInfos = auditLogInfo.Exceptions?.Select(exception => ExceptionToErrorInfoConverter.Convert(exception, true)) + ?? new List(); + + var exceptions = remoteServiceErrorInfos.Any() + ? JsonSerializer.Serialize(remoteServiceErrorInfos, indented: true) + : null; + + var comments = auditLogInfo + .Comments? + .JoinAsString(Environment.NewLine); + + var auditLog = new AuditLog( + auditLogId, + auditLogInfo.ApplicationName, + auditLogInfo.TenantId, + auditLogInfo.TenantName, + auditLogInfo.UserId, + auditLogInfo.UserName, + auditLogInfo.ExecutionTime, + auditLogInfo.ExecutionDuration, + auditLogInfo.ClientIpAddress, + auditLogInfo.ClientName, + auditLogInfo.ClientId, + auditLogInfo.CorrelationId, + auditLogInfo.BrowserInfo, + auditLogInfo.HttpMethod, + auditLogInfo.Url, + auditLogInfo.HttpStatusCode, + auditLogInfo.ImpersonatorUserId, + auditLogInfo.ImpersonatorTenantId, + extraProperties, + entityChanges, + actions, + exceptions, + comments + ); + + return Task.FromResult(auditLog); + } + } +} 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 new file mode 100644 index 000000000..56f1e1703 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs @@ -0,0 +1,347 @@ +using LINGYUN.Abp.Elasticsearch; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Nest; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +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 +{ + [Dependency(ReplaceServices = true)] + public class ElasticsearchAuditLogManager : IAuditLogManager, ISingletonDependency + { + private readonly AbpAuditingOptions _auditingOptions; + private readonly AbpElasticsearchOptions _elasticsearchOptions; + private readonly AbpAuditLoggingElasticsearchOptions _options; + private readonly ICurrentTenant _currentTenant; + private readonly IElasticsearchClientFactory _clientFactory; + private readonly IAuditLogInfoToAuditLogConverter _converter; + + public ILogger Logger { protected get; set; } + + public ElasticsearchAuditLogManager( + ICurrentTenant currentTenant, + IOptions elasticsearchOptions, + IOptions options, + IElasticsearchClientFactory clientFactory, + IOptions auditingOptions, + IAuditLogInfoToAuditLogConverter converter) + { + _options = options.Value; + _converter = converter; + _clientFactory = clientFactory; + _currentTenant = currentTenant; + _auditingOptions = auditingOptions.Value; + _elasticsearchOptions = elasticsearchOptions.Value; + + Logger = NullLogger.Instance; + } + + + public virtual async Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string httpMethod = null, + string url = null, + Guid? userId = null, + string userName = null, + string applicationName = null, + string correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var querys = BuildQueryDescriptor( + startTime, + endTime, + httpMethod, + url, + userId, + userName, + applicationName, + correlationId, + clientId, + clientIpAddress, + maxExecutionDuration, + minExecutionDuration, + hasException, + httpStatusCode); + + var response = await client.CountAsync(dsl => + dsl.Index(CreateIndex()) + .Query(log => log.Bool(b => b.Must(querys.ToArray()))), + cancellationToken); + + return response.Count; + } + + public virtual async Task> 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 correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var sortOrder = !sorting.IsNullOrWhiteSpace() && sorting.EndsWith("desc", StringComparison.InvariantCultureIgnoreCase) + ? SortOrder.Descending : SortOrder.Ascending; + sorting = !sorting.IsNullOrWhiteSpace() + ? sorting.Split()[0] + : nameof(AuditLog.ExecutionTime); + + if (_elasticsearchOptions.FieldCamelCase) + { + sorting = sorting.ToCamelCase(); + } + + var querys = BuildQueryDescriptor( + startTime, + endTime, + httpMethod, + url, + userId, + userName, + applicationName, + correlationId, + clientId, + clientIpAddress, + maxExecutionDuration, + minExecutionDuration, + hasException, + httpStatusCode); + + SourceFilterDescriptor ConvertFileSystem(SourceFilterDescriptor selector) + { + selector.IncludeAll(); + if (!includeDetails) + { + selector.Excludes(field => + field.Field(f => f.Actions) + .Field(f => f.Comments) + .Field(f => f.Exceptions) + .Field(f => f.EntityChanges)); + } + + return selector; + } + + var response = await client.SearchAsync(dsl => + dsl.Index(CreateIndex()) + .Query(log => log.Bool(b => b.Must(querys.ToArray()))) + .Source(ConvertFileSystem) + .Sort(log => log.Field(sorting, sortOrder)) + .From(skipCount) + .Size(maxResultCount), + cancellationToken); + + return response.Documents.ToList(); + } + + public virtual async Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var client = _clientFactory.Create(); + + var response = await client.GetAsync( + id, + dsl => + dsl.Index(CreateIndex()), + cancellationToken); + + return response.Source; + } + + public virtual async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) + { + var client = _clientFactory.Create(); + + await client.DeleteAsync( + id, + dsl => + dsl.Index(CreateIndex()), + cancellationToken); + } + + public virtual async Task SaveAsync( + AuditLogInfo auditInfo, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (!_auditingOptions.HideErrors) + { + return await SaveLogAsync(auditInfo, cancellationToken); + } + + try + { + return await SaveLogAsync(auditInfo, cancellationToken); + } + catch (Exception ex) + { + Logger.LogWarning("Could not save the audit log object: " + Environment.NewLine + auditInfo.ToString()); + Logger.LogException(ex, Microsoft.Extensions.Logging.LogLevel.Error); + } + return ""; + } + + protected virtual async Task SaveLogAsync( + AuditLogInfo auditLogInfo, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var auditLog = await _converter.ConvertAsync(auditLogInfo); + + var response = await client.IndexAsync( + auditLog, + (x) => x.Index(CreateIndex()) + .Id(auditLog.Id), + cancellationToken); + + return response.Id; + } + + protected virtual List, QueryContainer>> BuildQueryDescriptor( + DateTime? startTime = null, + DateTime? endTime = null, + string httpMethod = null, + string url = null, + Guid? userId = null, + string userName = null, + string applicationName = null, + string correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null) + { + var querys = new List, QueryContainer>>(); + + if (startTime.HasValue) + { + querys.Add((log) => log.DateRange((q) => q.Field(f => f.ExecutionTime).GreaterThanOrEquals(startTime))); + } + if (endTime.HasValue) + { + querys.Add((log) => log.DateRange((q) => q.Field(f => f.ExecutionTime).LessThanOrEquals(endTime))); + } + if (!httpMethod.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.HttpMethod.Suffix("keyword")).Value(httpMethod))); + } + if (!url.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Match((q) => q.Field(f => f.Url.Suffix("keyword")).Query(url))); + } + if (userId.HasValue) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.UserId.Suffix("keyword")).Value(userId))); + } + if (!userName.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.UserName.Suffix("keyword")).Value(userName))); + } + if (!applicationName.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.ApplicationName.Suffix("keyword")).Value(applicationName))); + } + if (!correlationId.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.CorrelationId.Suffix("keyword")).Value(correlationId))); + } + if (!clientId.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.ClientId.Suffix("keyword")).Value(clientId))); + } + if (!clientIpAddress.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.ClientIpAddress.Suffix("keyword")).Value(clientIpAddress))); + } + if (maxExecutionDuration.HasValue) + { + querys.Add((log) => log.Range((q) => q.Field(f => f.ExecutionDuration).LessThanOrEquals(maxExecutionDuration))); + } + if (minExecutionDuration.HasValue) + { + querys.Add((log) => log.Range((q) => q.Field(f => f.ExecutionDuration).GreaterThanOrEquals(minExecutionDuration))); + } + + + if (hasException.HasValue) + { + if (hasException.Value) + { + querys.Add( + (q) => q.Bool( + (b) => b.Must( + (m) => m.Exists( + (e) => e.Field((f) => f.Exceptions))) + ) + ); + } + else + { + querys.Add( + (q) => q.Bool( + (b) => b.MustNot( + (mn) => mn.Exists( + (e) => e.Field( + (f) => f.Exceptions))) + ) + ); + } + } + + if (httpStatusCode.HasValue) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.HttpStatusCode).Value(httpStatusCode))); + } + + return querys; + } + + 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"; + } + } +} 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 new file mode 100644 index 000000000..b909509dc --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchSecurityLogManager.cs @@ -0,0 +1,249 @@ +using LINGYUN.Abp.Elasticsearch; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Nest; +using System; +using System.Collections.Generic; +using System.Linq; +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 +{ + [Dependency(ReplaceServices = true)] + public class ElasticsearchSecurityLogManager : ISecurityLogManager, ISingletonDependency + { + private readonly AbpElasticsearchOptions _elasticsearchOptions; + private readonly AbpAuditLoggingElasticsearchOptions _options; + private readonly ICurrentTenant _currentTenant; + private readonly IGuidGenerator _guidGenerator; + private readonly IElasticsearchClientFactory _clientFactory; + + public ILogger Logger { protected get; set; } + + public ElasticsearchSecurityLogManager( + ICurrentTenant currentTenant, + IGuidGenerator guidGenerator, + IOptions elasticsearchOptions, + IOptions options, + IElasticsearchClientFactory clientFactory) + { + _options = options.Value; + _currentTenant = currentTenant; + _guidGenerator = guidGenerator; + _clientFactory = clientFactory; + _elasticsearchOptions = elasticsearchOptions.Value; + + Logger = NullLogger.Instance; + } + + public virtual async Task SaveAsync( + SecurityLogInfo securityLogInfo, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var securityLog = new SecurityLog( + _guidGenerator.Create(), + securityLogInfo); + + await client.IndexAsync( + securityLog, + (x) => x.Index(CreateIndex()) + .Id(securityLog.Id), + cancellationToken); + } + + public virtual async Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var client = _clientFactory.Create(); + + var response = await client.GetAsync( + id, + dsl => + dsl.Index(CreateIndex()), + cancellationToken); + + return response.Source; + } + + public virtual async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) + { + var client = _clientFactory.Create(); + + await client.DeleteAsync( + id, + dsl => + dsl.Index(CreateIndex()), + cancellationToken); + } + + public virtual async Task> GetListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var sortOrder = !sorting.IsNullOrWhiteSpace() && sorting.EndsWith("desc", StringComparison.InvariantCultureIgnoreCase) + ? SortOrder.Descending : SortOrder.Ascending; + sorting = !sorting.IsNullOrWhiteSpace() + ? sorting.Split()[0] + : nameof(SecurityLog.CreationTime); + + if (_elasticsearchOptions.FieldCamelCase) + { + sorting = sorting.ToCamelCase(); + } + + var querys = BuildQueryDescriptor( + startTime, + endTime, + applicationName, + identity, + action, + userId, + userName, + clientId, + clientIpAddress, + correlationId); + + var response = await client.SearchAsync(dsl => + dsl.Index(CreateIndex()) + .Query(log => log.Bool(b => b.Must(querys.ToArray()))) + .Source(log => log.IncludeAll()) + .Sort(log => log.Field(sorting, sortOrder)) + .From(skipCount) + .Size(maxResultCount), + cancellationToken); + + return response.Documents.ToList(); + } + + + public virtual async Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var querys = BuildQueryDescriptor( + startTime, + endTime, + applicationName, + identity, + action, + userId, + userName, + clientId, + clientIpAddress, + correlationId); + + var response = await client.CountAsync(dsl => + dsl.Index(CreateIndex()) + .Query(log => log.Bool(b => b.Must(querys.ToArray()))), + cancellationToken); + + return response.Count; + } + + protected virtual List, QueryContainer>> BuildQueryDescriptor( + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null) + { + var querys = new List, QueryContainer>>(); + + if (startTime.HasValue) + { + querys.Add((log) => log.DateRange((q) => q.Field(f => f.CreationTime).GreaterThanOrEquals(startTime))); + } + if (endTime.HasValue) + { + querys.Add((log) => log.DateRange((q) => q.Field(f => f.CreationTime).LessThanOrEquals(endTime))); + } + if (!applicationName.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.ApplicationName.Suffix("keyword")).Value(applicationName))); + } + if (!identity.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.Identity.Suffix("keyword")).Value(identity))); + } + if (!action.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.Action.Suffix("keyword")).Value(action))); + } + if (userId.HasValue) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.UserId.Suffix("keyword")).Value(userId))); + } + if (!userName.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.UserName.Suffix("keyword")).Value(userName))); + } + if (!clientId.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.ClientId.Suffix("keyword")).Value(clientId))); + } + if (!clientIpAddress.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.ClientIpAddress.Suffix("keyword")).Value(clientIpAddress))); + } + if (!correlationId.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.CorrelationId.Suffix("keyword")).Value(correlationId))); + } + + return querys; + } + + 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"; + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLogInfoToAuditLogConverter.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLogInfoToAuditLogConverter.cs new file mode 100644 index 000000000..ed9b120e3 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IAuditLogInfoToAuditLogConverter.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; +using Volo.Abp.Auditing; + +namespace LINGYUN.Abp.AuditLogging +{ + public interface IAuditLogInfoToAuditLogConverter + { + Task ConvertAsync(AuditLogInfo auditLogInfo); + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj new file mode 100644 index 000000000..733377977 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN.Abp.AuditLogging.EntityFrameworkCore.csproj @@ -0,0 +1,20 @@ + + + + + + netstandard2.1 + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreModule.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreModule.cs new file mode 100644 index 000000000..7feb58a34 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditLoggingEntityFrameworkCoreModule.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore +{ + [DependsOn( + typeof(Volo.Abp.Identity.EntityFrameworkCore.AbpIdentityEntityFrameworkCoreModule), + typeof(Volo.Abp.AuditLogging.EntityFrameworkCore.AbpAuditLoggingEntityFrameworkCoreModule))] + [DependsOn( + typeof(AbpAuditLoggingModule), + typeof(AbpAutoMapperModule))] + public class AbpAuditLoggingEntityFrameworkCoreModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => + { + options.AddProfile(validate: true); + }); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditingMapperProfile.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditingMapperProfile.cs new file mode 100644 index 000000000..3844b4e62 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AbpAuditingMapperProfile.cs @@ -0,0 +1,21 @@ +using AutoMapper; + +namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore +{ + public class AbpAuditingMapperProfile : Profile + { + public AbpAuditingMapperProfile() + { + CreateMap() + .MapExtraProperties(); + CreateMap(); + CreateMap() + .MapExtraProperties(); + CreateMap() + .MapExtraProperties(); + + CreateMap() + .MapExtraProperties(); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AuditLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AuditLogManager.cs new file mode 100644 index 000000000..dc668516d --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/AuditLogManager.cs @@ -0,0 +1,177 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Auditing; +using Volo.Abp.AuditLogging; +using Volo.Abp.DependencyInjection; +using Volo.Abp.ObjectMapping; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore +{ + [Dependency(ReplaceServices = true)] + public class AuditLogManager : IAuditLogManager, ISingletonDependency + { + protected IObjectMapper ObjectMapper { get; } + protected IAuditLogRepository AuditLogRepository { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + protected AbpAuditingOptions Options { get; } + protected IAuditLogInfoToAuditLogConverter Converter { get; } + + public ILogger Logger { protected get; set; } + + public AuditLogManager( + IObjectMapper objectMapper, + IAuditLogRepository auditLogRepository, + IUnitOfWorkManager unitOfWorkManager, + IOptions options, + IAuditLogInfoToAuditLogConverter converter) + { + ObjectMapper = objectMapper; + AuditLogRepository = auditLogRepository; + UnitOfWorkManager = unitOfWorkManager; + Converter = converter; + Options = options.Value; + + Logger = NullLogger.Instance; + } + + + public virtual async Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string httpMethod = null, + string url = null, + Guid? userId = null, + string userName = null, + string applicationName = null, + string correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + return await AuditLogRepository.GetCountAsync( + startTime, + endTime, + httpMethod, + url, + userId, + userName, + applicationName, + correlationId, + maxExecutionDuration, + minExecutionDuration, + hasException, + httpStatusCode, + cancellationToken); + } + + public virtual async Task> 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 correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + var auditLogs = await AuditLogRepository.GetListAsync( + sorting, + maxResultCount, + skipCount, + startTime, + endTime, + httpMethod, + url, + userId, + userName, + applicationName, + correlationId, + maxExecutionDuration, + minExecutionDuration, + hasException, + httpStatusCode, + includeDetails, + cancellationToken); + + return ObjectMapper.Map, List>(auditLogs); + } + + public virtual async Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var auditLog = await AuditLogRepository.GetAsync(id, includeDetails, cancellationToken); + + return ObjectMapper.Map(auditLog); + } + + public virtual async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) + { + using (var uow = UnitOfWorkManager.Begin(true)) + { + await AuditLogRepository.DeleteAsync(id); + await uow.CompleteAsync(); + } + } + + public virtual async Task SaveAsync( + AuditLogInfo auditInfo, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (!Options.HideErrors) + { + return await SaveLogAsync(auditInfo, cancellationToken); + } + + try + { + return await SaveLogAsync(auditInfo, cancellationToken); + } + catch (Exception ex) + { + Logger.LogWarning("Could not save the audit log object: " + Environment.NewLine + auditInfo.ToString()); + Logger.LogException(ex, LogLevel.Error); + } + return ""; + } + + protected virtual async Task SaveLogAsync( + AuditLogInfo auditInfo, + CancellationToken cancellationToken = default(CancellationToken)) + { + using (var uow = UnitOfWorkManager.Begin(true)) + { + var auditLog = await AuditLogRepository.InsertAsync( + await Converter.ConvertAsync(auditInfo), + false, + cancellationToken); + await uow.CompleteAsync(); + + return auditLog.Id.ToString(); + } + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/SecurityLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/SecurityLogManager.cs new file mode 100644 index 000000000..a626cd30f --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.EntityFrameworkCore/LINGYUN/Abp/AuditLogging/EntityFrameworkCore/SecurityLogManager.cs @@ -0,0 +1,144 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Identity; +using Volo.Abp.ObjectMapping; +using Volo.Abp.SecurityLog; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.AuditLogging.EntityFrameworkCore +{ + [Dependency(ReplaceServices = true)] + public class SecurityLogManager : ISecurityLogManager, ISingletonDependency + { + public ILogger Logger { get; set; } + + protected IObjectMapper ObjectMapper { get; } + protected AbpSecurityLogOptions SecurityLogOptions { get; } + protected IIdentitySecurityLogRepository IdentitySecurityLogRepository { get; } + protected IGuidGenerator GuidGenerator { get; } + protected IUnitOfWorkManager UnitOfWorkManager { get; } + + public SecurityLogManager( + IObjectMapper objectMapper, + ILogger logger, + IOptions securityLogOptions, + IIdentitySecurityLogRepository identitySecurityLogRepository, + IGuidGenerator guidGenerator, + IUnitOfWorkManager unitOfWorkManager) + { + Logger = logger; + ObjectMapper = objectMapper; + SecurityLogOptions = securityLogOptions.Value; + IdentitySecurityLogRepository = identitySecurityLogRepository; + GuidGenerator = guidGenerator; + UnitOfWorkManager = unitOfWorkManager; + } + + public virtual async Task SaveAsync( + SecurityLogInfo securityLogInfo, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (!SecurityLogOptions.IsEnabled) + { + return; + } + + using (var uow = UnitOfWorkManager.Begin(requiresNew: true)) + { + await IdentitySecurityLogRepository.InsertAsync( + new IdentitySecurityLog(GuidGenerator, securityLogInfo), + false, + cancellationToken); + await uow.CompleteAsync(); + } + } + + public virtual async Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + var securityLog = await IdentitySecurityLogRepository.GetAsync(id, includeDetails, cancellationToken); + + return ObjectMapper.Map(securityLog); + } + + public virtual async Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) + { + using (var uow = UnitOfWorkManager.Begin(true)) + { + await IdentitySecurityLogRepository.DeleteAsync(id); + await uow.CompleteAsync(); + } + } + + public virtual async Task> GetListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + var securityLogs = await IdentitySecurityLogRepository.GetListAsync( + sorting, + maxResultCount, + skipCount, + startTime, + endTime, + applicationName, + identity, + action, + userId, + userName, + clientId, + correlationId, + includeDetails, + cancellationToken); + + return ObjectMapper.Map, List>(securityLogs); + } + + + public virtual async Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + return await IdentitySecurityLogRepository.GetCountAsync( + startTime, + endTime, + applicationName, + identity, + action, + userId, + userName, + clientId, + correlationId, + cancellationToken); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN.Abp.AuditLogging.csproj b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN.Abp.AuditLogging.csproj new file mode 100644 index 000000000..92045c02d --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN.Abp.AuditLogging.csproj @@ -0,0 +1,16 @@ + + + + + + netstandard2.0 + + + + + + + + + + diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AbpAuditLoggingModule.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AbpAuditLoggingModule.cs new file mode 100644 index 000000000..b21994b08 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AbpAuditLoggingModule.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Auditing; +using Volo.Abp.ExceptionHandling; +using Volo.Abp.Guids; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.AuditLogging +{ + [DependsOn( + typeof(AbpAuditingModule), + typeof(AbpGuidsModule), + typeof(AbpExceptionHandlingModule))] + public class AbpAuditLoggingModule : AbpModule + { + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs new file mode 100644 index 000000000..cc6d36226 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using Volo.Abp.Auditing; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.AuditLogging +{ + [DisableAuditing] + public class AuditLog : IHasExtraProperties + { + public Guid Id { get; set; } + + public string ApplicationName { get; set; } + + public Guid? UserId { get; set; } + + public string UserName { get; set; } + + public Guid? TenantId { get; set; } + + public string TenantName { get; set; } + + public Guid? ImpersonatorUserId { get; set; } + + public Guid? ImpersonatorTenantId { get; set; } + + public DateTime ExecutionTime { get; set; } + + public int ExecutionDuration { get; set; } + + public string ClientIpAddress { get; set; } + + public string ClientName { get; set; } + + public string ClientId { get; set; } + + public string CorrelationId { get; set; } + + public string BrowserInfo { get; set; } + + public string HttpMethod { get; set; } + + public string Url { get; set; } + + public string Exceptions { get; set; } + + public string Comments { get; set; } + + public int? HttpStatusCode { get; set; } + + public List EntityChanges { get; set; } + + public List Actions { get; set; } + + public ExtraPropertyDictionary ExtraProperties { get; set; } + + public AuditLog() + { + Actions = new List(); + EntityChanges = new List(); + ExtraProperties = new ExtraPropertyDictionary(); + } + + public AuditLog( + Guid id, + string applicationName, + Guid? tenantId, + string tenantName, + Guid? userId, + string userName, + DateTime executionTime, + int executionDuration, + string clientIpAddress, + string clientName, + string clientId, + string correlationId, + string browserInfo, + string httpMethod, + string url, + int? httpStatusCode, + Guid? impersonatorUserId, + Guid? impersonatorTenantId, + ExtraPropertyDictionary extraPropertyDictionary, + List entityChanges, + List actions, + string exceptions, + string comments) + { + Id = id; + ApplicationName = applicationName; + TenantId = tenantId; + TenantName = tenantName; + UserId = userId; + UserName = userName; + ExecutionTime = executionTime; + ExecutionDuration = executionDuration; + ClientIpAddress = clientIpAddress; + ClientName = clientName; + ClientId = clientId; + CorrelationId = correlationId; + BrowserInfo = browserInfo; + HttpMethod = httpMethod; + Url = url; + HttpStatusCode = httpStatusCode; + ImpersonatorUserId = impersonatorUserId; + ImpersonatorTenantId = impersonatorTenantId; + + ExtraProperties = extraPropertyDictionary; + EntityChanges = entityChanges; + Actions = actions; + Exceptions = exceptions; + Comments = comments; + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLogAction.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLogAction.cs new file mode 100644 index 000000000..56f8b07e1 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLogAction.cs @@ -0,0 +1,47 @@ +using System; +using Volo.Abp.Auditing; +using Volo.Abp.Data; + +namespace LINGYUN.Abp.AuditLogging +{ + [DisableAuditing] + public class AuditLogAction : IHasExtraProperties + { + public Guid Id { get; set; } + + public Guid? TenantId { get; set; } + + public Guid AuditLogId { get; set; } + + public string ServiceName { get; set; } + + public string MethodName { get; set; } + + public string Parameters { get; set; } + + public DateTime ExecutionTime { get; set; } + + public int ExecutionDuration { get; set; } + + public ExtraPropertyDictionary ExtraProperties { get; set; } + + public AuditLogAction() + { + ExtraProperties = new ExtraPropertyDictionary(); + } + + public AuditLogAction(Guid id, Guid auditLogId, AuditLogActionInfo actionInfo, Guid? tenantId = null) + { + + Id = id; + TenantId = tenantId; + AuditLogId = auditLogId; + ExecutionTime = actionInfo.ExecutionTime; + ExecutionDuration = actionInfo.ExecutionDuration; + ExtraProperties = new ExtraPropertyDictionary(actionInfo.ExtraProperties); + ServiceName = actionInfo.ServiceName; + MethodName = actionInfo.MethodName; + Parameters = actionInfo.Parameters.Length > 2000 ? "" : actionInfo.Parameters; + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs new file mode 100644 index 000000000..7f41a33f3 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Volo.Abp.Auditing; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.AuditLogging +{ + [Dependency(ReplaceServices = true)] + public class AuditingStore : IAuditingStore, ITransientDependency + { + private readonly IAuditLogManager _manager; + + public AuditingStore( + IAuditLogManager manager) + { + _manager = manager; + } + + public virtual async Task SaveAsync(AuditLogInfo auditInfo) + { + await _manager.SaveAsync(auditInfo); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultAuditLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultAuditLogManager.cs new file mode 100644 index 000000000..a491ead1a --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultAuditLogManager.cs @@ -0,0 +1,96 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Auditing; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.AuditLogging +{ + [Dependency(TryRegister = true)] + public class DefaultAuditLogManager : IAuditLogManager, ISingletonDependency + { + public ILogger Logger { protected get; set; } + + public DefaultAuditLogManager() + { + Logger = NullLogger.Instance; + } + + public virtual Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string httpMethod = null, + string url = null, + Guid? userId = null, + string userName = null, + string applicationName = null, + string correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + Logger.LogDebug("No audit log manager is available!"); + return Task.FromResult(0L); + } + + public virtual Task> 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 correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + Logger.LogDebug("No audit log manager is available!"); + return Task.FromResult(new List()); + } + + public virtual Task SaveAsync( + AuditLogInfo auditInfo, + CancellationToken cancellationToken = default) + { + Logger.LogDebug("No audit log manager is available and is written to the local log by default"); + Logger.LogInformation(auditInfo.ToString()); + + return Task.FromResult(""); + } + + public virtual Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + Logger.LogDebug("No audit log manager is available!"); + + AuditLog auditLog = null; + return Task.FromResult(auditLog); + } + + public virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) + { + Logger.LogDebug("No audit log manager is available!"); + return Task.CompletedTask; + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultSecurityLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultSecurityLogManager.cs new file mode 100644 index 000000000..07086e6de --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/DefaultSecurityLogManager.cs @@ -0,0 +1,87 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.SecurityLog; + +namespace LINGYUN.Abp.AuditLogging +{ + [Dependency(TryRegister = true)] + public class DefaultSecurityLogManager : ISecurityLogManager, ISingletonDependency + { + public ILogger Logger { protected get; set; } + + public DefaultSecurityLogManager() + { + Logger = NullLogger.Instance; + } + + public Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + Logger.LogDebug("No security log manager is available!"); + return Task.FromResult(0L); + } + + public Task> GetListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + Logger.LogDebug("No security log manager is available!"); + return Task.FromResult(new List()); + } + + public Task SaveAsync( + SecurityLogInfo securityLogInfo, + CancellationToken cancellationToken = default(CancellationToken)) + { + Logger.LogDebug("No security log manager is available and is written to the local log by default"); + Logger.LogInformation(securityLogInfo.ToString()); + + return Task.CompletedTask; + } + + public virtual Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default) + { + Logger.LogDebug("No security log manager is available!"); + + SecurityLog securityLog = null; + return Task.FromResult(securityLog); + } + + public virtual Task DeleteAsync(Guid id, CancellationToken cancellationToken = default) + { + Logger.LogDebug("No security log manager is available!"); + return Task.CompletedTask; + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs new file mode 100644 index 000000000..fd44b658d --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityChange.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Volo.Abp.Auditing; +using Volo.Abp.Data; +using Volo.Abp.Guids; + +namespace LINGYUN.Abp.AuditLogging +{ + [DisableAuditing] + public class EntityChange : IHasExtraProperties + { + public Guid Id { get; set; } + + public Guid AuditLogId { get; set; } + + public Guid? TenantId { get; set; } + + public DateTime ChangeTime { get; set; } + + public EntityChangeType ChangeType { get; set; } + + public Guid? EntityTenantId { get; set; } + + public string EntityId { get; set; } + + public string EntityTypeFullName { get; set; } + + public List PropertyChanges { get; set; } + + public ExtraPropertyDictionary ExtraProperties { get; set; } + + public EntityChange() + { + PropertyChanges = new List(); + ExtraProperties = new ExtraPropertyDictionary(); + } + + public EntityChange( + IGuidGenerator guidGenerator, + Guid auditLogId, + EntityChangeInfo entityChangeInfo, + Guid? tenantId = null) + { + Id = guidGenerator.Create(); + AuditLogId = auditLogId; + TenantId = tenantId; + ChangeTime = entityChangeInfo.ChangeTime; + ChangeType = entityChangeInfo.ChangeType; + EntityId = entityChangeInfo.EntityId; + EntityTypeFullName = entityChangeInfo.EntityTypeFullName; + + PropertyChanges = entityChangeInfo + .PropertyChanges? + .Select(p => new EntityPropertyChange(guidGenerator, Id, p, tenantId)) + .ToList() + ?? new List(); + + ExtraProperties = new ExtraPropertyDictionary(); + if (entityChangeInfo.ExtraProperties != null) + { + foreach (var pair in entityChangeInfo.ExtraProperties) + { + ExtraProperties.Add(pair.Key, pair.Value); + } + } + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityPropertyChange.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityPropertyChange.cs new file mode 100644 index 000000000..5c6a95112 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/EntityPropertyChange.cs @@ -0,0 +1,43 @@ +using System; +using Volo.Abp.Auditing; +using Volo.Abp.Guids; + +namespace LINGYUN.Abp.AuditLogging +{ + [DisableAuditing] + public class EntityPropertyChange + { + public Guid Id { get; set; } + + public Guid? TenantId { get; set; } + + public Guid EntityChangeId { get; set; } + + public string NewValue { get; set; } + + public string OriginalValue { get; set; } + + public string PropertyName { get; set; } + + public string PropertyTypeFullName { get; set; } + + public EntityPropertyChange() + { + } + + public EntityPropertyChange( + IGuidGenerator guidGenerator, + Guid entityChangeId, + EntityPropertyChangeInfo entityChangeInfo, + Guid? tenantId = null) + { + Id = guidGenerator.Create(); + TenantId = tenantId; + EntityChangeId = entityChangeId; + NewValue = entityChangeInfo.NewValue; + OriginalValue = entityChangeInfo.OriginalValue; + PropertyName = entityChangeInfo.PropertyName; + PropertyTypeFullName = entityChangeInfo.PropertyTypeFullName; + } + } +} \ No newline at end of file diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IAuditLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IAuditLogManager.cs new file mode 100644 index 000000000..5743cb44c --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/IAuditLogManager.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Auditing; + +namespace LINGYUN.Abp.AuditLogging +{ + public interface IAuditLogManager + { + Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)); + + Task DeleteAsync( + Guid id, + CancellationToken cancellationToken = default(CancellationToken)); + + Task SaveAsync( + AuditLogInfo auditInfo, + CancellationToken cancellationToken = default(CancellationToken)); + + Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string httpMethod = null, + string url = null, + Guid? userId = null, + string userName = null, + string applicationName = null, + string correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + CancellationToken cancellationToken = default(CancellationToken)); + + Task> 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 correlationId = null, + string clientId = null, + string clientIpAddress = null, + int? maxExecutionDuration = null, + int? minExecutionDuration = null, + bool? hasException = null, + HttpStatusCode? httpStatusCode = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)); + + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/ISecurityLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/ISecurityLogManager.cs new file mode 100644 index 000000000..7fca8a5aa --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/ISecurityLogManager.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.SecurityLog; + +namespace LINGYUN.Abp.AuditLogging +{ + public interface ISecurityLogManager + { + Task GetAsync( + Guid id, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)); + + Task DeleteAsync( + Guid id, + CancellationToken cancellationToken = default(CancellationToken)); + + Task SaveAsync( + SecurityLogInfo securityLogInfo, + CancellationToken cancellationToken = default(CancellationToken)); + + Task> GetListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)); + + + Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string applicationName = null, + string identity = null, + string action = null, + Guid? userId = null, + string userName = null, + string clientId = null, + string clientIpAddress = null, + string correlationId = null, + CancellationToken cancellationToken = default(CancellationToken)); + + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLog.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLog.cs new file mode 100644 index 000000000..66f4dc04f --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLog.cs @@ -0,0 +1,72 @@ +using System; +using Volo.Abp.Data; +using Volo.Abp.SecurityLog; + +namespace LINGYUN.Abp.AuditLogging +{ + public class SecurityLog : IHasExtraProperties + { + public Guid Id { get; set; } + + public Guid? TenantId { get; set; } + + public string ApplicationName { get; set; } + + public string Identity { get; set; } + + public string Action { get; set; } + + public Guid? UserId { get; set; } + + public string UserName { get; set; } + + public string TenantName { get; set; } + + public string ClientId { get; set; } + + public string CorrelationId { get; set; } + + public string ClientIpAddress { get; set; } + + public string BrowserInfo { get; set; } + + public DateTime CreationTime { get; set; } + + public ExtraPropertyDictionary ExtraProperties { get; set; } + + public SecurityLog() + { + ExtraProperties = new ExtraPropertyDictionary(); + } + + public SecurityLog(Guid id, SecurityLogInfo securityLogInfo) + { + Id = id; + TenantId = securityLogInfo.TenantId; + TenantName = securityLogInfo.TenantName; + + ApplicationName = securityLogInfo.ApplicationName; + Identity = securityLogInfo.Identity; + Action = securityLogInfo.Action; + + UserId = securityLogInfo.UserId; + UserName = securityLogInfo.UserName; + + CreationTime = securityLogInfo.CreationTime; + + ClientIpAddress = securityLogInfo.ClientIpAddress; + ClientId = securityLogInfo.ClientId; + CorrelationId = securityLogInfo.CorrelationId; + BrowserInfo = securityLogInfo.BrowserInfo; + + ExtraProperties = new ExtraPropertyDictionary(); + if (securityLogInfo.ExtraProperties != null) + { + foreach (var pair in securityLogInfo.ExtraProperties) + { + ExtraProperties.Add(pair.Key, pair.Value); + } + } + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLogStore.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLogStore.cs new file mode 100644 index 000000000..b68c89f72 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/SecurityLogStore.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.SecurityLog; + +namespace LINGYUN.Abp.AuditLogging +{ + [Dependency(ReplaceServices = true)] + public class SecurityLogStore : ISecurityLogStore, ITransientDependency + { + private readonly ISecurityLogManager _manager; + + public SecurityLogStore( + ISecurityLogManager manager) + { + _manager = manager; + } + + public virtual async Task SaveAsync(SecurityLogInfo securityLogInfo) + { + await _manager.SaveAsync(securityLogInfo); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN.Abp.Auditing.Application.Contracts.csproj b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN.Abp.Auditing.Application.Contracts.csproj index 081f6af1d..c438f6539 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN.Abp.Auditing.Application.Contracts.csproj +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN.Abp.Auditing.Application.Contracts.csproj @@ -1,4 +1,4 @@ - + @@ -16,7 +16,6 @@ - diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AbpAuditingApplicationContractsModule.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AbpAuditingApplicationContractsModule.cs index 5839b4cab..907839e82 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AbpAuditingApplicationContractsModule.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AbpAuditingApplicationContractsModule.cs @@ -1,36 +1,34 @@ -using Volo.Abp.Application; -using Volo.Abp.AuditLogging; -using Volo.Abp.AuditLogging.Localization; -using Volo.Abp.Authorization; -using Volo.Abp.Features; -using Volo.Abp.Identity; -using Volo.Abp.Localization; -using Volo.Abp.Modularity; -using Volo.Abp.VirtualFileSystem; - -namespace LINGYUN.Abp.Auditing -{ - [DependsOn( - typeof(AbpFeaturesModule), - typeof(AbpAuthorizationModule), - typeof(AbpAuditLoggingDomainSharedModule), - typeof(AbpIdentityDomainSharedModule), - typeof(AbpDddApplicationContractsModule))] - public class AbpAuditingApplicationContractsModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.FileSets.AddEmbedded(); - }); - - Configure(options => - { - options.Resources - .Get() - .AddVirtualJson("/LINGYUN/Abp/Auditing/Localization/Resources"); - }); - } - } -} +using Volo.Abp.Application; +using Volo.Abp.AuditLogging; +using Volo.Abp.AuditLogging.Localization; +using Volo.Abp.Authorization; +using Volo.Abp.Features; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.Auditing +{ + [DependsOn( + typeof(AbpFeaturesModule), + typeof(AbpAuthorizationModule), + typeof(AbpAuditLoggingDomainSharedModule), + typeof(AbpDddApplicationContractsModule))] + public class AbpAuditingApplicationContractsModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + + Configure(options => + { + options.Resources + .Get() + .AddVirtualJson("/LINGYUN/Abp/Auditing/Localization/Resources"); + }); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogActionDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogActionDto.cs similarity index 86% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogActionDto.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogActionDto.cs index feacfa166..667fa9455 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogActionDto.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogActionDto.cs @@ -1,18 +1,18 @@ -using System; -using Volo.Abp.Application.Dtos; - -namespace LINGYUN.Abp.Auditing.Logging -{ - public class AuditLogActionDto : ExtensibleEntityDto - { - public string ServiceName { get; set; } - - public string MethodName { get; set; } - - public string Parameters { get; set; } - - public DateTime ExecutionTime { get; set; } - - public int ExecutionDuration { get; set; } - } -} +using System; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.Auditing.AuditLogs +{ + public class AuditLogActionDto : ExtensibleEntityDto + { + public string ServiceName { get; set; } + + public string MethodName { get; set; } + + public string Parameters { get; set; } + + public DateTime ExecutionTime { get; set; } + + public int ExecutionDuration { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogDto.cs similarity index 93% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogDto.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogDto.cs index 7cc0a1357..5ea2c5ee4 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogDto.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogDto.cs @@ -1,55 +1,55 @@ -using System; -using System.Collections.Generic; -using Volo.Abp.Application.Dtos; - -namespace LINGYUN.Abp.Auditing.Logging -{ - public class AuditLogDto : ExtensibleEntityDto - { - public string ApplicationName { get; set; } - - public Guid? UserId { get; set; } - - public string UserName { get; set; } - - public Guid? TenantId { get; set; } - - public string TenantName { get; set; } - - public Guid? ImpersonatorUserId { get; set; } - - public Guid? ImpersonatorTenantId { get; set; } - - public DateTime ExecutionTime { get; set; } - - public int ExecutionDuration { get; set; } - - public string ClientIpAddress { get; set; } - - public string ClientName { get; set; } - - public string ClientId { get; set; } - - public string CorrelationId { get; set; } - - public string BrowserInfo { get; set; } - - public string HttpMethod { get; set; } - - public string Url { get; set; } - - public string Exceptions { get; set; } - - public string Comments { get; set; } - - public int? HttpStatusCode { get; set; } - public List EntityChanges { get; set; } - public List Actions { get; set; } - - public AuditLogDto() - { - EntityChanges = new List(); - Actions = new List(); - } - } -} +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.Auditing.AuditLogs +{ + public class AuditLogDto : ExtensibleEntityDto + { + public string ApplicationName { get; set; } + + public Guid? UserId { get; set; } + + public string UserName { get; set; } + + public Guid? TenantId { get; set; } + + public string TenantName { get; set; } + + public Guid? ImpersonatorUserId { get; set; } + + public Guid? ImpersonatorTenantId { get; set; } + + public DateTime ExecutionTime { get; set; } + + public int ExecutionDuration { get; set; } + + public string ClientIpAddress { get; set; } + + public string ClientName { get; set; } + + public string ClientId { get; set; } + + public string CorrelationId { get; set; } + + public string BrowserInfo { get; set; } + + public string HttpMethod { get; set; } + + public string Url { get; set; } + + public string Exceptions { get; set; } + + public string Comments { get; set; } + + public int? HttpStatusCode { get; set; } + public List EntityChanges { get; set; } + public List Actions { get; set; } + + public AuditLogDto() + { + EntityChanges = new List(); + Actions = new List(); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogGetByPagedDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogGetByPagedDto.cs similarity index 82% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogGetByPagedDto.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogGetByPagedDto.cs index 80a91c739..18b8de1d2 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/AuditLogGetByPagedDto.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/AuditLogGetByPagedDto.cs @@ -2,7 +2,7 @@ using System.Net; using Volo.Abp.Application.Dtos; -namespace LINGYUN.Abp.Auditing.Logging +namespace LINGYUN.Abp.Auditing.AuditLogs { public class AuditLogGetByPagedDto : PagedAndSortedResultRequestDto { @@ -14,6 +14,8 @@ namespace LINGYUN.Abp.Auditing.Logging public string UserName { get; set; } public string ApplicationName { get; set; } public string CorrelationId { get; set; } + public string ClientId { get; set; } + public string ClientIpAddress { get; set; } public int? MaxExecutionDuration { get; set; } public int? MinExecutionDuration { get; set; } public bool? HasException { get; set; } diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/EntityChangeDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/EntityChangeDto.cs similarity index 90% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/EntityChangeDto.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/EntityChangeDto.cs index 2e153d70d..35370d73b 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/EntityChangeDto.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/EntityChangeDto.cs @@ -1,25 +1,25 @@ -using System; -using System.Collections.Generic; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Auditing; - -namespace LINGYUN.Abp.Auditing.Logging -{ - public class EntityChangeDto : ExtensibleEntityDto - { - public DateTime ChangeTime { get; set; } - - public EntityChangeType ChangeType { get; set; } - - public Guid? EntityTenantId { get; set; } - - public string EntityId { get; set; } - - public string EntityTypeFullName { get; set; } - public List PropertyChanges { get; set; } - public EntityChangeDto() - { - PropertyChanges = new List(); - } - } -} +using System; +using System.Collections.Generic; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Auditing; + +namespace LINGYUN.Abp.Auditing.AuditLogs +{ + public class EntityChangeDto : ExtensibleEntityDto + { + public DateTime ChangeTime { get; set; } + + public EntityChangeType ChangeType { get; set; } + + public Guid? EntityTenantId { get; set; } + + public string EntityId { get; set; } + + public string EntityTypeFullName { get; set; } + public List PropertyChanges { get; set; } + public EntityChangeDto() + { + PropertyChanges = new List(); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/EntityPropertyChangeDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/EntityPropertyChangeDto.cs similarity index 85% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/EntityPropertyChangeDto.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/EntityPropertyChangeDto.cs index 6e47a2f67..ef451c8d3 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/EntityPropertyChangeDto.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/EntityPropertyChangeDto.cs @@ -1,16 +1,16 @@ -using System; -using Volo.Abp.Application.Dtos; - -namespace LINGYUN.Abp.Auditing.Logging -{ - public class EntityPropertyChangeDto : EntityDto - { - public string NewValue { get; set; } - - public string OriginalValue { get; set; } - - public string PropertyName { get; set; } - - public string PropertyTypeFullName { get; set; } - } -} +using System; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.Auditing.AuditLogs +{ + public class EntityPropertyChangeDto : EntityDto + { + public string NewValue { get; set; } + + public string OriginalValue { get; set; } + + public string PropertyName { get; set; } + + public string PropertyTypeFullName { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/IAuditLogAppService.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/IAuditLogAppService.cs similarity index 86% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/IAuditLogAppService.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/IAuditLogAppService.cs index 13f8f8f91..75a691af6 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/IAuditLogAppService.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/AuditLogs/IAuditLogAppService.cs @@ -1,16 +1,16 @@ -using System; -using System.Threading.Tasks; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Application.Services; - -namespace LINGYUN.Abp.Auditing.Logging -{ - public interface IAuditLogAppService : IApplicationService - { - Task> GetListAsync(AuditLogGetByPagedDto input); - - Task GetAsync(Guid id); - - Task DeleteAsync(Guid id); - } -} +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.Auditing.AuditLogs +{ + public interface IAuditLogAppService : IApplicationService + { + Task> GetListAsync(AuditLogGetByPagedDto input); + + Task GetAsync(Guid id); + + Task DeleteAsync(Guid id); + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogDto.cs new file mode 100644 index 000000000..c3ed23ca3 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogDto.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; + +namespace LINGYUN.Abp.Auditing.Logging +{ + public class LogDto + { + public DateTime TimeStamp { get; set; } + public LogLevel Level { get; set; } + public string Message { get; set; } + public LogFieldDto Fields { get; set; } + public List Exceptions { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogExceptionDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogExceptionDto.cs new file mode 100644 index 000000000..7bf1e92a5 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogExceptionDto.cs @@ -0,0 +1,13 @@ +namespace LINGYUN.Abp.Auditing.Logging +{ + public class LogExceptionDto + { + public int Depth { get; set; } + public string Class { get; set; } + public string Message { get; set; } + public string Source { get; set; } + public string StackTrace { get; set; } + public int HResult { get; set; } + public string HelpURL { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogFieldDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogFieldDto.cs new file mode 100644 index 000000000..0bd6c1334 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogFieldDto.cs @@ -0,0 +1,17 @@ +namespace LINGYUN.Abp.Auditing.Logging +{ + public class LogFieldDto + { + public string Context { get; set; } + public string ActionId { get; set; } + public string ActionName { get; set; } + public string RequestId { get; set; } + public string RequestPath { get; set; } + public string ConnectionId { get; set; } + public string CorrelationId { get; set; } + public string ClientId { get; set; } + public string UserId { get; set; } + public int ProcessId { get; set; } + public int ThreadId { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogGetByPagedDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogGetByPagedDto.cs new file mode 100644 index 000000000..bd173e84c --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/Dto/LogGetByPagedDto.cs @@ -0,0 +1,18 @@ +using System; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.Auditing.Logging +{ + public class LogGetByPagedDto : PagedAndSortedResultRequestDto + { + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } + public string Context { get; set; } + public string RequestId { get; set; } + public string RequestPath { get; set; } + public string CorrelationId { get; set; } + public int? ProcessId { get; set; } + public int? ThreadId { get; set; } + public bool? HasException { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/ILogAppService.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/ILogAppService.cs new file mode 100644 index 000000000..0a5682354 --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Logging/ILogAppService.cs @@ -0,0 +1,14 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.Auditing.Logging +{ + public interface ILogAppService : IApplicationService + { + Task GetAsync(string id); + + Task> GetListAsync(LogGetByPagedDto input); + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/ISecurityLogAppService.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/ISecurityLogAppService.cs similarity index 86% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/ISecurityLogAppService.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/ISecurityLogAppService.cs index c52bac57a..1a92bbc1a 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/ISecurityLogAppService.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/ISecurityLogAppService.cs @@ -1,16 +1,16 @@ -using System; -using System.Threading.Tasks; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Application.Services; - -namespace LINGYUN.Abp.Auditing.Security -{ - public interface ISecurityLogAppService : IApplicationService - { - Task> GetListAsync(SecurityLogGetByPagedDto input); - - Task GetAsync(Guid id); - - Task DeleteAsync(Guid id); - } -} +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.Auditing.SecurityLogs +{ + public interface ISecurityLogAppService : IApplicationService + { + Task> GetListAsync(SecurityLogGetByPagedDto input); + + Task GetAsync(Guid id); + + Task DeleteAsync(Guid id); + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/SecurityLogDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogDto.cs similarity index 89% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/SecurityLogDto.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogDto.cs index a46d341d8..f572a1e90 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/SecurityLogDto.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogDto.cs @@ -1,30 +1,30 @@ -using System; -using Volo.Abp.Application.Dtos; - -namespace LINGYUN.Abp.Auditing.Security -{ - public class SecurityLogDto : ExtensibleEntityDto - { - public string ApplicationName { get; set; } - - public string Identity { get; set; } - - public string Action { get; set; } - - public Guid? UserId { get; set; } - - public string UserName { get; set; } - - public string TenantName { get; set; } - - public string ClientId { get; set; } - - public string CorrelationId { get; set; } - - public string ClientIpAddress { get; set; } - - public string BrowserInfo { get; set; } - - public DateTime CreationTime { get; set; } - } -} +using System; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.Auditing.SecurityLogs +{ + public class SecurityLogDto : ExtensibleEntityDto + { + public string ApplicationName { get; set; } + + public string Identity { get; set; } + + public string Action { get; set; } + + public Guid? UserId { get; set; } + + public string UserName { get; set; } + + public string TenantName { get; set; } + + public string ClientId { get; set; } + + public string CorrelationId { get; set; } + + public string ClientIpAddress { get; set; } + + public string BrowserInfo { get; set; } + + public DateTime CreationTime { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/SecurityLogGetByPagedDto.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogGetByPagedDto.cs similarity index 90% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/SecurityLogGetByPagedDto.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogGetByPagedDto.cs index 11a2d88cc..3e9c754cf 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/Security/SecurityLogGetByPagedDto.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application.Contracts/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogGetByPagedDto.cs @@ -1,18 +1,18 @@ -using System; -using Volo.Abp.Application.Dtos; - -namespace LINGYUN.Abp.Auditing.Security -{ - public class SecurityLogGetByPagedDto : PagedAndSortedResultRequestDto - { - public DateTime? StartTime { get; set; } - public DateTime? EndTime { get; set; } - public string ApplicationName { get; set; } - public string Identity { get; set; } - public string ActionName { get; set; } - public Guid? UserId { get; set; } - public string UserName { get; set; } - public string ClientId { get; set; } - public string CorrelationId { get; set; } - } -} +using System; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.Auditing.SecurityLogs +{ + public class SecurityLogGetByPagedDto : PagedAndSortedResultRequestDto + { + public DateTime? StartTime { get; set; } + public DateTime? EndTime { get; set; } + public string ApplicationName { get; set; } + public string Identity { get; set; } + public string ActionName { get; set; } + public Guid? UserId { get; set; } + public string UserName { get; set; } + public string ClientId { get; set; } + public string CorrelationId { get; set; } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN.Abp.Auditing.Application.csproj b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN.Abp.Auditing.Application.csproj index a1df8247a..82b9f92d8 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN.Abp.Auditing.Application.csproj +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN.Abp.Auditing.Application.csproj @@ -1,4 +1,4 @@ - + @@ -9,13 +9,13 @@ - - + + diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingApplicationModule.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingApplicationModule.cs index 5060cfb9f..253766a33 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingApplicationModule.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingApplicationModule.cs @@ -1,24 +1,24 @@ -using Microsoft.Extensions.DependencyInjection; -using Volo.Abp.AuditLogging; -using Volo.Abp.AutoMapper; -using Volo.Abp.Modularity; - -namespace LINGYUN.Abp.Auditing -{ - [DependsOn( - typeof(AbpAutoMapperModule), - typeof(AbpAuditLoggingDomainModule), - typeof(AbpAuditingApplicationContractsModule))] - public class AbpAuditingApplicationModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - context.Services.AddAutoMapperObjectMapper(); - - Configure(options => - { - options.AddProfile(validate: true); - }); - } - } -} +using LINGYUN.Abp.AuditLogging; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Auditing +{ + [DependsOn( + typeof(AbpAutoMapperModule), + typeof(AbpAuditLoggingModule), + typeof(AbpAuditingApplicationContractsModule))] + public class AbpAuditingApplicationModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => + { + options.AddProfile(validate: true); + }); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingMapperProfile.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingMapperProfile.cs index e4ce4c675..8ebb2145f 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingMapperProfile.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AbpAuditingMapperProfile.cs @@ -1,25 +1,30 @@ -using AutoMapper; -using LINGYUN.Abp.Auditing.Logging; -using LINGYUN.Abp.Auditing.Security; -using Volo.Abp.AuditLogging; -using Volo.Abp.AutoMapper; -using Volo.Abp.Identity; - -namespace LINGYUN.Abp.Auditing -{ - public class AbpAuditingMapperProfile : Profile - { - public AbpAuditingMapperProfile() - { - CreateMap() - .MapExtraProperties(); - CreateMap(); - CreateMap() - .MapExtraProperties(); - CreateMap() - .MapExtraProperties(); - - CreateMap(); - } - } -} +using AutoMapper; +using LINGYUN.Abp.Auditing.AuditLogs; +using LINGYUN.Abp.Auditing.Logging; +using LINGYUN.Abp.Auditing.SecurityLogs; +using LINGYUN.Abp.AuditLogging; +using LINGYUN.Abp.Logging; + +namespace LINGYUN.Abp.Auditing +{ + public class AbpAuditingMapperProfile : Profile + { + public AbpAuditingMapperProfile() + { + CreateMap() + .MapExtraProperties(); + CreateMap(); + CreateMap() + .MapExtraProperties(); + CreateMap() + .MapExtraProperties(); + + CreateMap() + .MapExtraProperties(); + + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Logging/AuditLogAppService.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AuditLogs/AuditLogAppService.cs similarity index 68% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Logging/AuditLogAppService.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AuditLogs/AuditLogAppService.cs index c21c8ce76..aa896cb7a 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Logging/AuditLogAppService.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/AuditLogs/AuditLogAppService.cs @@ -1,50 +1,52 @@ using LINGYUN.Abp.Auditing.Features; using LINGYUN.Abp.Auditing.Permissions; +using LINGYUN.Abp.AuditLogging; using Microsoft.AspNetCore.Authorization; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Volo.Abp.Application.Dtos; -using Volo.Abp.AuditLogging; using Volo.Abp.Features; -namespace LINGYUN.Abp.Auditing.Logging +namespace LINGYUN.Abp.Auditing.AuditLogs { [Authorize(AuditingPermissionNames.AuditLog.Default)] [RequiresFeature(AuditingFeatureNames.Logging.AuditLog)] public class AuditLogAppService : AuditingApplicationServiceBase, IAuditLogAppService { - protected IAuditLogRepository AuditLogRepository { get; } + protected IAuditLogManager AuditLogManager { get; } - public AuditLogAppService(IAuditLogRepository auditLogRepository) + public AuditLogAppService(IAuditLogManager auditLogManager) { - AuditLogRepository = auditLogRepository; + AuditLogManager = auditLogManager; } public virtual async Task GetAsync(Guid id) { - var auditLog = await AuditLogRepository.GetAsync(id, includeDetails: true); + var auditLog = await AuditLogManager.GetAsync(id, includeDetails: true); return ObjectMapper.Map(auditLog); } public virtual async Task> GetListAsync(AuditLogGetByPagedDto input) { - var auditLogCount = await AuditLogRepository + var auditLogCount = await AuditLogManager .GetCountAsync(input.StartTime, input.EndTime, input.HttpMethod, input.Url, input.UserId, input.UserName, - input.ApplicationName, input.CorrelationId, + input.ApplicationName, input.CorrelationId, + input.ClientId, input.ClientIpAddress, input.MaxExecutionDuration, input.MinExecutionDuration, input.HasException, input.HttpStatusCode); - var auditLogs = await AuditLogRepository + var auditLogs = await AuditLogManager .GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, input.StartTime, input.EndTime, input.HttpMethod, input.Url, input.UserId, input.UserName, - input.ApplicationName, input.CorrelationId, + input.ApplicationName, input.CorrelationId, + input.ClientId, input.ClientIpAddress, input.MaxExecutionDuration, input.MinExecutionDuration, input.HasException, input.HttpStatusCode, includeDetails: false); @@ -55,10 +57,7 @@ namespace LINGYUN.Abp.Auditing.Logging [Authorize(AuditingPermissionNames.AuditLog.Delete)] public virtual async Task DeleteAsync([Required] Guid id) { - var auditLog = await AuditLogRepository.GetAsync(id); - await AuditLogRepository.DeleteAsync(auditLog); - - await CurrentUnitOfWork.SaveChangesAsync(); + await AuditLogManager.DeleteAsync(id); } } } diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Logging/LogAppService.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Logging/LogAppService.cs new file mode 100644 index 000000000..34b60712e --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Logging/LogAppService.cs @@ -0,0 +1,44 @@ +using LINGYUN.Abp.Logging; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.Auditing.Logging +{ + public class LogAppService : AuditingApplicationServiceBase, ILogAppService + { + private readonly ILoggingManager _manager; + + public LogAppService(ILoggingManager manager) + { + _manager = manager; + } + + public virtual async Task GetAsync(string id) + { + var log = await _manager.GetAsync(id); + + return ObjectMapper.Map(log); + } + + public virtual async Task> GetListAsync(LogGetByPagedDto input) + { + var count = await _manager.GetCountAsync( + input.StartTime, input.EndTime, + input.Context, input.RequestId, input.RequestPath, + input.CorrelationId, input.ProcessId, input.ThreadId, + input.HasException); + + var logs = await _manager.GetListAsync( + input.Sorting, input.MaxResultCount, input.SkipCount, + input.StartTime, input.EndTime, + input.Context, input.RequestId, input.RequestPath, + input.CorrelationId, input.ProcessId, input.ThreadId, + input.HasException, + includeDetails: false); + + return new PagedResultDto(count, + ObjectMapper.Map, List>(logs)); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Security/SecurityLogAppService.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogAppService.cs similarity index 63% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Security/SecurityLogAppService.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogAppService.cs index 53bbf178f..2766bce8b 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/Security/SecurityLogAppService.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.Application/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogAppService.cs @@ -1,59 +1,56 @@ -using LINGYUN.Abp.Auditing.Features; -using LINGYUN.Abp.Auditing.Permissions; -using Microsoft.AspNetCore.Authorization; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Features; -using Volo.Abp.Identity; - -namespace LINGYUN.Abp.Auditing.Security -{ - [Authorize(AuditingPermissionNames.SecurityLog.Default)] - [RequiresFeature(AuditingFeatureNames.Logging.SecurityLog)] - public class SecurityLogAppService : AuditingApplicationServiceBase, ISecurityLogAppService - { - protected IIdentitySecurityLogRepository SecurityLogRepository { get; } - public SecurityLogAppService(IIdentitySecurityLogRepository securityLogRepository) - { - SecurityLogRepository = securityLogRepository; - } - - public virtual async Task GetAsync(Guid id) - { - var securityLog = await SecurityLogRepository.GetAsync(id, includeDetails: true); - - return ObjectMapper.Map(securityLog); - } - - public virtual async Task> GetListAsync(SecurityLogGetByPagedDto input) - { - var securityLogCount = await SecurityLogRepository - .GetCountAsync(input.StartTime, input.EndTime, - input.ApplicationName, input.Identity, input.ActionName, - input.UserId, input.UserName, input.ClientId, input.CorrelationId - ); - - var securityLogs = await SecurityLogRepository - .GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, - input.StartTime, input.EndTime, - input.ApplicationName, input.Identity, input.ActionName, - input.UserId, input.UserName, input.ClientId, input.CorrelationId, - includeDetails: false - ); - - return new PagedResultDto(securityLogCount, - ObjectMapper.Map, List>(securityLogs)); - } - - [Authorize(AuditingPermissionNames.SecurityLog.Delete)] - public virtual async Task DeleteAsync(Guid id) - { - var securityLog = await SecurityLogRepository.GetAsync(id); - await SecurityLogRepository.DeleteAsync(securityLog); - - await CurrentUnitOfWork.SaveChangesAsync(); - } - } -} +using LINGYUN.Abp.Auditing.Features; +using LINGYUN.Abp.Auditing.Permissions; +using LINGYUN.Abp.AuditLogging; +using Microsoft.AspNetCore.Authorization; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.Auditing.SecurityLogs +{ + [Authorize(AuditingPermissionNames.SecurityLog.Default)] + [RequiresFeature(AuditingFeatureNames.Logging.SecurityLog)] + public class SecurityLogAppService : AuditingApplicationServiceBase, ISecurityLogAppService + { + protected ISecurityLogManager SecurityLogManager { get; } + public SecurityLogAppService(ISecurityLogManager securityLogManager) + { + SecurityLogManager = securityLogManager; + } + + public virtual async Task GetAsync(Guid id) + { + var securityLog = await SecurityLogManager.GetAsync(id, includeDetails: true); + + return ObjectMapper.Map(securityLog); + } + + public virtual async Task> GetListAsync(SecurityLogGetByPagedDto input) + { + var securityLogCount = await SecurityLogManager + .GetCountAsync(input.StartTime, input.EndTime, + input.ApplicationName, input.Identity, input.ActionName, + input.UserId, input.UserName, input.ClientId, input.CorrelationId + ); + + var securityLogs = await SecurityLogManager + .GetListAsync(input.Sorting, input.MaxResultCount, input.SkipCount, + input.StartTime, input.EndTime, + input.ApplicationName, input.Identity, input.ActionName, + input.UserId, input.UserName, input.ClientId, input.CorrelationId, + includeDetails: false + ); + + return new PagedResultDto(securityLogCount, + ObjectMapper.Map, List>(securityLogs)); + } + + [Authorize(AuditingPermissionNames.SecurityLog.Delete)] + public virtual async Task DeleteAsync(Guid id) + { + await SecurityLogManager.DeleteAsync(id); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Logging/AuditLogController.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/AuditLogs/AuditLogController.cs similarity index 93% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Logging/AuditLogController.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/AuditLogs/AuditLogController.cs index 95d7dee4f..57cf524d3 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Logging/AuditLogController.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/AuditLogs/AuditLogController.cs @@ -1,43 +1,43 @@ -using Microsoft.AspNetCore.Mvc; -using System; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.Application.Dtos; -using Volo.Abp.AspNetCore.Mvc; - -namespace LINGYUN.Abp.Auditing.Logging -{ - [RemoteService(Name = AuditingRemoteServiceConsts.RemoteServiceName)] - [Area("auditing")] - [ControllerName("audit-log")] - [Route("api/auditing/audit-log")] - public class AuditLogController : AbpController, IAuditLogAppService - { - protected IAuditLogAppService AuditLogAppService { get; } - - public AuditLogController(IAuditLogAppService auditLogAppService) - { - AuditLogAppService = auditLogAppService; - } - - [HttpDelete] - [Route("{id}")] - public virtual async Task DeleteAsync(Guid id) - { - await AuditLogAppService.DeleteAsync(id); - } - - [HttpGet] - [Route("{id}")] - public virtual async Task GetAsync(Guid id) - { - return await AuditLogAppService.GetAsync(id); - } - - [HttpGet] - public virtual async Task> GetListAsync(AuditLogGetByPagedDto input) - { - return await AuditLogAppService.GetListAsync(input); - } - } -} +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.Auditing.AuditLogs +{ + [RemoteService(Name = AuditingRemoteServiceConsts.RemoteServiceName)] + [Area("auditing")] + [ControllerName("audit-log")] + [Route("api/auditing/audit-log")] + public class AuditLogController : AbpController, IAuditLogAppService + { + protected IAuditLogAppService AuditLogAppService { get; } + + public AuditLogController(IAuditLogAppService auditLogAppService) + { + AuditLogAppService = auditLogAppService; + } + + [HttpDelete] + [Route("{id}")] + public virtual async Task DeleteAsync(Guid id) + { + await AuditLogAppService.DeleteAsync(id); + } + + [HttpGet] + [Route("{id}")] + public virtual async Task GetAsync(Guid id) + { + return await AuditLogAppService.GetAsync(id); + } + + [HttpGet] + public virtual async Task> GetListAsync(AuditLogGetByPagedDto input) + { + return await AuditLogAppService.GetListAsync(input); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Logging/LogController.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Logging/LogController.cs new file mode 100644 index 000000000..52156e95c --- /dev/null +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Logging/LogController.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.Auditing.Logging +{ + [RemoteService(Name = AuditingRemoteServiceConsts.RemoteServiceName)] + [Area("auditing")] + [ControllerName("logging")] + [Route("api/auditing/logging")] + public class LogController : AbpController, ILogAppService + { + private readonly ILogAppService _service; + + public LogController(ILogAppService service) + { + _service = service; + } + + [HttpGet] + [Route("{id}")] + public virtual async Task GetAsync(string id) + { + return await _service.GetAsync(id); + } + + [HttpGet] + public virtual async Task> GetListAsync(LogGetByPagedDto input) + { + return await _service.GetListAsync(input); + } + } +} diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Security/SecurityLogController.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogController.cs similarity index 93% rename from aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Security/SecurityLogController.cs rename to aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogController.cs index 5720ccb1f..381b70111 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/Security/SecurityLogController.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.Auditing.HttpApi/LINGYUN/Abp/Auditing/SecurityLogs/SecurityLogController.cs @@ -1,43 +1,43 @@ -using Microsoft.AspNetCore.Mvc; -using System; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.Application.Dtos; -using Volo.Abp.AspNetCore.Mvc; - -namespace LINGYUN.Abp.Auditing.Security -{ - [RemoteService(Name = AuditingRemoteServiceConsts.RemoteServiceName)] - [Area("auditing")] - [ControllerName("security-log")] - [Route("api/auditing/security-log")] - public class SecurityLogController : AbpController, ISecurityLogAppService - { - protected ISecurityLogAppService SecurityLogAppService { get; } - - public SecurityLogController(ISecurityLogAppService securityLogAppService) - { - SecurityLogAppService = securityLogAppService; - } - - [HttpDelete] - [Route("{id}")] - public virtual async Task DeleteAsync(Guid id) - { - await SecurityLogAppService.DeleteAsync(id); - } - - [HttpGet] - [Route("{id}")] - public virtual async Task GetAsync(Guid id) - { - return await SecurityLogAppService.GetAsync(id); - } - - [HttpGet] - public virtual async Task> GetListAsync(SecurityLogGetByPagedDto input) - { - return await SecurityLogAppService.GetListAsync(input); - } - } -} +using Microsoft.AspNetCore.Mvc; +using System; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.AspNetCore.Mvc; + +namespace LINGYUN.Abp.Auditing.SecurityLogs +{ + [RemoteService(Name = AuditingRemoteServiceConsts.RemoteServiceName)] + [Area("auditing")] + [ControllerName("security-log")] + [Route("api/auditing/security-log")] + public class SecurityLogController : AbpController, ISecurityLogAppService + { + protected ISecurityLogAppService SecurityLogAppService { get; } + + public SecurityLogController(ISecurityLogAppService securityLogAppService) + { + SecurityLogAppService = securityLogAppService; + } + + [HttpDelete] + [Route("{id}")] + public virtual async Task DeleteAsync(Guid id) + { + await SecurityLogAppService.DeleteAsync(id); + } + + [HttpGet] + [Route("{id}")] + public virtual async Task GetAsync(Guid id) + { + return await SecurityLogAppService.GetAsync(id); + } + + [HttpGet] + public virtual async Task> GetListAsync(SecurityLogGetByPagedDto input) + { + return await SecurityLogAppService.GetListAsync(input); + } + } +} diff --git a/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN.Abp.Elasticsearch.csproj b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN.Abp.Elasticsearch.csproj new file mode 100644 index 000000000..3276d094b --- /dev/null +++ b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN.Abp.Elasticsearch.csproj @@ -0,0 +1,15 @@ + + + + + + netstandard2.0 + + + + + + + + + diff --git a/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchModule.cs b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchModule.cs new file mode 100644 index 000000000..35d663e6d --- /dev/null +++ b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchModule.cs @@ -0,0 +1,14 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Elasticsearch +{ + public class AbpElasticsearchModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + Configure(configuration.GetSection("Elasticsearch")); + } + } +} diff --git a/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchOptions.cs b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchOptions.cs new file mode 100644 index 000000000..19900b9af --- /dev/null +++ b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/AbpElasticsearchOptions.cs @@ -0,0 +1,69 @@ +using Elasticsearch.Net; +using Nest; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace LINGYUN.Abp.Elasticsearch +{ + public class AbpElasticsearchOptions + { + /// + /// 字段名称 是否为 camelCase 格式 + /// 如果为true, 在ES中为 camelCase + /// 如果为false,在ES中为 CamelCase + /// 默认:false + /// + public bool FieldCamelCase { get; set; } + public string TypeName { get; set; } + public string NodeUris { get; set; } + public int ConnectionLimit { get; set; } + public string UserName { get; set; } + public string Password { get; set; } + public TimeSpan ConnectionTimeout { get; set; } + public IConnection Connection { get; set; } + public ConnectionSettings.SourceSerializerFactory SerializerFactory { get; set; } + + public AbpElasticsearchOptions() + { + TypeName = "_doc"; + ConnectionLimit = ConnectionConfiguration.DefaultConnectionLimit; + ConnectionTimeout = ConnectionConfiguration.DefaultTimeout; + } + + internal IConnectionSettingsValues CreateConfiguration() + { + IConnectionPool connectionPool; + IEnumerable nodes = NodeUris + .Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries) + .Select(uriString => new Uri(uriString)); + if (nodes.Count() == 1) + { + connectionPool = new SingleNodeConnectionPool(nodes.First()); + } + else + { + connectionPool = new StaticConnectionPool(nodes); + } + + var configuration = new ConnectionSettings( + connectionPool, + Connection, + SerializerFactory) + .ConnectionLimit(ConnectionLimit) + .RequestTimeout(ConnectionTimeout); + + if (!FieldCamelCase) + { + configuration.DefaultFieldNameInferrer((name) => name); + } + + if (UserName.IsNullOrWhiteSpace()) + { + configuration.BasicAuthentication(UserName, Password); + } + + return configuration; + } + } +} diff --git a/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/ElasticsearchClientFactory.cs b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/ElasticsearchClientFactory.cs new file mode 100644 index 000000000..c94031caa --- /dev/null +++ b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/ElasticsearchClientFactory.cs @@ -0,0 +1,32 @@ +using Microsoft.Extensions.Options; +using Nest; +using System; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Elasticsearch +{ + public class ElasticsearchClientFactory : IElasticsearchClientFactory, ISingletonDependency + { + private readonly AbpElasticsearchOptions _options; + private readonly Lazy _lazyClient; + + public ElasticsearchClientFactory( + IOptions options) + { + _options = options.Value; + + _lazyClient = new Lazy(CreateClient); + } + + public IElasticClient Create() => _lazyClient.Value; + + protected virtual IElasticClient CreateClient() + { + var configuration = _options.CreateConfiguration(); + + var client = new ElasticClient(configuration); + + return client; + } + } +} diff --git a/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/IElasticsearchClientFactory.cs b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/IElasticsearchClientFactory.cs new file mode 100644 index 000000000..1ee2f3d79 --- /dev/null +++ b/aspnet-core/modules/elasticsearch/LINGYUN.Abp.Elasticsearch/LINGYUN/Abp/Elasticsearch/IElasticsearchClientFactory.cs @@ -0,0 +1,9 @@ +using Nest; + +namespace LINGYUN.Abp.Elasticsearch +{ + public interface IElasticsearchClientFactory + { + IElasticClient Create(); + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj new file mode 100644 index 000000000..4e50b169e --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN.Abp.Logging.Serilog.Elasticsearch.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.0 + + + + + + + + + + + + + + + diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchMapperProfile.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchMapperProfile.cs new file mode 100644 index 000000000..73aa97176 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchMapperProfile.cs @@ -0,0 +1,14 @@ +using AutoMapper; + +namespace LINGYUN.Abp.Logging.Serilog.Elasticsearch +{ + public class AbpLoggingSerilogElasticsearchMapperProfile : Profile + { + public AbpLoggingSerilogElasticsearchMapperProfile() + { + CreateMap(); + CreateMap(); + CreateMap(); + } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchModule.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchModule.cs new file mode 100644 index 000000000..448348c38 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchModule.cs @@ -0,0 +1,33 @@ +using LINGYUN.Abp.Elasticsearch; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Volo.Abp.AutoMapper; +using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Logging.Serilog.Elasticsearch +{ + [DependsOn( + typeof(AbpLoggingModule), + typeof(AbpElasticsearchModule), + typeof(AbpAutoMapperModule), + typeof(AbpJsonModule))] + public class AbpLoggingSerilogElasticsearchModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + var configuration = context.Services.GetConfiguration(); + + Configure(configuration.GetSection("Logging:Serilog:Elasticsearch")); + + context.Services.AddAutoMapperObjectMapper(); + + Configure(options => + { + options.AddProfile(validate: true); + }); + } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchOptions.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchOptions.cs new file mode 100644 index 000000000..f9069d29e --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/AbpLoggingSerilogElasticsearchOptions.cs @@ -0,0 +1,12 @@ +namespace LINGYUN.Abp.Logging.Serilog.Elasticsearch +{ + public class AbpLoggingSerilogElasticsearchOptions + { + public string IndexFormat { get; set; } + + public AbpLoggingSerilogElasticsearchOptions() + { + IndexFormat = "logstash-{0:yyyy.MM.dd}"; + } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogElasticsearchLoggingManager.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogElasticsearchLoggingManager.cs new file mode 100644 index 000000000..8c1807f17 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogElasticsearchLoggingManager.cs @@ -0,0 +1,265 @@ +using LINGYUN.Abp.Elasticsearch; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Nest; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.ObjectMapping; + +namespace LINGYUN.Abp.Logging.Serilog.Elasticsearch +{ + [Dependency(ReplaceServices = true)] + public class SerilogElasticsearchLoggingManager : ILoggingManager, ISingletonDependency + { + private static readonly Regex IndexFormatRegex = new Regex(@"^(.*)(?:\{0\:.+\})(.*)$"); + + private readonly IObjectMapper _objectMapper; + private readonly AbpLoggingSerilogElasticsearchOptions _options; + private readonly IElasticsearchClientFactory _clientFactory; + + public ILogger Logger { protected get; set; } + + public SerilogElasticsearchLoggingManager( + IObjectMapper objectMapper, + IOptions options, + IElasticsearchClientFactory clientFactory) + { + _objectMapper = objectMapper; + _clientFactory = clientFactory; + _options = options.Value; + + Logger = NullLogger.Instance; + } + + /// + /// + /// + /// 时间类型或者转换为timestamp都可以查询 + /// + /// + public virtual async Task GetAsync( + string id, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var response = await client.SearchAsync( + dsl => + dsl.Index(CreateIndex()) + .Query( + (q) => q.Bool( + (b) => b.Should( + (s) => s.Term( + (t) => t.Field("@timestamp").Value(id))))), + cancellationToken); + + return _objectMapper.Map(response.Documents.FirstOrDefault()); + } + + public virtual async Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string context = null, + string requestId = null, + string requestPath = null, + string correlationId = null, + int? processId = null, + int? threadId = null, + bool? hasException = null, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var querys = BuildQueryDescriptor( + startTime, + endTime, + context, + requestId, + requestPath, + correlationId, + processId, + threadId, + hasException); + + var response = await client.CountAsync((dsl) => + dsl.Index(CreateIndex()) + .Query(log => log.Bool(b => b.Must(querys.ToArray()))), + cancellationToken); + + return response.Count; + } + + /// + /// 获取日志列表 + /// + /// 排序字段,注意:忽略排序字段仅使用timestamp排序,根据传递的ASC、DESC字段区分倒序还是正序 + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public virtual async Task> GetListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + DateTime? startTime = null, + DateTime? endTime = null, + string context = null, + string requestId = null, + string requestPath = null, + string correlationId = null, + int? processId = null, + int? threadId = null, + bool? hasException = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)) + { + var client = _clientFactory.Create(); + + var sortOrder = !sorting.IsNullOrWhiteSpace() && sorting.EndsWith("desc", StringComparison.InvariantCultureIgnoreCase) + ? SortOrder.Descending : SortOrder.Ascending; + + var querys = BuildQueryDescriptor( + startTime, + endTime, + context, + requestId, + requestPath, + correlationId, + processId, + threadId, + hasException); + + SourceFilterDescriptor ConvertFileSystem(SourceFilterDescriptor selector) + { + selector.IncludeAll(); + if (!includeDetails) + { + selector.Excludes(field => + field.Field("exceptions")); + } + + return selector; + } + + var response = await client.SearchAsync((dsl) => + dsl.Index(CreateIndex()) + .Query(log => log.Bool(b => b.Must(querys.ToArray()))) + .Source(ConvertFileSystem) + .Sort(log => log.Field("@timestamp", sortOrder)) + .From(skipCount) + .Size(maxResultCount), + cancellationToken); + + return _objectMapper.Map, List>(response.Documents.ToList()); + } + + protected virtual List, QueryContainer>> BuildQueryDescriptor( + DateTime? startTime = null, + DateTime? endTime = null, + string context = null, + string requestId = null, + string requestPath = null, + string correlationId = null, + int? processId = null, + int? threadId = null, + bool? hasException = null) + { + var querys = new List, QueryContainer>>(); + + if (startTime.HasValue) + { + querys.Add((log) => log.DateRange((q) => q.Field(f => f.TimeStamp).GreaterThanOrEquals(startTime))); + } + if (endTime.HasValue) + { + querys.Add((log) => log.DateRange((q) => q.Field(f => f.TimeStamp).LessThanOrEquals(endTime))); + } + if (!context.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field((f) => f.Fields.Context.Suffix("keyword")).Value(context))); + } + if (!requestId.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Match((q) => q.Field(f => f.Fields.RequestId.Suffix("keyword")).Query(requestId))); + } + if (!requestPath.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.Fields.RequestPath.Suffix("keyword")).Value(requestPath))); + } + if (!correlationId.IsNullOrWhiteSpace()) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.Fields.CorrelationId.Suffix("keyword")).Value(correlationId))); + } + if (processId.HasValue) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.Fields.ProcessId).Value(processId))); + } + if (threadId.HasValue) + { + querys.Add((log) => log.Term((q) => q.Field(f => f.Fields.ThreadId).Value(threadId))); + } + + if (hasException.HasValue) + { + if (hasException.Value) + { + /* 存在exceptions字段则就是有异常信息 + * "exists": { + "field": "exceptions" + } + */ + querys.Add( + (q) => q.Exists( + (e) => e.Field("exceptions"))); + } + else + { + // 不存在 exceptions字段就是没有异常信息的消息 + /* + * "bool": { + "must_not": [ + { + "exists": { + "field": "exceptions" + } + } + ] + } + */ + querys.Add( + (q) => q.Bool( + (b) => b.MustNot( + (m) => m.Exists( + (e) => e.Field("exceptions"))))); + } + } + + return querys; + } + + protected virtual string CreateIndex(DateTimeOffset? offset = null) + { + if (!offset.HasValue) + { + return IndexFormatRegex.Replace(_options.IndexFormat, @"$1*$2"); + } + return string.Format(_options.IndexFormat, offset.Value).ToLowerInvariant(); + } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogException.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogException.cs new file mode 100644 index 000000000..c08ba39fe --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogException.cs @@ -0,0 +1,26 @@ +namespace LINGYUN.Abp.Logging.Serilog.Elasticsearch +{ + public class SerilogException + { + [Nest.PropertyName("SourceContext")] + public int Depth { get; set; } + + [Nest.PropertyName("ClassName")] + public string Class { get; set; } + + [Nest.PropertyName("Message")] + public string Message { get; set; } + + [Nest.PropertyName("Source")] + public string Source { get; set; } + + [Nest.PropertyName("StackTraceString")] + public string StackTrace { get; set; } + + [Nest.PropertyName("HResult")] + public int HResult { get; set; } + + [Nest.PropertyName("HelpURL")] + public string HelpURL { get; set; } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogField.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogField.cs new file mode 100644 index 000000000..d8be177eb --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogField.cs @@ -0,0 +1,38 @@ +namespace LINGYUN.Abp.Logging.Serilog.Elasticsearch +{ + public class SerilogField + { + [Nest.PropertyName("SourceContext")] + public string Context { get; set; } + + [Nest.PropertyName("ActionId")] + public string ActionId { get; set; } + + [Nest.PropertyName("ActionName")] + public string ActionName { get; set; } + + [Nest.PropertyName("RequestId")] + public string RequestId { get; set; } + + [Nest.PropertyName("RequestPath")] + public string RequestPath { get; set; } + + [Nest.PropertyName("ConnectionId")] + public string ConnectionId { get; set; } + + [Nest.PropertyName("CorrelationId")] + public string CorrelationId { get; set; } + + [Nest.PropertyName("ClientId")] + public string ClientId { get; set; } + + [Nest.PropertyName("UserId")] + public string UserId { get; set; } + + [Nest.PropertyName("ProcessId")] + public int ProcessId { get; set; } + + [Nest.PropertyName("ThreadId")] + public int ThreadId { get; set; } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogInfo.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogInfo.cs new file mode 100644 index 000000000..19bca0ea6 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging.Serilog.Elasticsearch/LINGYUN/Abp/AuditLogging/Serilog/Elasticsearch/SerilogInfo.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.Logging; +using Serilog.Formatting.Elasticsearch; +using System; +using System.Collections.Generic; + +namespace LINGYUN.Abp.Logging.Serilog.Elasticsearch +{ + [Serializable] + public class SerilogInfo + { + [Nest.PropertyName(ElasticsearchJsonFormatter.TimestampPropertyName)] + public DateTime TimeStamp { get; set; } + + [Nest.PropertyName(ElasticsearchJsonFormatter.LevelPropertyName)] + public LogLevel Level { get; set; } + + [Nest.PropertyName(ElasticsearchJsonFormatter.RenderedMessagePropertyName)] + public string Message { get; set; } + + [Nest.PropertyName("fields")] + public SerilogField Fields { get; set; } + + [Nest.PropertyName("exceptions")] + public List Exceptions { get; set; } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN.Abp.Logging.csproj b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN.Abp.Logging.csproj new file mode 100644 index 000000000..1e52c5a59 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN.Abp.Logging.csproj @@ -0,0 +1,14 @@ + + + + + + netstandard2.0 + + + + + + + + diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/AbpLoggingModule.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/AbpLoggingModule.cs new file mode 100644 index 000000000..f69d75d12 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/AbpLoggingModule.cs @@ -0,0 +1,9 @@ +using System; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Logging +{ + public class AbpLoggingModule : AbpModule + { + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/DefaultLoggingManager.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/DefaultLoggingManager.cs new file mode 100644 index 000000000..e17f902ab --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/DefaultLoggingManager.cs @@ -0,0 +1,41 @@ +using LINGYUN.Abp.Logging; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.AuditLogging +{ + [Dependency(TryRegister = true)] + public class DefaultLoggingManager : ILoggingManager, ISingletonDependency + { + public ILogger Logger { protected get; set; } + + public DefaultLoggingManager() + { + Logger = NullLogger.Instance; + } + + public Task GetAsync(string id, CancellationToken cancellationToken = default) + { + Logger.LogDebug("No logging manager is available!"); + LogInfo logInfo = null; + return Task.FromResult(logInfo); + } + + public Task GetCountAsync(DateTime? startTime = null, DateTime? endTime = null, string context = null, string requestId = null, string requestPath = null, string correlationId = null, int? processId = null, int? threadId = null, bool? hasException = null, CancellationToken cancellationToken = default) + { + Logger.LogDebug("No logging manager is available!"); + return Task.FromResult(0L); + } + + public Task> GetListAsync(string sorting = null, int maxResultCount = 50, int skipCount = 0, DateTime? startTime = null, DateTime? endTime = null, string context = null, string requestId = null, string requestPath = null, string correlationId = null, int? processId = null, int? threadId = null, bool? hasException = null, bool includeDetails = false, CancellationToken cancellationToken = default) + { + Logger.LogDebug("No logging manager is available!"); + return Task.FromResult(new List()); + } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/ILoggingManager.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/ILoggingManager.cs new file mode 100644 index 000000000..8935e5a92 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/ILoggingManager.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Logging +{ + public interface ILoggingManager + { + Task GetAsync( + string id, + CancellationToken cancellationToken = default(CancellationToken)); + + Task GetCountAsync( + DateTime? startTime = null, + DateTime? endTime = null, + string context = null, + string requestId = null, + string requestPath = null, + string correlationId = null, + int? processId = null, + int? threadId = null, + bool? hasException = null, + CancellationToken cancellationToken = default(CancellationToken)); + + Task> GetListAsync( + string sorting = null, + int maxResultCount = 50, + int skipCount = 0, + DateTime? startTime = null, + DateTime? endTime = null, + string context = null, + string requestId = null, + string requestPath = null, + string correlationId = null, + int? processId = null, + int? threadId = null, + bool? hasException = null, + bool includeDetails = false, + CancellationToken cancellationToken = default(CancellationToken)); + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogException.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogException.cs new file mode 100644 index 000000000..7b750706f --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogException.cs @@ -0,0 +1,13 @@ +namespace LINGYUN.Abp.Logging +{ + public class LogException + { + public int Depth { get; set; } + public string Class { get; set; } + public string Message { get; set; } + public string Source { get; set; } + public string StackTrace { get; set; } + public int HResult { get; set; } + public string HelpURL { get; set; } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogField.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogField.cs new file mode 100644 index 000000000..0d6106c67 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogField.cs @@ -0,0 +1,17 @@ +namespace LINGYUN.Abp.Logging +{ + public class LogField + { + public string Context { get; set; } + public string ActionId { get; set; } + public string ActionName { get; set; } + public string RequestId { get; set; } + public string RequestPath { get; set; } + public string ConnectionId { get; set; } + public string CorrelationId { get; set; } + public string ClientId { get; set; } + public string UserId { get; set; } + public int ProcessId { get; set; } + public int ThreadId { get; set; } + } +} diff --git a/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogInfo.cs b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogInfo.cs new file mode 100644 index 000000000..a9c6fc8d7 --- /dev/null +++ b/aspnet-core/modules/logging/LINGYUN.Abp.Logging/LINGYUN/Abp/AuditLogging/LogInfo.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; + +namespace LINGYUN.Abp.Logging +{ + public class LogInfo + { + public DateTime TimeStamp { get; set; } + public LogLevel Level { get; set; } + public string Message { get; set; } + public LogField Fields { get; set; } + public List Exceptions { get; set; } + } +} diff --git a/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj.user b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj.user new file mode 100644 index 000000000..dc63f8a8b --- /dev/null +++ b/aspnet-core/modules/oss-management/LINGYUN.Abp.OssManagement.Application/LINGYUN.Abp.OssManagement.Application.csproj.user @@ -0,0 +1,6 @@ + + + + false + + \ No newline at end of file diff --git a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/.gitignore b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/.gitignore index 53f2c2fc2..5550a092a 100644 --- a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/.gitignore +++ b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/.gitignore @@ -1,4 +1,5 @@ bin obj Logs -appsettings.*.json \ No newline at end of file +appsettings.*.json +Modules \ No newline at end of file diff --git a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs index dd05df80c..11b76eb88 100644 --- a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs +++ b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/BackendAdminHostModule.cs @@ -52,16 +52,21 @@ using Volo.Abp.PermissionManagement; using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.PermissionManagement.HttpApi; using Volo.Abp.PermissionManagement.IdentityServer; +using Volo.Abp.AspNetCore.Serilog; using Volo.Abp.Security.Claims; using Volo.Abp.Security.Encryption; using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.Threading; using Volo.Abp.VirtualFileSystem; +using LINGYUN.Abp.AuditLogging.Elasticsearch; +using LINGYUN.Abp.Logging.Serilog.Elasticsearch; namespace LINGYUN.Abp.BackendAdmin { [DependsOn( + typeof(AbpLoggingSerilogElasticsearchModule), + typeof(AbpAuditLoggingElasticsearchModule), typeof(AbpAspNetCoreMvcUiMultiTenancyModule), typeof(AbpSettingManagementApplicationModule), typeof(AbpSettingManagementHttpApiModule), @@ -77,7 +82,7 @@ namespace LINGYUN.Abp.BackendAdmin typeof(AbpEntityFrameworkCoreMySQLModule), typeof(AbpIdentityEntityFrameworkCoreModule),// 用户角色权限需要引用包 typeof(AbpIdentityServerEntityFrameworkCoreModule), // 客户端权限需要引用包 - typeof(AbpAuditLoggingEntityFrameworkCoreModule), + //typeof(AbpAuditLoggingEntityFrameworkCoreModule), typeof(AbpTenantManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementDomainIdentityModule), @@ -92,6 +97,7 @@ namespace LINGYUN.Abp.BackendAdmin typeof(AbpDbFinderMultiTenancyModule), typeof(AbpCachingStackExchangeRedisModule), typeof(AbpAspNetCoreHttpOverridesModule), + typeof(AbpAspNetCoreSerilogModule), typeof(AbpAutofacModule) )] public class BackendAdminHostModule : AbpModule @@ -346,6 +352,7 @@ namespace LINGYUN.Abp.BackendAdmin }); // 审计日志 app.UseAuditing(); + app.UseAbpSerilogEnrichers(); // 处理微信消息 // app.UseWeChatSignature(); // 路由 diff --git a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj index 78f076351..006f860e5 100644 --- a/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj +++ b/aspnet-core/services/admin/LINGYUN.Abp.BackendAdmin.HttpApi.Host/LINGYUN.Abp.BackendAdmin.HttpApi.Host.csproj @@ -33,11 +33,12 @@ - + - + + @@ -61,12 +62,14 @@ + + diff --git a/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests.csproj new file mode 100644 index 000000000..6342dc697 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests.csproj @@ -0,0 +1,18 @@ + + + + net5.0 + + false + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestBase.cs new file mode 100644 index 000000000..f27f8eb41 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestBase.cs @@ -0,0 +1,15 @@ +using LINGYUN.Abp.Tests; +using Moq.AutoMock; +using Nest; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Auditing; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public abstract class AbpAuditLoggingElasticsearchTestBase : AbpTestsBase + { + + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestModule.cs new file mode 100644 index 000000000..a787b3ccc --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AbpAuditLoggingElasticsearchTestModule.cs @@ -0,0 +1,39 @@ +using LINGYUN.Abp.Elasticsearch; +using LINGYUN.Abp.Tests; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + [DependsOn( + typeof(AbpTestsBaseModule), + typeof(AbpAuditLoggingElasticsearchModule))] + public class AbpAuditLoggingElasticsearchTestModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + var configurationOptions = new AbpConfigurationBuilderOptions + { + BasePath = @"D:\Projects\Development\Abp\AuditLogging\Elasticsearch", + EnvironmentName = "Development" + }; + + context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(configurationOptions)); + } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + var options = context.ServiceProvider.GetRequiredService>().Value; + var clientFactory = context.ServiceProvider.GetRequiredService(); + var client = clientFactory.Create(); + var indicesResponse = client.Cat.Indices(i => i.Index($"{options.IndexPrefix}-security-log")); + foreach (var index in indicesResponse.Records) + { + client.Indices.Delete(index.Index); + } + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogManagerTests.cs b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogManagerTests.cs new file mode 100644 index 000000000..f96e0c5dd --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.AuditLogging.Elasticsearch.Tests/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogManagerTests.cs @@ -0,0 +1,121 @@ +using Moq.AutoMock; +using Shouldly; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Auditing; +using Xunit; + +namespace LINGYUN.Abp.AuditLogging.Elasticsearch +{ + public class AuditLogManagerTests : AbpAuditLoggingElasticsearchTestBase + { + private readonly IAuditLogManager _manager; + + public AuditLogManagerTests() + { + _manager = GetRequiredService(); + } + + public async Task Save_Audit_Log_Should_Be_Find_By_Id() + { + var mock = new AutoMocker(); + var auditLogInfo = mock.CreateInstance(); + + var id = await _manager.SaveAsync(auditLogInfo); + id.ShouldNotBeNullOrWhiteSpace(); + + var findId = Guid.Parse(id); + var auditLog = await _manager.GetAsync(findId); + + auditLog.ShouldNotBeNull(); + auditLog.Id.ShouldBe(findId); + + await _manager.DeleteAsync(findId); + } + + [Fact] + public async Task Save_Audit_Log_Should_Get_List() + { + //await MockcAsync(10); + + // 异常应该只有3个 + (await _manager.GetCountAsync( + hasException: true)).ShouldBe(3); + + // 正常可以查询7个 + (await _manager.GetCountAsync( + hasException: false)).ShouldBe(7); + + // POST方法能查到5个 + (await _manager.GetCountAsync( + httpMethod: "POST")).ShouldBe(5); + + (await _manager.GetCountAsync( + startTime: DateTime.Now.AddDays(-1).AddHours(5))).ShouldBe(6); + + (await _manager.GetCountAsync( + endTime: DateTime.Now.AddDays(-1))).ShouldBe(4); + + (await _manager.GetCountAsync( + startTime: DateTime.Now.AddDays(-3).AddHours(1), + endTime: DateTime.Now)).ShouldBe(8); + + // 索引5只存在一个 + (await _manager.GetCountAsync( + userName: "_user_5", + clientId: "_client_5")).ShouldBe(1); + + var logs = await _manager.GetListAsync( + userName: "_user_5", + clientId: "_client_5"); + + logs.Count.ShouldBe(1); + logs[0].Url.ShouldBe("_url_5"); + logs[0].BrowserInfo.ShouldBe("_browser_5"); + logs[0].ApplicationName.ShouldBe("_app_5"); + } + + protected virtual async Task> MockcAsync(int count) + { + var mock = new AutoMocker(); + + var auditLogIds = new List(); + + for (int i = 1; i <= count; i++) + { + var auditLogInfo = mock.CreateInstance(); + auditLogInfo.ClientId = $"_client_{i}"; + auditLogInfo.Url = $"_url_{i}"; + auditLogInfo.UserName = $"_user_{i}"; + auditLogInfo.ApplicationName = $"_app_{i}"; + auditLogInfo.BrowserInfo = $"_browser_{i}"; + auditLogInfo.ExecutionTime = DateTime.Now; + + if (i % 3 == 0) + { + auditLogInfo.Exceptions.Add(new Exception($"_exception_{i}")); + } + + if (i % 2 == 0) + { + auditLogInfo.HttpMethod = "POST"; + } + + if (i % 4 == 0) + { + auditLogInfo.ExecutionTime = DateTime.Now.AddDays(-3); + } + + if (i % 5 == 0) + { + auditLogInfo.ExecutionTime = DateTime.Now.AddDays(-2); + } + + auditLogIds.Add(await _manager.SaveAsync(auditLogInfo)); + } + + return auditLogIds; + } + } +}