KEYCLOAK-19481 Make Id and RealmId mutable fields

This commit is contained in:
Michal Hajas 2021-10-08 15:28:10 +02:00 committed by Hynek Mlnařík
parent 26a2bbac60
commit 6e591305f9
21 changed files with 156 additions and 112 deletions

View file

@ -38,14 +38,9 @@ public class MapRootAuthenticationSessionEntity implements AbstractEntity, Updat
private int timestamp;
private Map<String, MapAuthenticationSessionEntity> authenticationSessions = new ConcurrentHashMap<>();
protected MapRootAuthenticationSessionEntity() {
this.id = null;
this.realmId = null;
}
protected MapRootAuthenticationSessionEntity() {}
public MapRootAuthenticationSessionEntity(String id, String realmId) {
Objects.requireNonNull(realmId, "realmId");
this.id = id;
this.realmId = realmId;
}
@ -55,6 +50,13 @@ public class MapRootAuthenticationSessionEntity implements AbstractEntity, Updat
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;

View file

@ -109,7 +109,7 @@ public class MapPermissionTicketStore implements PermissionTicketStore {
+ ", Resource: " + resourceId + ", owner: " + owner + ", scopeId: " + scopeId + " already exists.");
}
MapPermissionTicketEntity entity = new MapPermissionTicketEntity(null);
MapPermissionTicketEntity entity = new MapPermissionTicketEntity();
entity.setResourceId(resourceId);
entity.setRequester(requester);
entity.setCreatedTimestamp(System.currentTimeMillis());

View file

@ -24,7 +24,7 @@ import java.util.Objects;
public class MapPermissionTicketEntity implements AbstractEntity, UpdatableEntity {
private final String id;
private String id;
private String owner;
private String requester;
private Long createdTimestamp;
@ -39,15 +39,20 @@ public class MapPermissionTicketEntity implements AbstractEntity, UpdatableEntit
this.id = id;
}
public MapPermissionTicketEntity() {
this.id = null;
}
public MapPermissionTicketEntity() {}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
public String getOwner() {
return owner;
}

View file

