47 changed files with 6706 additions and 65 deletions
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<FeatureDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticFeatures = await StaticStore.GetFeaturesAsync(); |
||||
|
var dynamicFeatures = await DynamicStore.GetFeaturesAsync(); |
||||
|
|
||||
|
var mergedFeatures = new Dictionary<string, FeatureDefinition>(); |
||||
|
|
||||
|
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<IReadOnlyList<FeatureGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await StaticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await DynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, FeatureGroupDefinition>(); |
||||
|
|
||||
|
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<FeatureDefinition> 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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<PermissionGroupDefinition>> GetGroupsAsync() |
||||
|
{ |
||||
|
var staticGroups = await _staticStore.GetGroupsAsync(); |
||||
|
var dynamicGroups = await _dynamicStore.GetGroupsAsync(); |
||||
|
|
||||
|
var mergedGroups = new Dictionary<string, PermissionGroupDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
@ -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<IReadOnlyList<SettingDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticSettings = await _staticStore.GetAllAsync(); |
||||
|
var dynamicSettings = await _dynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedSettings = new Dictionary<string, SettingDefinition>(); |
||||
|
|
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -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<IReadOnlyList<TemplateDefinition>> GetAllAsync() |
||||
|
{ |
||||
|
var staticTemplates = await StaticStore.GetAllAsync(); |
||||
|
var dynamicTemplates = await DynamicStore.GetAllAsync(); |
||||
|
|
||||
|
var mergedTemplates = new Dictionary<string, TemplateDefinition>(); |
||||
|
|
||||
|
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; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue