Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix AddClientSecurityRuleInfoSource #510

Merged
merged 1 commit into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

public interface ISecurityRuleExpander : ISecurityModeExpander, ISecurityOperationExpander, ISecurityRoleExpander, IRoleFactorySecurityRuleExpander
{
DomainSecurityRule.ExpandedRolesSecurityRule FullExpand(DomainSecurityRule.RoleBaseSecurityRule securityRule);
DomainSecurityRule.ExpandedRolesSecurityRule FullRoleExpand(DomainSecurityRule.RoleBaseSecurityRule securityRule);

DomainSecurityRule FullDomainExpand(DomainSecurityRule securityRule);
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public void SecurityRoleExpander_FullExpandWithCustomExpandType_SecurityRuleCorr
var expander = this.rootServiceProvider.GetRequiredService<ISecurityRuleExpander>();

// Act
var expandResult = expander.FullExpand(ExampleSecurityOperation.EmployeeView.ToSecurityRule(HierarchicalExpandType.All));
var expandResult = expander.FullRoleExpand(ExampleSecurityOperation.EmployeeView.ToSecurityRule(HierarchicalExpandType.All));

// Assert
expandResult.Should()
Expand All @@ -90,7 +90,7 @@ public void SecurityRoleExpander_FullExpandWithCustomExpandTypeFromOperations_Se
var expander = this.rootServiceProvider.GetRequiredService<ISecurityRuleExpander>();

// Act
var expandResult = expander.FullExpand(ExampleSecurityOperation.BusinessUnitView);
var expandResult = expander.FullRoleExpand(ExampleSecurityOperation.BusinessUnitView);

// Assert
expandResult.Should()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ ISecuritySystemSettings SetSecurityAccessorInfinityStorage<TStorage>()

ISecuritySystemSettings SetDefaultSecurityRuleCredential(SecurityRuleCredential securityRuleCredential);

ISecuritySystemSettings SetClientDomainModeSecurityRuleSource<TClientDomainModeSecurityRuleSource>()
where TClientDomainModeSecurityRuleSource : class, IClientDomainModeSecurityRuleSource;

ISecuritySystemSettings AddClientSecurityRuleInfoSource<TClientSecurityRuleInfoSource>()
where TClientSecurityRuleInfoSource : class, IClientSecurityRuleInfoSource;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public class SecuritySystemSettings : ISecuritySystemSettings

private Type securityRuleParserType = typeof(ClientSecurityRuleParser);

private Type clientDomainModeSecurityRuleSource = typeof(ClientDomainModeSecurityRuleSource);

private Type? securityAccessorInfinityStorageType;

public bool InitializeAdministratorRole { get; set; } = true;
Expand Down Expand Up @@ -157,20 +159,27 @@ public ISecuritySystemSettings SetDefaultSecurityRuleCredential(SecurityRuleCred
return this;
}

public ISecuritySystemSettings SetClientDomainModeSecurityRuleSource<TClientDomainModeSecurityRuleSource>()
where TClientDomainModeSecurityRuleSource : class, IClientDomainModeSecurityRuleSource
{
this.clientDomainModeSecurityRuleSource = typeof(TClientDomainModeSecurityRuleSource);

return this;
}

public ISecuritySystemSettings AddClientSecurityRuleInfoSource<TClientSecurityRuleInfoSource>()
where TClientSecurityRuleInfoSource : class, IClientSecurityRuleInfoSource
{
this.registerActions.Add(sc => sc.AddSingleton<IClientSecurityRuleInfoSource, TClientSecurityRuleInfoSource>());
this.registerActions.Add(sc => sc.AddKeyedSingleton<IClientSecurityRuleInfoSource, TClientSecurityRuleInfoSource>(RootClientSecurityRuleInfoSource.ElementKey));

return this;
}


public ISecuritySystemSettings AddClientSecurityRuleInfoSource(Type sourceType)
{
this.registerActions.Add(
sc => sc.AddSingleton<IClientSecurityRuleInfoSource>(
sp => ActivatorUtilities.CreateInstance<SourceTypeClientSecurityRuleInfoSource>(sp, sourceType)));
sc => sc.AddKeyedSingleton<IClientSecurityRuleInfoSource>(RootClientSecurityRuleInfoSource.ElementKey,
(sp, _) => ActivatorUtilities.CreateInstance<SourceTypeClientSecurityRuleInfoSource>(sp, sourceType)));

return this;
}
Expand Down Expand Up @@ -211,6 +220,8 @@ public void Initialize(IServiceCollection services)
services.AddSingleton(this.defaultSecurityRuleCredential);

services.AddSingleton(typeof(ISecurityRuleParser), this.securityRuleParserType);

services.AddSingleton(typeof(IClientDomainModeSecurityRuleSource), this.clientDomainModeSecurityRuleSource);
}

