diff --git a/src/OpenPolicyAgent.Ucast.Linq/QueryableExtensions.cs b/src/OpenPolicyAgent.Ucast.Linq/QueryableExtensions.cs
index 52051f5..4eb7cec 100644
--- a/src/OpenPolicyAgent.Ucast.Linq/QueryableExtensions.cs
+++ b/src/OpenPolicyAgent.Ucast.Linq/QueryableExtensions.cs
@@ -36,6 +36,11 @@ public static Type GetHigherPrecedenceNumericType(Type a, Type b)
throw new InvalidOperationException($"Cannot determine precedence between {a} and {b}");
}
+ public static bool IsGuidType(Type type)
+ {
+ return type == typeof(Guid);
+ }
+
///
/// Builds a LINQ Lambda Expression from the UCAST tree, and then invokes
/// it under a LINQ Where expression on some queryable data source.
@@ -105,14 +110,18 @@ private static Expression BuildFieldExpression(UCASTNode node, ParameterExpre
///
/// The LINQ
/// Current UCAST node in the conditions tree.
- /// Derefered property lookup expression on the LINQ data source.
+ /// Deferred property lookup expression on the LINQ data source.
/// Dictionary mapping UCAST property names to lambdas that generate LINQ Expressions.
- /// Result, a LINQ Expression (Usually a BinaryExpression).
+ /// Result, a LINQ BinaryExpression.
/// Thrown when arguments are of incompatible types.
- private static Expression BuildFieldExpressionFromProperty(UCASTNode node, Expression property, MappingConfiguration mapper)
+ private static BinaryExpression BuildFieldExpressionFromProperty(UCASTNode node, Expression property, MappingConfiguration mapper)
{
Expression value = Expression.Constant(node.Value);
+ // If there is a type mismatch in an expression, it is usually from
+ // differing numeric types, or from things like a GUID vs String
+ // comparison. We try to make smart conversions here to ensure types
+ // are matched for the BinaryExpression result.
Type lhsType = property.Type;
Type rhsType = value.Type;
if (lhsType != rhsType)
@@ -130,6 +139,21 @@ private static Expression BuildFieldExpressionFromProperty(UCASTNode node, Ex
value = Expression.Convert(value, exprType);
}
}
+ // Convert GUID strings automatically when the property is a Guid.
+ // Rego doesn't have native GUID typess, so it'll always be a
+ // GUID-formatted string that the policy is trying to match
+ // against the property.
+ else if (IsGuidType(lhsType) && rhsType == typeof(string))
+ {
+ if (Guid.TryParse(node.Value?.ToString(), out Guid guid))
+ {
+ value = Expression.Constant(guid);
+ }
+ else
+ {
+ throw new ArgumentException($"Expected a GUID-formatted string, but got '{node.Value}'");
+ }
+ }
}
// Switch expression:
@@ -164,7 +188,6 @@ private static Expression BuildFieldInExpression(UCASTNode node, Expression p
var eq = new UCASTNode("field", "eq", node.Field);
var childValues = (List