From 71e530dbac91d9784bf46a62a0ee8fe7973a51e8 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Wed, 19 Oct 2022 17:32:20 -0700 Subject: [PATCH 1/9] Add custom OData resolver for promoting binary operand types. --- .../Parsers/ClaimsTypeDataUriResolver.cs | 75 +++++++++++++++++++ src/Service/Parsers/FilterParser.cs | 5 +- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 src/Service/Parsers/ClaimsTypeDataUriResolver.cs diff --git a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs new file mode 100644 index 0000000000..42a43dfe45 --- /dev/null +++ b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs @@ -0,0 +1,75 @@ +using Microsoft.OData.Edm; +using Microsoft.OData.UriParser; +using System; + +namespace Azure.DataApiBuilder.Service.Parsers +{ + /// + /// Custom OData Resolver which attempts to assist with processing resolved claims in the filter clause. + /// + /// + public class ClaimsTypeDataUriResolver : ODataUriResolver + { + /// + /// Between two nodes in the filter clause, determine which is the node representing an EDM model field (QueryNodeKind.SingleValuePropertyAccess) + /// and which node represents the constant likely resolved from access token claims (QueryNodeKind.Constant). + /// Overwrites the node from token claims with a new ConstantNode containing the original value cast as the type of the EDM Model field node. + /// + /// the operator kind + /// the left operand + /// the right operand + /// type reference for the result BinaryOperatorNode. + public override void PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperatorKind, ref SingleValueNode leftNode, ref SingleValueNode rightNode, out IEdmTypeReference typeReference) + { + // Check for string instances of @claims. directive and try to cast to the type on the other side of the operator. + if (leftNode.TypeReference.PrimitiveKind() != rightNode.TypeReference.PrimitiveKind()) + { + if ((leftNode.Kind == QueryNodeKind.SingleValuePropertyAccess) && (rightNode is ConstantNode)) + { + TryConvertNodeToTargetType(primaryOperand: ref leftNode, operandToConvert: ref rightNode); + } + else if (rightNode.Kind == QueryNodeKind.SingleValuePropertyAccess && leftNode is ConstantNode) + { + TryConvertNodeToTargetType(primaryOperand: ref rightNode, operandToConvert: ref leftNode); + } + } + + base.PromoteBinaryOperandTypes(binaryOperatorKind, ref leftNode, ref rightNode, out typeReference); + } + + /// + /// Helper class which tries to convert the operandToConvert node's value to the value type of + /// the primaryOperand node. + /// + /// Node representing the EDM Model field + /// Node representing a constant value (claims resolved node). + private static void TryConvertNodeToTargetType(ref SingleValueNode primaryOperand, ref SingleValueNode operandToConvert) + { + ConstantNode operandToConvertAsConstant = (ConstantNode)operandToConvert; + + if (primaryOperand.TypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.Int32) + { + string? objectValue = operandToConvertAsConstant.Value.ToString(); + if (objectValue is not null && Int32.TryParse(objectValue, out int result)) + { + operandToConvert = new ConstantNode(constantValue: result); + } + } + else if (primaryOperand.TypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.String) + { + string? objectValue = operandToConvertAsConstant.Value.ToString(); + if (objectValue is not null) + { + operandToConvert = new ConstantNode(constantValue: objectValue); + } + } + else if (primaryOperand.TypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.Boolean) + { + if (Boolean.TryParse(operandToConvertAsConstant.Value.ToString(), out bool result)) + { + operandToConvert = new ConstantNode(constantValue: result); + } + } + } + } +} diff --git a/src/Service/Parsers/FilterParser.cs b/src/Service/Parsers/FilterParser.cs index d3177a84f4..cab9d8869c 100644 --- a/src/Service/Parsers/FilterParser.cs +++ b/src/Service/Parsers/FilterParser.cs @@ -44,7 +44,10 @@ public FilterClause GetFilterClause(string filterQueryString, string resourcePat try { Uri relativeUri = new(resourcePath + '/' + filterQueryString, UriKind.Relative); - ODataUriParser parser = new(_model!, relativeUri); + ODataUriParser parser = new(_model!, relativeUri) + { + Resolver = new ClaimsTypeDataUriResolver() + }; return parser.ParseFilter(); } catch (ODataException e) From 896d655ac07379efd256bed613637f7df1c1bc10 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Oct 2022 12:50:45 -0700 Subject: [PATCH 2/9] Update method signatures to address code readability and simplification feedback --- .../Parsers/ClaimsTypeDataUriResolver.cs | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs index 42a43dfe45..43fe99699c 100644 --- a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs +++ b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs @@ -1,6 +1,5 @@ using Microsoft.OData.Edm; using Microsoft.OData.UriParser; -using System; namespace Azure.DataApiBuilder.Service.Parsers { @@ -11,9 +10,10 @@ namespace Azure.DataApiBuilder.Service.Parsers public class ClaimsTypeDataUriResolver : ODataUriResolver { /// - /// Between two nodes in the filter clause, determine which is the node representing an EDM model field (QueryNodeKind.SingleValuePropertyAccess) - /// and which node represents the constant likely resolved from access token claims (QueryNodeKind.Constant). - /// Overwrites the node from token claims with a new ConstantNode containing the original value cast as the type of the EDM Model field node. + /// Between two nodes in the filter clause, determine the: + /// - PrimaryOperand: Node representing an OData EDM model object and has Kind == QueryNodeKind.SingleValuePropertyAccess. + /// - OperandToConvert: Node representing a constant value and has kind QueryNodeKind.Constant. + /// This resolver will overwrite the OperandToConvert node to a new ConstantNode where the value type is that of the PrimaryOperand node. /// /// the operator kind /// the left operand @@ -21,16 +21,21 @@ public class ClaimsTypeDataUriResolver : ODataUriResolver /// type reference for the result BinaryOperatorNode. public override void PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperatorKind, ref SingleValueNode leftNode, ref SingleValueNode rightNode, out IEdmTypeReference typeReference) { - // Check for string instances of @claims. directive and try to cast to the type on the other side of the operator. if (leftNode.TypeReference.PrimitiveKind() != rightNode.TypeReference.PrimitiveKind()) { if ((leftNode.Kind == QueryNodeKind.SingleValuePropertyAccess) && (rightNode is ConstantNode)) { - TryConvertNodeToTargetType(primaryOperand: ref leftNode, operandToConvert: ref rightNode); + TryConvertNodeToTargetType( + targetType: leftNode.TypeReference.PrimitiveKind(), + operandToConvert: ref rightNode + ); } else if (rightNode.Kind == QueryNodeKind.SingleValuePropertyAccess && leftNode is ConstantNode) { - TryConvertNodeToTargetType(primaryOperand: ref rightNode, operandToConvert: ref leftNode); + TryConvertNodeToTargetType( + targetType: rightNode.TypeReference.PrimitiveKind(), + operandToConvert: ref leftNode + ); } } @@ -38,34 +43,32 @@ public override void PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperator } /// - /// Helper class which tries to convert the operandToConvert node's value to the value type of - /// the primaryOperand node. + /// Uses type specific parsers to attempt conversion the supplied node to a new ConstantNode of type targetType. /// - /// Node representing the EDM Model field - /// Node representing a constant value (claims resolved node). - private static void TryConvertNodeToTargetType(ref SingleValueNode primaryOperand, ref SingleValueNode operandToConvert) + /// Primitive type (string, bool, int, etc.) of the primary node's value. + /// Node representing a constant value which should be converted to a ConstantNode of type targetType. + private static void TryConvertNodeToTargetType(EdmPrimitiveTypeKind targetType, ref SingleValueNode operandToConvert) { - ConstantNode operandToConvertAsConstant = (ConstantNode)operandToConvert; + ConstantNode preConvertedConstant = (ConstantNode)operandToConvert; - if (primaryOperand.TypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.Int32) + if (targetType == EdmPrimitiveTypeKind.Int32) { - string? objectValue = operandToConvertAsConstant.Value.ToString(); - if (objectValue is not null && Int32.TryParse(objectValue, out int result)) + if (int.TryParse(preConvertedConstant.Value.ToString(), out int result)) { operandToConvert = new ConstantNode(constantValue: result); } } - else if (primaryOperand.TypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.String) + else if (targetType == EdmPrimitiveTypeKind.String) { - string? objectValue = operandToConvertAsConstant.Value.ToString(); + string? objectValue = preConvertedConstant.Value.ToString(); if (objectValue is not null) { operandToConvert = new ConstantNode(constantValue: objectValue); } } - else if (primaryOperand.TypeReference.PrimitiveKind() == EdmPrimitiveTypeKind.Boolean) + else if (targetType == EdmPrimitiveTypeKind.Boolean) { - if (Boolean.TryParse(operandToConvertAsConstant.Value.ToString(), out bool result)) + if (bool.TryParse(preConvertedConstant.Value.ToString(), out bool result)) { operandToConvert = new ConstantNode(constantValue: result); } From b239948548b0fc99ab5367b90de8b89910dab927 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Oct 2022 13:13:15 -0700 Subject: [PATCH 3/9] Additional null checking. --- src/Service/Parsers/ClaimsTypeDataUriResolver.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs index 43fe99699c..cc2f9a8b08 100644 --- a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs +++ b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs @@ -51,6 +51,11 @@ private static void TryConvertNodeToTargetType(EdmPrimitiveTypeKind targetType, { ConstantNode preConvertedConstant = (ConstantNode)operandToConvert; + if (preConvertedConstant.Value is null) + { + return; + } + if (targetType == EdmPrimitiveTypeKind.Int32) { if (int.TryParse(preConvertedConstant.Value.ToString(), out int result)) From 35c6fd60f6c4bd4439f36d08019daa29b715570b Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Oct 2022 13:36:58 -0700 Subject: [PATCH 4/9] Adds custom OData resolver only for authorization policy processing. --- src/Service/Parsers/ClaimsTypeDataUriResolver.cs | 5 ++++- src/Service/Parsers/FilterParser.cs | 12 ++++++++---- src/Service/Resolvers/AuthorizationPolicyHelpers.cs | 5 ++++- src/Service/Services/RestService.cs | 5 ++++- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs index cc2f9a8b08..1333bb2c90 100644 --- a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs +++ b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs @@ -4,7 +4,10 @@ namespace Azure.DataApiBuilder.Service.Parsers { /// - /// Custom OData Resolver which attempts to assist with processing resolved claims in the filter clause. + /// Custom OData Resolver which attempts to assist with processing resolved token claims + /// within an authorization policy string that will be used to create an OData filter clause. + /// This resolver's type coercion is meant to be utilized for authorization policy processing + /// and URL query string processing. /// /// public class ClaimsTypeDataUriResolver : ODataUriResolver diff --git a/src/Service/Parsers/FilterParser.cs b/src/Service/Parsers/FilterParser.cs index cab9d8869c..c800f0e15e 100644 --- a/src/Service/Parsers/FilterParser.cs +++ b/src/Service/Parsers/FilterParser.cs @@ -29,8 +29,9 @@ public void BuildModel(ISqlMetadataProvider sqlMetadataProvider) /// /// Represents the $filter part of the query string /// Represents the resource path, in our case the entity name. + /// ODataUriResolver resolving different kinds of Uri parsing context. /// An AST FilterClause that represents the filter portion of the WHERE clause. - public FilterClause GetFilterClause(string filterQueryString, string resourcePath) + public FilterClause GetFilterClause(string filterQueryString, string resourcePath, ODataUriResolver? customResolver = null) { if (_model == null) { @@ -44,10 +45,13 @@ public FilterClause GetFilterClause(string filterQueryString, string resourcePat try { Uri relativeUri = new(resourcePath + '/' + filterQueryString, UriKind.Relative); - ODataUriParser parser = new(_model!, relativeUri) + ODataUriParser parser = new(_model!, relativeUri); + + if (customResolver is not null) { - Resolver = new ClaimsTypeDataUriResolver() - }; + parser.Resolver = customResolver; + } + return parser.ParseFilter(); } catch (ODataException e) diff --git a/src/Service/Resolvers/AuthorizationPolicyHelpers.cs b/src/Service/Resolvers/AuthorizationPolicyHelpers.cs index 46417b4210..0761e47a05 100644 --- a/src/Service/Resolvers/AuthorizationPolicyHelpers.cs +++ b/src/Service/Resolvers/AuthorizationPolicyHelpers.cs @@ -86,7 +86,10 @@ public static void ProcessAuthorizationPolicies( // Parse and save the values that are needed to later generate SQL query predicates // FilterClauseInDbPolicy is an Abstract Syntax Tree representing the parsed policy text. - return sqlMetadataProvider.GetODataParser().GetFilterClause(dbPolicyClause, $"{entityName}.{resourcePath}"); + return sqlMetadataProvider.GetODataParser().GetFilterClause( + filterQueryString: dbPolicyClause, + resourcePath: $"{entityName}.{resourcePath}", + customResolver: new ClaimsTypeDataUriResolver()); } return null; diff --git a/src/Service/Services/RestService.cs b/src/Service/Services/RestService.cs index 2df0ab2c5e..e45f011f8d 100644 --- a/src/Service/Services/RestService.cs +++ b/src/Service/Services/RestService.cs @@ -161,7 +161,10 @@ RuntimeConfigProvider runtimeConfigProvider // Parse and save the values that are needed to later generate queries in the given RestRequestContext. // DbPolicyClause is an Abstract Syntax Tree representing the parsed policy text. - context.DbPolicyClause = _sqlMetadataProvider.GetODataParser().GetFilterClause(dbPolicy, $"{context.EntityName}.{context.DatabaseObject.FullName}"); + context.DbPolicyClause = _sqlMetadataProvider.GetODataParser().GetFilterClause( + filterQueryString: dbPolicy, + resourcePath: $"{context.EntityName}.{context.DatabaseObject.FullName}", + customResolver: new ClaimsTypeDataUriResolver()); } // At this point for DELETE, the primary key should be populated in the Request Context. From 53380c2b30db34bd9b16e5b8a688e3898772d90f Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Oct 2022 16:29:19 -0700 Subject: [PATCH 5/9] Added unit tests and fixed errors in type handling that arose. And introduced EDM Model builder handling of Guid types. --- .../Unittests/ODataASTVisitorUnitTests.cs | 46 +++++++++++++++++++ .../Parsers/ClaimsTypeDataUriResolver.cs | 8 ++++ src/Service/Parsers/EdmModelBuilder.cs | 6 ++- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs b/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs index 231b71e239..ff0af67ac1 100644 --- a/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs +++ b/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs @@ -2,10 +2,12 @@ using System.Threading.Tasks; using Azure.DataApiBuilder.Config; using Azure.DataApiBuilder.Service.Exceptions; +using Azure.DataApiBuilder.Service.GraphQLBuilder.GraphQLTypes; using Azure.DataApiBuilder.Service.Models; using Azure.DataApiBuilder.Service.Parsers; using Azure.DataApiBuilder.Service.Resolvers; using Azure.DataApiBuilder.Service.Tests.SqlTests; +using Microsoft.OData; using Microsoft.OData.Edm; using Microsoft.OData.UriParser; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -99,6 +101,50 @@ public void VisitorLeftFieldGreaterThanRightNullFilterTest() ); } + [DataTestMethod] + // Constant on left side and OData EDM object on right side of binary operator. (L->R) + [DataRow("'1' eq int_types", false, DisplayName = "L->R: Cast token claim of type string to integer, left to right ")] + [DataRow("'13B4F4EC-C45B-46EC-99F2-77BC22A256A7' eq guid_types", false, DisplayName = "L->R: Cast token claim of type string to GUID")] + [DataRow("'true' eq boolean_types", false, DisplayName = "L->R: Cast token claim of type string to bool (true)")] + [DataRow("'false' eq boolean_types", false, DisplayName = "L->R: Cast token claim of type string to bool (false)")] + [DataRow("1 eq string_types", false, DisplayName = "L->R: Cast token claim of type int to string")] + [DataRow("true eq string_types", false, DisplayName = "L->R: Cast token claim of type bool to string")] + // Constant on right side and OData EDM object on left side of binary operator. (R->L) + [DataRow("int_types eq '1'", false, DisplayName = "R->L: Cast token claim of type string to integer")] + [DataRow("guid_types eq '13B4F4EC-C45B-46EC-99F2-77BC22A256A7'", false, DisplayName = "R->L: Cast token claim of type string to GUID")] + [DataRow("boolean_types eq 'true'", false, DisplayName = "R->L: Cast token claim of type string to bool (true)")] + [DataRow("boolean_types eq 'false'", false, DisplayName = "R->L: Cast token claim of type string to bool (false)")] + [DataRow("string_types eq 1", false, DisplayName = "R->L: Cast token claim of type int to string")] + [DataRow("string_types eq true", false, DisplayName = "R->L: Cast token claim of type bool to string")] + // Comparisons expected to fail due to inability to cast + [DataRow("boolean_types eq 2", true, DisplayName = "Fail to cast arbitrary int to bool")] + [DataRow("guid_types eq 1", true, DisplayName = "Fail to cast arbitrary int to GUID")] + [DataRow("guid_types eq 'stringConstant'", true, DisplayName = "Fail to cast arbitrary string to GUID")] + public void CustomODataUriParserResolverTest(string resolvedAuthZPolicyText, bool errorExpected) + { + // Arrange + string entityName = "SupportedType"; + string tableName = "type_table"; + string filterQueryString = "?$filter=" + resolvedAuthZPolicyText; + string expectedErrorMessageFragment = "A binary operator with incompatible types was detected."; + + //Act + Assert + try + { + FilterClause ast = _sqlMetadataProvider + .GetODataParser() + .GetFilterClause( + filterQueryString, + resourcePath: $"{entityName}.{DEFAULT_SCHEMA_NAME}.{tableName}", + customResolver: new ClaimsTypeDataUriResolver()); + Assert.IsFalse(errorExpected, message: "Filter clause creation was expected to fail."); + } + catch (Exception e) when (e is DataApiBuilderException || e is ODataException) + { + Assert.IsTrue(errorExpected, message: "Filter clause creation was not expected to fail."); + Assert.IsTrue(e.Message.Contains(expectedErrorMessageFragment)); + } + } #endregion #region Negative Tests /// diff --git a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs index 1333bb2c90..a489b08647 100644 --- a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs +++ b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs @@ -1,3 +1,4 @@ +using System; using Microsoft.OData.Edm; using Microsoft.OData.UriParser; @@ -81,6 +82,13 @@ private static void TryConvertNodeToTargetType(EdmPrimitiveTypeKind targetType, operandToConvert = new ConstantNode(constantValue: result); } } + else if (targetType == EdmPrimitiveTypeKind.Guid) + { + if (Guid.TryParse(preConvertedConstant.Value.ToString(), out Guid result)) + { + operandToConvert = new ConstantNode(constantValue: result); + } + } } } } diff --git a/src/Service/Parsers/EdmModelBuilder.cs b/src/Service/Parsers/EdmModelBuilder.cs index 9383ca4aef..647ea41d28 100644 --- a/src/Service/Parsers/EdmModelBuilder.cs +++ b/src/Service/Parsers/EdmModelBuilder.cs @@ -76,10 +76,12 @@ SourceDefinition sourceDefinition switch (columnSystemType.Name) { - case "String": - case "Guid": + case "String": type = EdmPrimitiveTypeKind.String; break; + case "Guid": + type = EdmPrimitiveTypeKind.Guid; + break; case "Byte": type = EdmPrimitiveTypeKind.Byte; break; From dac7e16d654df1110a74fea50472f9c9c90e1477 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Oct 2022 16:30:19 -0700 Subject: [PATCH 6/9] remove bad using. --- src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs b/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs index ff0af67ac1..912843fe9c 100644 --- a/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs +++ b/src/Service.Tests/Unittests/ODataASTVisitorUnitTests.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Azure.DataApiBuilder.Config; using Azure.DataApiBuilder.Service.Exceptions; -using Azure.DataApiBuilder.Service.GraphQLBuilder.GraphQLTypes; using Azure.DataApiBuilder.Service.Models; using Azure.DataApiBuilder.Service.Parsers; using Azure.DataApiBuilder.Service.Resolvers; From 87611e9de394c48f132b4ee8dcce427ee70e6325 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 20 Oct 2022 16:41:02 -0700 Subject: [PATCH 7/9] remove extra whitespace. --- src/Service/Parsers/EdmModelBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/Parsers/EdmModelBuilder.cs b/src/Service/Parsers/EdmModelBuilder.cs index 647ea41d28..ea07f87a7b 100644 --- a/src/Service/Parsers/EdmModelBuilder.cs +++ b/src/Service/Parsers/EdmModelBuilder.cs @@ -76,7 +76,7 @@ SourceDefinition sourceDefinition switch (columnSystemType.Name) { - case "String": + case "String": type = EdmPrimitiveTypeKind.String; break; case "Guid": From 5674b93e85664c177d635383d165dab8efb07287 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Fri, 21 Oct 2022 10:11:14 -0700 Subject: [PATCH 8/9] updated comment to reflect that the custom resolver is NOT meant for URL query string processing. --- src/Service/Parsers/ClaimsTypeDataUriResolver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs index a489b08647..7b803c8c32 100644 --- a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs +++ b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs @@ -8,7 +8,7 @@ namespace Azure.DataApiBuilder.Service.Parsers /// Custom OData Resolver which attempts to assist with processing resolved token claims /// within an authorization policy string that will be used to create an OData filter clause. /// This resolver's type coercion is meant to be utilized for authorization policy processing - /// and URL query string processing. + /// and NOT URL query string processing. /// /// public class ClaimsTypeDataUriResolver : ODataUriResolver From d12d7eab75b24b4b79e7d75f5eff9b6cb64477e5 Mon Sep 17 00:00:00 2001 From: Sean Leonard Date: Thu, 27 Oct 2022 15:11:24 -0700 Subject: [PATCH 9/9] update comment and casting logic --- src/Service/Parsers/ClaimsTypeDataUriResolver.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs index a489b08647..3daa6bdefc 100644 --- a/src/Service/Parsers/ClaimsTypeDataUriResolver.cs +++ b/src/Service/Parsers/ClaimsTypeDataUriResolver.cs @@ -47,15 +47,15 @@ public override void PromoteBinaryOperandTypes(BinaryOperatorKind binaryOperator } /// - /// Uses type specific parsers to attempt conversion the supplied node to a new ConstantNode of type targetType. + /// Uses type specific parsers to attempt converting the supplied node to a new ConstantNode of type targetType. /// /// Primitive type (string, bool, int, etc.) of the primary node's value. /// Node representing a constant value which should be converted to a ConstantNode of type targetType. private static void TryConvertNodeToTargetType(EdmPrimitiveTypeKind targetType, ref SingleValueNode operandToConvert) { - ConstantNode preConvertedConstant = (ConstantNode)operandToConvert; + ConstantNode? preConvertedConstant = operandToConvert as ConstantNode; - if (preConvertedConstant.Value is null) + if (preConvertedConstant?.Value is null) { return; }