Skip to content

Commit

Permalink
Revert "refactor: Quick return of merging effects" (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
sagilio committed Mar 30, 2021
1 parent b633663 commit 17363d1
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 52 deletions.
25 changes: 25 additions & 0 deletions NetCasbin/Abstractions/IChainEffector.cs
@@ -0,0 +1,25 @@
using Casbin.Effect;

namespace Casbin
{
public interface IChainEffector
{
public bool Result { get; }

public bool CanChain { get; }

public bool HitPolicy { get; }

public string EffectExpression { get; }

public EffectExpressionType PolicyEffectType { get; }

public void StartChain(string policyEffect);

public bool Chain(PolicyEffect effect);

public bool TryChain(PolicyEffect effect);

public bool TryChain(PolicyEffect effect, out bool? result);
}
}
29 changes: 12 additions & 17 deletions NetCasbin/Abstractions/IEffector.cs
Expand Up @@ -2,24 +2,19 @@

namespace Casbin
{
/// <summary>
/// Effector is the interface for Casbin effectors.
/// </summary>
public interface IEffector
{
public bool Result { get; }

public bool CanChain { get; }

public bool HitPolicy { get; }

public string EffectExpression { get; }

public EffectExpressionType PolicyEffectType { get; }

public void StartChain(string policyEffect);

public bool Chain(PolicyEffect effect);

public bool TryChain(PolicyEffect effect);

public bool TryChain(PolicyEffect effect, out bool? result);
/// <summary>
/// Merges all matching results collected by the enforcer into a single decision.
/// </summary>
/// <param name="policyEffect">The expression of [policy_effect].</param>
/// <param name="effects">The effects of all matched rules.</param>
/// <param name="results">The matcher results of all matched rules.</param>
/// <param name="hitPolicyIndex"></param>
/// <returns>The final effect.</returns>
bool MergeEffects(string policyEffect, PolicyEffect[] effects, float[] results, out int hitPolicyIndex);
}
}
81 changes: 70 additions & 11 deletions NetCasbin/Effect/DefaultEffector.cs
Expand Up @@ -6,8 +6,75 @@ namespace Casbin.Effect
/// <summary>
/// DefaultEffector is default effector for Casbin.
/// </summary>
public class DefaultEffector : IEffector
public class DefaultEffector : IEffector, IChainEffector
{
/// <summary>
/// Merges all matching results collected by the enforcer into a single decision.
/// </summary>
/// <param name="effectExpression"></param>
/// <param name="effects"></param>
/// <param name="results"></param>
/// <param name="hitPolicyIndex"></param>
/// <returns></returns>
public bool MergeEffects(string effectExpression, PolicyEffect[] effects, float[] results, out int hitPolicyIndex)
{
return MergeEffects(effectExpression, effects.AsSpan(), results.AsSpan(), out hitPolicyIndex);
}


/// <summary>
/// Merges all matching results collected by the enforcer into a single decision.
/// </summary>
/// <param name="effectExpression"></param>
/// <param name="effects"></param>
/// <param name="results"></param>
/// <param name="hitPolicyIndex"></param>
/// <returns></returns>
private bool MergeEffects(string effectExpression, Span<PolicyEffect> effects, Span<float> results, out int hitPolicyIndex)
{
PolicyEffectType = ParsePolicyEffectType(effectExpression);
return MergeEffects(PolicyEffectType, effects, results, out hitPolicyIndex);
}

/// <summary>
/// Merges all matching results collected by the enforcer into a single decision.
/// </summary>
/// <param name="effectExpressionType"></param>
/// <param name="effects"></param>
/// <param name="results"></param>
/// <param name="hitPolicyIndex"></param>
/// <returns></returns>
private bool MergeEffects(EffectExpressionType effectExpressionType, Span<PolicyEffect> effects, Span<float> results, out int hitPolicyIndex)
{
bool finalResult = false;
hitPolicyIndex = -1;
for (int index = 0; index < effects.Length; index++)
{
if (EffectEvaluator.TryEvaluate(effects[index] , effectExpressionType,
ref finalResult, out bool hitPolicy))
{
if (hitPolicy)
{
hitPolicyIndex = index;
}
return finalResult;
}
}

return finalResult;
}

public static EffectExpressionType ParsePolicyEffectType(string effectExpression) => effectExpression switch
{
PermConstants.PolicyEffect.AllowOverride => EffectExpressionType.AllowOverride,
PermConstants.PolicyEffect.DenyOverride => EffectExpressionType.DenyOverride,
PermConstants.PolicyEffect.AllowAndDeny => EffectExpressionType.AllowAndDeny,
PermConstants.PolicyEffect.Priority => EffectExpressionType.Priority,
_ => throw new NotSupportedException("Not supported policy effect.")
};

#region IChainEffector

public bool Result { get; private set; }

public bool HitPolicy { get; private set; }
Expand All @@ -21,7 +88,7 @@ public class DefaultEffector : IEffector
public void StartChain(string effectExpression)
{
EffectExpression = effectExpression ?? throw new ArgumentNullException(nameof(effectExpression));
PolicyEffectType = ParseEffectExpressionType(EffectExpression);
PolicyEffectType = ParsePolicyEffectType(EffectExpression);
CanChain = true;
Result = false;
}
Expand Down Expand Up @@ -83,14 +150,6 @@ public bool TryChain(PolicyEffect effect, out bool? result)
result = null;
return false;
}

private static EffectExpressionType ParseEffectExpressionType(string effectExpression) => effectExpression switch
{
PermConstants.PolicyEffect.AllowOverride => EffectExpressionType.AllowOverride,
PermConstants.PolicyEffect.DenyOverride => EffectExpressionType.DenyOverride,
PermConstants.PolicyEffect.AllowAndDeny => EffectExpressionType.AllowAndDeny,
PermConstants.PolicyEffect.Priority => EffectExpressionType.Priority,
_ => throw new NotSupportedException("Not supported policy effect.")
};
#endregion
}
}
140 changes: 116 additions & 24 deletions NetCasbin/Enforcer.cs
Expand Up @@ -67,7 +67,7 @@ public Enforcer(IModel model, IAdapter adapter = null)
#endregion

