From 610b0511bdad88647709c80ec024b1e5be5f71d2 Mon Sep 17 00:00:00 2001 From: cKey <35512826+colinin@users.noreply.github.com> Date: Sun, 4 Oct 2020 16:18:30 +0800 Subject: [PATCH] create a rule engine module --- aspnet-core/LINGYUN.MicroService.sln | 20 +++- .../LINGYUN.Abp.Rules.csproj | 14 +++ .../LINGYUN/Abp/Rules/AbpRulesEngineModule.cs | 16 ++++ .../Rules/EntityChangedRulesInterceptor.cs | 48 ++++++++++ .../EntityChangedRulesInterceptorRegistrar.cs | 28 ++++++ .../LINGYUN/Abp/Rules/EntityRuleContext.cs | 18 ++++ .../LINGYUN/Abp/Rules/ErrorType.cs | 8 ++ .../LINGYUN/Abp/Rules/ExpressionType.cs | 7 ++ .../Abp/Rules/IEntityRuleContributor.cs | 9 ++ .../LINGYUN/Abp/Rules/INeedRule.cs | 6 ++ .../LINGYUN/Abp/Rules/IRuleFinder.cs | 11 +++ .../Abp/Rules/NullEntityRuleContributor.cs | 13 +++ .../LINGYUN/Abp/Rules/NullRuleFinder.cs | 15 +++ .../LINGYUN/Abp/Rules/Rule.cs | 90 ++++++++++++++++++ .../LINGYUN/Abp/Rules/RuleGroup.cs | 39 ++++++++ .../LINGYUN/Abp/Rules/RuleParam.cs | 43 +++++++++ .../common/LINGYUN.Abp.Rules/README.md | 7 ++ .../LINGYUN.Abp.RulesEngine.csproj | 19 ++++ .../Abp/RulesEngine/AbpMsRulesEngineModule.cs | 22 +++++ .../RulesEngine/MsEntityRuleContributor.cs | 50 ++++++++++ .../RulesEngine/MsRulesEngineMapperProfile.cs | 27 ++++++ .../common/LINGYUN.Abp.RulesEngine/README.md | 7 ++ .../LINGYUN.ApiGateway.Host/event-bus-cap.db | Bin 32768 -> 32768 bytes docker-compose.yml | 5 +- vueJs/src/api/auditing.ts | 2 +- .../views/admin/auditing/audit-log/index.vue | 2 +- .../admin/auditing/security-log/index.vue | 2 +- 27 files changed, 518 insertions(+), 10 deletions(-) create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN.Abp.Rules.csproj create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/AbpRulesEngineModule.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptor.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptorRegistrar.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityRuleContext.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ErrorType.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ExpressionType.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IEntityRuleContributor.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/INeedRule.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IRuleFinder.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullEntityRuleContributor.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullRuleFinder.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/Rule.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleGroup.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleParam.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.Rules/README.md create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN.Abp.RulesEngine.csproj create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/AbpMsRulesEngineModule.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsEntityRuleContributor.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsRulesEngineMapperProfile.cs create mode 100644 aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/README.md diff --git a/aspnet-core/LINGYUN.MicroService.sln b/aspnet-core/LINGYUN.MicroService.sln index 38cb09383..2bb914e1a 100644 --- a/aspnet-core/LINGYUN.MicroService.sln +++ b/aspnet-core/LINGYUN.MicroService.sln @@ -233,11 +233,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.Client EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "auditing", "auditing", "{67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Auditing.Application.Contracts", "modules\auditing\LINGYUN.Abp.Auditing.Application.Contracts\LINGYUN.Abp.Auditing.Application.Contracts.csproj", "{F40F88F1-CA90-4A79-B772-80E287E25982}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Auditing.Application.Contracts", "modules\auditing\LINGYUN.Abp.Auditing.Application.Contracts\LINGYUN.Abp.Auditing.Application.Contracts.csproj", "{F40F88F1-CA90-4A79-B772-80E287E25982}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Auditing.Application", "modules\auditing\LINGYUN.Abp.Auditing.Application\LINGYUN.Abp.Auditing.Application.csproj", "{AC3C8985-73C2-472A-8E76-A0B8786FEC3F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Auditing.Application", "modules\auditing\LINGYUN.Abp.Auditing.Application\LINGYUN.Abp.Auditing.Application.csproj", "{AC3C8985-73C2-472A-8E76-A0B8786FEC3F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Auditing.HttpApi", "modules\auditing\LINGYUN.Abp.Auditing.HttpApi\LINGYUN.Abp.Auditing.HttpApi.csproj", "{07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Auditing.HttpApi", "modules\auditing\LINGYUN.Abp.Auditing.HttpApi\LINGYUN.Abp.Auditing.HttpApi.csproj", "{07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Rules", "modules\common\LINGYUN.Abp.Rules\LINGYUN.Abp.Rules.csproj", "{8ACB30CF-2311-4C0A-AE79-92C1A7667353}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RulesEngine", "modules\common\LINGYUN.Abp.RulesEngine\LINGYUN.Abp.RulesEngine.csproj", "{FD007B55-A0F1-4EF8-9CFD-6D8AD1B61B65}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -633,6 +637,14 @@ Global {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}.Debug|Any CPU.Build.0 = Debug|Any CPU {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}.Release|Any CPU.ActiveCfg = Release|Any CPU {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F}.Release|Any CPU.Build.0 = Release|Any CPU + {8ACB30CF-2311-4C0A-AE79-92C1A7667353}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8ACB30CF-2311-4C0A-AE79-92C1A7667353}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8ACB30CF-2311-4C0A-AE79-92C1A7667353}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8ACB30CF-2311-4C0A-AE79-92C1A7667353}.Release|Any CPU.Build.0 = Release|Any CPU + {FD007B55-A0F1-4EF8-9CFD-6D8AD1B61B65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD007B55-A0F1-4EF8-9CFD-6D8AD1B61B65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD007B55-A0F1-4EF8-9CFD-6D8AD1B61B65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD007B55-A0F1-4EF8-9CFD-6D8AD1B61B65}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -753,6 +765,8 @@ Global {F40F88F1-CA90-4A79-B772-80E287E25982} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} {AC3C8985-73C2-472A-8E76-A0B8786FEC3F} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} {07E19CA8-671D-4D58-9FED-5FEE9AE01A2F} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4} + {8ACB30CF-2311-4C0A-AE79-92C1A7667353} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} + {FD007B55-A0F1-4EF8-9CFD-6D8AD1B61B65} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN.Abp.Rules.csproj b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN.Abp.Rules.csproj new file mode 100644 index 000000000..44dc17105 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN.Abp.Rules.csproj @@ -0,0 +1,14 @@ + + + + + + netstandard2.0 + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/AbpRulesEngineModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/AbpRulesEngineModule.cs new file mode 100644 index 000000000..c19f6df37 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/AbpRulesEngineModule.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Domain; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Rules +{ + [DependsOn( + typeof(AbpDddDomainModule))] + public class AbpRulesEngineModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + context.Services.OnRegistred(EntityChangedRulesInterceptorRegistrar.RegisterIfNeeded); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptor.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptor.cs new file mode 100644 index 000000000..948dde25f --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptor.cs @@ -0,0 +1,48 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Entities; +using Volo.Abp.DynamicProxy; + +namespace LINGYUN.Abp.Rules +{ + public class EntityChangedRulesInterceptor : AbpInterceptor, ITransientDependency + { + protected IRuleFinder RuleFinder { get; } + protected IEntityRuleContributor EntityRuleContributor { get; } + + public EntityChangedRulesInterceptor( + IRuleFinder ruleFinder, + IEntityRuleContributor entityRuleContributor) + { + RuleFinder = ruleFinder; + EntityRuleContributor = entityRuleContributor; + } + + public override async Task InterceptAsync(IAbpMethodInvocation invocation) + { + var entityObj = invocation.Arguments.First(); + // TODO: 针对实体的变更执行一次定义的规则 + // IBasicRepository.InsertAsync || IBasicRepository.UpdateAsync || IBasicRepository.DeleteAsync + if (entityObj != null && entityObj is IEntity entity) + { + await ApplyEntityRuleAsync(entity); + } + + await invocation.ProceedAsync(); + } + + protected virtual async Task ApplyEntityRuleAsync(IEntity entity) + { + Type entityType = ProxyHelper.GetUnProxiedType(entity); + // 加载规则列表 + var groups = await RuleFinder.GetRuleGroupsAsync(entityType); + if (groups.Any()) + { + // 应用规则 + await EntityRuleContributor.ApplyAsync(new EntityRuleContext(groups, entity)); + } + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptorRegistrar.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptorRegistrar.cs new file mode 100644 index 000000000..3b7b11a4e --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityChangedRulesInterceptorRegistrar.cs @@ -0,0 +1,28 @@ +using System; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.DynamicProxy; + +namespace LINGYUN.Abp.Rules +{ + public static class EntityChangedRulesInterceptorRegistrar + { + public static void RegisterIfNeeded(IOnServiceRegistredContext context) + { + if (ShouldIntercept(context.ImplementationType)) + { + context.Interceptors.TryAdd(); + } + } + + private static bool ShouldIntercept(Type type) + { + // 拦截器的要求 + // 1、继承自IBasicRepository的仓储 + // 2、继承自INeedRule接口的实体 + return !DynamicProxyIgnoreTypes.Contains(type) && + type.IsAssignableTo(typeof(IBasicRepository<>)) && + type.GetGenericTypeDefinition().IsAssignableTo(typeof(INeedRule)); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityRuleContext.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityRuleContext.cs new file mode 100644 index 000000000..58bbd744e --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/EntityRuleContext.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Volo.Abp.Domain.Entities; + +namespace LINGYUN.Abp.Rules +{ + public class EntityRuleContext + { + public List Groups { get; } + public IEntity Entity { get; } + public EntityRuleContext( + List groups, + IEntity entity) + { + Groups = groups; + Entity = entity; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ErrorType.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ErrorType.cs new file mode 100644 index 000000000..6b5825435 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ErrorType.cs @@ -0,0 +1,8 @@ +namespace LINGYUN.Abp.Rules +{ + public enum ErrorType + { + Warning = 0, + Error = 1 + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ExpressionType.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ExpressionType.cs new file mode 100644 index 000000000..49fb8dcc1 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/ExpressionType.cs @@ -0,0 +1,7 @@ +namespace LINGYUN.Abp.Rules +{ + public enum ExpressionType + { + LambdaExpression = 0 + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IEntityRuleContributor.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IEntityRuleContributor.cs new file mode 100644 index 000000000..badbd75ff --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IEntityRuleContributor.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Rules +{ + public interface IEntityRuleContributor + { + Task ApplyAsync(EntityRuleContext context); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/INeedRule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/INeedRule.cs new file mode 100644 index 000000000..7a1faab36 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/INeedRule.cs @@ -0,0 +1,6 @@ +namespace LINGYUN.Abp.Rules +{ + public interface INeedRule + { + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IRuleFinder.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IRuleFinder.cs new file mode 100644 index 000000000..ee3f61064 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/IRuleFinder.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Rules +{ + public interface IRuleFinder + { + Task> GetRuleGroupsAsync(Type entityType); + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullEntityRuleContributor.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullEntityRuleContributor.cs new file mode 100644 index 000000000..52a170c94 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullEntityRuleContributor.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Rules +{ + public class NullEntityRuleContributor : IEntityRuleContributor, ISingletonDependency + { + public Task ApplyAsync(EntityRuleContext context) + { + return Task.CompletedTask; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullRuleFinder.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullRuleFinder.cs new file mode 100644 index 000000000..81aaa79cc --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/NullRuleFinder.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Rules +{ + public class NullRuleFinder : IRuleFinder, ISingletonDependency + { + public Task> GetRuleGroupsAsync(Type entityType) + { + return Task.FromResult(new List()); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/Rule.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/Rule.cs new file mode 100644 index 000000000..f35e5b054 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/Rule.cs @@ -0,0 +1,90 @@ +using JetBrains.Annotations; +using System; +using System.Collections.Generic; +using Volo.Abp; + +namespace LINGYUN.Abp.Rules +{ + /// + /// ref: https://github.com/microsoft/RulesEngine/blob/master/src/RulesEngine/RulesEngine/Models/Rule.cs + /// + public class Rule + { + [NotNull] + public string Name { get; } + public string Operator { get; } + public string ErrorMessage { get; } + public DateTime CreationTime { get; } + public ErrorType ErrorType { get; } + public ExpressionType? ExpressionType { get; } + public List Rules { get; } + public List InjectRules { get; } + public List Params { get; } + public string Expression { get; } + public string SuccessEvent { get; } + + public Rule( + [NotNull] string name, + string @operator, + DateTime creationTime, + string expression = null, + string successEvent = null, + ErrorType errorType = ErrorType.Warning, + ExpressionType? expressionType = null) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + + Name = name; + Operator = @operator; + CreationTime = creationTime; + Expression = expression; + SuccessEvent = successEvent; + ErrorType = errorType; + ExpressionType = expressionType; + + Rules = new List(); + Params = new List(); + InjectRules = new List(); + } + + public Rule CreateChildren(Rule rule) + { + Rules.Add(rule); + + return this; + } + + public Rule WithParam(RuleParam param) + { + Params.AddIfNotContains(param); + return this; + } + + public Rule InjectRule(string ruleName) + { + InjectRules.AddIfNotContains(ruleName); + + return this; + } + + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + if (obj is Rule rule) + { + return rule.Name.Equals(Name); + } + + return false; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleGroup.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleGroup.cs new file mode 100644 index 000000000..c6447a204 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleGroup.cs @@ -0,0 +1,39 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using Volo.Abp; + +namespace LINGYUN.Abp.Rules +{ + public class RuleGroup + { + [NotNull] + public string Name { get; } + public List InjectRules { get; } + public List Rules { get; } + + public RuleGroup( + [NotNull] string name) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + + Name = name; + + Rules = new List(); + InjectRules = new List(); + } + + public RuleGroup InjectRule(string ruleName) + { + InjectRules.AddIfNotContains(ruleName); + + return this; + } + + public RuleGroup WithRule(Rule rule) + { + Rules.AddIfNotContains(rule); + + return this; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleParam.cs b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleParam.cs new file mode 100644 index 000000000..2601e4c47 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/LINGYUN/Abp/Rules/RuleParam.cs @@ -0,0 +1,43 @@ +using JetBrains.Annotations; +using Volo.Abp; + +namespace LINGYUN.Abp.Rules +{ + public class RuleParam + { + [NotNull] + public string Name { get; } + + [NotNull] + public string Expression { get; } + public RuleParam( + [NotNull] string name, + [NotNull] string expression) + { + Check.NotNullOrWhiteSpace(name, nameof(name)); + Check.NotNullOrWhiteSpace(expression, nameof(expression)); + + Name = name; + Expression = expression; + } + + public override int GetHashCode() + { + return Name.GetHashCode(); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + + if (obj is RuleParam param) + { + return param.Name.Equals(Name); + } + return base.Equals(obj); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Rules/README.md b/aspnet-core/modules/common/LINGYUN.Abp.Rules/README.md new file mode 100644 index 000000000..b37832f46 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.Rules/README.md @@ -0,0 +1,7 @@ +# LINGYUN.Abp.Rules + +规则引擎定义 + +## 配置使用 + +待完善 \ No newline at end of file diff --git a/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN.Abp.RulesEngine.csproj b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN.Abp.RulesEngine.csproj new file mode 100644 index 000000000..093bd2658 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN.Abp.RulesEngine.csproj @@ -0,0 +1,19 @@ + + + + + + netstandard2.0 + + + + + + + + + + + + + diff --git a/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/AbpMsRulesEngineModule.cs b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/AbpMsRulesEngineModule.cs new file mode 100644 index 000000000..f56421321 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/AbpMsRulesEngineModule.cs @@ -0,0 +1,22 @@ +using LINGYUN.Abp.Rules; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.AutoMapper; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.RulesEngine +{ + [DependsOn( + typeof(AbpRulesEngineModule), + typeof(AbpAutoMapperModule))] + public class AbpMsRulesEngineModule : AbpModule + { + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddAutoMapperObjectMapper(); + Configure(options => + { + options.AddProfile(validate: true); + }); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsEntityRuleContributor.cs b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsEntityRuleContributor.cs new file mode 100644 index 000000000..b59b621bb --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsEntityRuleContributor.cs @@ -0,0 +1,50 @@ +using LINGYUN.Abp.Rules; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using RulesEngine.Extensions; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.ObjectMapping; +using MsRulesEngine = RulesEngine.RulesEngine; +using MsWorkflowRules = RulesEngine.Models.WorkflowRules; + +namespace LINGYUN.Abp.RulesEngine +{ + [Dependency(ServiceLifetime.Transient, ReplaceServices = true)] + [ExposeServices(typeof(IEntityRuleContributor))] + public class MsEntityRuleContributor : IEntityRuleContributor + { + protected ILogger Logger { get; } + protected IObjectMapper ObjectMapper { get; } + public MsEntityRuleContributor( + IObjectMapper objectMapper, + ILogger logger) + { + Logger = logger; + ObjectMapper = objectMapper; + } + + public Task ApplyAsync(EntityRuleContext context) + { + var workflowRules = ObjectMapper.Map, List>(context.Groups); + + var rulesEngine = new MsRulesEngine(workflowRules.ToArray(), Logger); + + foreach(var workflow in workflowRules) + { + var ruleRsults = rulesEngine.ExecuteRule(workflow.WorkflowName, context.Entity); + ruleRsults.OnSuccess((eventName) => + { + Logger.LogDebug($"{workflow.WorkflowName} evaluation resulted in succees - {eventName}"); + }); + ruleRsults.OnFail(() => + { + Logger.LogWarning($"{workflow.WorkflowName} evaluation resulted in failure"); + }); + } + + return Task.CompletedTask; + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsRulesEngineMapperProfile.cs b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsRulesEngineMapperProfile.cs new file mode 100644 index 000000000..deffe9a2f --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/LINGYUN/Abp/RulesEngine/MsRulesEngineMapperProfile.cs @@ -0,0 +1,27 @@ +using AutoMapper; +using LINGYUN.Abp.Rules; +using MsExpressionType = RulesEngine.Models.RuleExpressionType; +using MsRule = RulesEngine.Models.Rule; +using MsRuleErrorType = RulesEngine.Models.ErrorType; +using MsRuleParam = RulesEngine.Models.LocalParam; +using MsWorkflowRules = RulesEngine.Models.WorkflowRules; + +namespace LINGYUN.Abp.RulesEngine +{ + public class MsRulesEngineMapperProfile : Profile + { + public MsRulesEngineMapperProfile() + { + CreateMap(); + CreateMap() + .ForMember(r => r.LocalParams, map => map.MapFrom(m => m.Params)) + .ForMember(r => r.WorkflowRulesToInject, map => map.MapFrom(m => m.InjectRules)) + .ForMember(r => r.ErrorType, map => map.MapFrom(m => (MsRuleErrorType)m.ErrorType.GetHashCode())) + .ForMember(r => r.RuleExpressionType, map => map.MapFrom(m => (MsExpressionType)m.ExpressionType.GetHashCode())); + CreateMap() + .ForMember(wr => wr.WorkflowName, map => map.MapFrom(m => m.Name)) + .ForMember(wr => wr.Rules, map => map.MapFrom(m => m.Rules)) + .ForMember(wr => wr.WorkflowRulesToInject, map => map.MapFrom(m => m.InjectRules)); + } + } +} diff --git a/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/README.md b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/README.md new file mode 100644 index 000000000..b50241c85 --- /dev/null +++ b/aspnet-core/modules/common/LINGYUN.Abp.RulesEngine/README.md @@ -0,0 +1,7 @@ +# LINGYUN.Abp.RulesEngine + +规则引擎 [microsoft/RulesEngine](https://github.com/microsoft/RulesEngine) (RulesEngine) 实现 + +## 配置使用 + +待完善 \ No newline at end of file diff --git a/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db b/aspnet-core/services/apigateway/LINGYUN.ApiGateway.Host/event-bus-cap.db index 5eb62e8538e51e6f1a1a16a7f1d0c18f3bf45561..cf34328b79d32a17a79c28167582b02a6a21d143 100644 GIT binary patch delta 227 zcmZo@U}|V!njp>V$-uzC0maM{HOv`3Hzq9L=i>zmF$gd)a4LY{W* zU)gC@3mDjd90wu&$8tu$7BH{^ImSZzkAC@BEnomz!=MJ_e2M^an1LM0&9C*v6!^Kb v8CaMcfDU52%F@N;uvs7=nj5GV=#>2E86uoaK$Rdv**7*SF>N*~I>!qD$+I&@ delta 230 zcmZo@U}|V!njp>V#=yY90mY0HHOv{^HYP0K=VJv5G4lTgk__zpzc=#<2yt#!i1cP+ zX>n)b*_%=4uRK&){#s7tYjei*f|8xFZ{Ac+O@NeEMq%eiwm4}&) zQAq!FUkeymA)H6Qe5@8Qus}JVB7hub5NGpieK7@o s-mMI*Ob!g(*_;Y&S6R9?3j{=S!yGh2gcIyokb^fiDlu&~Dmupt0C*cU>;M1& diff --git a/docker-compose.yml b/docker-compose.yml index 40e2c449e..95ccac15d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -67,10 +67,7 @@ services: abp-vue-admin-client: build: - context: ./vueJs - volumes: - - /var/opt/abp/data/client/nginx:/etc/nginx/nginx.conf - - /var/opt/abp/data/client/nginx/conf.d:/etc/nginx/conf.d/default.conf + context: ./aspnet-core/services/Publish/client restart: always volumes: diff --git a/vueJs/src/api/auditing.ts b/vueJs/src/api/auditing.ts index 5cd00a57d..5b5590718 100644 --- a/vueJs/src/api/auditing.ts +++ b/vueJs/src/api/auditing.ts @@ -9,7 +9,7 @@ export default class AuditingService { const _url = '/api/auditing/audit-log/' + id return ApiService.Get(_url, serviceUrl) } - + public static getAuditLogs(payload: AuditLogGetPaged) { let _url = '/api/auditing/audit-log?' payload.skipCount = abpPagerFormat(payload.skipCount, payload.maxResultCount) diff --git a/vueJs/src/views/admin/auditing/audit-log/index.vue b/vueJs/src/views/admin/auditing/audit-log/index.vue index 242977f92..c9f39dfc4 100644 --- a/vueJs/src/views/admin/auditing/audit-log/index.vue +++ b/vueJs/src/views/admin/auditing/audit-log/index.vue @@ -125,7 +125,7 @@