[java-identity-provider] branch main updated: IDP-1998 - DynamicAttributePredicate is limited to single value inputs
Scott Cantor
cantor.2 at osu.edu
Thu Aug 25 15:29:01 UTC 2022
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=10a3966f8d7b447869b565a75746ba4104a9580b
The following commit(s) were added to refs/heads/main by this push:
new 10a3966f8 IDP-1998 - DynamicAttributePredicate is limited to single value inputs
10a3966f8 is described below
commit 10a3966f8d7b447869b565a75746ba4104a9580b
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Aug 25 11:26:12 2022 -0400
IDP-1998 - DynamicAttributePredicate is limited to single value inputs
https://shibboleth.atlassian.net/browse/IDP-1998
---
.../profile/logic/DynamicAttributePredicate.java | 41 +++++++--
.../logic/DynamicAttributePredicateTest.java | 99 ++++++++++++++++++++++
2 files changed, 134 insertions(+), 6 deletions(-)
diff --git a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/logic/DynamicAttributePredicate.java b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/logic/DynamicAttributePredicate.java
index ab6686bc3..0f199dab2 100644
--- a/idp-profile-api/src/main/java/net/shibboleth/idp/profile/logic/DynamicAttributePredicate.java
+++ b/idp-profile-api/src/main/java/net/shibboleth/idp/profile/logic/DynamicAttributePredicate.java
@@ -45,6 +45,11 @@ import java.util.function.Function;
* Predicate over an {@link AttributeContext} that derives the value(s) to match based
* on one or more supplied Functions instead of static values.
*
+ * <p>Each function installed must return a value that matches a value of the attribute
+ * corresponding to the map key.</p>
+ *
+ * <p>Functions may return a {@link String} or a {@link Collection} containing them.</p>
+ *
* @since 3.4.0
*/
public class DynamicAttributePredicate extends AbstractAttributePredicate {
@@ -53,7 +58,7 @@ public class DynamicAttributePredicate extends AbstractAttributePredicate {
@Nonnull private final Logger log = LoggerFactory.getLogger(DynamicAttributePredicate.class);
/** Map of attribute IDs to functions. */
- @Nonnull @NonnullElements private ListMultimap<String,Function<ProfileRequestContext,String>> attributeFunctionMap;
+ @Nonnull @NonnullElements private ListMultimap<String,Function<ProfileRequestContext,Object>> attributeFunctionMap;
/** Constructor. */
public DynamicAttributePredicate() {
@@ -66,11 +71,11 @@ public class DynamicAttributePredicate extends AbstractAttributePredicate {
* @param map map of attribute/function pairs
*/
public void setAttributeFunctionMap(
- @Nonnull @NonnullElements final Map<String,Collection<Function<ProfileRequestContext,String>>> map) {
+ @Nonnull @NonnullElements final Map<String,Collection<Function<ProfileRequestContext,Object>>> map) {
Constraint.isNotNull(map, "Attribute/value map cannot be null");
attributeFunctionMap.clear();
- for (final Map.Entry<String,Collection<Function<ProfileRequestContext,String>>> entry : map.entrySet()) {
+ for (final Map.Entry<String,Collection<Function<ProfileRequestContext,Object>>> entry : map.entrySet()) {
final String attributeId = StringSupport.trimOrNull(entry.getKey());
attributeFunctionMap.putAll(attributeId, List.copyOf(entry.getValue()));
}
@@ -103,6 +108,7 @@ public class DynamicAttributePredicate extends AbstractAttributePredicate {
return false;
}
+// Checkstyle: CyclomaticComplexity OFF
/**
* Implementation of the condition to evaluate.
*
@@ -125,9 +131,31 @@ public class DynamicAttributePredicate extends AbstractAttributePredicate {
boolean matched = false;
- for (final Function<ProfileRequestContext,String> fn : attributeFunctionMap.get(id)) {
- if (findMatch(fn.apply(profileRequestContext), attribute)) {
- matched = true;
+ for (final Function<ProfileRequestContext,Object> fn : attributeFunctionMap.get(id)) {
+
+ final Object candidate = fn.apply(profileRequestContext);
+
+ if (candidate instanceof String) {
+ matched = findMatch((String) candidate, attribute);
+ } else if (candidate instanceof Collection<?>) {
+ for (final Object subcandidate : (Collection<?>) candidate) {
+ if (subcandidate instanceof String) {
+ if (findMatch((String) subcandidate, attribute)) {
+ matched = true;
+ break;
+ }
+ } else {
+ log.error(
+ "Collection returned by function for attribute {} contained an unsupported type: {}",
+ id, subcandidate.getClass().getName());
+ }
+ }
+ } else {
+ log.error("Function for attribute {} returned an unsupported type: {}", id,
+ candidate.getClass().getName());
+ }
+
+ if (matched) {
break;
}
}
@@ -140,6 +168,7 @@ public class DynamicAttributePredicate extends AbstractAttributePredicate {
return true;
}
+// Checkstyle: CyclomaticComplexity ON
/**
* Look for a matching value in an attribute.
diff --git a/idp-profile-api/src/test/java/net/shibboleth/idp/profile/logic/DynamicAttributePredicateTest.java b/idp-profile-api/src/test/java/net/shibboleth/idp/profile/logic/DynamicAttributePredicateTest.java
new file mode 100644
index 000000000..6a5442ae1
--- /dev/null
+++ b/idp-profile-api/src/test/java/net/shibboleth/idp/profile/logic/DynamicAttributePredicateTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.idp.profile.logic;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.ScopedStringAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.context.AttributeContext;
+import net.shibboleth.idp.profile.context.RelyingPartyContext;
+import net.shibboleth.utilities.java.support.logic.FunctionSupport;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static org.testng.Assert.*;
+
+/**
+ * Unit test for {@link DynamicAttributePredicate}.
+ */
+public class DynamicAttributePredicateTest {
+
+ @Test
+ public void testInvalid() {
+ final ProfileRequestContext prc = createProfileRequestContext("foo", List.of("bar", "baz"));
+ DynamicAttributePredicate predicate = new DynamicAttributePredicate();
+
+ predicate.setAttributeFunctionMap(Map.of("foo", Collections.singleton(FunctionSupport.constant(List.of(10)))));
+ assertFalse(predicate.test(prc));
+
+ predicate.setAttributeFunctionMap(Map.of("foo", Collections.singleton(FunctionSupport.constant(10))));
+ assertFalse(predicate.test(prc));
+ }
+
+ @Test
+ public void testString() {
+ final ProfileRequestContext prc = createProfileRequestContext("foo", List.of("bar", "baz"));
+ DynamicAttributePredicate predicate = new DynamicAttributePredicate();
+
+ predicate.setAttributeFunctionMap(Map.of("foo2", Collections.singleton(FunctionSupport.constant(List.of("bar")))));
+ assertFalse(predicate.test(prc));
+
+ predicate.setAttributeFunctionMap(Map.of("foo2", Collections.singleton(FunctionSupport.constant("bar"))));
+ assertFalse(predicate.test(prc));
+
+ predicate.setAttributeFunctionMap(Map.of("foo2", Collections.singleton(FunctionSupport.constant("*"))));
+ assertFalse(predicate.test(prc));
+
+ predicate.setAttributeFunctionMap(Map.of("foo", Collections.singleton(FunctionSupport.constant("*"))));
+ assertTrue(predicate.test(prc));
+
+ predicate.setAttributeFunctionMap(Map.of("foo", Collections.singleton(FunctionSupport.constant(List.of("bar", "baz")))));
+ assertTrue(predicate.test(prc));
+ }
+
+ private ProfileRequestContext createProfileRequestContext(final String name, final Collection<String> values) {
+ final ProfileRequestContext prc = new ProfileRequestContext();
+ final RelyingPartyContext rpc = new RelyingPartyContext();
+ final IdPAttribute attribute = new IdPAttribute(name);
+ final List<IdPAttributeValue> attributeValues = new ArrayList<>();
+ for (final String value : values) {
+ final int i = value.indexOf('@');
+ if (i == -1) {
+ attributeValues.add(new StringAttributeValue(value));
+ } else {
+ attributeValues.add(new ScopedStringAttributeValue(value.substring(0,i), value.substring(i + 1)));
+ }
+ }
+ attribute.setValues(attributeValues);
+ final AttributeContext ac = new AttributeContext();
+ ac.setIdPAttributes(Collections.singletonList(attribute));
+ ac.setUnfilteredIdPAttributes(Collections.singletonList(attribute));
+ rpc.addSubcontext(ac);
+ prc.addSubcontext(rpc);
+ return prc;
+ }
+
+}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list