Skip to content

Commit 0ad3518

Browse files
Copilothsluoyz
andcommitted
Log expression compilation errors and replace single quotes in expressions
Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com>
1 parent 9e1d858 commit 0ad3518

4 files changed

Lines changed: 51 additions & 1 deletion

File tree

Casbin.UnitTests/Mock/MockLogger.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#if !NET452
22
using System;
3+
using System.Collections.Generic;
34
using Microsoft.Extensions.Logging;
45
using Xunit.Abstractions;
56

@@ -11,11 +12,14 @@ public class MockLogger<T> : ILogger<T>
1112

1213
public MockLogger(ITestOutputHelper testOutputHelper) => _testOutputHelper = testOutputHelper;
1314

15+
public List<(LogLevel Level, Exception Exception, string Message)> Logs { get; } = new();
16+
1417
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
1518
Func<TState, Exception, string> formatter)
1619
{
1720
string outPut = formatter(state, null);
1821
_testOutputHelper.WriteLine(outPut);
22+
Logs.Add((logLevel, exception, outPut));
1923
}
2024

2125
public bool IsEnabled(LogLevel logLevel) => true;

Casbin.UnitTests/ModelTests/EnforcerTest.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,4 +1290,33 @@ public async Task TestEnforceExWithMatcherAsync()
12901290
}
12911291

12921292
#endregion
1293+
1294+
#if !NET452
1295+
#region ExpressionHandler Tests
1296+
1297+
[Fact]
1298+
public void TestExpressionHandlerSingleQuoteReplacement()
1299+
{
1300+
Enforcer e = new(TestModelFixture.GetBasicTestModel());
1301+
// Single quotes should be replaced with double quotes to handle DynamicExpresso limitations
1302+
string matcherWithSingleQuotes = "r.sub == 'alice' && r.obj == p.obj && r.act == p.act";
1303+
1304+
Assert.True(e.EnforceWithMatcher(matcherWithSingleQuotes, "alice", "data1", "read"));
1305+
Assert.False(e.EnforceWithMatcher(matcherWithSingleQuotes, "alice", "data1", "write"));
1306+
Assert.False(e.EnforceWithMatcher(matcherWithSingleQuotes, "bob", "data1", "read"));
1307+
}
1308+
1309+
[Fact]
1310+
public void TestExpressionHandlerLogsWarningOnInvalidExpression()
1311+
{
1312+
var logger = new MockLogger<Enforcer>(_testOutputHelper);
1313+
Enforcer e = new(TestModelFixture.GetBasicTestModel()) { Logger = logger };
1314+
1315+
// An invalid expression should return false and log a warning
1316+
Assert.False(e.EnforceWithMatcher("this_is_not_valid!!!", "alice", "data1", "read"));
1317+
Assert.Contains(logger.Logs, log => log.Level == Microsoft.Extensions.Logging.LogLevel.Warning);
1318+
}
1319+
1320+
#endregion
1321+
#endif
12931322
}

Casbin/Enforcer.Internal.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ private bool InternalEnforce<TRequest, TPolicy>(in EnforceContext context, in TR
7272
{
7373
EnforceSession session = new EnforceSession();
7474
IExpressionHandler expressionHandler = Model.ExpressionHandler;
75+
#if !NET452
76+
if (expressionHandler is ExpressionHandler exprHandler)
77+
{
78+
exprHandler.Logger = Logger;
79+
}
80+
#endif
7581
PolicyScanner<TRequest> scanner = context.View.PolicyAssertion.Scan(in requestValues);
7682

7783
EffectChain effectChain = new();

Casbin/Evaluation/ExpressionHandler.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using Casbin.Functions;
66
using Casbin.Model;
77
using DynamicExpresso;
8+
#if !NET452
9+
using Microsoft.Extensions.Logging;
10+
#endif
811

912
namespace Casbin.Evaluation;
1013

@@ -20,6 +23,10 @@ internal class ExpressionHandler : IExpressionHandler
2023

2124
private bool TryCompile { get; set; } = true;
2225

26+
#if !NET452
27+
internal ILogger Logger { get; set; }
28+
#endif
29+
2330
public ExpressionHandler()
2431
{
2532
_interpreter = CreateInterpreter();
@@ -65,6 +72,7 @@ public bool Invoke<TRequest, TPolicy>(in EnforceContext context, string expressi
6572
where TRequest : IRequestValues
6673
where TPolicy : IPolicyValues
6774
{
75+
expressionString = expressionString.Replace('\'', '"');
6876
if (context.View.SupportGeneric is false)
6977
{
7078
if (_cachePool.TryGetFunc(expressionString,
@@ -117,9 +125,12 @@ private bool TryCompileExpression<TRequest, TPolicy>(in EnforceContext context,
117125
{
118126
func = CompileExpression<TRequest, TPolicy>(in context, expressionString);
119127
}
120-
catch (Exception)
128+
catch (Exception e)
121129
{
122130
func = null;
131+
#if !NET452
132+
Logger?.LogWarning(e, "Failed to compile the expression \"{ExpressionString}\".", expressionString);
133+
#endif
123134
return false;
124135
}
125136
return true;

0 commit comments

Comments
 (0)