diff --git a/src/Framework.SecuritySystem.Abstract/Expanders/ISecurityRuleExpander.cs b/src/Framework.SecuritySystem.Abstract/Expanders/ISecurityRuleExpander.cs index fab9bb2a5..eeab77106 100644 --- a/src/Framework.SecuritySystem.Abstract/Expanders/ISecurityRuleExpander.cs +++ b/src/Framework.SecuritySystem.Abstract/Expanders/ISecurityRuleExpander.cs @@ -9,5 +9,5 @@ public interface ISecurityRuleExpander : ISecurityModeExpander, { DomainSecurityRule.ExpandedRolesSecurityRule FullRoleExpand(DomainSecurityRule.RoleBaseSecurityRule securityRule); - DomainSecurityRule FullDomainExpand(DomainSecurityRule securityRule); + DomainSecurityRule FullDomainExpand(DomainSecurityRule securityRule, SecurityRuleExpandSettings? settings = null); } diff --git a/src/Framework.SecuritySystem.Abstract/Expanders/SecurityModeExpanderExtensions.cs b/src/Framework.SecuritySystem.Abstract/Expanders/SecurityModeExpanderExtensions.cs index da3e428a4..2ed331519 100644 --- a/src/Framework.SecuritySystem.Abstract/Expanders/SecurityModeExpanderExtensions.cs +++ b/src/Framework.SecuritySystem.Abstract/Expanders/SecurityModeExpanderExtensions.cs @@ -9,4 +9,9 @@ public static DomainSecurityRule Expand(this ISecurityModeExpander expander, Dom nameof(securityRule), $"{nameof(SecurityRule)} with mode '{securityRule}' not found for type '{securityRule.DomainType.Name}'"); } + + public static DomainSecurityRule? TryExpand(this ISecurityModeExpander expander, SecurityRule.ModeSecurityRule securityRule) + { + return expander.TryExpand(securityRule.ToDomain()); + } } diff --git a/src/Framework.SecuritySystem.Abstract/Expanders/SecurityRuleExpandSettings.cs b/src/Framework.SecuritySystem.Abstract/Expanders/SecurityRuleExpandSettings.cs new file mode 100644 index 000000000..1d78447bb --- /dev/null +++ b/src/Framework.SecuritySystem.Abstract/Expanders/SecurityRuleExpandSettings.cs @@ -0,0 +1,13 @@ +using Framework.Core; + +namespace Framework.SecuritySystem.Expanders; + +public record SecurityRuleExpandSettings(DeepEqualsCollection IgnoredTypes) +{ + public SecurityRuleExpandSettings(IEnumerable ignoredTypes) + : this(DeepEqualsCollection.Create(ignoredTypes)) + { + } + + public static SecurityRuleExpandSettings Disabled { get; } = new(new[] { typeof(SecurityRule) }); +} diff --git a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceBuilder.cs b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceBuilder.cs index 7ca33ebe7..0e43dea33 100644 --- a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceBuilder.cs +++ b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceBuilder.cs @@ -2,23 +2,24 @@ using Framework.Core; using Framework.Persistent; +using Framework.SecuritySystem.ProviderFactories; using Framework.SecuritySystem.SecurityRuleInfo; using Microsoft.Extensions.DependencyInjection; namespace Framework.SecuritySystem.DependencyInjection.DomainSecurityServiceBuilder; -public abstract class DomainSecurityServiceBuilder : IDomainSecurityServiceBuilder +public abstract class DomainSecurityServiceBuilder { public abstract Type DomainType { get; } - public abstract void Register(IServiceCollection services); + public abstract void Register(IServiceCollection services, bool addSelfRelativePath); } internal class DomainSecurityServiceBuilder : DomainSecurityServiceBuilder, IDomainSecurityServiceBuilder where TDomainObject : IIdentityObject { - private readonly List functorTypes = []; + private readonly List injectorTypes = []; private readonly Dictionary domainObjectSecurityDict = []; @@ -28,11 +29,11 @@ internal class DomainSecurityServiceBuilder : DomainSecurityServi private Type? customServiceType; - private Type? dependencyServiceType; + private Type? dependencyInjectorType; public override Type DomainType { get; } = typeof(TDomainObject); - public override void Register(IServiceCollection services) + public override void Register(IServiceCollection services, bool addSelfRelativePath) { foreach (var (modeSecurityRule, implementedSecurityRule) in this.domainObjectSecurityDict) { @@ -49,50 +50,12 @@ public override void Register(IServiceCollection services) services.AddSingleton(pair.Type, pair.Instance); } - foreach (var (decl, impl) in this.GetRegisterDomainSecurityService()) + if (addSelfRelativePath) { - if (decl == null) - { - services.AddScoped(impl); - } - else - { - services.AddScoped(decl, impl); - } + services.AddSingleton, SelfRelativeDomainPathInfo>(); } - } - - private IEnumerable<(Type? Decl, Type Impl)> GetRegisterDomainSecurityService() - { - var baseServiceType = typeof(IDomainSecurityService); - - var actualCustomServiceType = this.customServiceType ?? this.dependencyServiceType; - - var functorTypeDecl = typeof(IOverrideSecurityProviderFunctor); - - var realFunctorTypes = this.functorTypes.Where(f => f.HasInterfaceMethodOverride(functorTypeDecl)).ToList(); - - if (realFunctorTypes.Any()) - { - foreach (var functorType in realFunctorTypes) - { - yield return (functorTypeDecl, functorType); - } - - var withFunctorActualCustomServiceType = actualCustomServiceType ?? typeof(ContextDomainSecurityService); - - yield return (null, withFunctorActualCustomServiceType); - - var withWrappedFunctorServiceType = typeof(DomainSecurityServiceWithFunctor<,>).MakeGenericType( - withFunctorActualCustomServiceType, - typeof(TDomainObject)); - yield return (baseServiceType, withWrappedFunctorServiceType); - } - else if (actualCustomServiceType != null) - { - yield return (baseServiceType, actualCustomServiceType); - } + services.AddScoped(typeof(IDomainSecurityService), this.customServiceType ?? typeof(DomainSecurityService)); } public IDomainSecurityServiceBuilder SetMode(SecurityRule.ModeSecurityRule modeSecurityRule, DomainSecurityRule implementedSecurityRule) @@ -111,6 +74,7 @@ public IDomainSecurityServiceBuilder SetPath(SecurityPath SetDependency() { + this.dependencyInjectorType = this.dependencyServiceType = typeof(DependencyDomainSecurityService); return this; @@ -142,8 +106,8 @@ public IDomainSecurityServiceBuilder SetCustomService Override() - where TSecurityFunctor : IOverrideSecurityProviderFunctor + public IDomainSecurityServiceBuilder AddInjector() + where TSecurityFunctor : ISecurityProviderInjector { this.functorTypes.Add(typeof(TSecurityFunctor)); diff --git a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceRootBuilder.cs b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceRootBuilder.cs index f164502ad..e7b7ed206 100644 --- a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceRootBuilder.cs +++ b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceRootBuilder.cs @@ -32,7 +32,7 @@ private IDomainSecurityServiceRootBuilder AddMetadataInternal where TDomainObject : IIdentityObject { - return this.AddInternal(b => b.Override().Pipe(TMetadata.Setup)); + return this.AddInternal(b => b.AddInjector().Pipe(TMetadata.Setup)); } private IDomainSecurityServiceRootBuilder AddInternal(Action> setup) @@ -51,14 +51,7 @@ public void Register(IServiceCollection services) { foreach (var domainBuilder in this.domainBuilders) { - domainBuilder.Register(services); - - if (this.AutoAddSelfRelativePath) - { - services.AddSingleton( - typeof(IRelativeDomainPathInfo<,>).MakeGenericType(domainBuilder.DomainType, domainBuilder.DomainType), - typeof(SelfRelativeDomainPathInfo<>).MakeGenericType(domainBuilder.DomainType)); - } + domainBuilder.Register(services, this.AutoAddSelfRelativePath); } } } diff --git a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceWithFunctor.cs b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceWithFunctor.cs deleted file mode 100644 index 6d13b0baf..000000000 --- a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/DomainSecurityServiceWithFunctor.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Framework.SecuritySystem.Expanders; - -namespace Framework.SecuritySystem.DependencyInjection.DomainSecurityServiceBuilder; - -public class DomainSecurityServiceWithFunctor( - ISecurityRuleExpander securityRuleExpander, - TOriginalDomainSecurityService originalDomainSecurityService, - IEnumerable> functorList) - : DomainSecurityService(securityRuleExpander) - where TOriginalDomainSecurityService : IDomainSecurityService -{ - protected override ISecurityProvider CreateSecurityProvider(SecurityRule.ModeSecurityRule securityRule) - { - var actualSecurityRule = (SecurityRule?)securityRuleExpander.TryExpand(securityRule.ToDomain()) ?? securityRule; - - var originalSecurityProvider = originalDomainSecurityService.GetSecurityProvider(actualSecurityRule); - - return functorList.Aggregate( - originalSecurityProvider, - (provider, functor) => functor.OverrideSecurityProvider(provider, securityRule)); - } - - protected override ISecurityProvider CreateSecurityProvider(DomainSecurityRule.OperationSecurityRule securityRule) - { - var originalSecurityProvider = originalDomainSecurityService.GetSecurityProvider(securityRule); - - return functorList.Aggregate( - originalSecurityProvider, - (provider, functor) => functor.OverrideSecurityProvider(provider, securityRule)); - } - - protected override ISecurityProvider CreateSecurityProvider(DomainSecurityRule.NonExpandedRolesSecurityRule securityRule) - { - var originalSecurityProvider = originalDomainSecurityService.GetSecurityProvider(securityRule); - - return functorList.Aggregate( - originalSecurityProvider, - (provider, functor) => functor.OverrideSecurityProvider(provider, securityRule)); - } - - protected override ISecurityProvider CreateSecurityProvider(DomainSecurityRule.ExpandedRolesSecurityRule securityRule) - { - var originalSecurityProvider = originalDomainSecurityService.GetSecurityProvider(securityRule); - - return functorList.Aggregate( - originalSecurityProvider, - (provider, functor) => functor.OverrideSecurityProvider(provider, securityRule)); - } - - protected override ISecurityProvider CreateFinalSecurityProvider(DomainSecurityRule securityRule) - { - return originalDomainSecurityService.GetSecurityProvider(securityRule); - } -} diff --git a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceBuilder.cs b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceBuilder.cs index 0991a85de..fb0072f9a 100644 --- a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceBuilder.cs +++ b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceBuilder.cs @@ -1,5 +1,7 @@ using System.Linq.Expressions; +using Framework.SecuritySystem.ProviderFactories; + using Microsoft.Extensions.DependencyInjection; namespace Framework.SecuritySystem.DependencyInjection.DomainSecurityServiceBuilder; @@ -39,11 +41,6 @@ public interface IDomainSecurityServiceBuilder IDomainSecurityServiceBuilder SetCustomService() where TDomainSecurityService : IDomainSecurityService; - IDomainSecurityServiceBuilder Override() - where TSecurityFunctor : IOverrideSecurityProviderFunctor; -} - -public interface IDomainSecurityServiceBuilder -{ - void Register(IServiceCollection services); + IDomainSecurityServiceBuilder AddInjector() + where TSecurityFunctor : ISecurityProviderInjector; } diff --git a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceMetadata.cs b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceMetadata.cs index a5af1816b..8f24a741f 100644 --- a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceMetadata.cs +++ b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IDomainSecurityServiceMetadata.cs @@ -1,6 +1,13 @@ -namespace Framework.SecuritySystem.DependencyInjection.DomainSecurityServiceBuilder; +using Framework.SecuritySystem.ProviderFactories; -public interface IDomainSecurityServiceMetadata : IDomainSecurityServiceMetadata, IOverrideSecurityProviderFunctor +namespace Framework.SecuritySystem.DependencyInjection.DomainSecurityServiceBuilder; + +public interface IDomainSecurityServiceMetadata : + IDomainSecurityServiceMetadata, + ISecurityProviderInjector, + ISecurityProviderInjector, + ISecurityProviderInjector, + ISecurityProviderInjector { static Type IDomainSecurityServiceMetadata.DomainType { get; } = typeof(TDomainObject); diff --git a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IOverrideSecurityProviderFunctor.cs b/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IOverrideSecurityProviderFunctor.cs deleted file mode 100644 index 1fb78ec5a..000000000 --- a/src/Framework.SecuritySystem/DependencyInjection/DomainSecurityServiceBuilder/IOverrideSecurityProviderFunctor.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Framework.SecuritySystem.DependencyInjection.DomainSecurityServiceBuilder; - -public interface IOverrideSecurityProviderFunctor -{ - ISecurityProvider OverrideSecurityProvider(ISecurityProvider baseProvider, SecurityRule.ModeSecurityRule securityRule) => baseProvider; - - ISecurityProvider OverrideSecurityProvider(ISecurityProvider baseProvider, DomainSecurityRule.OperationSecurityRule securityRule) => baseProvider; - - ISecurityProvider OverrideSecurityProvider(ISecurityProvider baseProvider, DomainSecurityRule.NonExpandedRolesSecurityRule securityRule) => baseProvider; - - ISecurityProvider OverrideSecurityProvider(ISecurityProvider baseProvider, DomainSecurityRule.ExpandedRolesSecurityRule securityRule) => baseProvider; -} diff --git a/src/Framework.SecuritySystem/DomainServices/ContextDomainSecurityService.cs b/src/Framework.SecuritySystem/DomainServices/ContextDomainSecurityService.cs deleted file mode 100644 index dece7d37c..000000000 --- a/src/Framework.SecuritySystem/DomainServices/ContextDomainSecurityService.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Framework.SecuritySystem.Expanders; -using Framework.SecuritySystem.Services; - -namespace Framework.SecuritySystem; - -public class ContextDomainSecurityService( - ISecurityRuleExpander securityRuleExpander, - IDomainSecurityProviderFactory domainSecurityProviderFactory, - SecurityPath? securityPath = null) - : DomainSecurityService(securityRuleExpander) -{ - protected virtual ISecurityProvider Create( - DomainSecurityRule securityRule, - SecurityPath customSecurityPath) => domainSecurityProviderFactory.Create(securityRule, customSecurityPath); - - protected override ISecurityProvider CreateFinalSecurityProvider(DomainSecurityRule securityRule) => - this.Create(securityRule, securityPath ?? SecurityPath.Empty); -} diff --git a/src/Framework.SecuritySystem/DomainServices/DependencySecurity/_Base/DependencyDomainSecurityServiceBase.cs b/src/Framework.SecuritySystem/DomainServices/DependencySecurity/_Base/DependencyDomainSecurityServiceBase.cs deleted file mode 100644 index b186a1342..000000000 --- a/src/Framework.SecuritySystem/DomainServices/DependencySecurity/_Base/DependencyDomainSecurityServiceBase.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Framework.SecuritySystem.Expanders; - -namespace Framework.SecuritySystem; - -public abstract class DependencyDomainSecurityServiceBase( - ISecurityRuleExpander securityRuleExpander, - IDomainSecurityService baseDomainSecurityService) - : DomainSecurityServiceBase -{ - protected override ISecurityProvider CreateSecurityProvider(SecurityRule securityRule) - { - if (securityRule is SecurityRule.ModeSecurityRule modeSecurityRule - && securityRuleExpander.TryExpand(modeSecurityRule.ToDomain()) is { } customSecurityRule) - { - return this.CreateSecurityProvider(customSecurityRule); - } - else - { - return this.CreateDependencySecurityProvider(baseDomainSecurityService.GetSecurityProvider(securityRule)); - } - } - - protected abstract ISecurityProvider CreateDependencySecurityProvider(ISecurityProvider baseProvider); -} diff --git a/src/Framework.SecuritySystem/DomainServices/DomainSecurityService.cs b/src/Framework.SecuritySystem/DomainServices/DomainSecurityService.cs index e041eab41..56f759b76 100644 --- a/src/Framework.SecuritySystem/DomainServices/DomainSecurityService.cs +++ b/src/Framework.SecuritySystem/DomainServices/DomainSecurityService.cs @@ -1,60 +1,15 @@ -using Framework.SecuritySystem.Expanders; - -using static Framework.SecuritySystem.DomainSecurityRule; +using Framework.SecuritySystem.Services; namespace Framework.SecuritySystem; -public abstract class DomainSecurityService(ISecurityRuleExpander securityRuleExpander) : DomainSecurityServiceBase +public class DomainSecurityService(IDomainSecurityProviderFactory domainSecurityProviderFactory) + : DomainSecurityServiceBase { - protected sealed override ISecurityProvider CreateSecurityProvider(SecurityRule baseSecurityRule) - { - switch (baseSecurityRule) - { - case SecurityRule.ModeSecurityRule securityRule: - return this.CreateSecurityProvider(securityRule); - - case DomainModeSecurityRule securityRule: - return this.CreateSecurityProvider(securityRuleExpander.Expand(securityRule)); - - case ClientSecurityRule securityRule: - return this.CreateSecurityProvider(securityRuleExpander.Expand(securityRule)); - - case OperationSecurityRule securityRule: - return this.CreateSecurityProvider(securityRule); - - case NonExpandedRolesSecurityRule securityRule: - return this.CreateSecurityProvider(securityRule); - - case ExpandedRolesSecurityRule securityRule: - return this.CreateSecurityProvider(securityRule); - - case DomainSecurityRule securityRule: - return this.CreateFinalSecurityProvider(securityRule); - - default: - throw new ArgumentOutOfRangeException(nameof(baseSecurityRule)); - } - } - - protected virtual ISecurityProvider CreateSecurityProvider(SecurityRule.ModeSecurityRule securityRule) - { - return this.GetSecurityProvider(securityRule.ToDomain()); - } - - protected virtual ISecurityProvider CreateSecurityProvider(OperationSecurityRule securityRule) - { - return this.GetSecurityProvider(securityRuleExpander.Expand(securityRule)); - } - - protected virtual ISecurityProvider CreateSecurityProvider(NonExpandedRolesSecurityRule securityRule) - { - return this.GetSecurityProvider(securityRuleExpander.Expand(securityRule)); - } - - protected virtual ISecurityProvider CreateSecurityProvider(ExpandedRolesSecurityRule securityRule) - { - return this.CreateFinalSecurityProvider(securityRule); - } + protected virtual ISecurityProvider CreateSecurityProvider( + SecurityRule securityRule, + SecurityPath? customSecurityPath) => + domainSecurityProviderFactory.Create(securityRule, customSecurityPath); - protected abstract ISecurityProvider CreateFinalSecurityProvider(DomainSecurityRule securityRule); + protected override ISecurityProvider CreateSecurityProvider(SecurityRule securityRule) => + this.CreateSecurityProvider(securityRule, null); } diff --git a/src/Framework.SecuritySystem/DomainServices/DomainSecurityServiceBase.cs b/src/Framework.SecuritySystem/DomainServices/DomainSecurityServiceBase.cs index 9482481ef..21d6d71d3 100644 --- a/src/Framework.SecuritySystem/DomainServices/DomainSecurityServiceBase.cs +++ b/src/Framework.SecuritySystem/DomainServices/DomainSecurityServiceBase.cs @@ -7,11 +7,11 @@ public abstract class DomainSecurityServiceBase : IDomainSecurity private readonly IDictionaryCache> providersCache; protected DomainSecurityServiceBase() => - this.providersCache = new DictionaryCache>(securityRule => - { - return this.CreateSecurityProvider(securityRule) - .OverrideAccessDeniedResult(accessDeniedResult => accessDeniedResult with { SecurityRule = securityRule }); - }).WithLock(); + this.providersCache = new DictionaryCache>( + securityRule => + this.CreateSecurityProvider(securityRule) + .OverrideAccessDeniedResult(accessDeniedResult => accessDeniedResult with { SecurityRule = securityRule })) + .WithLock(); protected abstract ISecurityProvider CreateSecurityProvider(SecurityRule securityRule); diff --git a/src/Framework.SecuritySystem/Expanders/RootSecurityRuleExpande.cs b/src/Framework.SecuritySystem/Expanders/RootSecurityRuleExpander.cs similarity index 85% rename from src/Framework.SecuritySystem/Expanders/RootSecurityRuleExpande.cs rename to src/Framework.SecuritySystem/Expanders/RootSecurityRuleExpander.cs index e013e7418..142e57ffd 100644 --- a/src/Framework.SecuritySystem/Expanders/RootSecurityRuleExpande.cs +++ b/src/Framework.SecuritySystem/Expanders/RootSecurityRuleExpander.cs @@ -71,14 +71,26 @@ public ExpandedRolesSecurityRule FullRoleExpand(RoleBaseSecurityRule securityRul } } - public DomainSecurityRule FullDomainExpand(DomainSecurityRule securityRule) + public DomainSecurityRule FullDomainExpand(DomainSecurityRule securityRule, SecurityRuleExpandSettings? settings = null) { - return new FullDomainExpandVisitor(this).Visit(securityRule); + return new FullDomainExpandVisitor(this, settings).Visit(securityRule); } - private class FullDomainExpandVisitor(ISecurityRuleExpander expander) + private class FullDomainExpandVisitor(ISecurityRuleExpander expander, SecurityRuleExpandSettings? settings) : SecurityRuleVisitor { + public override DomainSecurityRule Visit(DomainSecurityRule baseSecurityRule) + { + if (settings != null && settings.IgnoredTypes.Any(ignoredType => ignoredType.IsInstanceOfType(baseSecurityRule))) + { + return baseSecurityRule; + } + else + { + return base.Visit(baseSecurityRule); + } + } + protected override DomainSecurityRule Visit(RoleBaseSecurityRule baseSecurityRule) => expander.FullRoleExpand(baseSecurityRule); protected override DomainSecurityRule Visit(DomainModeSecurityRule securityRule) => this.Visit(expander.Expand(securityRule)); diff --git a/src/Framework.SecuritySystem/ProviderFactories/CurrentUserSecurityProviderFactory.cs b/src/Framework.SecuritySystem/ProviderFactories/CurrentUserSecurityProviderFactory.cs new file mode 100644 index 000000000..a2d601786 --- /dev/null +++ b/src/Framework.SecuritySystem/ProviderFactories/CurrentUserSecurityProviderFactory.cs @@ -0,0 +1,24 @@ +using Framework.Core; +using Framework.SecuritySystem.UserSource; + +using Microsoft.Extensions.DependencyInjection; + +namespace Framework.SecuritySystem.ProviderFactories; + +public class CurrentUserSecurityProviderFactory( + IServiceProvider serviceProvider) + : IDefaultSecurityProviderFactory +{ + public ISecurityProvider Create(DomainSecurityRule.CurrentUserSecurityRule securityRule, SecurityPath? securityPath) + { + var args = new object?[] + { + securityRule.RelativePathKey == null + ? null + : new CurrentUserSecurityProviderRelativeKey(securityRule.RelativePathKey) + }.Where(arg => arg != null) + .ToArray(arg => arg!); + + return ActivatorUtilities.CreateInstance>(serviceProvider, args); + } +} diff --git a/src/Framework.SecuritySystem/ProviderFactories/DependencyBaseSecurityProviderInjector.cs b/src/Framework.SecuritySystem/ProviderFactories/DependencyBaseSecurityProviderInjector.cs new file mode 100644 index 000000000..c8acf0f4d --- /dev/null +++ b/src/Framework.SecuritySystem/ProviderFactories/DependencyBaseSecurityProviderInjector.cs @@ -0,0 +1,32 @@ +using Framework.SecuritySystem.Expanders; + +namespace Framework.SecuritySystem.ProviderFactories; + +public abstract class + DependencyBaseSecurityProviderFactory( + ISecurityModeExpander securityRuleExpander, + IDomainSecurityService baseDomainSecurityService) + : IDefaultSecurityProviderFactory +{ + public bool AllowOptimize { get; } = false; + + public ISecurityProvider Create(SecurityRule securityRule, SecurityPath securityPath) + { + return this.CreateDependencySecurityProvider(baseDomainSecurityService.GetSecurityProvider(this.GetActualSecurityRule(securityRule))); + } + + public SecurityRule GetActualSecurityRule(SecurityRule securityRule) + { + if (securityRule is SecurityRule.ModeSecurityRule modeSecurityRule + && securityRuleExpander.TryExpand(modeSecurityRule) is { } customSecurityRule) + { + return customSecurityRule; + } + else + { + return securityRule; + } + } + + protected abstract ISecurityProvider CreateDependencySecurityProvider(ISecurityProvider baseProvider); +} diff --git a/src/Framework.SecuritySystem/ProviderFactories/IDefaultSecurityProviderFactory.cs b/src/Framework.SecuritySystem/ProviderFactories/IDefaultSecurityProviderFactory.cs new file mode 100644 index 000000000..d9be91fca --- /dev/null +++ b/src/Framework.SecuritySystem/ProviderFactories/IDefaultSecurityProviderFactory.cs @@ -0,0 +1,7 @@ +namespace Framework.SecuritySystem.ProviderFactories; + +public interface IDefaultSecurityProviderFactory : ISecurityProviderFactory + where TSecurityRule : SecurityRule +{ + bool AllowOptimize => true; +} diff --git a/src/Framework.SecuritySystem/ProviderFactories/ISecurityProviderFactory.cs b/src/Framework.SecuritySystem/ProviderFactories/ISecurityProviderFactory.cs new file mode 100644 index 000000000..947c8e6f3 --- /dev/null +++ b/src/Framework.SecuritySystem/ProviderFactories/ISecurityProviderFactory.cs @@ -0,0 +1,7 @@ +namespace Framework.SecuritySystem.ProviderFactories; + +public interface ISecurityProviderFactory + where TSecurityRule : SecurityRule +{ + ISecurityProvider Create(TSecurityRule securityRule, SecurityPath? customSecurityPath); +} diff --git a/src/Framework.SecuritySystem/ProviderFactories/ISecurityProviderInjector.cs b/src/Framework.SecuritySystem/ProviderFactories/ISecurityProviderInjector.cs new file mode 100644 index 000000000..9398cbc1a --- /dev/null +++ b/src/Framework.SecuritySystem/ProviderFactories/ISecurityProviderInjector.cs @@ -0,0 +1,15 @@ +namespace Framework.SecuritySystem.ProviderFactories; + +public interface ISecurityProviderInjector : ISecurityProviderInjector + where TSecurityRule : SecurityRule +{ + Type ISecurityProviderInjector.SecurityRuleType => typeof(TSecurityRule); + + + ISecurityProviderFactory Inject(ISecurityProviderFactory baseFactory) => baseFactory; +} + +public interface ISecurityProviderInjector +{ + Type SecurityRuleType { get; } +} diff --git a/src/Framework.SecuritySystem/ProviderFactories/RoleBaseSecurityProviderInjector.cs b/src/Framework.SecuritySystem/ProviderFactories/RoleBaseSecurityProviderInjector.cs new file mode 100644 index 000000000..9b97ad460 --- /dev/null +++ b/src/Framework.SecuritySystem/ProviderFactories/RoleBaseSecurityProviderInjector.cs @@ -0,0 +1,11 @@ +using Framework.SecuritySystem.Services; + +namespace Framework.SecuritySystem.ProviderFactories; + +public class RoleBaseSecurityProviderFactory( + IRoleBaseSecurityProviderFactory roleBaseSecurityProviderFactory) + : IDefaultSecurityProviderFactory +{ + public ISecurityProvider Create(DomainSecurityRule.RoleBaseSecurityRule securityRule, SecurityPath securityPath) => + roleBaseSecurityProviderFactory.Create(securityRule, securityPath); +} diff --git a/src/Framework.SecuritySystem/ProviderFactories/SecurityProviderFactory.cs b/src/Framework.SecuritySystem/ProviderFactories/SecurityProviderFactory.cs new file mode 100644 index 000000000..0e3a3bcda --- /dev/null +++ b/src/Framework.SecuritySystem/ProviderFactories/SecurityProviderFactory.cs @@ -0,0 +1,16 @@ +namespace Framework.SecuritySystem.ProviderFactories; + +public class SecurityProviderFactory( + Func, ISecurityProvider> createFunc) + : ISecurityProviderFactory + where TSecurityRule : SecurityRule +{ + public ISecurityProvider Create(TSecurityRule securityRule, SecurityPath securityPath) + { + return createFunc(securityRule, securityPath); + } + + public static ISecurityProviderFactory Create( + Func, ISecurityProvider> createFunc) => + new SecurityProviderFactory(createFunc); +} diff --git a/src/Framework.SecuritySystem/DomainServices/DependencySecurity/DependencyDomainSecurityService.cs b/src/Framework.SecuritySystem/ProviderFactories/TypedDependencySecurityProviderFactory.cs similarity index 64% rename from src/Framework.SecuritySystem/DomainServices/DependencySecurity/DependencyDomainSecurityService.cs rename to src/Framework.SecuritySystem/ProviderFactories/TypedDependencySecurityProviderFactory.cs index 9f8c48918..c0cc30232 100644 --- a/src/Framework.SecuritySystem/DomainServices/DependencySecurity/DependencyDomainSecurityService.cs +++ b/src/Framework.SecuritySystem/ProviderFactories/TypedDependencySecurityProviderFactory.cs @@ -1,16 +1,15 @@ using Framework.QueryableSource; using Framework.SecuritySystem.Expanders; -namespace Framework.SecuritySystem; +namespace Framework.SecuritySystem.ProviderFactories; -public class DependencyDomainSecurityService( - ISecurityRuleExpander securityRuleExpander, +public class TypedDependencySecurityProviderFactory( + ISecurityModeExpander securityRuleExpander, IDomainSecurityService baseDomainSecurityService, IQueryableSource queryableSource, IRelativeDomainPathInfo pathInfo) - : DependencyDomainSecurityServiceBase( - securityRuleExpander, - baseDomainSecurityService) + : DependencyBaseSecurityProviderFactory(securityRuleExpander, baseDomainSecurityService) { protected override ISecurityProvider CreateDependencySecurityProvider(ISecurityProvider baseProvider) { diff --git a/src/Framework.SecuritySystem/DomainServices/DependencySecurity/UntypedDependencyDomainSecurityService.cs b/src/Framework.SecuritySystem/ProviderFactories/UntypedDependencySecurityProviderInjector.cs similarity index 54% rename from src/Framework.SecuritySystem/DomainServices/DependencySecurity/UntypedDependencyDomainSecurityService.cs rename to src/Framework.SecuritySystem/ProviderFactories/UntypedDependencySecurityProviderInjector.cs index 9d6ec0268..44b9a3cbf 100644 --- a/src/Framework.SecuritySystem/DomainServices/DependencySecurity/UntypedDependencyDomainSecurityService.cs +++ b/src/Framework.SecuritySystem/ProviderFactories/UntypedDependencySecurityProviderInjector.cs @@ -2,17 +2,15 @@ using Framework.QueryableSource; using Framework.SecuritySystem.Expanders; -namespace Framework.SecuritySystem; +namespace Framework.SecuritySystem.ProviderFactories; -public class UntypedDependencyDomainSecurityService( - ISecurityRuleExpander securityRuleExpander, +public class UntypedDependencySecurityProviderFactory( + ISecurityModeExpander securityRuleExpander, IDomainSecurityService baseDomainSecurityService, IQueryableSource queryableSource) - : DependencyDomainSecurityServiceBase( - securityRuleExpander, - baseDomainSecurityService) - where TDomainObject : IIdentityObject - where TBaseDomainObject : class, IIdentityObject + : DependencyBaseSecurityProviderFactory(securityRuleExpander, baseDomainSecurityService) + where TDomainObject : IIdentityObject where TBaseDomainObject : class, IIdentityObject { protected override ISecurityProvider CreateDependencySecurityProvider(ISecurityProvider baseProvider) { diff --git a/src/Framework.SecuritySystem/Services/DomainSecurityProviderFactory.cs b/src/Framework.SecuritySystem/Services/DomainSecurityProviderFactory.cs deleted file mode 100644 index f7612c77a..000000000 --- a/src/Framework.SecuritySystem/Services/DomainSecurityProviderFactory.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System.Linq.Expressions; - -using Microsoft.Extensions.DependencyInjection; - -using Framework.Core; -using Framework.SecuritySystem.UserSource; - -using static Framework.SecuritySystem.DomainSecurityRule; - -namespace Framework.SecuritySystem.Services; - -public class DomainSecurityProviderFactory( - IServiceProvider serviceProvider, - ISecurityRuleDeepOptimizer deepOptimizer, - IRoleBaseSecurityProviderFactory roleBaseSecurityProviderFactory) : IDomainSecurityProviderFactory -{ - public virtual ISecurityProvider Create( - DomainSecurityRule securityRule, - SecurityPath securityPath) - { - return this.CreateInternal(deepOptimizer.Optimize(securityRule), securityPath); - } - - protected virtual ISecurityProvider CreateInternal( - DomainSecurityRule baseSecurityRule, - SecurityPath securityPath) - { - switch (baseSecurityRule) - { - case RoleBaseSecurityRule securityRule: - return roleBaseSecurityProviderFactory.Create(securityRule, securityPath); - - case CurrentUserSecurityRule securityRule: - { - var args = new object?[] - { - securityRule.RelativePathKey == null - ? null - : new CurrentUserSecurityProviderRelativeKey(securityRule.RelativePathKey) - }.Where(arg => arg != null) - .ToArray(arg => arg!); - - return ActivatorUtilities.CreateInstance>(serviceProvider, args); - } - - case ProviderSecurityRule securityRule: - { - var securityProviderType = - securityRule.GenericSecurityProviderType.MakeGenericType(typeof(TDomainObject)); - - var securityProvider = securityRule.Key == null - ? serviceProvider.GetRequiredService(securityProviderType) - : serviceProvider.GetRequiredKeyedService(securityProviderType, securityRule.Key); - - return (ISecurityProvider)securityProvider; - } - - case ProviderFactorySecurityRule securityRule: - { - var securityProviderFactoryType = - securityRule.GenericSecurityProviderFactoryType.MakeGenericType(typeof(TDomainObject)); - - var securityProviderFactoryUntyped = - securityRule.Key == null - ? serviceProvider.GetRequiredService(securityProviderFactoryType) - : serviceProvider.GetRequiredKeyedService(securityProviderFactoryType, securityRule.Key); - - var securityProviderFactory = (IFactory>)securityProviderFactoryUntyped; - - return securityProviderFactory.Create(); - } - - case ConditionFactorySecurityRule securityRule: - { - var conditionFactoryType = - securityRule.GenericConditionFactoryType.MakeGenericType(typeof(TDomainObject)); - - var conditionFactoryUntyped = serviceProvider.GetRequiredService(conditionFactoryType); - - var conditionFactory = (IFactory>>)conditionFactoryUntyped; - - return SecurityProvider.Create(conditionFactory.Create()); - } - - case RelativeConditionSecurityRule securityRule: - { - var conditionInfo = securityRule.RelativeConditionInfo; - - var factoryType = typeof(RequiredRelativeConditionFactory<,>).MakeGenericType( - typeof(TDomainObject), - conditionInfo.RelativeDomainObjectType); - - var untypedConditionFactory = ActivatorUtilities.CreateInstance(serviceProvider, factoryType, conditionInfo); - - var conditionFactory = (IFactory>>)untypedConditionFactory; - - var condition = conditionFactory.Create(); - - return SecurityProvider.Create(condition); - } - - case FactorySecurityRule securityRule: - { - var dynamicRoleFactoryUntyped = serviceProvider.GetRequiredService(securityRule.RuleFactoryType); - - var dynamicRoleFactory = (IFactory)dynamicRoleFactoryUntyped; - - return this.CreateInternal(dynamicRoleFactory.Create(), securityPath); - } - - case OverrideAccessDeniedMessageSecurityRule securityRule: - { - return this.CreateInternal(securityRule.BaseSecurityRule, securityPath) - .OverrideAccessDeniedResult( - accessDeniedResult => accessDeniedResult with { CustomMessage = securityRule.CustomMessage }); - } - - case OrSecurityRule securityRule: - return this.CreateInternal(securityRule.Left, securityPath).Or(this.CreateInternal(securityRule.Right, securityPath)); - - case AndSecurityRule securityRule: - return this.CreateInternal(securityRule.Left, securityPath).And(this.CreateInternal(securityRule.Right, securityPath)); - - case NegateSecurityRule securityRule: - return this.CreateInternal(securityRule.InnerRule, securityPath).Negate(); - - case DomainModeSecurityRule: - case SecurityRuleHeader: - case ClientSecurityRule: - throw new Exception("Must be optimized"); - - default: - throw new ArgumentOutOfRangeException(nameof(baseSecurityRule)); - } - } -} diff --git a/src/Framework.SecuritySystem/Services/IDomainSecurityProviderFactory.cs b/src/Framework.SecuritySystem/Services/IDomainSecurityProviderFactory.cs deleted file mode 100644 index ef44f19f3..000000000 --- a/src/Framework.SecuritySystem/Services/IDomainSecurityProviderFactory.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Framework.SecuritySystem.Services; - -public interface IDomainSecurityProviderFactory -{ - ISecurityProvider Create( - DomainSecurityRule securityRule, - SecurityPath securityPath); -} diff --git a/src/Framework.SecuritySystem/Services/IRootSecurityProviderFactory.cs b/src/Framework.SecuritySystem/Services/IRootSecurityProviderFactory.cs new file mode 100644 index 000000000..ba6bb0a91 --- /dev/null +++ b/src/Framework.SecuritySystem/Services/IRootSecurityProviderFactory.cs @@ -0,0 +1,5 @@ +using Framework.SecuritySystem.ProviderFactories; + +namespace Framework.SecuritySystem.Services; + +public interface IRootSecurityProviderFactory : ISecurityProviderFactory; diff --git a/src/Framework.SecuritySystem/Services/ISecurityRuleDeepOptimizer.cs b/src/Framework.SecuritySystem/Services/ISecurityRuleDeepOptimizer.cs index 2a5b4f7f6..7c6c1e676 100644 --- a/src/Framework.SecuritySystem/Services/ISecurityRuleDeepOptimizer.cs +++ b/src/Framework.SecuritySystem/Services/ISecurityRuleDeepOptimizer.cs @@ -1,6 +1,8 @@ -namespace Framework.SecuritySystem.Services; +using Framework.SecuritySystem.Expanders; + +namespace Framework.SecuritySystem.Services; public interface ISecurityRuleDeepOptimizer { - DomainSecurityRule Optimize(DomainSecurityRule securityRule); + DomainSecurityRule Optimize(DomainSecurityRule securityRule, SecurityRuleExpandSettings? settings = null); } diff --git a/src/Framework.SecuritySystem/Services/ISecurityRuleTypeResolver.cs b/src/Framework.SecuritySystem/Services/ISecurityRuleTypeResolver.cs new file mode 100644 index 000000000..d8911c832 --- /dev/null +++ b/src/Framework.SecuritySystem/Services/ISecurityRuleTypeResolver.cs @@ -0,0 +1,5 @@ +using Framework.Core; + +namespace Framework.SecuritySystem.Services; + +public interface ISecurityRuleTypeResolver : ITypeResolver; diff --git a/src/Framework.SecuritySystem/Services/RootSecurityProviderFactory.cs b/src/Framework.SecuritySystem/Services/RootSecurityProviderFactory.cs new file mode 100644 index 000000000..510f7e72b --- /dev/null +++ b/src/Framework.SecuritySystem/Services/RootSecurityProviderFactory.cs @@ -0,0 +1,210 @@ +using System.Linq.Expressions; + +using Microsoft.Extensions.DependencyInjection; + +using Framework.Core; +using Framework.SecuritySystem.UserSource; + +using static Framework.SecuritySystem.DomainSecurityRule; +using Framework.SecuritySystem.ProviderFactories; +using Framework.SecuritySystem.Expanders; + +namespace Framework.SecuritySystem.Services; + +public class RootSecurityProviderFactory( + ISecurityRuleDeepOptimizer deepOptimizer, + IDefaultSecurityProviderFactory defaultSecurityProviderFactory, + IEnumerable> injectors) : ISecurityProviderFactory + where TSecurityRule : DomainSecurityRule +{ + public ISecurityProvider Create(TSecurityRule securityRule, SecurityPath? securityPath) + { + var optimizeSettings = defaultSecurityProviderFactory.AllowOptimize + ? new SecurityRuleExpandSettings(injectors.Select(injector => injector.SecurityRuleType)) + : SecurityRuleExpandSettings.Disabled; + + var actualSecurityRule = deepOptimizer.Optimize(securityRule, optimizeSettings); + + injectors.Aggregate(defaultFactory, (state, injector) => injector.Inject(state)).Create(securityRule, securityPath); + } +} + +public class RootSecurityProviderFactory( + IServiceProvider serviceProvider, + ISecurityRuleTypeResolver securityRuleTypeResolver, + ISecurityRuleDeepOptimizer deepOptimizer) : IRootSecurityProviderFactory +{ + public ISecurityProvider Create(SecurityRule securityRule, SecurityPath? securityPath) + { + var securityRuleType = securityRuleTypeResolver.Resolve(securityRule); + + var injectorType = typeof(ISecurityProviderInjector<,>).MakeGenericType(typeof(TDomainObject), securityRuleType); + + var defaultFactory = serviceProvider.GetRequiredService( + typeof(IDefaultSecurityProviderFactory<,>).MakeGenericType(injectorType, securityRuleType)); + + var injectors = serviceProvider.GetRequiredService(typeof(IEnumerable<>).MakeGenericType(injectorType)); + + + switch (baseSecurityRule) + { + case DomainSecurityRule securityRule: + return this.CreateInternal(deepOptimizer.Optimize(securityRule), securityPath); + + case SecurityRule.ModeSecurityRule securityRule: + return this.Create(securityRule.ToDomain(), securityPath); + + default: + throw new ArgumentOutOfRangeException(nameof(baseSecurityRule)); + } + } + + private class InternalDomainSecurityProviderFactory( + DomainSecurityProviderFactory rootFactory, + ISecurityProviderFactory defaultFactory, + IEnumerable> injectors, + ISecurityRuleDeepOptimizer deepOptimizer, + TSecurityRule securityRule, + SecurityPath securityPath) : IFactory> + where TSecurityRule : SecurityRule + { + public ISecurityProvider Create() + { + if (!injectors.Any()) + { + + } + else + { + injectors.Aggregate(defaultFactory, (state, injector) => injector.Inject(state)).Create(securityRule, securityPath); + } + } + } + + private ISecurityProvider Create( + TSecurityRule securityRule, + SecurityPath securityPath, + ISecurityProviderFactory defaultFactory, + IEnumerable> injectors) + where TSecurityRule : SecurityRule => + injectors.Aggregate(defaultFactory, (state, injector) => injector.Inject(state)).Create(securityRule, securityPath); +} + +internal class InternalDomainSecurityProviderFactory( + IServiceProvider serviceProvider, + IRoleBaseSecurityProviderFactory roleBaseSecurityProviderFactory, + SecurityPath securityPath, + ISecurityProviderInjector injectors) + where TSecurityRule : SecurityRule +{ + protected virtual ISecurityProvider Create(DomainSecurityRule baseSecurityRule) + { + switch (baseSecurityRule) + { + case RoleBaseSecurityRule securityRule: + return roleBaseSecurityProviderFactory.Create(securityRule, securityPath); + + case CurrentUserSecurityRule securityRule: + { + var args = new object?[] + { + securityRule.RelativePathKey == null + ? null + : new CurrentUserSecurityProviderRelativeKey(securityRule.RelativePathKey) + }.Where(arg => arg != null) + .ToArray(arg => arg!); + + return ActivatorUtilities.CreateInstance>(serviceProvider, args); + } + + case ProviderSecurityRule securityRule: + { + var securityProviderType = + securityRule.GenericSecurityProviderType.MakeGenericType(typeof(TDomainObject)); + + var securityProvider = securityRule.Key == null + ? serviceProvider.GetRequiredService(securityProviderType) + : serviceProvider.GetRequiredKeyedService(securityProviderType, securityRule.Key); + + return (ISecurityProvider)securityProvider; + } + + case ProviderFactorySecurityRule securityRule: + { + var securityProviderFactoryType = + securityRule.GenericSecurityProviderFactoryType.MakeGenericType(typeof(TDomainObject)); + + var securityProviderFactoryUntyped = + securityRule.Key == null + ? serviceProvider.GetRequiredService(securityProviderFactoryType) + : serviceProvider.GetRequiredKeyedService(securityProviderFactoryType, securityRule.Key); + + var securityProviderFactory = (IFactory>)securityProviderFactoryUntyped; + + return securityProviderFactory.Create(); + } + + case ConditionFactorySecurityRule securityRule: + { + var conditionFactoryType = + securityRule.GenericConditionFactoryType.MakeGenericType(typeof(TDomainObject)); + + var conditionFactoryUntyped = serviceProvider.GetRequiredService(conditionFactoryType); + + var conditionFactory = (IFactory>>)conditionFactoryUntyped; + + return SecurityProvider.Create(conditionFactory.Create()); + } + + case RelativeConditionSecurityRule securityRule: + { + var conditionInfo = securityRule.RelativeConditionInfo; + + var factoryType = typeof(RequiredRelativeConditionFactory<,>).MakeGenericType( + typeof(TDomainObject), + conditionInfo.RelativeDomainObjectType); + + var untypedConditionFactory = ActivatorUtilities.CreateInstance(serviceProvider, factoryType, conditionInfo); + + var conditionFactory = (IFactory>>)untypedConditionFactory; + + var condition = conditionFactory.Create(); + + return SecurityProvider.Create(condition); + } + + case FactorySecurityRule securityRule: + { + var dynamicRoleFactoryUntyped = serviceProvider.GetRequiredService(securityRule.RuleFactoryType); + + var dynamicRoleFactory = (IFactory)dynamicRoleFactoryUntyped; + + return this.Create(dynamicRoleFactory.Create()); + } + + case OverrideAccessDeniedMessageSecurityRule securityRule: + { + return this.Create(securityRule.BaseSecurityRule) + .OverrideAccessDeniedResult( + accessDeniedResult => accessDeniedResult with { CustomMessage = securityRule.CustomMessage }); + } + + case OrSecurityRule securityRule: + return this.Create(securityRule.Left).Or(this.Create(securityRule.Right)); + + case AndSecurityRule securityRule: + return this.Create(securityRule.Left).And(this.Create(securityRule.Right)); + + case NegateSecurityRule securityRule: + return this.Create(securityRule.InnerRule).Negate(); + + case DomainModeSecurityRule: + case SecurityRuleHeader: + case ClientSecurityRule: + throw new Exception("Must be optimized"); + + default: + throw new ArgumentOutOfRangeException(nameof(baseSecurityRule)); + } + } +} diff --git a/src/Framework.SecuritySystem/Services/SecurityRuleDeepOptimizer.cs b/src/Framework.SecuritySystem/Services/SecurityRuleDeepOptimizer.cs index 1ebed0775..0846274b0 100644 --- a/src/Framework.SecuritySystem/Services/SecurityRuleDeepOptimizer.cs +++ b/src/Framework.SecuritySystem/Services/SecurityRuleDeepOptimizer.cs @@ -9,7 +9,7 @@ public class SecurityRuleDeepOptimizer : ISecurityRuleDeepOptimizer private readonly ISecurityRuleBasicOptimizer basicOptimizer; - private readonly IDictionaryCache cache; + private readonly IDictionaryCache<(DomainSecurityRule, SecurityRuleExpandSettings?), DomainSecurityRule> cache; public SecurityRuleDeepOptimizer( ISecurityRuleExpander expander, @@ -17,16 +17,16 @@ public SecurityRuleDeepOptimizer( { this.expander = expander; this.basicOptimizer = basicOptimizer; - this.cache = new DictionaryCache(this.Visit).WithLock(); + this.cache = new DictionaryCache<(DomainSecurityRule, SecurityRuleExpandSettings?), DomainSecurityRule>(pair => this.Visit(pair.Item1, pair.Item2)).WithLock(); } - protected virtual DomainSecurityRule Visit(DomainSecurityRule baseSecurityRule) + protected virtual DomainSecurityRule Visit(DomainSecurityRule baseSecurityRule, SecurityRuleExpandSettings? settings) { - var visitedRule = this.basicOptimizer.Optimize(this.expander.FullDomainExpand(baseSecurityRule)); + var visitedRule = this.basicOptimizer.Optimize(this.expander.FullDomainExpand(baseSecurityRule, settings)); - return visitedRule == baseSecurityRule ? visitedRule : this.Visit(visitedRule); + return visitedRule == baseSecurityRule ? visitedRule : this.Visit(visitedRule, settings); } - DomainSecurityRule ISecurityRuleDeepOptimizer.Optimize(DomainSecurityRule securityRule) => - this.cache[securityRule]; + DomainSecurityRule ISecurityRuleDeepOptimizer.Optimize(DomainSecurityRule securityRule, SecurityRuleExpandSettings? settings) => + this.cache[(securityRule, settings)]; } diff --git a/src/Framework.SecuritySystem/Services/SecurityRuleTypeResolver.cs b/src/Framework.SecuritySystem/Services/SecurityRuleTypeResolver.cs new file mode 100644 index 000000000..0ff4cab9b --- /dev/null +++ b/src/Framework.SecuritySystem/Services/SecurityRuleTypeResolver.cs @@ -0,0 +1,11 @@ +using Framework.Core; + +namespace Framework.SecuritySystem.Services; + +public class SecurityRuleTypeResolver : ITypeResolver +{ + public Type Resolve(SecurityRule securityRule) => securityRule.GetType(); + + public IEnumerable GetTypes() => + typeof(SecurityRule).Assembly.GetTypes().Where(t => !t.IsAbstract && typeof(SecurityRule).IsAssignableFrom(t)); +}