private void AddSecurityRole(IServiceCollection serviceCollection, FullSecurityRole fullSecurityRole)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ private static IServiceCollection RegisterGeneralSecuritySystem(this IServiceCol
.AddNotImplemented<IPrincipalManagementService>($"{nameof(IPrincipalManagementService)} not supported", isScoped: true)

.AddSingleton<IClientSecurityRuleNameExtractor, ClientSecurityRuleNameExtractor>()
.AddSingleton<IClientDomainModeSecurityRuleSource, ClientDomainModeSecurityRuleSource>()
.AddSingleton<IClientSecurityRuleInfoSource, RootClientSecurityRuleInfoSource>()
.AddKeyedSingleton<IClientSecurityRuleInfoSource, DomainModeClientSecurityRuleInfoSource>(RootClientSecurityRuleInfoSource.ElementKey)
.AddSingleton<IClientSecurityRuleResolver, ClientSecurityRuleResolver>()
Expand Down
29 changes: 25 additions & 4 deletions src/Framework.SecuritySystem/Expanders/RootSecurityRuleExpande.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using static Framework.SecuritySystem.DomainSecurityRule;
using Framework.SecuritySystem.Services;

using static Framework.SecuritySystem.DomainSecurityRule;

namespace Framework.SecuritySystem.Expanders;

Expand All @@ -7,7 +9,8 @@ public class RootSecurityRuleExpander(
ISecurityOperationExpander securityOperationExpander,
ISecurityRoleExpander securityRoleExpander,
IRoleFactorySecurityRuleExpander roleFactorySecurityRuleExpander,
ISecurityRoleSource securityRoleSource)
ISecurityRoleSource securityRoleSource,
ISecurityRuleImplementationResolver implementationResolver)
: ISecurityRuleExpander
{
public DomainSecurityRule? TryExpand(DomainModeSecurityRule securityRule)
Expand All @@ -30,7 +33,7 @@ public RoleBaseSecurityRule Expand(RoleFactorySecurityRule securityRule)
return roleFactorySecurityRuleExpander.Expand(securityRule);
}

public ExpandedRolesSecurityRule FullExpand(RoleBaseSecurityRule securityRule)
public ExpandedRolesSecurityRule FullRoleExpand(RoleBaseSecurityRule securityRule)
{
switch (securityRule)
{
Expand All @@ -47,10 +50,28 @@ public ExpandedRolesSecurityRule FullExpand(RoleBaseSecurityRule securityRule)
return expandedRolesSecurityRule;

case RoleFactorySecurityRule dynamicRoleSecurityRule:
return this.FullExpand(this.Expand(dynamicRoleSecurityRule));
return this.FullRoleExpand(this.Expand(dynamicRoleSecurityRule));

default:
throw new ArgumentOutOfRangeException(nameof(securityRule));
}
}

public DomainSecurityRule FullDomainExpand(DomainSecurityRule securityRule)
{
return new FullDomainExpandVisitor(this, implementationResolver).Visit(securityRule);
}

