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

add domainSecurityRule checks to ISecuritySystem #523

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -67,7 +67,7 @@ public record FactorySecurityRule(Type RuleFactoryType) : DomainSecurityRule;

public record OverrideAccessDeniedMessageSecurityRule(DomainSecurityRule BaseSecurityRule, string CustomMessage) : DomainSecurityRule;

public abstract record RoleBaseSecurityRule : DomainSecurityRule
public abstract record RoleBaseSecurityRule : DomainSecurityRule, IRoleBaseSecurityRuleCustomData
{
/// <summary>
/// Тип разворачивания деревьев (как правило для просмотра самого дерева выбирается HierarchicalExpandType.All)
Expand All @@ -78,7 +78,10 @@ public abstract record RoleBaseSecurityRule : DomainSecurityRule

public SecurityPathRestriction? CustomRestriction { get; init; } = null;

public HierarchicalExpandType SafeExpandType => this.CustomExpandType ?? HierarchicalExpandType.Children;
public HierarchicalExpandType GetSafeExpandType () => this.CustomExpandType ?? HierarchicalExpandType.Children;


public RoleBaseSecurityRuleCustomData GetCustomData() => new(this);

public bool EqualsCustoms(RoleBaseSecurityRule other)
{
Expand All @@ -96,6 +99,23 @@ public bool EqualsCustoms(RoleBaseSecurityRule other)
public static implicit operator RoleBaseSecurityRule(RoleBaseSecurityRule[] securityRules) => securityRules.ToSecurityRule();
}

public record RoleBaseSecurityRuleCustomData(HierarchicalExpandType? CustomExpandType, SecurityRuleCredential? CustomCredential, SecurityPathRestriction? CustomRestriction) : IRoleBaseSecurityRuleCustomData
{
public RoleBaseSecurityRuleCustomData(IRoleBaseSecurityRuleCustomData roleBaseSecurityRule)
:this(roleBaseSecurityRule.CustomExpandType, roleBaseSecurityRule.CustomCredential, roleBaseSecurityRule.CustomRestriction)
{
}
}

public interface IRoleBaseSecurityRuleCustomData
{
public HierarchicalExpandType? CustomExpandType { get; }

public SecurityRuleCredential? CustomCredential { get; }

public SecurityPathRestriction? CustomRestriction { get; }
}

public record RoleGroupSecurityRule(DeepEqualsCollection<RoleBaseSecurityRule> Children) : RoleBaseSecurityRule;

public record AnyRoleSecurityRule : RoleBaseSecurityRule;
Expand Down Expand Up @@ -132,7 +152,7 @@ public override string ToString() => this.SecurityRoles.Count == 1
else
{
return new NonExpandedRolesSecurityRule(DeepEqualsCollection.Create(rule1.SecurityRoles.Union(rule2.SecurityRoles)))
.WithCopyCustoms(rule1);
.TryApplyCustoms(rule1);
}
}
}
Expand Down Expand Up @@ -161,7 +181,7 @@ public static ExpandedRolesSecurityRule Create(IEnumerable<SecurityRole> securit
else
{
return new ExpandedRolesSecurityRule(DeepEqualsCollection.Create(rule1.SecurityRoles.Union(rule2.SecurityRoles)))
.WithCopyCustoms(rule1);
.TryApplyCustoms(rule1);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,29 @@ public static NonExpandedRolesSecurityRule ToSecurityRule(
SecurityPathRestriction? customRestriction = null) =>
new[] { securityRole }.ToSecurityRule(customExpandType, customCredential, customRestriction);

public static RoleGroupSecurityRule ToSecurityRule(
public static RoleBaseSecurityRule ToSecurityRule(
this IEnumerable<RoleBaseSecurityRule> securityRules,
HierarchicalExpandType? customExpandType = null,
SecurityRuleCredential? customCredential = null,
SecurityPathRestriction? customRestriction = null) =>
new(
DeepEqualsCollection.Create(securityRules))
SecurityPathRestriction? customRestriction = null)
{
var cache = securityRules.ToList();

if (cache.Count == 1)
{
CustomExpandType = customExpandType, CustomCredential = customCredential, CustomRestriction = customRestriction
};
return cache.Single().TryApplyCustoms(customExpandType, customCredential, customRestriction);
}
else
{
return new RoleGroupSecurityRule(
DeepEqualsCollection.Create(cache))
{
CustomExpandType = customExpandType,
CustomCredential = customCredential,
CustomRestriction = customRestriction
};
}
}

public static DomainSecurityRule Or(
this DomainSecurityRule securityRule,
Expand Down Expand Up @@ -192,12 +205,23 @@ public static DomainSecurityRule WithOverrideAccessDeniedMessage(
string customMessage) =>
new OverrideAccessDeniedMessageSecurityRule(securityRule, customMessage);

public static T WithCopyCustoms<T>(this T securityRule, RoleBaseSecurityRule customSource)
public static T TryApplyCustoms<T>(
this T securityRule,
HierarchicalExpandType? customExpandType = null,
SecurityRuleCredential? customCredential = null,
SecurityPathRestriction? customRestriction = null)
where T : RoleBaseSecurityRule =>
securityRule with
{
CustomExpandType = securityRule.CustomExpandType ?? customSource.CustomExpandType,
CustomCredential = securityRule.CustomCredential ?? customSource.CustomCredential,
CustomRestriction = securityRule.CustomRestriction ?? customSource.CustomRestriction,
};

customExpandType is null && customCredential is null && customRestriction is null
? securityRule
: securityRule with
{
CustomExpandType = securityRule.CustomExpandType ?? customExpandType,
CustomCredential = securityRule.CustomCredential ?? customCredential,
CustomRestriction = securityRule.CustomRestriction ?? customRestriction,
};

public static T TryApplyCustoms<T>(this T securityRule, IRoleBaseSecurityRuleCustomData customSource)
where T : RoleBaseSecurityRule =>
securityRule.TryApplyCustoms(customSource.CustomExpandType, customSource.CustomCredential, customSource.CustomRestriction);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

public interface IDomainSecurityRoleExtractor
{
IEnumerable<SecurityRole> Extract(DomainSecurityRule securityRule);
IEnumerable<SecurityRole> ExtractSecurityRoles(DomainSecurityRule securityRule);

DomainSecurityRule.RoleBaseSecurityRule ExtractSecurityRule(DomainSecurityRule securityRule);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

public interface ISecuritySystem
{
bool HasAccess(DomainSecurityRule.RoleBaseSecurityRule securityRule);
bool HasAccess(DomainSecurityRule securityRule);

bool IsAdministrator() => this.HasAccess(SecurityRole.Administrator);

void CheckAccess(DomainSecurityRule.RoleBaseSecurityRule securityRule);
void CheckAccess(DomainSecurityRule securityRule);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public AccessorsFilterInfo<TDomainObject> CreateFilter(
() => FuncHelper.Create(
(TDomainObject domainObject) =>
{
var filter = builder.GetAccessorsFilter(domainObject, securityRule.SafeExpandType);
var filter = builder.GetAccessorsFilter(domainObject, securityRule.GetSafeExpandType());

return permissionSystem.GetPermissionSource(securityRule).GetAccessors(filter);
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public SecurityFilterInfo<TDomainObject> CreateFilter(DomainSecurityRule.RoleBas

var optimizedPermissions = permissionOptimizationService.Optimize(rawPermissions);

var expandedPermissions = optimizedPermissions.Select(permission => this.TryExpandPermission(permission, securityRule.SafeExpandType));
var expandedPermissions = optimizedPermissions.Select(permission => this.TryExpandPermission(permission, securityRule.GetSafeExpandType()));

var builder = this.CreateBuilder(securityPath);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public SecurityFilterInfo<TDomainObject> CreateFilter(DomainSecurityRule.RoleBas
{
var builder = this.CreateBuilder(securityPath);

var permissionFilterExpression = builder.GetSecurityFilterExpression(securityRule.SafeExpandType).ExpandConst().InlineEval();
var permissionFilterExpression = builder.GetSecurityFilterExpression(securityRule.GetSafeExpandType()).ExpandConst().InlineEval();

var permissionQuery = permissionSystem.GetPermissionSource(securityRule).GetPermissionQuery();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ public DomainSecurityRule.RoleBaseSecurityRule Expand(DomainSecurityRule.RoleFac
{
var factory = (IFactory<DomainSecurityRule.RoleBaseSecurityRule>)serviceProvider.GetRequiredService(securityRule.RoleFactoryType);

return factory.Create().WithCopyCustoms(securityRule);
return factory.Create().TryApplyCustoms(securityRule);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ public ExpandedRolesSecurityRule FullRoleExpand(RoleBaseSecurityRule securityRul
{
case AnyRoleSecurityRule:

return ExpandedRolesSecurityRule.Create(securityRoleSource.SecurityRoles).WithCopyCustoms(securityRule);
return ExpandedRolesSecurityRule.Create(securityRoleSource.SecurityRoles).TryApplyCustoms(securityRule);

case RoleGroupSecurityRule roleGroupSecurityRule:

return ExpandedRolesSecurityRule
.Create(roleGroupSecurityRule.Children.SelectMany(c => this.FullRoleExpand(c).SecurityRoles))
.WithCopyCustoms(securityRule);
.TryApplyCustoms(securityRule);

case OperationSecurityRule operationSecurityRule:
return this.Expand(this.Expand(operationSecurityRule));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public SecurityRoleExpander(ISecurityRoleSource securityRoleSource)
.ToArray();

return new DomainSecurityRule.ExpandedRolesSecurityRule(DeepEqualsCollection.Create(securityRoles))
.WithCopyCustoms(securityRule);
.TryApplyCustoms(securityRule);

}).WithLock();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class ClientSecurityRuleResolver(
{
var request = from clientSecurityRuleInfo in clientSecurityRuleInfoSource.GetInfos()

let roles = domainSecurityRoleExtractor.Extract(clientSecurityRuleInfo.Implementation)
let roles = domainSecurityRoleExtractor.ExtractSecurityRoles(clientSecurityRuleInfo.Implementation)

where roles.Contains(securityRole)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class DomainModeSecurityRuleResolver(
{
var request = from domainModeSecurityRuleInfo in domainModeSecurityRuleInfoList

let roles = domainSecurityRoleExtractor.Extract(domainModeSecurityRuleInfo.Implementation)
let roles = domainSecurityRoleExtractor.ExtractSecurityRoles(domainModeSecurityRuleInfo.Implementation)

where roles.Contains(securityRole)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,39 @@

namespace Framework.SecuritySystem.SecurityRuleInfo;

public class DomainSecurityRoleExtractor(ISecurityRuleExpander expander) : IDomainSecurityRoleExtractor
public class DomainSecurityRoleExtractor : IDomainSecurityRoleExtractor
{
private readonly IDictionaryCache<DomainSecurityRule, IReadOnlySet<SecurityRole>> cache =
new DictionaryCache<DomainSecurityRule, IReadOnlySet<SecurityRole>>(
securityRule =>
{
var usedRoles = new HashSet<SecurityRole>();
private readonly IDictionaryCache<DomainSecurityRule, DomainSecurityRule.RoleBaseSecurityRule> rulesCache;

new ScanVisitor(usedRoles).Visit(expander.FullDomainExpand(securityRule));
private readonly IDictionaryCache<DomainSecurityRule, IReadOnlySet<SecurityRole>> rolesCache;

return usedRoles;
}).WithLock();
public DomainSecurityRoleExtractor(ISecurityRuleExpander expander)
{
this.rulesCache =
new DictionaryCache<DomainSecurityRule, DomainSecurityRule.RoleBaseSecurityRule>(
securityRule =>
{
var usedRules = new HashSet<DomainSecurityRule.ExpandedRolesSecurityRule>();

new ScanVisitor(usedRules).Visit(expander.FullDomainExpand(securityRule));

return usedRules.ToArray();
}).WithLock();

this.rolesCache =
new DictionaryCache<DomainSecurityRule, IReadOnlySet<SecurityRole>>(
securityRule => expander.FullRoleExpand(this.rulesCache[securityRule]).SecurityRoles.ToHashSet()).WithLock();
}

public IEnumerable<SecurityRole> ExtractSecurityRoles(DomainSecurityRule securityRule) => this.rolesCache[securityRule];

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

private class ScanVisitor(ISet<SecurityRole> usedRoles) : SecurityRuleVisitor
private class ScanVisitor(ISet<DomainSecurityRule.ExpandedRolesSecurityRule> usedRules) : SecurityRuleVisitor
{
protected override DomainSecurityRule Visit(DomainSecurityRule.ExpandedRolesSecurityRule securityRule)
{
usedRoles.UnionWith(securityRule.SecurityRoles);
usedRules.Add(securityRule);

return securityRule;
}
Expand Down
18 changes: 15 additions & 3 deletions src/Framework.SecuritySystem/SecuritySystem/SecuritySystem.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
using Framework.SecuritySystem.ExternalSystem;
using Framework.SecuritySystem.SecurityRuleInfo;

namespace Framework.SecuritySystem;

public class SecuritySystem(
IAccessDeniedExceptionService accessDeniedExceptionService,
IReadOnlyList<IPermissionSystem> permissionSystems) : ISecuritySystem
IReadOnlyList<IPermissionSystem> permissionSystems,
IDomainSecurityRoleExtractor domainSecurityRoleExtractor) : ISecuritySystem
{
public bool HasAccess(DomainSecurityRule.RoleBaseSecurityRule securityRule)
public bool HasAccess(DomainSecurityRule securityRule)
{
return this.HasAccess(domainSecurityRoleExtractor.ExtractSecurityRule(securityRule));
}

public void CheckAccess(DomainSecurityRule securityRule)
{
this.CheckAccess(domainSecurityRoleExtractor.ExtractSecurityRule(securityRule));
}

private bool HasAccess(DomainSecurityRule.RoleBaseSecurityRule securityRule)
{
return permissionSystems.Any(v => v.GetPermissionSource(securityRule).HasAccess());
}

public void CheckAccess(DomainSecurityRule.RoleBaseSecurityRule securityRule)
private void CheckAccess(DomainSecurityRule.RoleBaseSecurityRule securityRule)
{
if (!this.HasAccess(securityRule))
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using Framework.SecuritySystem.ExternalSystem;
using Framework.SecuritySystem.SecurityRuleInfo;

namespace Framework.SecuritySystem;

public class SecuritySystemFactory(
IAccessDeniedExceptionService accessDeniedExceptionService,
IDomainSecurityRoleExtractor domainSecurityRoleExtractor,
IEnumerable<IPermissionSystemFactory> permissionSystems) : ISecuritySystemFactory
{
public ISecuritySystem Create(SecurityRuleCredential securityRuleCredential)
{
return new SecuritySystem(accessDeniedExceptionService, permissionSystems.Select(f => f.Create(securityRuleCredential)).ToList());
return new SecuritySystem(accessDeniedExceptionService, permissionSystems.Select(f => f.Create(securityRuleCredential)).ToList(), domainSecurityRoleExtractor);
}
}
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.5.4.0")]
[assembly: AssemblyFileVersion("22.5.4.0")]
[assembly: AssemblyInformationalVersion("22.5.4.0")]
[assembly: AssemblyVersion("22.5.5.0")]
[assembly: AssemblyFileVersion("22.5.5.0")]
[assembly: AssemblyInformationalVersion("22.5.5.0")]

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