mirror of
https://github.com/keycloak/keycloak.git
synced 2026-02-03 20:39:33 -05:00
Check only for the existence of the attribute if only the key is specified
Closes #45983 Signed-off-by: Stefan Guilhen <sguilhen@redhat.com>
This commit is contained in:
parent
021d544000
commit
2111dcf913
2 changed files with 42 additions and 13 deletions
|
|
@ -50,8 +50,17 @@ public class UserAttributeWorkflowConditionProvider implements WorkflowCondition
|
|||
}
|
||||
|
||||
String[] parsedKeyValuePair = parseKeyValuePair(expectedAttribute);
|
||||
List<String> values = user.getAttributes().getOrDefault(parsedKeyValuePair[0], List.of());
|
||||
List<String> expectedValues = List.of(parsedKeyValuePair[1].split(","));
|
||||
String key = parsedKeyValuePair[0];
|
||||
String valuePart = parsedKeyValuePair[1];
|
||||
|
||||
// Presence-only: "key:" -> true if user has at least one attribute with that key
|
||||
if (valuePart.isEmpty()) {
|
||||
List<String> values = user.getAttributes().getOrDefault(key, List.of());
|
||||
return !values.isEmpty();
|
||||
}
|
||||
|
||||
List<String> values = user.getAttributes().getOrDefault(key, List.of());
|
||||
List<String> expectedValues = List.of(valuePart.split(","));
|
||||
|
||||
return collectionEquals(expectedValues, values);
|
||||
}
|
||||
|
|
@ -62,7 +71,14 @@ public class UserAttributeWorkflowConditionProvider implements WorkflowCondition
|
|||
|
||||
String[] parsedKeyValuePair = parseKeyValuePair(expectedAttribute);
|
||||
String attributeName = parsedKeyValuePair[0];
|
||||
List<String> expectedValues = Arrays.asList(parsedKeyValuePair[1].split(","));
|
||||
String valuePart = parsedKeyValuePair[1];
|
||||
|
||||
// Presence-only: require at least one attribute with this name for the user
|
||||
if (valuePart.isEmpty()) {
|
||||
return cb.greaterThan(createTotalCountSubquery(cb, query, path, attributeName), 0L);
|
||||
}
|
||||
|
||||
List<String> expectedValues = Arrays.asList(valuePart.split(","));
|
||||
|
||||
// Subquery to count how many of the expected values the user has
|
||||
// to check if there is no missing value
|
||||
|
|
@ -95,24 +111,29 @@ public class UserAttributeWorkflowConditionProvider implements WorkflowCondition
|
|||
|
||||
// Subquery to count total attributes with this name for the user
|
||||
// to check if there are no extra values
|
||||
Subquery<Long> totalCountSubquery = query.subquery(Long.class);
|
||||
Root<UserAttributeEntity> attrRoot2 = totalCountSubquery.from(UserAttributeEntity.class);
|
||||
totalCountSubquery.select(cb.count(attrRoot2));
|
||||
totalCountSubquery.where(
|
||||
cb.and(
|
||||
cb.equal(attrRoot2.get("user").get("id"), path.get("id")),
|
||||
cb.equal(attrRoot2.get("name"), attributeName)
|
||||
)
|
||||
);
|
||||
createTotalCountSubquery(cb, query, path, attributeName);
|
||||
|
||||
// Both counts must equal the expected count (exact match)
|
||||
int expectedCount = expectedValues.size();
|
||||
return cb.and(
|
||||
cb.equal(matchingCountSubquery, expectedCount),
|
||||
cb.equal(totalCountSubquery, expectedCount)
|
||||
cb.equal(createTotalCountSubquery(cb, query, path, attributeName), expectedCount)
|
||||
);
|
||||
}
|
||||
|
||||
private Subquery<Long> createTotalCountSubquery(CriteriaBuilder cb, CriteriaQuery<String> query, Root<?> path, String attributeName) {
|
||||
Subquery<Long> totalCountSubquery = query.subquery(Long.class);
|
||||
Root<UserAttributeEntity> attrRoot = totalCountSubquery.from(UserAttributeEntity.class);
|
||||
totalCountSubquery.select(cb.count(attrRoot));
|
||||
totalCountSubquery.where(
|
||||
cb.and(
|
||||
cb.equal(attrRoot.get("user").get("id"), path.get("id")),
|
||||
cb.equal(attrRoot.get("name"), attributeName)
|
||||
)
|
||||
);
|
||||
return totalCountSubquery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() {
|
||||
if (expectedAttribute == null) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,14 @@ public class UserAttributeWorkflowConditionTest extends AbstractWorkflowTest {
|
|||
managedRealm.admin().users().userProfile().update(upConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionForAnyValuedAttribute() {
|
||||
createWorkflow(List.of());
|
||||
assertUserAttribute("user-1", true, "singleValue");
|
||||
assertUserAttribute("user-2", true, "v1", "v2", "v3");
|
||||
assertUserAttribute("user-3", false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionForSingleValuedAttribute() {
|
||||
String expected = "valid";
|
||||
|
|
|
|||
Loading…
Reference in a new issue