MapUserProvider in KC20 needs to store username compatible with KC19 to be no-downtime-upgradable

Closes #14678
This commit is contained in:
vramik 2022-10-05 20:40:31 +02:00 committed by Hynek Mlnařík
parent f80a8fbed0
commit f49582cf63
24 changed files with 99 additions and 75 deletions

View file

@ -21,7 +21,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import org.keycloak.models.utils.KeycloakModelUtils;
/**
* Migration functions for users.
@ -35,9 +34,9 @@ public class JpaUserMigration {
JpaUserMigration::migrateTreeFrom1To2
);
// adds lower-case variant of username into json
// adds a usernameWithCase column into json
private static ObjectNode migrateTreeFrom1To2(ObjectNode node) {
JsonNode usernameNode = node.path("fUsername");
return node.put("usernameLowerCase", KeycloakModelUtils.toLowerCaseSafe(usernameNode.asText()));
return node.put("usernameWithCase", usernameNode.asText());
}
}

View file

@ -52,6 +52,7 @@ public class JpaUserMapKeycloakTransaction extends JpaMapKeycloakTransaction<Jpa
root.get("entityVersion"),
root.get("realmId"),
root.get("username"),
root.get("usernameWithCase"),
root.get("firstName"),
root.get("lastName"),
root.get("email"),

View file

@ -58,10 +58,17 @@ public class JpaUserModelCriteriaBuilder extends JpaModelCriteriaBuilder<JpaUser
validateValue(value, modelField, op, String.class);
return new JpaUserModelCriteriaBuilder((cb, query, root) ->
cb.equal(root.get("username"), value[0].toString().toLowerCase())
);
} else if (modelField == UserModel.SearchableFields.USERNAME) {
validateValue(value, modelField, op, String.class);
return new JpaUserModelCriteriaBuilder((cb, query, root) ->
cb.or(
cb.and(
cb.equal(root.get("usernameLowerCase"), value[0].toString().toLowerCase()),
cb.equal(root.get("usernameWithCase"), value[0]),
cb.ge(root.get("entityVersion"), 2)
),
cb.and(
@ -71,13 +78,6 @@ public class JpaUserModelCriteriaBuilder extends JpaModelCriteriaBuilder<JpaUser
)
);
} else if (modelField == UserModel.SearchableFields.USERNAME) {
validateValue(value, modelField, op, String.class);
return new JpaUserModelCriteriaBuilder((cb, query, root) ->
cb.equal(root.get("username"), value[0])
);
} else if (modelField == UserModel.SearchableFields.REALM_ID ||
modelField == UserModel.SearchableFields.EMAIL ||
modelField == UserModel.SearchableFields.FEDERATION_LINK) {
@ -188,16 +188,7 @@ public class JpaUserModelCriteriaBuilder extends JpaModelCriteriaBuilder<JpaUser
validateValue(value, modelField, op, String.class);
return new JpaUserModelCriteriaBuilder((cb, query, root) ->
cb.or(
cb.and(
cb.like(root.get("usernameLowerCase"), value[0].toString().toLowerCase()),
cb.ge(root.get("entityVersion"), 2)
),
cb.and(
cb.like(root.get("username"), value[0].toString().toLowerCase()),
cb.le(root.get("entityVersion"), 1)
)
)
cb.like(root.get("username"), value[0].toString().toLowerCase())
);
} else {
@ -209,7 +200,16 @@ public class JpaUserModelCriteriaBuilder extends JpaModelCriteriaBuilder<JpaUser
validateValue(value, modelField, op, String.class);
return new JpaUserModelCriteriaBuilder((cb, query, root) ->
cb.like(root.get("username"), value[0].toString())
cb.or(
cb.and(
cb.like(root.get("usernameWithCase"), value[0].toString()),
cb.ge(root.get("entityVersion"), 2)
),
cb.and(
cb.like(root.get("username"), value[0].toString()),
cb.le(root.get("entityVersion"), 1)
)
)
);
} else {

View file

@ -52,6 +52,7 @@ import org.keycloak.models.map.user.MapUserConsentEntity;
import org.keycloak.models.map.user.MapUserCredentialEntity;
import org.keycloak.models.map.user.MapUserEntity;
import org.keycloak.models.map.user.MapUserFederatedIdentityEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
import static org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory.CLONER;
@ -98,7 +99,7 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J
@Column(insertable = false, updatable = false)
@Basic(fetch = FetchType.LAZY)
private String usernameLowerCase;
private String usernameWithCase;
@Column(insertable = false, updatable = false)
@Basic(fetch = FetchType.LAZY)
@ -167,13 +168,15 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J
* It is used to select user without metadata(json) field.
*/
public JpaUserEntity(final UUID id, final int version, final Integer entityVersion, final String realmId, final String username,
final String firstName, final String lastName, final String email, final String emailConstraint,
final String federationLink, final Boolean enabled, final Boolean emailVerified, final Long timestamp) {
final String usernameWithCase, final String firstName, final String lastName, final String email,
final String emailConstraint, final String federationLink, final Boolean enabled, final Boolean emailVerified,
final Long timestamp) {
this.id = id;
this.version = version;
this.entityVersion = entityVersion;
this.realmId = realmId;
this.username = username;
this.usernameWithCase = usernameWithCase;
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
@ -232,16 +235,20 @@ public class JpaUserEntity extends MapUserEntity.AbstractUserEntity implements J
this.metadata.setRealmId(realmId);
}
/**
* @return User's username with respecting letter case.
*/
@Override
public String getUsername() {
if (this.isMetadataInitialized()) return this.metadata.getUsername();
return this.username;
if (this.isMetadataInitialized()) return this.metadata.getUsernameWithCase();
//entities with entityVersion 1 the usernameWithCase might not be filled yet, therefore there is tha fallback to username field
return this.usernameWithCase == null ? this.username : this.usernameWithCase;
}
@Override
public void setUsername(String username) {
this.metadata.setUsername(username);
this.metadata.setUsernameLowerCase(username);
this.metadata.setUsername(KeycloakModelUtils.toLowerCaseSafe(username));
this.metadata.setUsernameWithCase(username);
}
@Override

