From e0b72e29cbf2d08503a631ef38a372e25be873f3 Mon Sep 17 00:00:00 2001 From: Sanjula Herath Date: Wed, 12 Aug 2026 16:11:09 +0530 Subject: [PATCH 1/3] Fix RAR schema validator integer keyword normalization Normalize integer-valued schema keywords before creating the Vert.x JsonObject used for RAR authorization details schema validation. This avoids ClassCastException failures when JSON schema numeric keywords such as minItems, maxItems, minLength, and maxLength are represented as integral Double values. The normalization is recursive, preserves the caller-owned schema map, and only converts non-negative integer-range values for supported schema-size keywords. --- ...thorizationDetailsSchemaValidatorImpl.java | 96 ++++++++++++++++++- ...thorizationDetailsSchemaValidatorTest.java | 76 +++++++++++++++ 2 files changed, 171 insertions(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java index a7bcad71b15..92c4ab0892a 100644 --- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java +++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java @@ -37,7 +37,14 @@ import org.wso2.carbon.identity.oauth.rar.exception.AuthorizationDetailsProcessingException; import org.wso2.carbon.identity.oauth.rar.model.AuthorizationDetail; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.Set; import static org.wso2.carbon.identity.oauth.rar.util.AuthorizationDetailsConstants.SCHEMA_VALIDATION_FAILED_ERR_MSG_FORMAT; import static org.wso2.carbon.identity.oauth.rar.util.AuthorizationDetailsConstants.TYPE_VALIDATION_FAILED_ERR_MSG_FORMAT; @@ -68,6 +75,8 @@ public class AuthorizationDetailsSchemaValidatorImpl implements AuthorizationDet private static final String ADDITIONAL_PROPERTIES = "additionalProperties"; private static final String BASE_URI = "https://wso2.com/identity-server/schemas"; + private static final Set NON_NEGATIVE_INTEGER_SCHEMA_KEYWORDS = Set.of("minItems", "maxItems", + "minLength", "maxLength", "minProperties", "maxProperties"); private static volatile AuthorizationDetailsSchemaValidator instance; private final JsonSchemaOptions jsonSchemaOptions; @@ -218,9 +227,94 @@ public boolean isSchemaCompliant(final Map schema, final Authori return false; } - final JsonObject jsonSchema = new JsonObject(schema); + final JsonObject jsonSchema = new JsonObject(this.normalizeSchemaMap(schema)); jsonSchema.put(ADDITIONAL_PROPERTIES, false); // Ensure no unknown fields are allowed return this.isSchemaCompliant(jsonSchema, authorizationDetail); } + + private Map normalizeSchemaMap(final Map schema) { + + final Map normalizedSchema = new HashMap<>(); + for (Map.Entry entry : schema.entrySet()) { + normalizedSchema.put(entry.getKey(), this.normalizeSchemaValue(entry.getKey(), entry.getValue())); + } + return normalizedSchema; + } + + @SuppressWarnings("unchecked") + private Object normalizeSchemaValue(final String key, final Object value) { + + if (NON_NEGATIVE_INTEGER_SCHEMA_KEYWORDS.contains(key)) { + return this.normalizeNonNegativeIntegerSchemaKeyword(value); + } + if (value instanceof Map) { + return this.normalizeSchemaMap((Map) value); + } + if (value instanceof Collection) { + return this.normalizeSchemaCollection((Collection) value); + } + return value; + } + + @SuppressWarnings("unchecked") + private List normalizeSchemaCollection(final Collection values) { + + final List normalizedValues = new ArrayList<>(values.size()); + for (Object value : values) { + if (value instanceof Map) { + normalizedValues.add(this.normalizeSchemaMap((Map) value)); + } else if (value instanceof Collection) { + normalizedValues.add(this.normalizeSchemaCollection((Collection) value)); + } else { + normalizedValues.add(value); + } + } + return normalizedValues; + } + + private Object normalizeNonNegativeIntegerSchemaKeyword(final Object value) { + + if (!(value instanceof Number)) { + return value; + } + + final Number number = (Number) value; + if (number instanceof Integer) { + return number; + } + if (number instanceof Byte || number instanceof Short) { + final int intValue = number.intValue(); + return intValue >= 0 ? intValue : value; + } + if (number instanceof Long) { + final long longValue = number.longValue(); + return longValue >= 0 && longValue <= Integer.MAX_VALUE ? (int) longValue : value; + } + if (number instanceof BigInteger) { + return this.normalizeBigInteger((BigInteger) number, value); + } + if (number instanceof BigDecimal) { + try { + return this.normalizeBigInteger(((BigDecimal) number).toBigIntegerExact(), value); + } catch (ArithmeticException e) { + return value; + } + } + + final double doubleValue = number.doubleValue(); + if (Double.isFinite(doubleValue) && doubleValue >= 0 && doubleValue <= Integer.MAX_VALUE + && doubleValue == Math.rint(doubleValue)) { + return (int) doubleValue; + } + return value; + } + + private Object normalizeBigInteger(final BigInteger integerValue, final Object originalValue) { + + if (integerValue.signum() >= 0 && integerValue.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) <= 0) { + return integerValue.intValue(); + } + return originalValue; + } } diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java index 35ae924def7..167f3f94dd0 100644 --- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java +++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java @@ -34,6 +34,7 @@ import java.util.HashMap; import java.util.Map; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.wso2.carbon.identity.oauth.rar.util.TestConstants.TEST_SCHEMA; @@ -92,6 +93,43 @@ public void shouldThrowAuthorizationDetailsProcessingException_whenAuthorization assertTrue(this.uut.isSchemaCompliant(TEST_SCHEMA, testAuthorizationDetail)); } + @Test + public void shouldReturnTrue_whenMapSchemaContainsIntegralDoubleIntegerKeywords() + throws AuthorizationDetailsProcessingException { + + TestDAOUtils.TestAuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail(); + testAuthorizationDetail.setType(TEST_TYPE); + testAuthorizationDetail.setName("test_name_v1"); + testAuthorizationDetail.setActions(Arrays.asList("initiate", "cancel")); + + Map schema = this.getTestSchemaWithDoubleIntegerKeywords(); + + assertTrue(this.uut.isSchemaCompliant(schema, testAuthorizationDetail)); + + Map actionsSchema = this.getPropertySchema(schema, "actions"); + Map nameSchema = this.getPropertySchema(schema, "name"); + assertTrue(actionsSchema.get("minItems") instanceof Double); + assertTrue(actionsSchema.get("maxItems") instanceof Double); + assertTrue(nameSchema.get("minLength") instanceof Double); + assertTrue(nameSchema.get("maxLength") instanceof Double); + assertEquals(actionsSchema.get("minItems"), 1.0d); + assertEquals(actionsSchema.get("maxItems"), 3.0d); + assertEquals(nameSchema.get("minLength"), 1.0d); + assertEquals(nameSchema.get("maxLength"), 20.0d); + } + + @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class}) + public void shouldThrowAuthorizationDetailsProcessingException_whenMapSchemaViolatesNormalizedMaxItems() + throws AuthorizationDetailsProcessingException { + + TestDAOUtils.TestAuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail(); + testAuthorizationDetail.setType(TEST_TYPE); + testAuthorizationDetail.setName("test_name_v1"); + testAuthorizationDetail.setActions(Arrays.asList("initiate", "cancel", "confirm", "revoke")); + + this.uut.isSchemaCompliant(this.getTestSchemaWithDoubleIntegerKeywords(), testAuthorizationDetail); + } + @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class}) public void shouldThrowAuthorizationDetailsProcessingException_whenSchemaIsInvalid1() throws AuthorizationDetailsProcessingException { @@ -137,4 +175,42 @@ private Map getTestSchema() { schema.put("properties", properties); return schema; } + + private Map getTestSchemaWithDoubleIntegerKeywords() { + + final Map items = new HashMap<>(); + items.put("type", "string"); + + final Map actions = new HashMap<>(); + actions.put("type", "array"); + actions.put("items", items); + actions.put("minItems", 1.0d); + actions.put("maxItems", 3.0d); + + final Map type = new HashMap<>(); + type.put("type", "string"); + type.put("enum", Collections.singletonList("test_type_v1")); + + final Map name = new HashMap<>(); + name.put("type", "string"); + name.put("minLength", 1.0d); + name.put("maxLength", 20.0d); + + final Map properties = new HashMap<>(); + properties.put("type", type); + properties.put("actions", actions); + properties.put("name", name); + + final Map schema = new HashMap<>(); + schema.put("type", "object"); + schema.put("required", Arrays.asList("type", "actions", "name")); + schema.put("properties", properties); + return schema; + } + + @SuppressWarnings("unchecked") + private Map getPropertySchema(final Map schema, final String propertyName) { + + return (Map) ((Map) schema.get("properties")).get(propertyName); + } } From b5aceb627d4b3ff61502179cf19c0483521c74eb Mon Sep 17 00:00:00 2001 From: Sanjula Herath Date: Thu, 13 Aug 2026 19:14:13 +0530 Subject: [PATCH 2/3] Recurse into subschemas of keyword named properties The schema normalizer selected values for integer conversion by key name alone. When an authorization detail property was itself named after one of the six supported keywords, its subschema was handed to the numeric converter, returned unchanged and never recursed into. Nested minItems and maxItems values therefore stayed as Double and validation still failed with the ClassCastException reported in wso2/product-is#28292. Gate the keyword conversion on the value actually being a Number so map and collection values continue through the recursive paths. Add regression coverage for keyword named properties, boundary values, keywords nested inside schema lists, caller owned map immutability and unrelated numeric keywords that must never be converted. --- ...thorizationDetailsSchemaValidatorImpl.java | 2 +- ...thorizationDetailsSchemaValidatorTest.java | 169 ++++++++++++++++++ 2 files changed, 170 insertions(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java index 92c4ab0892a..6584a100c66 100644 --- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java +++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java @@ -245,7 +245,7 @@ private Map normalizeSchemaMap(final Map schema) @SuppressWarnings("unchecked") private Object normalizeSchemaValue(final String key, final Object value) { - if (NON_NEGATIVE_INTEGER_SCHEMA_KEYWORDS.contains(key)) { + if (value instanceof Number && NON_NEGATIVE_INTEGER_SCHEMA_KEYWORDS.contains(key)) { return this.normalizeNonNegativeIntegerSchemaKeyword(value); } if (value instanceof Map) { diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java index 167f3f94dd0..e5dfd2f4a2f 100644 --- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java +++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java @@ -130,6 +130,109 @@ public void shouldThrowAuthorizationDetailsProcessingException_whenMapSchemaViol this.uut.isSchemaCompliant(this.getTestSchemaWithDoubleIntegerKeywords(), testAuthorizationDetail); } + @Test + public void shouldReturnTrue_whenPropertyNameMatchesIntegerSchemaKeyword() + throws AuthorizationDetailsProcessingException { + + TestDAOUtils.TestAuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail(); + testAuthorizationDetail.setType(TEST_TYPE); + testAuthorizationDetail.setDetail("maxLength", Collections.singletonList("initiate")); + + assertTrue(this.uut.isSchemaCompliant(this.getTestSchemaWithKeywordNamedProperty(), testAuthorizationDetail)); + } + + @Test + public void shouldReturnTrue_whenIntegerKeywordsAreAtBoundaryValues() + throws AuthorizationDetailsProcessingException { + + TestDAOUtils.TestAuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail(); + testAuthorizationDetail.setType(TEST_TYPE); + testAuthorizationDetail.setActions(Collections.singletonList("initiate")); + + final Map items = new HashMap<>(); + items.put("type", "string"); + + final Map actions = new HashMap<>(); + actions.put("type", "array"); + actions.put("items", items); + actions.put("minItems", 0.0d); + actions.put("maxItems", (double) Integer.MAX_VALUE); + + final Map type = new HashMap<>(); + type.put("type", "string"); + type.put("enum", Collections.singletonList("test_type_v1")); + + final Map properties = new HashMap<>(); + properties.put("type", type); + properties.put("actions", actions); + + final Map schema = new HashMap<>(); + schema.put("type", "object"); + schema.put("required", Collections.singletonList("type")); + schema.put("properties", properties); + + assertTrue(this.uut.isSchemaCompliant(schema, testAuthorizationDetail)); + } + + @Test + public void shouldReturnTrue_whenIntegerKeywordsAreNestedInsideSchemaLists() + throws AuthorizationDetailsProcessingException { + + TestDAOUtils.TestAuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail(); + testAuthorizationDetail.setType(TEST_TYPE); + testAuthorizationDetail.setName("test_name_v1"); + + final Map minLengthConstraint = new HashMap<>(); + minLengthConstraint.put("type", "string"); + minLengthConstraint.put("minLength", 2.0d); + + final Map maxLengthConstraint = new HashMap<>(); + maxLengthConstraint.put("type", "string"); + maxLengthConstraint.put("maxLength", 20.0d); + + final Map name = new HashMap<>(); + name.put("allOf", Arrays.asList(minLengthConstraint, maxLengthConstraint)); + + final Map type = new HashMap<>(); + type.put("type", "string"); + type.put("enum", Collections.singletonList("test_type_v1")); + + final Map properties = new HashMap<>(); + properties.put("type", type); + properties.put("name", name); + + final Map schema = new HashMap<>(); + schema.put("type", "object"); + schema.put("required", Collections.singletonList("type")); + schema.put("properties", properties); + + assertTrue(this.uut.isSchemaCompliant(schema, testAuthorizationDetail)); + } + + @Test + public void shouldNotMutateCallerOwnedSchema_whenValidatingMapSchema() + throws AuthorizationDetailsProcessingException { + + TestDAOUtils.TestAuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail(); + testAuthorizationDetail.setType(TEST_TYPE); + testAuthorizationDetail.setName("test_name_v1"); + testAuthorizationDetail.setActions(Arrays.asList("initiate", "cancel")); + testAuthorizationDetail.setDetail("amount", 5); + + Map schema = this.getTestSchemaWithMixedNumericKeywords(); + + assertTrue(this.uut.isSchemaCompliant(schema, testAuthorizationDetail)); + + // The validator must not inject `additionalProperties` into the caller owned map. + assertFalse(schema.containsKey("additionalProperties")); + // Nested maps and nested lists must be left exactly as the caller provided them. + assertEquals(schema, this.getTestSchemaWithMixedNumericKeywords()); + + Map amountSchema = this.getPropertySchema(schema, "amount"); + assertTrue(amountSchema.get("minimum") instanceof Double); + assertTrue(amountSchema.get("multipleOf") instanceof Double); + } + @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class}) public void shouldThrowAuthorizationDetailsProcessingException_whenSchemaIsInvalid1() throws AuthorizationDetailsProcessingException { @@ -208,6 +311,72 @@ private Map getTestSchemaWithDoubleIntegerKeywords() { return schema; } + private Map getTestSchemaWithMixedNumericKeywords() { + + final Map items = new HashMap<>(); + items.put("type", "string"); + + final Map actions = new HashMap<>(); + actions.put("type", "array"); + actions.put("items", items); + actions.put("minItems", 1.0d); + actions.put("maxItems", 3.0d); + + final Map type = new HashMap<>(); + type.put("type", "string"); + type.put("enum", Collections.singletonList("test_type_v1")); + + final Map name = new HashMap<>(); + name.put("type", "string"); + name.put("minLength", 1.0d); + name.put("maxLength", 20.0d); + + // `minimum` and `multipleOf` accept non integral values and must never be converted. + final Map amount = new HashMap<>(); + amount.put("type", "number"); + amount.put("minimum", 1.0d); + amount.put("multipleOf", 1.0d); + + final Map properties = new HashMap<>(); + properties.put("type", type); + properties.put("actions", actions); + properties.put("name", name); + properties.put("amount", amount); + + final Map schema = new HashMap<>(); + schema.put("type", "object"); + schema.put("required", Arrays.asList("type", "actions", "name")); + schema.put("properties", properties); + return schema; + } + + private Map getTestSchemaWithKeywordNamedProperty() { + + final Map type = new HashMap<>(); + type.put("type", "string"); + type.put("enum", Collections.singletonList("test_type_v1")); + + final Map items = new HashMap<>(); + items.put("type", "string"); + + // An authorization detail property may legitimately be named after a schema keyword. + final Map keywordNamedProperty = new HashMap<>(); + keywordNamedProperty.put("type", "array"); + keywordNamedProperty.put("items", items); + keywordNamedProperty.put("minItems", 1.0d); + keywordNamedProperty.put("maxItems", 3.0d); + + final Map properties = new HashMap<>(); + properties.put("type", type); + properties.put("maxLength", keywordNamedProperty); + + final Map schema = new HashMap<>(); + schema.put("type", "object"); + schema.put("required", Collections.singletonList("type")); + schema.put("properties", properties); + return schema; + } + @SuppressWarnings("unchecked") private Map getPropertySchema(final Map schema, final String propertyName) { From eb54bc83a8bace6a5be6f49fa7f33376f6ff1ca4 Mon Sep 17 00:00:00 2001 From: Sanjula Date: Mon, 28 Sep 2026 13:38:00 +0530 Subject: [PATCH 3/3] Normalize minContains and maxContains schema keywords --- ...thorizationDetailsSchemaValidatorImpl.java | 2 +- ...thorizationDetailsSchemaValidatorTest.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java index 6584a100c66..a16532db47a 100644 --- a/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java +++ b/components/org.wso2.carbon.identity.oauth.rar/src/main/java/org/wso2/carbon/identity/oauth/rar/core/AuthorizationDetailsSchemaValidatorImpl.java @@ -76,7 +76,7 @@ public class AuthorizationDetailsSchemaValidatorImpl implements AuthorizationDet private static final String ADDITIONAL_PROPERTIES = "additionalProperties"; private static final String BASE_URI = "https://wso2.com/identity-server/schemas"; private static final Set NON_NEGATIVE_INTEGER_SCHEMA_KEYWORDS = Set.of("minItems", "maxItems", - "minLength", "maxLength", "minProperties", "maxProperties"); + "minLength", "maxLength", "minProperties", "maxProperties", "minContains", "maxContains"); private static volatile AuthorizationDetailsSchemaValidator instance; private final JsonSchemaOptions jsonSchemaOptions; diff --git a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java index e5dfd2f4a2f..0e81229abca 100644 --- a/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java +++ b/components/org.wso2.carbon.identity.oauth.rar/src/test/java/org/wso2/carbon/identity/oauth/rar/AuthorizationDetailsSchemaValidatorTest.java @@ -110,10 +110,14 @@ public void shouldReturnTrue_whenMapSchemaContainsIntegralDoubleIntegerKeywords( Map nameSchema = this.getPropertySchema(schema, "name"); assertTrue(actionsSchema.get("minItems") instanceof Double); assertTrue(actionsSchema.get("maxItems") instanceof Double); + assertTrue(actionsSchema.get("minContains") instanceof Double); + assertTrue(actionsSchema.get("maxContains") instanceof Double); assertTrue(nameSchema.get("minLength") instanceof Double); assertTrue(nameSchema.get("maxLength") instanceof Double); assertEquals(actionsSchema.get("minItems"), 1.0d); assertEquals(actionsSchema.get("maxItems"), 3.0d); + assertEquals(actionsSchema.get("minContains"), 1.0d); + assertEquals(actionsSchema.get("maxContains"), 1.0d); assertEquals(nameSchema.get("minLength"), 1.0d); assertEquals(nameSchema.get("maxLength"), 20.0d); } @@ -130,6 +134,18 @@ public void shouldThrowAuthorizationDetailsProcessingException_whenMapSchemaViol this.uut.isSchemaCompliant(this.getTestSchemaWithDoubleIntegerKeywords(), testAuthorizationDetail); } + @Test(expectedExceptions = {AuthorizationDetailsProcessingException.class}) + public void shouldThrowAuthorizationDetailsProcessingException_whenMapSchemaViolatesNormalizedMaxContains() + throws AuthorizationDetailsProcessingException { + + TestDAOUtils.TestAuthorizationDetail testAuthorizationDetail = new TestDAOUtils.TestAuthorizationDetail(); + testAuthorizationDetail.setType(TEST_TYPE); + testAuthorizationDetail.setName("test_name_v1"); + testAuthorizationDetail.setActions(Arrays.asList("initiate", "initiate")); + + this.uut.isSchemaCompliant(this.getTestSchemaWithDoubleIntegerKeywords(), testAuthorizationDetail); + } + @Test public void shouldReturnTrue_whenPropertyNameMatchesIntegerSchemaKeyword() throws AuthorizationDetailsProcessingException { @@ -284,11 +300,17 @@ private Map getTestSchemaWithDoubleIntegerKeywords() { final Map items = new HashMap<>(); items.put("type", "string"); + final Map contains = new HashMap<>(); + contains.put("const", "initiate"); + final Map actions = new HashMap<>(); actions.put("type", "array"); actions.put("items", items); actions.put("minItems", 1.0d); actions.put("maxItems", 3.0d); + actions.put("contains", contains); + actions.put("minContains", 1.0d); + actions.put("maxContains", 1.0d); final Map type = new HashMap<>(); type.put("type", "string");