Update the entityVersion also for downgrades, as it needs to match the JSON and auxiliary tables.

Will trigger also when changes to a child occur, like for example when attributes change.

Closes #9716
This commit is contained in:
Alexander Schwartz 2022-01-25 15:36:30 +01:00 committed by Hynek Mlnařík
parent 571f2d5107
commit de2c1fbb45
7 changed files with 126 additions and 109 deletions

View file

@ -62,6 +62,8 @@ import org.keycloak.models.map.storage.MapStorageProviderFactory;
import org.keycloak.models.map.storage.jpa.client.JpaClientMapKeycloakTransaction;
import org.keycloak.models.map.storage.jpa.clientscope.JpaClientScopeMapKeycloakTransaction;
import org.keycloak.models.map.storage.jpa.clientscope.entity.JpaClientScopeEntity;
import org.keycloak.models.map.storage.jpa.hibernate.listeners.JpaEntityVersionListener;
import org.keycloak.models.map.storage.jpa.hibernate.listeners.JpaOptimisticLockingListener;
import org.keycloak.models.map.storage.jpa.role.JpaRoleMapKeycloakTransaction;
import org.keycloak.models.map.storage.jpa.role.entity.JpaRoleEntity;
import org.keycloak.models.map.storage.jpa.updater.MapJpaUpdaterProvider;
@ -185,9 +187,13 @@ public class JpaMapStorageProviderFactory implements
final EventListenerRegistry eventListenerRegistry =
sessionFactoryServiceRegistry.getService( EventListenerRegistry.class );
eventListenerRegistry.appendListeners(EventType.PRE_INSERT, JpaChildEntityListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_UPDATE, JpaChildEntityListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_DELETE, JpaChildEntityListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_INSERT, JpaOptimisticLockingListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_UPDATE, JpaOptimisticLockingListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_DELETE, JpaOptimisticLockingListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_INSERT, JpaEntityVersionListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_UPDATE, JpaEntityVersionListener.INSTANCE);
eventListenerRegistry.appendListeners(EventType.PRE_DELETE, JpaEntityVersionListener.INSTANCE);
}
@Override

View file

@ -1,13 +1,13 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -17,6 +17,7 @@
package org.keycloak.models.map.storage.jpa;
import java.io.Serializable;
import java.util.Objects;
import org.keycloak.models.map.common.AbstractEntity;
@ -39,4 +40,25 @@ public interface JpaRootEntity extends AbstractEntity, Serializable {
* @param entityVersion sets current supported version to JPA entity.
*/
void setEntityVersion(Integer entityVersion);
/**
* In case of any update on entity, we want to update the entityVersion
* to current one.
* This includes downgrading from a future version of Keycloak, as the entityVersion must match the JSON
* and the additional tables this version writes.
*
* The listener {@link org.keycloak.models.map.storage.jpa.hibernate.listeners.JpaEntityVersionListener}
* calls this method whenever the root entity or one of its children changes.
*
* Future versions of this method might restrict downgrading to downgrade only from the next version.
*/
default void updateEntityVersion() {
Integer ev = getEntityVersion();
Integer currentEv = getCurrentSchemaVersion();
if (ev != null && !Objects.equals(ev, currentEv)) {
setEntityVersion(currentEv);
}
}
Integer getCurrentSchemaVersion();
}

View file