public string ModelPath { get; private set; }
public bool IsFiltered => Adapter is IFilteredAdapter { IsFiltered: true };
public bool IsFiltered => Adapter is IFilteredAdapter {IsFiltered: true};

public IExpressionHandler ExpressionHandler { get; private set; }

Expand Down Expand Up @@ -365,7 +365,7 @@ public Task<bool> EnforceAsync(params object[] requestValues)
/// <returns>Whether to allow the request.</returns>
public bool Enforce(params object[] requestValues)
{
return Enforce((IReadOnlyList<object>)requestValues);
return Enforce((IReadOnlyList<object>) requestValues);
}

#if !NET45
Expand Down Expand Up @@ -472,12 +472,107 @@ private bool Enforce(IReadOnlyList<object> requestValues, ICollection<IEnumerabl
bool hasEval = Utility.HasEval(expressionString);

bool finalResult = false;
IEffector effector = Effector;
effector.StartChain(effect);
if (policyCount is not 0)
IChainEffector chainEffector = Effector as IChainEffector;
bool isChainEffector = chainEffector is not null;
if (isChainEffector)
{
foreach (var policyValues in policyList)
chainEffector.StartChain(effect);

if (policyCount is not 0)
{
foreach (IReadOnlyList<string> policyValues in policyList)
{
if (policyTokenCount != policyValues.Count)
{
throw new ArgumentException($"Invalid policy size: expected {policyTokenCount}, got {policyValues.Count}.");
}

ExpressionHandler.SetPolicyParameters(policyValues);

bool expressionResult;

if (hasEval)
{
string expressionStringWithRule = RewriteEval(expressionString, ExpressionHandler.PolicyTokens, policyValues);
expressionResult = ExpressionHandler.Invoke(expressionStringWithRule, requestValues);
}
else
{
expressionResult = ExpressionHandler.Invoke(expressionString, requestValues);
}

var nowEffect = GetEffect(expressionResult);

if (nowEffect is not PolicyEffect.Indeterminate && ExpressionHandler.Parameters.TryGetValue("p_eft", out Parameter parameter))
{
string policyEffect = parameter.Value as string;
nowEffect = policyEffect switch
{
"allow" => PolicyEffect.Allow,
"deny" => PolicyEffect.Deny,
_ => PolicyEffect.Indeterminate
};
}

bool chainResult = chainEffector.TryChain(nowEffect);

if (explain && chainEffector.HitPolicy)
{
explains.Add(policyValues);
}

if (chainResult is false || chainEffector.CanChain is false)
{
break;
}
}

finalResult = chainEffector.Result;
}
else
{
if (hasEval)
{
throw new ArgumentException("Please make sure rule exists in policy when using eval() in matcher");
}

IReadOnlyList<string> policyValues = Enumerable.Repeat(string.Empty, policyTokenCount).ToArray();
ExpressionHandler.SetPolicyParameters(policyValues);
var nowEffect = GetEffect(ExpressionHandler.Invoke(expressionString, requestValues));

if (chainEffector.TryChain(nowEffect))
{
finalResult = chainEffector.Result;
}

if (explain && chainEffector.HitPolicy)
{
explains.Add(policyValues);
}
}

#if !NET45
if (explain)
{
Logger?.LogEnforceResult(requestValues, finalResult, explains);
}
else
{
Logger?.LogEnforceResult(requestValues, finalResult);
}
#endif
return finalResult;
}

int hitPolicyIndex;
if (policyCount != 0)
{
PolicyEffect[] policyEffects = new PolicyEffect[policyCount];

for (int i = 0; i < policyCount; i++)
{
IReadOnlyList<string> policyValues = policyList[i];

if (policyTokenCount != policyValues.Count)
{
throw new ArgumentException($"Invalid policy size: expected {policyTokenCount}, got {policyValues.Count}.");
Expand All @@ -499,7 +594,13 @@ private bool Enforce(IReadOnlyList<object> requestValues, ICollection<IEnumerabl

var nowEffect = GetEffect(expressionResult);

if (nowEffect is not PolicyEffect.Indeterminate && ExpressionHandler.Parameters.TryGetValue("p_eft", out Parameter parameter))
if (nowEffect is PolicyEffect.Indeterminate)
{
policyEffects[i] = nowEffect;
continue;
}

if (ExpressionHandler.Parameters.TryGetValue("p_eft", out Parameter parameter))
{
string policyEffect = parameter.Value as string;
nowEffect = policyEffect switch
Expand All @@ -510,20 +611,15 @@ private bool Enforce(IReadOnlyList<object> requestValues, ICollection<IEnumerabl
};
}

bool chainResult = effector.TryChain(nowEffect);

if (explain && effector.HitPolicy)
{
explains.Add(policyValues);
}
policyEffects[i] = nowEffect;

if (chainResult is false || effector.CanChain is false)
if (effect.Equals(PermConstants.PolicyEffect.Priority))
{
break;
}
}

finalResult = effector.Result;
finalResult = Effector.MergeEffects(effect, policyEffects, null, out hitPolicyIndex);
}
else
{
Expand All @@ -535,16 +631,12 @@ private bool Enforce(IReadOnlyList<object> requestValues, ICollection<IEnumerabl
IReadOnlyList<string> policyValues = Enumerable.Repeat(string.Empty, policyTokenCount).ToArray();
ExpressionHandler.SetPolicyParameters(policyValues);
var nowEffect = GetEffect(ExpressionHandler.Invoke(expressionString, requestValues));
finalResult = Effector.MergeEffects(effect, new[] { nowEffect }, null, out hitPolicyIndex);
}

if (effector.TryChain(nowEffect))
{
finalResult = effector.Result;
}

if (explain && effector.HitPolicy)
{
explains.Add(policyValues);
}
if (explain && hitPolicyIndex is not -1)
{
explains.Add(policyList[hitPolicyIndex]);
}

#if !NET45
Expand Down

0 comments on commit 17363d1

Please sign in to comment.