Empty error message when validation issue due the PersonNameProhibitedValidator validation

closes #26750

Signed-off-by: mposolda <mposolda@gmail.com>
This commit is contained in:
mposolda 2024-02-02 18:32:38 +01:00 committed by Pedro Igor
parent 486b199548
commit f468885fdd
6 changed files with 65 additions and 5 deletions

View file

@ -62,7 +62,7 @@ public class PatternValidator extends AbstractStringValidator implements Configu
property = new ProviderConfigProperty(); property = new ProviderConfigProperty();
property.setName(CFG_ERROR_MESSAGE); property.setName(CFG_ERROR_MESSAGE);
property.setLabel("Error message key"); property.setLabel("Error message key");
property.setHelpText("Key of the error message in i18n bundle. Dafault message key is " + MESSAGE_NO_MATCH); property.setHelpText("Key of the error message in i18n bundle. Default message key is " + MESSAGE_NO_MATCH);
property.setType(ProviderConfigProperty.STRING_TYPE); property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property); configProperties.add(property);
} }

View file

@ -23,6 +23,8 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.keycloak.utils.StringUtil;
/** /**
* A typed wrapper around a {@link Map} based {@link Validator} configuration. * A typed wrapper around a {@link Map} based {@link Validator} configuration.
*/ */
@ -90,7 +92,7 @@ public class ValidatorConfig {
public String getStringOrDefault(String key, String defaultValue) { public String getStringOrDefault(String key, String defaultValue) {
Object value = config.get(key); Object value = config.get(key);
if (value instanceof String) { if (value instanceof String && StringUtil.isNotBlank((String) value)) {
return (String) value; return (String) value;
} }
return defaultValue; return defaultValue;

View file

@ -52,7 +52,7 @@ public class PersonNameProhibitedCharactersValidator extends AbstractStringValid
property = new ProviderConfigProperty(); property = new ProviderConfigProperty();
property.setName(CFG_ERROR_MESSAGE); property.setName(CFG_ERROR_MESSAGE);
property.setLabel("Error message key"); property.setLabel("Error message key");
property.setHelpText("Key of the error message in i18n bundle. Dafault message key is " + MESSAGE_NO_MATCH); property.setHelpText("Key of the error message in i18n bundle. Default message key is " + MESSAGE_NO_MATCH);
property.setType(ProviderConfigProperty.STRING_TYPE); property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property); configProperties.add(property);
} }

View file

@ -48,7 +48,7 @@ public class UsernameIDNHomographValidator implements SimpleValidator, Configure
property = new ProviderConfigProperty(); property = new ProviderConfigProperty();
property.setName(CFG_ERROR_MESSAGE); property.setName(CFG_ERROR_MESSAGE);
property.setLabel("Error message key"); property.setLabel("Error message key");
property.setHelpText("Key of the error message in i18n bundle. Dafault message key is " + MESSAGE_NO_MATCH); property.setHelpText("Key of the error message in i18n bundle. Default message key is " + MESSAGE_NO_MATCH);
property.setType(ProviderConfigProperty.STRING_TYPE); property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property); configProperties.add(property);
} }

View file

@ -52,7 +52,7 @@ public class UsernameProhibitedCharactersValidator extends AbstractStringValidat
property = new ProviderConfigProperty(); property = new ProviderConfigProperty();
property.setName(CFG_ERROR_MESSAGE); property.setName(CFG_ERROR_MESSAGE);
property.setLabel("Error message key"); property.setLabel("Error message key");
property.setHelpText("Key of the error message in i18n bundle. Dafault message key is " + MESSAGE_NO_MATCH); property.setHelpText("Key of the error message in i18n bundle. Default message key is " + MESSAGE_NO_MATCH);
property.setType(ProviderConfigProperty.STRING_TYPE); property.setType(ProviderConfigProperty.STRING_TYPE);
configProperties.add(property); configProperties.add(property);
} }

View file

@ -79,6 +79,7 @@ import org.keycloak.userprofile.UserProfileConstants;
import org.keycloak.userprofile.UserProfileContext; import org.keycloak.userprofile.UserProfileContext;
import org.keycloak.userprofile.UserProfileProvider; import org.keycloak.userprofile.UserProfileProvider;
import org.keycloak.userprofile.ValidationException; import org.keycloak.userprofile.ValidationException;
import org.keycloak.userprofile.validator.PersonNameProhibitedCharactersValidator;
import org.keycloak.userprofile.validator.UsernameIDNHomographValidator; import org.keycloak.userprofile.validator.UsernameIDNHomographValidator;
import org.keycloak.validate.ValidationError; import org.keycloak.validate.ValidationError;
import org.keycloak.validate.validators.EmailValidator; import org.keycloak.validate.validators.EmailValidator;
@ -1052,6 +1053,63 @@ public class UserProfileTest extends AbstractUserProfileTest {
} }
} }
@Test
@ModelTest(realmName = "test")
public void testPersonNameProhibitedCharsValidator(KeycloakSession session) {
UserProfileProvider provider = getUserProfileProvider(session);
UPConfig config = parseDefaultConfig();
UPAttribute lastNameAttr = config.getAttribute(UserModel.LAST_NAME);
Map<String, Object> origValidatorCfg = lastNameAttr.getValidations().get(PersonNameProhibitedCharactersValidator.ID);
try {
// Should fail with the default error message
Map<String, Object> attributes = new HashMap<>();
attributes.put(UserModel.USERNAME, "abc");
attributes.put(UserModel.EMAIL, "test@keycloak.org");
attributes.put(UserModel.FIRST_NAME, "Foo");
attributes.put(UserModel.LAST_NAME, "Jo&hn");
UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
try {
profile.validate();
fail("Should fail validation");
} catch (ValidationException ve) {
assertTrue(ve.hasError(PersonNameProhibitedCharactersValidator.MESSAGE_NO_MATCH));
}
// custom error message should be used
lastNameAttr.getValidations().put(PersonNameProhibitedCharactersValidator.ID, Map.of(PersonNameProhibitedCharactersValidator.CFG_ERROR_MESSAGE, "error-something"));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
try {
profile.validate();
fail("Should fail validation");
} catch (ValidationException ve) {
assertTrue(ve.hasError("error-something"));
}
// error-message config parameters used with empty value. Default error message should be used
lastNameAttr = config.getAttribute(UserModel.LAST_NAME);
lastNameAttr.getValidations().put(PersonNameProhibitedCharactersValidator.ID, Map.of(PersonNameProhibitedCharactersValidator.CFG_ERROR_MESSAGE, ""));
provider.setConfiguration(config);
profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes);
try {
profile.validate();
fail("Should fail validation");
} catch (ValidationException ve) {
assertTrue(ve.hasError(PersonNameProhibitedCharactersValidator.MESSAGE_NO_MATCH));
}
} finally {
// Rollback
lastNameAttr.getValidations().put(PersonNameProhibitedCharactersValidator.ID, origValidatorCfg);
provider.setConfiguration(config);
}
}
@Test @Test
public void testCustomAttributeRequired() { public void testCustomAttributeRequired() {
getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomAttributeRequired); getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testCustomAttributeRequired);