@ -129,17 +129,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
return metadata != null;
}
/**
* In case of any update on entity, we want to update the entityVerion
* to current one.
*/
private void checkEntityVersionForUpdate() {
Integer ev = getEntityVersion();
if (ev != null && ev < CURRENT_SCHEMA_VERSION_CLIENT) {
setEntityVersion(CURRENT_SCHEMA_VERSION_CLIENT);
}
}
@Override
public Integer getEntityVersion() {
if (isMetadataInitialized()) return metadata.getEntityVersion();
@ -151,6 +140,11 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
metadata.setEntityVersion(entityVersion);
}
@Override
public Integer getCurrentSchemaVersion() {
return CURRENT_SCHEMA_VERSION_CLIENT;
}
@Override
public int getVersion() {
return version;
@ -174,7 +168,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setRealmId(String realmId) {
checkEntityVersionForUpdate();
metadata.setRealmId(realmId);
}
@ -186,13 +179,11 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setClientId(String clientId) {
checkEntityVersionForUpdate();
metadata.setClientId(clientId);
}
@Override
public void setEnabled(Boolean enabled) {
checkEntityVersionForUpdate();
metadata.setEnabled(enabled);
}
@ -209,13 +200,11 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setClientScope(String id, Boolean defaultScope) {
checkEntityVersionForUpdate();
metadata.setClientScope(id, defaultScope);
}
@Override
public void removeClientScope(String id) {
checkEntityVersionForUpdate();
metadata.removeClientScope(id);
}
@ -231,19 +220,16 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void removeProtocolMapper(String id) {
checkEntityVersionForUpdate();
metadata.removeProtocolMapper(id);
}
@Override
public void setProtocolMapper(String id, MapProtocolMapperEntity mapping) {
checkEntityVersionForUpdate();
metadata.setProtocolMapper(id, mapping);
}
@Override
public void addRedirectUri(String redirectUri) {
checkEntityVersionForUpdate();
metadata.addRedirectUri(redirectUri);
}
@ -254,25 +240,21 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void removeRedirectUri(String redirectUri) {
checkEntityVersionForUpdate();
metadata.removeRedirectUri(redirectUri);
}
@Override
public void setRedirectUris(Set<String> redirectUris) {
checkEntityVersionForUpdate();
metadata.setRedirectUris(redirectUris);
}
@Override
public void addScopeMapping(String id) {
checkEntityVersionForUpdate();
metadata.addScopeMapping(id);
}
@Override
public void removeScopeMapping(String id) {
checkEntityVersionForUpdate();
metadata.removeScopeMapping(id);
}
@ -283,7 +265,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void addWebOrigin(String webOrigin) {
checkEntityVersionForUpdate();
metadata.addWebOrigin(webOrigin);
}
@ -294,13 +275,11 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void removeWebOrigin(String webOrigin) {
checkEntityVersionForUpdate();
metadata.removeWebOrigin(webOrigin);
}
@Override
public void setWebOrigins(Set<String> webOrigins) {
checkEntityVersionForUpdate();
metadata.setWebOrigins(webOrigins);
}
@ -316,13 +295,11 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void removeAuthenticationFlowBindingOverride(String binding) {
checkEntityVersionForUpdate();
metadata.removeAuthenticationFlowBindingOverride(binding);
}
@Override
public void setAuthenticationFlowBindingOverride(String binding, String flowId) {
checkEntityVersionForUpdate();
metadata.setAuthenticationFlowBindingOverride(binding, flowId);
}
@ -333,7 +310,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setBaseUrl(String baseUrl) {
checkEntityVersionForUpdate();
metadata.setBaseUrl(baseUrl);
}
@ -344,7 +320,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setClientAuthenticatorType(String clientAuthenticatorType) {
checkEntityVersionForUpdate();
metadata.setClientAuthenticatorType(clientAuthenticatorType);
}
@ -355,7 +330,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setDescription(String description) {
checkEntityVersionForUpdate();
metadata.setDescription(description);
}
@ -366,7 +340,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setManagementUrl(String managementUrl) {
checkEntityVersionForUpdate();
metadata.setManagementUrl(managementUrl);
}
@ -377,7 +350,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setName(String name) {
checkEntityVersionForUpdate();
metadata.setName(name);
}
@ -388,7 +360,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setNodeReRegistrationTimeout(Integer nodeReRegistrationTimeout) {
checkEntityVersionForUpdate();
metadata.setNodeReRegistrationTimeout(nodeReRegistrationTimeout);
}
@ -399,7 +370,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setNotBefore(Integer notBefore) {
checkEntityVersionForUpdate();
metadata.setNotBefore(notBefore);
}
@ -411,7 +381,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setProtocol(String protocol) {
checkEntityVersionForUpdate();
metadata.setProtocol(protocol);
}
@ -422,7 +391,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setRegistrationToken(String registrationToken) {
checkEntityVersionForUpdate();
metadata.setRegistrationToken(registrationToken);
}
@ -433,7 +401,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setRootUrl(String rootUrl) {
checkEntityVersionForUpdate();
metadata.setRootUrl(rootUrl);
}
@ -444,7 +411,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setScope(Set<String> scope) {
checkEntityVersionForUpdate();
metadata.setScope(scope);
}
@ -455,7 +421,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setSecret(String secret) {
checkEntityVersionForUpdate();
metadata.setSecret(secret);
}
@ -466,7 +431,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setAlwaysDisplayInConsole(Boolean alwaysDisplayInConsole) {
checkEntityVersionForUpdate();
metadata.setAlwaysDisplayInConsole(alwaysDisplayInConsole);
}
@ -477,7 +441,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setBearerOnly(Boolean bearerOnly) {
checkEntityVersionForUpdate();
metadata.setBearerOnly(bearerOnly);
}
@ -488,7 +451,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setConsentRequired(Boolean consentRequired) {
checkEntityVersionForUpdate();
metadata.setConsentRequired(consentRequired);
}
@ -499,7 +461,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setDirectAccessGrantsEnabled(Boolean directAccessGrantsEnabled) {
checkEntityVersionForUpdate();
metadata.setDirectAccessGrantsEnabled(directAccessGrantsEnabled);
}
@ -510,7 +471,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setFrontchannelLogout(Boolean frontchannelLogout) {
checkEntityVersionForUpdate();
metadata.setFrontchannelLogout(frontchannelLogout);
}
@ -521,7 +481,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setFullScopeAllowed(Boolean fullScopeAllowed) {
checkEntityVersionForUpdate();
metadata.setFullScopeAllowed(fullScopeAllowed);
}
@ -532,7 +491,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setImplicitFlowEnabled(Boolean implicitFlowEnabled) {
checkEntityVersionForUpdate();
metadata.setImplicitFlowEnabled(implicitFlowEnabled);
}
@ -543,7 +501,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setPublicClient(Boolean publicClient) {
checkEntityVersionForUpdate();
metadata.setPublicClient(publicClient);
}
@ -554,7 +511,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setServiceAccountsEnabled(Boolean serviceAccountsEnabled) {
checkEntityVersionForUpdate();
metadata.setServiceAccountsEnabled(serviceAccountsEnabled);
}
@ -565,7 +521,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setStandardFlowEnabled(Boolean standardFlowEnabled) {
checkEntityVersionForUpdate();
metadata.setStandardFlowEnabled(standardFlowEnabled);
}
@ -576,13 +531,11 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setSurrogateAuthRequired(Boolean surrogateAuthRequired) {
checkEntityVersionForUpdate();
metadata.setSurrogateAuthRequired(surrogateAuthRequired);
}
@Override
public void removeAttribute(String name) {
checkEntityVersionForUpdate();
for (Iterator<JpaClientAttributeEntity> iterator = attributes.iterator(); iterator.hasNext();) {
JpaClientAttributeEntity attr = iterator.next();
if (Objects.equals(attr.getName(), name)) {
@ -593,7 +546,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setAttribute(String name, List<String> values) {
checkEntityVersionForUpdate();
removeAttribute(name);
for (String value : values) {
JpaClientAttributeEntity attribute = new JpaClientAttributeEntity(this, name, value);
@ -622,7 +574,6 @@ public class JpaClientEntity extends AbstractClientEntity implements JpaRootEnti
@Override
public void setAttributes(Map<String, List<String>> attributes) {
checkEntityVersionForUpdate();
for (Iterator<JpaClientAttributeEntity> iterator = this.attributes.iterator(); iterator.hasNext();) {
iterator.remove();
}

View file

@ -113,17 +113,6 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
return metadata != null;
}
/**
* In case of any update on entity, we want to update the entityVerion
* to current one.
*/
private void checkEntityVersionForUpdate() {
Integer ev = getEntityVersion();
if (ev != null && ev < CURRENT_SCHEMA_VERSION_CLIENT_SCOPE) {
setEntityVersion(CURRENT_SCHEMA_VERSION_CLIENT_SCOPE);
}
}
@Override
public Integer getEntityVersion() {
if (isMetadataInitialized()) return metadata.getEntityVersion();
@ -135,6 +124,11 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
metadata.setEntityVersion(entityVersion);
}
@Override
public Integer getCurrentSchemaVersion() {
return CURRENT_SCHEMA_VERSION_CLIENT_SCOPE;
}
@Override
public int getVersion() {
return version;
@ -158,7 +152,6 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
@Override
public void setRealmId(String realmId) {
checkEntityVersionForUpdate();
metadata.setRealmId(realmId);
}
@ -169,19 +162,16 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
@Override
public void addProtocolMapper(MapProtocolMapperEntity mapping) {
checkEntityVersionForUpdate();
metadata.addProtocolMapper(mapping);
}
@Override
public void addScopeMapping(String id) {
checkEntityVersionForUpdate();
metadata.addScopeMapping(id);
}
@Override
public void removeScopeMapping(String id) {
checkEntityVersionForUpdate();
metadata.removeScopeMapping(id);
}
@ -197,7 +187,6 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
@Override
public void setDescription(String description) {
checkEntityVersionForUpdate();
metadata.setDescription(description);
}
@ -209,7 +198,6 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
@Override
public void setName(String name) {
checkEntityVersionForUpdate();
metadata.setName(name);
}
@ -220,13 +208,11 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
@Override
public void setProtocol(String protocol) {
checkEntityVersionForUpdate();
metadata.setProtocol(protocol);
}
@Override
public void removeAttribute(String name) {
checkEntityVersionForUpdate();
for (Iterator<JpaClientScopeAttributeEntity> iterator = attributes.iterator(); iterator.hasNext();) {
JpaClientScopeAttributeEntity attr = iterator.next();
if (Objects.equals(attr.getName(), name)) {
@ -237,7 +223,6 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
@Override
public void setAttribute(String name, List<String> values) {
checkEntityVersionForUpdate();
removeAttribute(name);
for (String value : values) {
JpaClientScopeAttributeEntity attribute = new JpaClientScopeAttributeEntity(this, name, value);
@ -266,7 +251,6 @@ public class JpaClientScopeEntity extends AbstractClientScopeEntity implements J
@Override
public void setAttributes(Map<String, List<String>> attributes) {
checkEntityVersionForUpdate();
for (Iterator<JpaClientScopeAttributeEntity> iterator = this.attributes.iterator(); iterator.hasNext();) {
iterator.remove();
}

View file

@ -0,0 +1,69 @@
/*
* Copyright 2022. Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.models.map.storage.jpa.hibernate.listeners;
import org.hibernate.HibernateException;
import org.hibernate.event.spi.PreDeleteEvent;
import org.hibernate.event.spi.PreDeleteEventListener;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.keycloak.models.map.storage.jpa.JpaChildEntity;
import org.keycloak.models.map.storage.jpa.JpaRootEntity;
/**
* Listen on changes on child- and root entities and updates the current entity version of the root.
*
* This support a multiple level parent-child relationship, where the upmost parent needs the entity version to be updated.
*/
public class JpaEntityVersionListener implements PreInsertEventListener, PreDeleteEventListener, PreUpdateEventListener {
public static final JpaEntityVersionListener INSTANCE = new JpaEntityVersionListener();
/**
* Traverse from current entity up to the upmost parent, then update the entity version if it is a root entity.
*/
public void updateEntityVersion(Object entity) throws HibernateException {
Object root = entity;
while(root instanceof JpaChildEntity) {
root = ((JpaChildEntity<?>) entity).getParent();
}
if (root instanceof JpaRootEntity) {
((JpaRootEntity) root).updateEntityVersion();
}
}
@Override
public boolean onPreInsert(PreInsertEvent event) {
updateEntityVersion(event.getEntity());
return false;
}
@Override
public boolean onPreDelete(PreDeleteEvent event) {
updateEntityVersion(event.getEntity());
return false;
}
@Override
public boolean onPreUpdate(PreUpdateEvent event) {
updateEntityVersion(event.getEntity());
return false;
}
}

View file

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.keycloak.models.map.storage.jpa;
package org.keycloak.models.map.storage.jpa.hibernate.listeners;
import org.hibernate.HibernateException;
import org.hibernate.Session;
@ -25,22 +25,23 @@ import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.keycloak.models.map.storage.jpa.JpaChildEntity;
import javax.persistence.LockModeType;
/**
* Listen on changes on child entities and forces an optimistic locking increment on the topmost parent.
* Listen on changes on child entities and forces an optimistic locking increment on the topmost parent aka root.
*
* This support a multiple level parent-child relationship, where only the upmost parent is locked.
*/
public class JpaChildEntityListener implements PreInsertEventListener, PreDeleteEventListener, PreUpdateEventListener {
public class JpaOptimisticLockingListener implements PreInsertEventListener, PreDeleteEventListener, PreUpdateEventListener {
public static final JpaChildEntityListener INSTANCE = new JpaChildEntityListener();
public static final JpaOptimisticLockingListener INSTANCE = new JpaOptimisticLockingListener();
/**
* Check if the entity is a child with a parent and force optimistic locking increment on the upmost parent.
* Check if the entity is a child with a parent and force optimistic locking increment on the upmost parent aka root.
*/
public void checkRoot(Session session, Object entity) throws HibernateException {
public void lockRootEntity(Session session, Object entity) throws HibernateException {
if(entity instanceof JpaChildEntity) {
Object root = entity;
while (root instanceof JpaChildEntity) {
@ -52,19 +53,19 @@ public class JpaChildEntityListener implements PreInsertEventListener, PreDelete
@Override
public boolean onPreInsert(PreInsertEvent event) {
checkRoot(event.getSession(), event.getEntity());
lockRootEntity(event.getSession(), event.getEntity());
return false;
}
@Override
public boolean onPreDelete(PreDeleteEvent event) {
checkRoot(event.getSession(), event.getEntity());
lockRootEntity(event.getSession(), event.getEntity());
return false;
}
@Override
public boolean onPreUpdate(PreUpdateEvent event) {
checkRoot(event.getSession(), event.getEntity());
lockRootEntity(event.getSession(), event.getEntity());
return false;
}
}

View file

@ -121,15 +121,9 @@ public class JpaRoleEntity extends AbstractRoleEntity implements JpaRootEntity {
return metadata != null;
}
/**
* In case of any update on entity, we want to update the entityVerion
* to current one.
*/
private void checkEntityVersionForUpdate() {
Integer ev = getEntityVersion();
if (ev != null && ev < CURRENT_SCHEMA_VERSION_ROLE) {
setEntityVersion(CURRENT_SCHEMA_VERSION_ROLE);
}
@Override
public Integer getCurrentSchemaVersion() {
return CURRENT_SCHEMA_VERSION_ROLE;
}
@Override
@ -189,25 +183,21 @@ public class JpaRoleEntity extends AbstractRoleEntity implements JpaRootEntity {
@Override
public void setRealmId(String realmId) {
checkEntityVersionForUpdate();
metadata.setRealmId(realmId);
}
@Override
public void setClientId(String clientId) {
checkEntityVersionForUpdate();
metadata.setClientId(clientId);
}
@Override
public void setName(String name) {
checkEntityVersionForUpdate();
metadata.setName(name);
}
@Override
public void setDescription(String description) {
checkEntityVersionForUpdate();
metadata.setDescription(description);
}
@ -218,19 +208,16 @@ public class JpaRoleEntity extends AbstractRoleEntity implements JpaRootEntity {
@Override
public void setCompositeRoles(Set<String> compositeRoles) {
checkEntityVersionForUpdate();
metadata.setCompositeRoles(compositeRoles);
}
@Override
public void addCompositeRole(String roleId) {
checkEntityVersionForUpdate();
metadata.addCompositeRole(roleId);
}
@Override
public void removeCompositeRole(String roleId) {
checkEntityVersionForUpdate();
metadata.removeCompositeRole(roleId);
}
@ -255,7 +242,6 @@ public class JpaRoleEntity extends AbstractRoleEntity implements JpaRootEntity {
@Override
public void setAttributes(Map<String, List<String>> attributes) {
checkEntityVersionForUpdate();
for (Iterator<JpaRoleAttributeEntity> iterator = this.attributes.iterator(); iterator.hasNext();) {
iterator.remove();
}
@ -268,7 +254,6 @@ public class JpaRoleEntity extends AbstractRoleEntity implements JpaRootEntity {
@Override
public void setAttribute(String name, List<String> values) {
checkEntityVersionForUpdate();
removeAttribute(name);
for (String value : values) {
JpaRoleAttributeEntity attribute = new JpaRoleAttributeEntity(this, name, value);
@ -278,7 +263,6 @@ public class JpaRoleEntity extends AbstractRoleEntity implements JpaRootEntity {
@Override
public void removeAttribute(String name) {
checkEntityVersionForUpdate();
for (Iterator<JpaRoleAttributeEntity> iterator = attributes.iterator(); iterator.hasNext();) {
JpaRoleAttributeEntity attr = iterator.next();
if (Objects.equals(attr.getName(), name)) {