Cannot set unmanagedAttributePolicy without profile attributes
Closes #31153 Signed-off-by: Martin Kanis <mkanis@redhat.com>
This commit is contained in:
parent
5526976d1c
commit
e5848bdcf9
4 changed files with 45 additions and 14 deletions
|
@ -28,7 +28,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration of the User Profile for one realm.
|
* Configuration of the User Profile for one realm.
|
||||||
*
|
*
|
||||||
* @author Vlastimil Elias <velias@redhat.com>
|
* @author Vlastimil Elias <velias@redhat.com>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -71,7 +71,7 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method used for predicate which returns true if any of the configuredScopes is requested in current auth flow.
|
* Method used for predicate which returns true if any of the configuredScopes is requested in current auth flow.
|
||||||
*
|
*
|
||||||
* @param context to get current auth flow from
|
* @param context to get current auth flow from
|
||||||
* @param configuredScopes to be evaluated
|
* @param configuredScopes to be evaluated
|
||||||
* @return
|
* @return
|
||||||
|
@ -248,13 +248,13 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
|
||||||
protected UserProfileMetadata decorateUserProfileForCache(UserProfileMetadata decoratedMetadata, UPConfig parsedConfig) {
|
protected UserProfileMetadata decorateUserProfileForCache(UserProfileMetadata decoratedMetadata, UPConfig parsedConfig) {
|
||||||
UserProfileContext context = decoratedMetadata.getContext();
|
UserProfileContext context = decoratedMetadata.getContext();
|
||||||
|
|
||||||
if (parsedConfig == null) {
|
if (parsedConfig == null || parsedConfig.getAttributes() == null) {
|
||||||
return decoratedMetadata;
|
return decoratedMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, UPGroup> groupsByName = asHashMap(parsedConfig.getGroups());
|
Map<String, UPGroup> groupsByName = asHashMap(parsedConfig.getGroups());
|
||||||
int guiOrder = 0;
|
int guiOrder = 0;
|
||||||
|
|
||||||
for (UPAttribute attrConfig : parsedConfig.getAttributes()) {
|
for (UPAttribute attrConfig : parsedConfig.getAttributes()) {
|
||||||
String attributeName = attrConfig.getName();
|
String attributeName = attrConfig.getName();
|
||||||
|
|
||||||
|
@ -413,7 +413,7 @@ public class DeclarativeUserProfileProvider implements UserProfileProvider {
|
||||||
private Map<String, UPGroup> asHashMap(List<UPGroup> groups) {
|
private Map<String, UPGroup> asHashMap(List<UPGroup> groups) {
|
||||||
return groups.stream().collect(Collectors.toMap(g -> g.getName(), g -> g));
|
return groups.stream().collect(Collectors.toMap(g -> g.getName(), g -> g));
|
||||||
}
|
}
|
||||||
|
|
||||||
private AttributeGroupMetadata toAttributeGroupMeta(UPGroup group) {
|
private AttributeGroupMetadata toAttributeGroupMeta(UPGroup group) {
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -50,7 +50,7 @@ import org.keycloak.validate.Validators;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods to work with User Profile Configurations
|
* Utility methods to work with User Profile Configurations
|
||||||
*
|
*
|
||||||
* @author Vlastimil Elias <velias@redhat.com>
|
* @author Vlastimil Elias <velias@redhat.com>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -112,13 +112,13 @@ public class UPConfigUtils {
|
||||||
errors.addAll(validateAttributeGroups(config));
|
errors.addAll(validateAttributeGroups(config));
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<String> validateAttributeGroups(UPConfig config) {
|
private static List<String> validateAttributeGroups(UPConfig config) {
|
||||||
long groupsWithoutName = config.getGroups().stream().filter(g -> g.getName() == null).collect(Collectors.counting());
|
long groupsWithoutName = config.getGroups().stream().filter(g -> g.getName() == null).collect(Collectors.counting());
|
||||||
|
|
||||||
if (groupsWithoutName > 0) {
|
if (groupsWithoutName > 0) {
|
||||||
String errorMessage = "Name is mandatory for groups, found " + groupsWithoutName + " group(s) without name.";
|
String errorMessage = "Name is mandatory for groups, found " + groupsWithoutName + " group(s) without name.";
|
||||||
return Collections.singletonList(errorMessage);
|
return Collections.singletonList(errorMessage);
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
@ -128,13 +128,11 @@ public class UPConfigUtils {
|
||||||
Set<String> groups = config.getGroups().stream()
|
Set<String> groups = config.getGroups().stream()
|
||||||
.map(g -> g.getName())
|
.map(g -> g.getName())
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
if (config.getAttributes() != null) {
|
if (config.getAttributes() != null) {
|
||||||
Set<String> attNamesCache = new HashSet<>();
|
Set<String> attNamesCache = new HashSet<>();
|
||||||
config.getAttributes().forEach((attribute) -> validateAttribute(session, attribute, groups, errors, attNamesCache));
|
config.getAttributes().forEach((attribute) -> validateAttribute(session, attribute, groups, errors, attNamesCache));
|
||||||
errors.addAll(validateRootAttributes(config));
|
errors.addAll(validateRootAttributes(config));
|
||||||
} else {
|
|
||||||
errors.add("UserProfile configuration without 'attributes' section is not allowed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
|
@ -200,13 +198,13 @@ public class UPConfigUtils {
|
||||||
if (attributeConfig.getSelector() != null) {
|
if (attributeConfig.getSelector() != null) {
|
||||||
validateScopes(attributeConfig.getSelector().getScopes(), "selector.scopes", attributeName, errors, session);
|
validateScopes(attributeConfig.getSelector().getScopes(), "selector.scopes", attributeName, errors, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributeConfig.getGroup() != null) {
|
if (attributeConfig.getGroup() != null) {
|
||||||
if (!groups.contains(attributeConfig.getGroup())) {
|
if (!groups.contains(attributeConfig.getGroup())) {
|
||||||
errors.add("Attribute '" + attributeName + "' references unknown group '" + attributeConfig.getGroup() + "'");
|
errors.add("Attribute '" + attributeName + "' references unknown group '" + attributeConfig.getGroup() + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributeConfig.getAnnotations()!=null) {
|
if (attributeConfig.getAnnotations()!=null) {
|
||||||
validateAnnotations(attributeConfig.getAnnotations(), errors, attributeName);
|
validateAnnotations(attributeConfig.getAnnotations(), errors, attributeName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1315,6 +1315,39 @@ public class UserProfileTest extends AbstractUserProfileTest {
|
||||||
profile.validate();
|
profile.validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNullAttributesInConfig() {
|
||||||
|
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testNullAttributesInConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void testNullAttributesInConfig(KeycloakSession session) {
|
||||||
|
UserProfileProvider provider = getUserProfileProvider(session);
|
||||||
|
UPConfig config = UPConfigUtils.parseSystemDefaultConfig();
|
||||||
|
config.setAttributes(null);
|
||||||
|
config.setUnmanagedAttributePolicy(UnmanagedAttributePolicy.ENABLED);
|
||||||
|
|
||||||
|
provider.setConfiguration(config);
|
||||||
|
|
||||||
|
Map<String, Object> attributes = new HashMap<>();
|
||||||
|
|
||||||
|
attributes.put(UserModel.USERNAME, "user");
|
||||||
|
attributes.put(UserModel.FIRST_NAME, "John");
|
||||||
|
attributes.put(UserModel.LAST_NAME, "Doe");
|
||||||
|
attributes.put(UserModel.EMAIL, org.keycloak.models.utils.KeycloakModelUtils.generateId() + "@keycloak.org");
|
||||||
|
|
||||||
|
UserProfile profile = provider.create(UserProfileContext.USER_API, attributes);
|
||||||
|
|
||||||
|
profile.validate();
|
||||||
|
|
||||||
|
config.setAttributes(Collections.emptyList());
|
||||||
|
try {
|
||||||
|
provider.setConfiguration(config);
|
||||||
|
Assert.fail("Expected to fail as we are trying to remove required attributes email and username");
|
||||||
|
} catch (ComponentValidationException cve) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCustomAttributeOptional() {
|
public void testCustomAttributeOptional() {
|
||||||
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomAttributeOptional);
|
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomAttributeOptional);
|
||||||
|
|
Loading…
Reference in a new issue