From 0a677cbcd8d758b2d32ca21871d7fb9b4dcfb090 Mon Sep 17 00:00:00 2001 From: colin Date: Fri, 7 Aug 2026 11:24:44 +0800 Subject: [PATCH] feat: Merge static and dynamic definition --- .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../appsettings.Development.json | 31 ++- .../appsettings.json | 103 +++---- .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../MergeFeatureDefinitionManager.cs | 254 ++++++++++++++++++ .../MergePermissionDefinitionManager.cs | 188 +++++++++++++ .../MergeSettingDefinitionManager.cs | 73 +++++ .../MergeTemplateDefinitionManager.cs | 86 ++++++ .../Aliyun/AbpBlobStoringAliyunTestModule.cs | 26 +- 47 files changed, 6706 insertions(+), 65 deletions(-) create mode 100644 aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs create mode 100644 aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs create mode 100644 aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs create mode 100644 aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs create mode 100644 aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.Applications.Single/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.AuthServer/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.AuthServer/appsettings.Development.json b/aspnet-core/services/LY.MicroService.AuthServer/appsettings.Development.json index 71a38fe74..dda64ee4b 100644 --- a/aspnet-core/services/LY.MicroService.AuthServer/appsettings.Development.json +++ b/aspnet-core/services/LY.MicroService.AuthServer/appsettings.Development.json @@ -177,19 +177,26 @@ }, "WriteTo": [ { - "Name": "Console", + "Name": "Async", "Args": { - "restrictedToMinimumLevel": "Debug", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" - } - }, - { - "Name": "Elasticsearch", - "Args": { - "nodeUris": "http://localhost:9200", - "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", - "autoRegisterTemplate": true, - "autoRegisterTemplateVersion": "ESv7" + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Elasticsearch", + "Args": { + "nodeUris": "http://localhost:9200", + "indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}", + "autoRegisterTemplate": true, + "autoRegisterTemplateVersion": "ESv7" + } + } + ] } } ] diff --git a/aspnet-core/services/LY.MicroService.AuthServer/appsettings.json b/aspnet-core/services/LY.MicroService.AuthServer/appsettings.json index baa0334c7..a8b5a668e 100644 --- a/aspnet-core/services/LY.MicroService.AuthServer/appsettings.json +++ b/aspnet-core/services/LY.MicroService.AuthServer/appsettings.json @@ -38,55 +38,62 @@ "Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName", "WithUniqueId" ], "WriteTo": [ { - "Name": "Console", + "Name": "Async", "Args": { - "restrictedToMinimumLevel": "Debug", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" - } - }, - { - "Name": "File", - "Args": { - "path": "Logs/Debug-.log", - "restrictedToMinimumLevel": "Debug", - "rollingInterval": "Day", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" - } - }, - { - "Name": "File", - "Args": { - "path": "Logs/Info-.log", - "restrictedToMinimumLevel": "Information", - "rollingInterval": "Day", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" - } - }, - { - "Name": "File", - "Args": { - "path": "Logs/Warn-.log", - "restrictedToMinimumLevel": "Warning", - "rollingInterval": "Day", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" - } - }, - { - "Name": "File", - "Args": { - "path": "Logs/Error-.log", - "restrictedToMinimumLevel": "Error", - "rollingInterval": "Day", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" - } - }, - { - "Name": "File", - "Args": { - "path": "Logs/Fatal-.log", - "restrictedToMinimumLevel": "Fatal", - "rollingInterval": "Day", - "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + "configure": [ + { + "Name": "Console", + "Args": { + "restrictedToMinimumLevel": "Debug", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Debug-.log", + "restrictedToMinimumLevel": "Debug", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Info-.log", + "restrictedToMinimumLevel": "Information", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Warn-.log", + "restrictedToMinimumLevel": "Warning", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Error-.log", + "restrictedToMinimumLevel": "Error", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "File", + "Args": { + "path": "Logs/Fatal-.log", + "restrictedToMinimumLevel": "Fatal", + "rollingInterval": "Day", + "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}" + } + } + ] } } ] diff --git a/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.LocalizationManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.PlatformManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.TaskManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WebhooksManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs new file mode 100644 index 000000000..887001b2f --- /dev/null +++ b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeFeatureDefinitionManager.cs @@ -0,0 +1,254 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Features; + +[Dependency(ReplaceServices = true)] +public class MergeFeatureDefinitionManager : FeatureDefinitionManager +{ + public MergeFeatureDefinitionManager( + IStaticFeatureDefinitionStore staticStore, + IDynamicFeatureDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + + public async override Task> GetAllAsync() + { + var staticFeatures = await StaticStore.GetFeaturesAsync(); + var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); + + var mergedFeatures = new Dictionary(); + + foreach (var staticFeature in staticFeatures) + { + mergedFeatures[staticFeature.Name] = staticFeature; + } + + foreach (var dynamicFeature in dynamicFeatures) + { + if (mergedFeatures.TryGetValue(dynamicFeature.Name, out var existingFeature)) + { + MergeFeatureMetadata(existingFeature, dynamicFeature); + + foreach (var child in dynamicFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + else + { + mergedFeatures[dynamicFeature.Name] = dynamicFeature; + } + } + + return mergedFeatures.Values.ToImmutableList(); + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await StaticStore.GetGroupsAsync(); + var dynamicGroups = await DynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupFeatures(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupFeatures(FeatureGroupDefinition target, FeatureGroupDefinition source) + { + foreach (var sourceFeature in source.Features) + { + var existingFeature = GetFeatureOrNull(target, sourceFeature.Name); + + if (existingFeature == null) + { + var newFeature = target.AddFeature( + sourceFeature.Name, + sourceFeature.DefaultValue, + sourceFeature.DisplayName, + sourceFeature.Description, + sourceFeature.ValueType, + sourceFeature.IsVisibleToClients, + sourceFeature.IsAvailableToHost + ); + + CopyFeatureDetails(sourceFeature, newFeature); + + foreach (var child in sourceFeature.Children) + { + AddChildFeatureRecursively(newFeature, child); + } + } + else + { + MergeFeatureMetadata(existingFeature, sourceFeature); + + foreach (var child in sourceFeature.Children) + { + MergeChildFeature(existingFeature, child); + } + } + } + } + + private static void AddChildFeatureRecursively(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + + private static void MergeChildFeature(FeatureDefinition parent, FeatureDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.CreateChild( + sourceChild.Name, + sourceChild.DefaultValue, + sourceChild.DisplayName, + sourceChild.Description, + sourceChild.ValueType, + sourceChild.IsVisibleToClients, + sourceChild.IsAvailableToHost + ); + CopyFeatureDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildFeatureRecursively(newChild, grandchild); + } + } + else + { + MergeFeatureMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildFeature(existingChild, grandchild); + } + } + } + + private static void CopyFeatureDetails(FeatureDefinition source, FeatureDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + } + + private static void MergeFeatureMetadata(FeatureDefinition target, FeatureDefinition source) + { + if (source.DisplayName != null) + { + target.DisplayName = source.DisplayName; + } + + if (source.Description != null) + { + target.Description = source.Description; + } + + if (source.DefaultValue != null) + { + target.DefaultValue = source.DefaultValue; + } + + if (source.ValueType != null) + { + target.ValueType = source.ValueType; + } + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.AllowedProviders) + { + if (!target.AllowedProviders.Contains(provider)) + { + target.AllowedProviders.Add(provider); + } + } + + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsAvailableToHost = target.IsAvailableToHost || source.IsAvailableToHost; + } + + + public static FeatureDefinition GetFeatureOrNull( + FeatureGroupDefinition group, + [NotNull] string name) + { + Check.NotNull(name, nameof(name)); + + return GetFeatureOrNullRecursively(group.Features, name); + } + + private static FeatureDefinition GetFeatureOrNullRecursively( + IReadOnlyList features, + string name) + { + foreach (var feature in features) + { + if (feature.Name == name) + { + return feature; + } + + var childFeature = GetFeatureOrNullRecursively(feature.Children, name); + if (childFeature != null) + { + return childFeature; + } + } + + return null; + } +} diff --git a/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs new file mode 100644 index 000000000..68b34e48b --- /dev/null +++ b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergePermissionDefinitionManager.cs @@ -0,0 +1,188 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace Volo.Abp.Authorization.Permissions; + +[Dependency(ReplaceServices = true)] +public class MergePermissionDefinitionManager : PermissionDefinitionManager +{ + private readonly IStaticPermissionDefinitionStore _staticStore; + private readonly IDynamicPermissionDefinitionStore _dynamicStore; + + public MergePermissionDefinitionManager( + IStaticPermissionDefinitionStore staticStore, + IDynamicPermissionDefinitionStore dynamicStore) : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetGroupsAsync() + { + var staticGroups = await _staticStore.GetGroupsAsync(); + var dynamicGroups = await _dynamicStore.GetGroupsAsync(); + + var mergedGroups = new Dictionary(); + + foreach (var staticGroup in staticGroups) + { + mergedGroups[staticGroup.Name] = staticGroup; + } + + foreach (var dynamicGroup in dynamicGroups) + { + if (mergedGroups.TryGetValue(dynamicGroup.Name, out var existingGroup)) + { + MergeGroupPermissions(existingGroup, dynamicGroup); + } + else + { + mergedGroups[dynamicGroup.Name] = dynamicGroup; + } + } + + return mergedGroups.Values.ToImmutableList(); + } + + private static void MergeGroupPermissions(PermissionGroupDefinition target, PermissionGroupDefinition source) + { + foreach (var sourcePermission in source.Permissions) + { + var existingPermission = target.GetPermissionOrNull(sourcePermission.Name); + + if (existingPermission == null) + { + var newPermission = target.AddPermission( + sourcePermission.Name, + sourcePermission.DisplayName, + sourcePermission.MultiTenancySide, + sourcePermission.IsEnabled + ); + + CopyPermissionDetails(sourcePermission, newPermission); + + foreach (var child in sourcePermission.Children) + { + AddChildPermissionRecursively(newPermission, child); + } + } + else + { + MergePermissionMetadata(existingPermission, sourcePermission); + + foreach (var sourceChild in sourcePermission.Children) + { + MergeChildPermissions(existingPermission, sourceChild); + } + } + } + } + + private static void AddChildPermissionRecursively(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + + private static void MergeChildPermissions(PermissionDefinition parent, PermissionDefinition sourceChild) + { + var existingChild = parent.Children.FirstOrDefault(c => c.Name == sourceChild.Name); + + if (existingChild == null) + { + var newChild = parent.AddChild( + sourceChild.Name, + sourceChild.DisplayName, + sourceChild.MultiTenancySide, + sourceChild.IsEnabled + ); + CopyPermissionDetails(sourceChild, newChild); + + foreach (var grandchild in sourceChild.Children) + { + AddChildPermissionRecursively(newChild, grandchild); + } + } + else + { + MergePermissionMetadata(existingChild, sourceChild); + + foreach (var grandchild in sourceChild.Children) + { + MergeChildPermissions(existingChild, grandchild); + } + } + } + + private static void CopyPermissionDetails(PermissionDefinition source, PermissionDefinition target) + { + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + } + + private static void MergePermissionMetadata(PermissionDefinition target, PermissionDefinition source) + { + target.DisplayName = source.DisplayName; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + + foreach (var checker in source.StateCheckers) + { + if (!target.StateCheckers.Contains(checker)) + { + target.StateCheckers.Add(checker); + } + } + + if (source.MultiTenancySide != MultiTenancySides.Both) + { + target.MultiTenancySide |= source.MultiTenancySide; + } + + target.IsEnabled = target.IsEnabled || source.IsEnabled; + } +} \ No newline at end of file diff --git a/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs new file mode 100644 index 000000000..c3c479f4f --- /dev/null +++ b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeSettingDefinitionManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Settings; + +[Dependency(ReplaceServices = true)] +public class MergeSettingDefinitionManager : SettingDefinitionManager +{ + private readonly IStaticSettingDefinitionStore _staticStore; + private readonly IDynamicSettingDefinitionStore _dynamicStore; + + public MergeSettingDefinitionManager( + IStaticSettingDefinitionStore staticStore, + IDynamicSettingDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + _staticStore = staticStore; + _dynamicStore = dynamicStore; + } + + public async override Task> GetAllAsync() + { + var staticSettings = await _staticStore.GetAllAsync(); + var dynamicSettings = await _dynamicStore.GetAllAsync(); + + var mergedSettings = new Dictionary(); + + foreach (var staticSetting in staticSettings) + { + mergedSettings[staticSetting.Name] = staticSetting; + } + + foreach (var dynamicSetting in dynamicSettings) + { + if (mergedSettings.TryGetValue(dynamicSetting.Name, out var existingSetting)) + { + MergeSetting(existingSetting, dynamicSetting); + } + else + { + mergedSettings[dynamicSetting.Name] = dynamicSetting; + } + } + + return mergedSettings.Values.ToImmutableList(); + } + + private static void MergeSetting(SettingDefinition target, SettingDefinition source) + { + target.DisplayName = source.DisplayName; + target.Description = source.Description ?? target.Description; + target.DefaultValue = source.DefaultValue ?? target.DefaultValue; + target.IsVisibleToClients = target.IsVisibleToClients || source.IsVisibleToClients; + target.IsInherited = target.IsInherited || source.IsInherited; + target.IsEncrypted = target.IsEncrypted || source.IsEncrypted; + + foreach (var property in source.Properties) + { + target.Properties[property.Key] = property.Value; + } + + foreach (var provider in source.Providers) + { + if (!target.Providers.Contains(provider)) + { + target.Providers.Add(provider); + } + } + } +} + diff --git a/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs new file mode 100644 index 000000000..0a45a8908 --- /dev/null +++ b/aspnet-core/templates/micro/content/host/PackageName.CompanyName.ProjectName.HttpApi.Host/Overrides/MergeTemplateDefinitionManager.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace Volo.Abp.TextTemplatin; + + +[Dependency(ReplaceServices = true)] +public class MergeTemplateDefinitionManager : TemplateDefinitionManager +{ + public MergeTemplateDefinitionManager( + IStaticTemplateDefinitionStore staticStore, + IDynamicTemplateDefinitionStore dynamicStore) + : base(staticStore, dynamicStore) + { + } + public async override Task> GetAllAsync() + { + var staticTemplates = await StaticStore.GetAllAsync(); + var dynamicTemplates = await DynamicStore.GetAllAsync(); + + var mergedTemplates = new Dictionary(); + + foreach (var staticTemplate in staticTemplates) + { + mergedTemplates[staticTemplate.Name] = staticTemplate; + } + + foreach (var dynamicTemplate in dynamicTemplates) + { + if (mergedTemplates.TryGetValue(dynamicTemplate.Name, out var existingTemplate)) + { + MergeTemplate(existingTemplate, dynamicTemplate); + } + else + { + mergedTemplates[dynamicTemplate.Name] = dynamicTemplate; + } + } + + return mergedTemplates.Values.ToImmutableList(); + } + + private static TemplateDefinition MergeTemplate(TemplateDefinition staticTemplate, TemplateDefinition dynamicTemplate) + { + var localizationResourceName = dynamicTemplate.LocalizationResourceName ?? staticTemplate.LocalizationResourceName; + var defaultCultureName = dynamicTemplate.DefaultCultureName ?? staticTemplate.DefaultCultureName; + var displayName = dynamicTemplate.DisplayName ?? staticTemplate.DisplayName; + var isLayout = dynamicTemplate.IsLayout || staticTemplate.IsLayout; + var layout = dynamicTemplate.Layout ?? staticTemplate.Layout; + + var mergedTemplate = new TemplateDefinition( + staticTemplate.Name, + localizationResourceName, + displayName, + isLayout, + layout, + defaultCultureName + ); + + foreach (var property in staticTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + foreach (var property in dynamicTemplate.Properties) + { + mergedTemplate.Properties[property.Key] = property.Value; + } + + if (!string.IsNullOrEmpty(dynamicTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = dynamicTemplate.RenderEngine; + } + else if (!string.IsNullOrEmpty(staticTemplate.RenderEngine)) + { + mergedTemplate.RenderEngine = staticTemplate.RenderEngine; + } + + mergedTemplate.IsInlineLocalized = dynamicTemplate.IsInlineLocalized || staticTemplate.IsInlineLocalized; + + return mergedTemplate; + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs index 7fa0456e7..8cfe76bac 100644 --- a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN/Abp/BlobStoring/Aliyun/AbpBlobStoringAliyunTestModule.cs @@ -1,13 +1,16 @@ -using Aliyun.OSS; +using AlibabaCloud.OSS.V2; +using AlibabaCloud.OSS.V2.Credentials; using LINGYUN.Abp.Aliyun; using LINGYUN.Abp.Aliyun.Settings; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.Autofac; using Volo.Abp.BlobStoring; using Volo.Abp.Modularity; using Volo.Abp.Security.Encryption; +using Volo.Abp.Threading; namespace LINGYUN.Abp.BlobStoring.Aliyun { @@ -42,13 +45,26 @@ namespace LINGYUN.Abp.BlobStoring.Aliyun _accessKeySecret = encryptionService.Decrypt(_configuration["Settings:" + AliyunSettingNames.Authorization.AccessKeySecret]); } - public override void OnApplicationShutdown(ApplicationShutdownContext context) + public async override Task OnApplicationShutdownAsync(ApplicationShutdownContext context) { - var ossClient = new OssClient(_endPoint, _accessKeyId, _accessKeySecret); - if (ossClient.DoesBucketExist(_bucketName)) + var ossClient = new Client( + new Configuration + { + Endpoint = _endPoint, + CredentialsProvider = new StaticCredentialsProvider(_accessKeyId, _accessKeySecret), + }); + if (await ossClient.IsBucketExistAsync(_bucketName)) { - ossClient.DeleteBucket(_bucketName); + await ossClient.DeleteBucketAsync(new AlibabaCloud.OSS.V2.Models.DeleteBucketRequest + { + Bucket = _bucketName, + }); } } + + public override void OnApplicationShutdown(ApplicationShutdownContext context) + { + AsyncHelper.RunSync(async () => await OnApplicationShutdownAsync(context)); + } } }