View file

@ -20,7 +20,6 @@ import java.io.Serializable;
import org.keycloak.models.map.common.DeepCloner;
import org.keycloak.models.map.user.MapUserEntityImpl;
import org.keycloak.models.utils.KeycloakModelUtils;
/**
* Class that contains all the user metadata that is written as JSON into the database.
@ -38,7 +37,7 @@ public class JpaUserMetadata extends MapUserEntityImpl implements Serializable {
}
private Integer entityVersion;
private String usernameLowerCase;
private String usernameWithCase;
public Integer getEntityVersion() {
return entityVersion;
@ -48,7 +47,11 @@ public class JpaUserMetadata extends MapUserEntityImpl implements Serializable {
this.entityVersion = entityVersion;
}
public void setUsernameLowerCase(String username) {
this.usernameLowerCase = KeycloakModelUtils.toLowerCaseSafe(username);
public void setUsernameWithCase(String username) {
this.usernameWithCase = username;
}
public String getUsernameWithCase() {
return this.usernameWithCase;
}
}

View file

@ -25,10 +25,10 @@ limitations under the License.
<changeSet author="keycloak" id="users-10245">
<ext:addGeneratedColumn tableName="kc_user">
<ext:column name="usernamelowercase" type="VARCHAR(255)" jsonColumn="metadata" jsonProperty="usernameLowerCase"/>
<ext:column name="usernamewithcase" type="VARCHAR(255)" jsonColumn="metadata" jsonProperty="usernameWithCase"/>
</ext:addGeneratedColumn>
<createIndex tableName="kc_user" indexName="user_username_lower_case_realmid">
<column name="usernamelowercase"/>
<createIndex tableName="kc_user" indexName="user_username_with_case_realmid">
<column name="usernamewithcase"/>
<column name="realmid"/>
</createIndex>

View file

@ -36,7 +36,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
public abstract class MapUserAdapter extends AbstractUserModel<MapUserEntity> {
public MapUserAdapter(KeycloakSession session, RealmModel realm, MapUserEntity entity) {
super(session, realm, entity);
@ -47,9 +46,12 @@ public abstract class MapUserAdapter extends AbstractUserModel<MapUserEntity> {
return entity.getId();
}
/**
* @return username. Letter case is determined by a realm setting.
*/
@Override
public String getUsername() {
return entity.getUsername();
return KeycloakModelUtils.isUsernameCaseSensitive(realm) ? entity.getUsername() : entity.getUsername().toLowerCase();
}
@Override

View file