private class FullDomainExpandVisitor(ISecurityRuleExpander expander, ISecurityRuleImplementationResolver implementationResolver)
: SecurityRuleVisitor
{
protected override DomainSecurityRule Visit(SecurityRuleHeader securityRule)
{
return this.Visit(implementationResolver.Resolve(securityRule));
}

protected override DomainSecurityRule Visit(RoleBaseSecurityRule baseSecurityRule) => expander.FullRoleExpand(baseSecurityRule);

protected override DomainSecurityRule Visit(DomainModeSecurityRule securityRule) => this.Visit(expander.Expand(securityRule));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class ClientDomainModeSecurityRuleSource(IEnumerable<DomainModeSecurityRu
: IClientDomainModeSecurityRuleSource
{
public IEnumerable<DomainSecurityRule.DomainModeSecurityRule> GetRules() =>
domainModeSecurityRuleInfoList
.Where(info => info.Implementation != SecurityRule.Disabled)
.Select(info => info.SecurityRule);
domainModeSecurityRuleInfoList.Where(this.Allowed).Select(info => info.SecurityRule);

protected virtual bool Allowed(DomainModeSecurityRuleInfo info) => info.Implementation != SecurityRule.Disabled;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,20 @@ public class DomainSecurityRoleExtractor(ISecurityRuleExpander expander) : IDoma
{
var usedRoles = new HashSet<SecurityRole>();

new ScanVisitor(expander, usedRoles).Visit(securityRule);
new ScanVisitor(usedRoles).Visit(expander.FullDomainExpand(securityRule));

return usedRoles;
}).WithLock();

public IEnumerable<SecurityRole> Extract(DomainSecurityRule securityRule) => this.cache[securityRule];

private class ScanVisitor(ISecurityRuleExpander expander, ISet<SecurityRole> usedRoles) : SecurityRuleVisitor
private class ScanVisitor(ISet<SecurityRole> usedRoles) : SecurityRuleVisitor
{
protected override DomainSecurityRule Visit(DomainSecurityRule.DomainModeSecurityRule securityRule)
protected override DomainSecurityRule Visit(DomainSecurityRule.ExpandedRolesSecurityRule securityRule)
{
return this.Visit(expander.Expand(securityRule));
}

protected override DomainSecurityRule Visit(DomainSecurityRule.RoleBaseSecurityRule baseSecurityRule)
{
var expandedRule = expander.FullExpand(baseSecurityRule);

usedRoles.UnionWith(expandedRule.SecurityRoles);
usedRoles.UnionWith(securityRule.SecurityRoles);

return baseSecurityRule;
return securityRule;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ protected virtual ISecurityProvider<TDomainObject> CreateInternal(
switch (baseSecurityRule)
{
case DomainModeSecurityRule securityRule:
return this.Create(securityModeExpander.Expand(securityRule), securityPath);
return this.CreateInternal(securityModeExpander.Expand(securityRule), securityPath);

case SecurityRuleHeader securityRuleHeader:
return this.CreateInternal(implementationResolver.Resolve(securityRuleHeader), securityPath);

case RoleBaseSecurityRule securityRule:
return roleBaseSecurityProviderFactory.Create(securityRule, securityPath);
Expand Down Expand Up @@ -121,9 +124,6 @@ protected virtual ISecurityProvider<TDomainObject> CreateInternal(
accessDeniedResult => accessDeniedResult with { CustomMessage = securityRule.CustomMessage });
}

case SecurityRuleHeader securityRuleHeader:
return this.CreateInternal(implementationResolver.Resolve(securityRuleHeader), securityPath);

case OrSecurityRule securityRule:
return this.CreateInternal(securityRule.Left, securityPath).Or(this.CreateInternal(securityRule.Right, securityPath));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private ISecurityProvider<TDomainObject> Create(
private IEnumerable<(DomainSecurityRule.ExpandedRolesSecurityRule SecurityRule, SecurityPathRestriction Restriction)> GetRegroupedRoles(
DomainSecurityRule.RoleBaseSecurityRule securityRule)
{
var expandedSecurityRule = securityRuleExpander.FullExpand(securityRule);
var expandedSecurityRule = securityRuleExpander.FullRoleExpand(securityRule);

return from securityRole in expandedSecurityRule.SecurityRoles

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class SecurityRolesIdentsResolver(
{
public IEnumerable<Guid> Resolve(DomainSecurityRule.RoleBaseSecurityRule securityRule, bool includeVirtual = false)
{
return securityRuleExpander.FullExpand(securityRule)
return securityRuleExpander.FullRoleExpand(securityRule)
.SecurityRoles
.Select(securityRoleSource.GetSecurityRole)
.Where(sr => includeVirtual || !sr.Information.IsVirtual)
Expand Down
26 changes: 2 additions & 24 deletions src/Framework.SecuritySystem/Services/SecurityRuleDeepOptimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,24 @@ public class SecurityRuleDeepOptimizer : ISecurityRuleDeepOptimizer

private readonly ISecurityRuleBasicOptimizer basicOptimizer;

private readonly ISecurityRuleImplementationResolver implementationResolver;

private readonly IDictionaryCache<DomainSecurityRule, DomainSecurityRule> cache;

public SecurityRuleDeepOptimizer(
ISecurityRuleExpander expander,
ISecurityRuleBasicOptimizer basicOptimizer,
ISecurityRuleImplementationResolver implementationResolver)
ISecurityRuleBasicOptimizer basicOptimizer)
{
this.expander = expander;
this.basicOptimizer = basicOptimizer;
this.implementationResolver = implementationResolver;
this.cache = new DictionaryCache<DomainSecurityRule, DomainSecurityRule>(this.Visit).WithLock();
}

protected virtual DomainSecurityRule Visit(DomainSecurityRule baseSecurityRule)
{
var visitedRule = this.InternalVisit(baseSecurityRule);
var visitedRule = this.basicOptimizer.Optimize(this.expander.FullDomainExpand(baseSecurityRule));

return visitedRule == baseSecurityRule ? visitedRule : this.Visit(visitedRule);
}

protected virtual DomainSecurityRule InternalVisit(DomainSecurityRule baseSecurityRule)
{
switch (baseSecurityRule)
{
case DomainSecurityRule.DomainModeSecurityRule securityRule:
return this.expander.Expand(securityRule);

case DomainSecurityRule.RoleBaseSecurityRule securityRule:
return this.expander.FullExpand(securityRule);

case DomainSecurityRule.SecurityRuleHeader securityRuleHeader:
return this.implementationResolver.Resolve(securityRuleHeader);

default:
return this.basicOptimizer.Optimize(baseSecurityRule);
}
}

DomainSecurityRule ISecurityRuleDeepOptimizer.Optimize(DomainSecurityRule securityRule) =>
this.cache[securityRule];
}
6 changes: 6 additions & 0 deletions src/Framework.SecuritySystem/Services/SecurityRuleVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ protected virtual DomainSecurityRule Visit(DomainModeSecurityRule securityRule)
return securityRule;
}

protected virtual DomainSecurityRule Visit(SecurityRuleHeader securityRule)
{
return securityRule;
}

protected virtual DomainSecurityRule Visit(OperationSecurityRule securityRule)
{
return securityRule;
Expand Down Expand Up @@ -82,6 +87,7 @@ protected virtual DomainSecurityRule Visit(NegateSecurityRule baseSecurityRule)
{
RoleBaseSecurityRule securityRule => this.Visit(securityRule),
DomainModeSecurityRule securityRule => this.Visit(securityRule),
SecurityRuleHeader securityRule => this.Visit(securityRule),
OrSecurityRule securityRule => this.Visit(securityRule),
AndSecurityRule securityRule => this.Visit(securityRule),
NegateSecurityRule securityRule => this.Visit(securityRule),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public Expression<Func<TPermission, bool>> GetContainsIdentsExpr<TSecurityContex

public IPermissionSource<TPermission> GetPermissionSource(DomainSecurityRule.RoleBaseSecurityRule securityRule)
{
if (securityRuleExpander.FullExpand(securityRule).SecurityRoles.Contains(bindingInfo.SecurityRole))
if (securityRuleExpander.FullRoleExpand(securityRule).SecurityRoles.Contains(bindingInfo.SecurityRole))
{
return new VirtualPermissionSource<TPrincipal, TPermission>(
serviceProvider,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Framework.SecuritySystem;

namespace SampleSystem.Security;

public static class SampleSystemSecurityGroup
{
public static DomainSecurityRule.SecurityRuleHeader TestGroup { get; } = new(nameof(TestGroup));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Framework.SecuritySystem.SecurityRuleInfo;

using SampleSystem.Domain;

namespace SampleSystem.Security;

public class SampleSystemClientDomainModeSecurityRuleSource(IEnumerable<DomainModeSecurityRuleInfo> domainModeSecurityRuleInfoList)
: ClientDomainModeSecurityRuleSource(domainModeSecurityRuleInfoList)
{
protected override bool Allowed(DomainModeSecurityRuleInfo info)
{
return base.Allowed(info) && typeof(PersistentDomainObjectBase).IsAssignableFrom(info.SecurityRule.DomainType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,11 @@ public static ISecuritySystemSettings AddSecurityRoles(this ISecuritySystemSetti
public static ISecuritySystemSettings AddSecurityRules(this ISecuritySystemSettings settings)
{
return settings.AddSecurityRule(
SampleSystemSecurityRule.TestRestriction,
SecurityRule.Disabled.And((TestRestrictionObject v) => v.RestrictionHandler));
SampleSystemSecurityRule.TestRestriction,
SecurityRule.Disabled.And((TestRestrictionObject v) => v.RestrictionHandler))
.AddSecurityRule(
SampleSystemSecurityGroup.TestGroup,
new DomainSecurityRule.DomainModeSecurityRule(typeof(Employee), SecurityRule.View));
}

public static ISecuritySystemSettings AddCustomSecurityOperations(this ISecuritySystemSettings settings)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public static IServiceCollection RegisterGeneralDependencyInjection(this IServic
.AddSecurityRoles()
.AddSecurityRules()
.AddCustomSecurityOperations()
.SetClientDomainModeSecurityRuleSource<SampleSystemClientDomainModeSecurityRuleSource>()
.AddClientSecurityRuleInfoSource(typeof(SampleSystemSecurityGroup))
.SetUserSource<Employee>(employee => employee.Id, employee => employee.Login, employee => employee.Active)
.AddVirtualPermissions()
)
Expand Down
6 changes: 3 additions & 3 deletions src/__SolutionItems/CommonAssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
[assembly: AssemblyCompany("Luxoft")]
[assembly: AssemblyCopyright("Copyright © Luxoft 2009-2024")]

[assembly: AssemblyVersion("22.4.0.0")]
[assembly: AssemblyFileVersion("22.4.0.0")]
[assembly: AssemblyInformationalVersion("22.4.0.0")]
[assembly: AssemblyVersion("22.4.1.0")]
[assembly: AssemblyFileVersion("22.4.1.0")]
[assembly: AssemblyInformationalVersion("22.4.1.0")]

#if DEBUG
[assembly: AssemblyConfiguration("Debug")]
Expand Down
Loading