@ -30,7 +30,7 @@ import java.util.Objects;
public class MapPolicyEntity implements AbstractEntity, UpdatableEntity {
private final String id;
private String id;
private String name;
private String description;
private String type;
@ -48,9 +48,7 @@ public class MapPolicyEntity implements AbstractEntity, UpdatableEntity {
this.id = id;
}
public MapPolicyEntity() {
this.id = null;
}
public MapPolicyEntity() {}
public String getName() {
return name;
@ -182,6 +180,13 @@ public class MapPolicyEntity implements AbstractEntity, UpdatableEntity {
return id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return updated;

View file

@ -29,7 +29,7 @@ import java.util.Set;
public class MapResourceEntity implements AbstractEntity, UpdatableEntity {
private final String id;
private String id;
private String name;
private String displayName;
private final Set<String> uris = new HashSet<>();
@ -47,15 +47,20 @@ public class MapResourceEntity implements AbstractEntity, UpdatableEntity {
this.id = id;
}
public MapResourceEntity() {
this.id = null;
}
public MapResourceEntity() {}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
public String getName() {
return name;
}

View file

@ -26,7 +26,7 @@ import java.util.Objects;
public class MapResourceServerEntity implements AbstractEntity, UpdatableEntity {
private final String id;
private String id;
private boolean updated = false;
private boolean allowRemoteResourceManagement;
@ -37,15 +37,20 @@ public class MapResourceServerEntity implements AbstractEntity, UpdatableEntity
this.id = id;
}
public MapResourceServerEntity() {
this.id = null;
}
public MapResourceServerEntity() {}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
public boolean isAllowRemoteResourceManagement() {
return allowRemoteResourceManagement;
}

View file

@ -24,7 +24,7 @@ import java.util.Objects;
public class MapScopeEntity implements AbstractEntity, UpdatableEntity {
private final String id;
private String id;
private String name;
private String displayName;
private String iconUri;
@ -35,15 +35,20 @@ public class MapScopeEntity implements AbstractEntity, UpdatableEntity {
this.id = id;
}
public MapScopeEntity() {
this.id = null;
}
public MapScopeEntity() {}
@Override
public String getId() {
return id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
public String getName() {
return name;
}

View file

@ -42,9 +42,7 @@ public interface MapClientEntity extends AbstractEntity, UpdatableEntity {
protected boolean updated;
private String id;
protected AbstractClientEntity() {
this.id = null;
}
protected AbstractClientEntity() {}
public AbstractClientEntity(String id) {
this.id = id;
@ -55,6 +53,13 @@ public interface MapClientEntity extends AbstractEntity, UpdatableEntity {
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;

View file

@ -468,6 +468,11 @@ public class MapClientEntityLazyDelegate implements MapClientEntity {
return getReadDelegate().getId();
}
@Override
public void setId(String id) {
getWriteDelegate().setId(id);
}
@Override
public boolean isUpdated() {
return isWriteDelegateInitialized() && getWriteDelegate().isUpdated();

View file

@ -33,8 +33,8 @@ import org.keycloak.models.map.common.UpdatableEntity;
public class MapClientScopeEntity implements AbstractEntity, UpdatableEntity {
private final String id;
private final String realmId;
private String id;
private String realmId;
private String name;
private String protocol;
@ -49,14 +49,9 @@ public class MapClientScopeEntity implements AbstractEntity, UpdatableEntity {
*/
protected boolean updated;
protected MapClientScopeEntity() {
this.id = null;
this.realmId = null;
}
protected MapClientScopeEntity() {}
public MapClientScopeEntity(String id, String realmId) {
Objects.requireNonNull(realmId, "realmId");
this.id = id;
this.realmId = realmId;
}
@ -66,6 +61,13 @@ public class MapClientScopeEntity implements AbstractEntity, UpdatableEntity {
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;
@ -148,6 +150,11 @@ public class MapClientScopeEntity implements AbstractEntity, UpdatableEntity {
return this.realmId;
}
public void setRealmId(String realmId) {
this.updated |= !Objects.equals(this.realmId, realmId);
this.realmId = realmId;
}
public Stream<String> getScopeMappings() {
return scopeMappings.stream();
}

View file

@ -23,5 +23,5 @@ package org.keycloak.models.map.common;
public interface AbstractEntity {
String getId();
void setId(String id);
}

View file

@ -54,7 +54,6 @@ public class Serialization {
.setVisibility(PropertyAccessor.FIELD, Visibility.ANY)
.activateDefaultTyping(new LaissezFaireSubTypeValidator() /* TODO - see javadoc */, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.PROPERTY)
.addMixIn(UpdatableEntity.class, IgnoreUpdatedMixIn.class)
.addMixIn(AbstractEntity.class, AbstractEntityMixIn.class)
;
public static final ConcurrentHashMap<Class<?>, ObjectReader> READERS = new ConcurrentHashMap<>();
@ -64,11 +63,6 @@ public class Serialization {
@JsonIgnore public abstract boolean isUpdated();
}
abstract class AbstractEntityMixIn {
@JsonTypeInfo(property="id", use=Id.CLASS, include=As.WRAPPER_ARRAY)
abstract Object getId();
}
static {
JavaType type = TypeFactory.unknownType();
JavaType streamType = MAPPER.getTypeFactory().constructParametricType(Stream.class, type);
@ -78,10 +72,6 @@ public class Serialization {
public static <T extends AbstractEntity> T from(T orig) {
return from(orig, null);
}
public static <T extends AbstractEntity> T from(T orig, String newId) {
if (orig == null) {
return null;
}
@ -94,26 +84,10 @@ public class Serialization {
ObjectWriter writer = WRITERS.computeIfAbsent(origClass, MAPPER::writerFor);
final T res;
res = reader.readValue(writer.writeValueAsBytes(orig));
if (newId != null) {
updateId(origClass, res, newId);
}
return res;
} catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
private static <K> void updateId(Class<?> origClass, AbstractEntity res, K newId) {
Field field = Reflections.findDeclaredField(origClass, "id");
if (field == null) {
throw new IllegalArgumentException("Cannot find id for " + origClass + " class");
}
try {
Reflections.setAccessible(field).set(res, newId);
} catch (IllegalArgumentException | IllegalAccessException ex) {
Logger.getLogger(Serialization.class.getName()).log(Level.SEVERE, null, ex);
throw new IllegalArgumentException("Cannot set id for " + origClass + " class");
}
}
}

View file

@ -34,7 +34,7 @@ import java.util.Set;
public class MapGroupEntity implements AbstractEntity, UpdatableEntity {
private String id;
private final String realmId;
private String realmId;
private String name;
private String parentId;
@ -46,14 +46,9 @@ public class MapGroupEntity implements AbstractEntity, UpdatableEntity {
*/
protected boolean updated;
protected MapGroupEntity() {
this.id = null;
this.realmId = null;
}
protected MapGroupEntity() {}
public MapGroupEntity(String id, String realmId) {
Objects.requireNonNull(realmId, "realmId");
this.id = id;
this.realmId = realmId;
}
@ -63,6 +58,13 @@ public class MapGroupEntity implements AbstractEntity, UpdatableEntity {
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;
@ -113,6 +115,11 @@ public class MapGroupEntity implements AbstractEntity, UpdatableEntity {
return this.realmId;
}
public void setRealmId(String realmId) {
this.updated |= !Objects.equals(this.realmId, realmId);
this.realmId = realmId;
}
public Set<String> getGrantedRoles() {
return grantedRoles;
}

View file

@ -39,11 +39,7 @@ public class MapUserLoginFailureEntity implements AbstractEntity, UpdatableEntit
private long lastFailure;
private String lastIPFailure;
public MapUserLoginFailureEntity() {
this.id = null;
this.realmId = null;
this.userId = null;
}
public MapUserLoginFailureEntity() {}
public MapUserLoginFailureEntity(String id, String realmId, String userId) {
this.id = id;
@ -56,6 +52,13 @@ public class MapUserLoginFailureEntity implements AbstractEntity, UpdatableEntit
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;

View file

@ -130,9 +130,7 @@ public class MapRealmEntity implements AbstractEntity, UpdatableEntity {
*/
protected boolean updated;
protected MapRealmEntity() {
this.id = null;
}
protected MapRealmEntity() {}
public MapRealmEntity(String id) {
this.id = id;
@ -143,6 +141,13 @@ public class MapRealmEntity implements AbstractEntity, UpdatableEntity {
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated

View file

@ -42,14 +42,9 @@ public class MapRoleEntity implements AbstractEntity, UpdatableEntity {
*/
protected boolean updated;
protected MapRoleEntity() {
this.id = null;
this.realmId = null;
}
protected MapRoleEntity() {}
public MapRoleEntity(String id, String realmId) {
Objects.requireNonNull(realmId, "realmId");
this.id = id;
this.realmId = realmId;
}
@ -59,6 +54,13 @@ public class MapRoleEntity implements AbstractEntity, UpdatableEntity {
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;

View file

@ -214,7 +214,7 @@ public class ConcurrentHashMapKeycloakTransaction<K, V extends AbstractEntity &
if (key == null) {
K newKey = keyConvertor.yieldNewUniqueKey();
key = keyConvertor.keyToString(newKey);
value = Serialization.from(value, key);
value.setId(key);
}
addTask(key, new CreateOperation(value));
return value;

View file

@ -62,7 +62,7 @@ public class ConcurrentHashMapStorage<K, V extends AbstractEntity & UpdatableEnt
K key = keyConvertor.fromStringSafe(value.getId());
if (key == null) {
key = keyConvertor.yieldNewUniqueKey();
value = Serialization.from(value, keyConvertor.keyToString(key));
value.setId(keyConvertor.keyToString(key));
}
store.putIfAbsent(key, value);
return value;

View file

@ -42,8 +42,8 @@ import java.util.stream.Stream;
*/
public class MapUserEntity implements AbstractEntity, UpdatableEntity {
private final String id;
private final String realmId;
private String id;
private String realmId;
private String username;
private String firstName;
@ -71,14 +71,9 @@ public class MapUserEntity implements AbstractEntity, UpdatableEntity {
*/
protected boolean updated;
protected MapUserEntity() {
this.id = null;
this.realmId = null;
}
protected MapUserEntity() {}
public MapUserEntity(String id, String realmId) {
Objects.requireNonNull(realmId, "realmId");
this.id = id;
this.realmId = realmId;
}
@ -88,6 +83,13 @@ public class MapUserEntity implements AbstractEntity, UpdatableEntity {
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated
@ -100,6 +102,11 @@ public class MapUserEntity implements AbstractEntity, UpdatableEntity {
return realmId;
}
public void setRealmId(String realmId) {
this.updated |= !Objects.equals(this.realmId, realmId);
this.realmId = realmId;
}
public String getUsername() {
return username;
}

View file

@ -52,16 +52,9 @@ public class MapAuthenticatedClientSessionEntity implements AbstractEntity, Upda
private boolean offline;
public MapAuthenticatedClientSessionEntity() {
this.id = null;
this.realmId = null;
}
public MapAuthenticatedClientSessionEntity() {}
public MapAuthenticatedClientSessionEntity(String id, String userSessionId, String realmId, String clientId, boolean offline) {
Objects.requireNonNull(userSessionId, "userSessionId");
Objects.requireNonNull(realmId, "realmId");
Objects.requireNonNull(clientId, "clientId");
this.id = id;
this.userSessionId = userSessionId;
this.realmId = realmId;
@ -75,6 +68,13 @@ public class MapAuthenticatedClientSessionEntity implements AbstractEntity, Upda
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;

View file

@ -69,14 +69,9 @@ public class MapUserSessionEntity implements AbstractEntity, UpdatableEntity {
private boolean offline;
public MapUserSessionEntity() {
this.id = null;
this.realmId = null;
}
public MapUserSessionEntity() {}
public MapUserSessionEntity(String id, String realmId) {
Objects.requireNonNull(realmId, "realmId");
this.id = id;
this.realmId = realmId;
}
@ -103,6 +98,13 @@ public class MapUserSessionEntity implements AbstractEntity, UpdatableEntity {
return this.id;
}
@Override
public void setId(String id) {
if (this.id != null) throw new IllegalStateException("Id cannot be changed");
this.id = id;
this.updated |= id != null;
}
@Override
public boolean isUpdated() {
return this.updated;