@ -80,8 +80,7 @@ import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProvi
import static org.keycloak.models.map.storage.QueryParameters.Order.ASCENDING;
import static org.keycloak.models.map.storage.QueryParameters.withCriteria;
import static org.keycloak.models.map.storage.criteria.DefaultModelCriteria.criteria;
import static org.keycloak.models.map.user.MapUserProviderFactory.REALM_ATTR_USERNAME_CASE_SENSITIVE;
import static org.keycloak.models.map.user.MapUserProviderFactory.REALM_ATTR_USERNAME_CASE_SENSITIVE_DEFAULT;
import static org.keycloak.models.utils.KeycloakModelUtils.isUsernameCaseSensitive;
public class MapUserProvider implements UserProvider.Streams {
@ -95,10 +94,6 @@ public class MapUserProvider implements UserProvider.Streams {
session.getTransactionManager().enlist(tx);
}
private Boolean getUsernameCaseSensitiveAttribute(RealmModel realm) {
return realm.getAttribute(REALM_ATTR_USERNAME_CASE_SENSITIVE, REALM_ATTR_USERNAME_CASE_SENSITIVE_DEFAULT);
}
private Function<MapUserEntity, UserModel> entityToAdapterFunc(RealmModel realm) {
// Clone entity before returning back, to avoid giving away a reference to the live object to the caller
return origEntity -> new MapUserAdapter(session, realm, origEntity) {
@ -336,7 +331,7 @@ public class MapUserProvider implements UserProvider.Streams {
LOG.tracef("addUser(%s, %s, %s, %s, %s)%s", realm, id, username, addDefaultRoles, addDefaultRequiredActions, getShortStackTrace());
DefaultModelCriteria<UserModel> mcb = criteria();
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
.compare(getUsernameCaseSensitiveAttribute(realm) ?
.compare(isUsernameCaseSensitive(realm) ?
SearchableFields.USERNAME :
SearchableFields.USERNAME_CASE_INSENSITIVE, Operator.EQ, username);
@ -496,7 +491,7 @@ public class MapUserProvider implements UserProvider.Streams {
LOG.tracef("getUserByUsername(%s, %s)%s", realm, username, getShortStackTrace());
DefaultModelCriteria<UserModel> mcb = criteria();
mcb = mcb.compare(SearchableFields.REALM_ID, Operator.EQ, realm.getId())
.compare(getUsernameCaseSensitiveAttribute(realm) ?
.compare(isUsernameCaseSensitive(realm) ?
SearchableFields.USERNAME :
SearchableFields.USERNAME_CASE_INSENSITIVE, Operator.EQ, username);
@ -596,7 +591,7 @@ public class MapUserProvider implements UserProvider.Streams {
criteria = mcb.and(criteria, searchCriteria);
break;
case USERNAME:
criteria = getUsernameCaseSensitiveAttribute(realm) ?
criteria = isUsernameCaseSensitive(realm) ?
criteria.compare(SearchableFields.USERNAME, Operator.LIKE, searchedString) :
criteria.compare(SearchableFields.USERNAME_CASE_INSENSITIVE, Operator.ILIKE, searchedString);
break;
@ -783,7 +778,7 @@ public class MapUserProvider implements UserProvider.Streams {
}
return mcb.or(
getUsernameCaseSensitiveAttribute(realm) ?
isUsernameCaseSensitive(realm) ?
mcb.compare(SearchableFields.USERNAME, Operator.LIKE, value) :
mcb.compare(SearchableFields.USERNAME_CASE_INSENSITIVE, Operator.ILIKE, value),
mcb.compare(SearchableFields.EMAIL, Operator.ILIKE, value),

View file

@ -40,9 +40,6 @@ import static org.keycloak.models.map.common.AbstractMapProviderFactory.MapProvi
*/
public class MapUserProviderFactory extends AbstractMapProviderFactory<MapUserProvider, MapUserEntity, UserModel> implements UserProviderFactory<MapUserProvider>, InvalidationHandler {
public static final String REALM_ATTR_USERNAME_CASE_SENSITIVE = "keycloak.username-search.case-sensitive";
public static final Boolean REALM_ATTR_USERNAME_CASE_SENSITIVE_DEFAULT = Boolean.FALSE;
public MapUserProviderFactory() {
super(UserModel.class, MapUserProvider.class);
}

View file

@ -143,4 +143,7 @@ public final class Constants {
public static final String DEFAULT_ACR_VALUES = "default.acr.values";
public static final int MINIMUM_LOA = 0;
public static final int NO_LOA = -1;
public static final Boolean REALM_ATTR_USERNAME_CASE_SENSITIVE_DEFAULT = Boolean.FALSE;
public static final String REALM_ATTR_USERNAME_CASE_SENSITIVE = "keycloak.username-search.case-sensitive";
}

View file

@ -76,6 +76,9 @@ import org.keycloak.provider.ProviderFactory;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import static org.keycloak.models.Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE;
import static org.keycloak.models.Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE_DEFAULT;
/**
* Set of helper methods, which are useful in various model implementations.
*
@ -852,4 +855,16 @@ public final class KeycloakModelUtils {
return SecretGenerator.SECRET_LENGTH_256_BITS;
}
/**
* Returns <code>true</code> if given realm has attribute {@link Constants#REALM_ATTR_USERNAME_CASE_SENSITIVE}
* set and its value is <code>true</code>. Otherwise default value of it is returned. The default setting
* can be seen at {@link Constants#REALM_ATTR_USERNAME_CASE_SENSITIVE_DEFAULT}.
*
* @param realm
* @return See the description
* @throws NullPointerException if <code>realm</code> is <code>null</code>
*/
public static boolean isUsernameCaseSensitive(RealmModel realm) {
return realm.getAttribute(REALM_ATTR_USERNAME_CASE_SENSITIVE, REALM_ATTR_USERNAME_CASE_SENSITIVE_DEFAULT);
}
}

View file

@ -20,7 +20,9 @@ import javax.ws.rs.core.Response;
import java.util.List;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.validation.Validation;
import org.keycloak.userprofile.UserProfileAttributeValidationContext;
@ -63,6 +65,8 @@ public class DuplicateUsernameValidator implements SimpleValidator {
UserModel existing = session.users().getUserByUsername(session.getContext().getRealm(), value);
UserModel user = UserProfileAttributeValidationContext.from(context).getAttributeContext().getUser();
if (! KeycloakModelUtils.isUsernameCaseSensitive(session.getContext().getRealm())) value = value.toLowerCase();
if (user != null && !value.equals(user.getFirstAttribute(UserModel.USERNAME)) && (existing != null && !existing.getId().equals(user.getId()))) {
context.addError(new ValidationError(ID, inputHint, Messages.USERNAME_EXISTS)
.setStatusCode(Response.Status.CONFLICT));

View file

@ -20,6 +20,7 @@ import java.util.List;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.services.messages.Messages;
import org.keycloak.services.validation.Validation;
import org.keycloak.userprofile.AttributeContext;
@ -65,6 +66,8 @@ public class UsernameMutationValidator implements SimpleValidator {
UserModel user = attributeContext.getUser();
RealmModel realm = context.getSession().getContext().getRealm();
if (! KeycloakModelUtils.isUsernameCaseSensitive(realm)) value = value.toLowerCase();
if (!realm.isEditUsernameAllowed() && user != null && !value.equals(user.getFirstAttribute(UserModel.USERNAME))) {
if (realm.isRegistrationEmailAsUsername() && UserProfileContext.UPDATE_PROFILE.equals(attributeContext.getContext())) {
// if username changed is because email as username is allowed so no validation should happen for update profile

View file

@ -49,6 +49,7 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import org.keycloak.models.utils.KeycloakModelUtils;
import static org.keycloak.storage.UserStorageProviderModel.IMPORT_ENABLED;
import static org.keycloak.utils.StreamsUtil.paginatedStream;
@ -124,6 +125,7 @@ public class UserMapStorage implements UserLookupProvider.Streams, UserStoragePr
@Override
public void setUsername(String innerUsername) {
innerUsername = KeycloakModelUtils.isUsernameCaseSensitive(realm) ? innerUsername : innerUsername.toLowerCase();
if (! Objects.equals(innerUsername, username.toLowerCase())) {
throw new RuntimeException("Unsupported");
}

View file

@ -325,8 +325,6 @@ public class AssertEvents implements TestRule {
description.appendText("contains scope in any order");
}
});
} else if (key.equals(Details.USERNAME) && value != null) {
return detail(key, Matchers.equalToIgnoringCase(value));
} else {
return detail(key, CoreMatchers.equalTo(value));
}

View file

@ -391,7 +391,7 @@ public class AccountRestServiceTest extends AbstractRestServiceTest {
user.setUsername("updatedUsername");
user = updateAndGet(user);
assertThat("updatedusername", Matchers.equalToIgnoringCase(user.getUsername()));
assertThat("updatedusername", Matchers.equalTo(user.getUsername()));
realmRep.setEditUsernameAllowed(false);

View file

@ -145,7 +145,6 @@ import org.keycloak.testsuite.auth.page.login.Login;
import org.keycloak.testsuite.auth.page.login.SAMLIDPInitiatedLogin;
import org.keycloak.testsuite.auth.page.login.SAMLPostLoginTenant1;
import org.keycloak.testsuite.auth.page.login.SAMLPostLoginTenant2;
import org.keycloak.testsuite.model.StoreProvider;
import org.keycloak.testsuite.page.AbstractPage;
import org.keycloak.testsuite.saml.AbstractSamlTest;
import org.keycloak.testsuite.updaters.ClientAttributeUpdater;
@ -804,8 +803,7 @@ public class SAMLServletAdapterTest extends AbstractSAMLServletAdapterTest {
UserRepresentation topGroupUser = createUserRepresentation("topGroupUser", "top@redhat.com", "", "", true);
setPasswordFor(topGroupUser, PASSWORD);
String expectedString = StoreProvider.getCurrentProvider().isMapStore() ? "principal=topGroupUser" : "principal=topgroupuser";
assertSuccessfulLogin(salesPostServletPage, topGroupUser, testRealmSAMLPostLoginPage, expectedString);
assertSuccessfulLogin(salesPostServletPage, topGroupUser, testRealmSAMLPostLoginPage, "principal=topgroupuser");
salesPostServletPage.logout();
checkLoggedOut(salesPostServletPage, testRealmSAMLPostLoginPage);

View file

@ -450,7 +450,7 @@ public class ClientTest extends AbstractAdminTest {
getCleanup().addClientUuid(id);
response.close();
UserRepresentation userRep = realm.clients().get(id).getServiceAccountUser();
MatcherAssert.assertThat("service-account-serviceclient", Matchers.equalToIgnoringCase(userRep.getUsername()));
MatcherAssert.assertThat("service-account-serviceclient", Matchers.equalTo(userRep.getUsername()));
// KEYCLOAK-11197 service accounts are no longer created with a placeholder e-mail.
assertNull(userRep.getEmail());
}

View file

@ -626,7 +626,7 @@ public class FineGrainAdminUnitTest extends AbstractKeycloakTest {
// Should only return the list of users that belong to "top" group
List<UserRepresentation> queryUsers = realmClient.realm(TEST).users().list();
Assert.assertEquals(queryUsers.size(), 1);
MatcherAssert.assertThat("groupmember", Matchers.equalToIgnoringCase(queryUsers.get(0).getUsername()));
MatcherAssert.assertThat("groupmember", Matchers.equalTo(queryUsers.get(0).getUsername()));
for (UserRepresentation user : queryUsers) {
System.out.println(user.getUsername());
}

View file

@ -24,6 +24,7 @@ import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.AuthorizationResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.common.Profile;
import org.keycloak.models.Constants;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
import org.keycloak.representations.idm.ManagementPermissionRepresentation;
@ -56,7 +57,6 @@ import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.keycloak.models.map.user.MapUserProviderFactory.REALM_ATTR_USERNAME_CASE_SENSITIVE;
public class UsersTest extends AbstractAdminTest {
@ -79,7 +79,7 @@ public class UsersTest extends AbstractAdminTest {
public void searchUserCaseSensitiveFirst() throws Exception {
Assume.assumeFalse(isJpaRealmProvider());
Map<String, String> attributes = new HashMap<>();
attributes.put(REALM_ATTR_USERNAME_CASE_SENSITIVE, "true");
attributes.put(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, "true");
try (AutoCloseable c = new RealmAttributeUpdater(adminClient.realm(REALM_NAME))
.updateWith(r -> r.setAttributes(attributes))
.update()) {
@ -90,7 +90,7 @@ public class UsersTest extends AbstractAdminTest {
RealmRepresentation realmRep = adminClient.realm(REALM_NAME).toRepresentation();
RealmBuilder.edit(realmRep)
.attribute(REALM_ATTR_USERNAME_CASE_SENSITIVE, "false");
.attribute(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, "false");
realm.update(realmRep);
assertCaseInsensitiveSearch();
@ -101,7 +101,7 @@ public class UsersTest extends AbstractAdminTest {
public void searchUserCaseInSensitiveFirst() throws Exception {
Assume.assumeFalse(isJpaRealmProvider());
Map<String, String> attributes = new HashMap<>();
attributes.put(REALM_ATTR_USERNAME_CASE_SENSITIVE, "false");
attributes.put(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, "false");
try (AutoCloseable c = new RealmAttributeUpdater(adminClient.realm(REALM_NAME))
.updateWith(r -> r.setAttributes(attributes))
.update()) {
@ -112,7 +112,7 @@ public class UsersTest extends AbstractAdminTest {
RealmRepresentation realmRep = adminClient.realm(REALM_NAME).toRepresentation();
RealmBuilder.edit(realmRep)
.attribute(REALM_ATTR_USERNAME_CASE_SENSITIVE, "true");
.attribute(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, "true");
realm.update(realmRep);
assertCaseSensitiveSearch();

View file

@ -382,7 +382,7 @@ public class UserStorageTest extends AbstractAuthTest {
testRealmAccountPage.navigateTo();
loginPage.clickRegister();
registerPage.register("firstName", "lastName", "email@mail.com", "verify-email", "password", "password");
registerPage.register("firstName", "lastName", "email@mail.com", "verifyEmail", "password", "password");
verifyEmailPage.assertCurrent();

View file

@ -112,7 +112,7 @@ public class RegisterTest extends AbstractTestRealmKeycloakTest {
assertEquals("", registerPage.getPassword());
assertEquals("", registerPage.getPasswordConfirm());
events.expectRegister("rolerichuser", "registerExistingUser@email")
events.expectRegister("roleRichUser", "registerExistingUser@email")
.removeDetail(Details.EMAIL)
.user((String) null).error("username_in_use").assertEvent();
}
@ -136,7 +136,7 @@ public class RegisterTest extends AbstractTestRealmKeycloakTest {
assertEquals("", registerPage.getPassword());
assertEquals("", registerPage.getPasswordConfirm());
events.expectRegister("registerexistinguser", "registerExistingUser@email")
events.expectRegister("registerExistingUser", "registerExistingUser@email")
.removeDetail(Details.EMAIL)
.user((String) null).error("email_in_use").assertEvent();
}
@ -330,7 +330,7 @@ public class RegisterTest extends AbstractTestRealmKeycloakTest {
registerPage.register("firstName", "lastName", null, "registerUserMissingEmail", "password", "password");
registerPage.assertCurrent();
assertEquals("Please specify email.", registerPage.getInputAccountErrors().getEmailError());
events.expectRegister("registerusermissingemail", null)
events.expectRegister("registerUserMissingEmail", null)
.removeDetail("email")
.error("invalid_registration").assertEvent();
}
@ -345,7 +345,7 @@ public class RegisterTest extends AbstractTestRealmKeycloakTest {
registerPage.assertCurrent();
assertEquals("registerUserInvalidEmailemail", registerPage.getEmail());
assertEquals("Invalid email address.", registerPage.getInputAccountErrors().getEmailError());
events.expectRegister("registeruserinvalidemail", "registerUserInvalidEmailemail")
events.expectRegister("registerUserInvalidEmail", "registerUserInvalidEmailemail")
.error("invalid_registration").assertEvent();
}

View file

@ -221,7 +221,7 @@ public class RegisterWithUserProfileTest extends RegisterTest {
registerPage.assertCurrent();
assertEquals("Length must be between 3 and 255.", registerPage.getInputAccountErrors().getLastNameError());
events.expectRegister("registeruserinvalidlastnamelength", "registerUserInvalidLastNameLength@email")
events.expectRegister("registerUserInvalidLastNameLength", "registerUserInvalidLastNameLength@email")
.error("invalid_registration").assertEvent();
}

View file

@ -49,7 +49,6 @@ import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertFalse;
@ -57,8 +56,6 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeThat;
import org.keycloak.models.jpa.JpaUserProvider;
import static org.keycloak.models.map.user.MapUserProviderFactory.REALM_ATTR_USERNAME_CASE_SENSITIVE;
/**
*
@ -135,7 +132,7 @@ public class UserModelTest extends KeycloakModelTest {
realm1Id = inComittedTransaction((Function<KeycloakSession, String>) session -> {
RealmModel realm = session.realms().createRealm("realm1");
realm.setDefaultRole(session.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName()));
realm.setAttribute(REALM_ATTR_USERNAME_CASE_SENSITIVE, true);
realm.setAttribute(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, true);
return realm.getId();
});
@ -155,7 +152,7 @@ public class UserModelTest extends KeycloakModelTest {
realm2Id = inComittedTransaction((Function<KeycloakSession, String>) session -> {
RealmModel realm = session.realms().createRealm("realm2");
realm.setDefaultRole(session.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName()));
realm.setAttribute(REALM_ATTR_USERNAME_CASE_SENSITIVE, false);
realm.setAttribute(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, false);
return realm.getId();
});