MapUserProvider in KC20 needs to store username compatible with KC19 to be no-downtime-upgradable
Closes #14678
This commit is contained in:
parent
f80a8fbed0
commit
f49582cf63
24 changed files with 99 additions and 75 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue