parent
15b2f8e26d
commit
ae90b232ff
20 changed files with 1890 additions and 9 deletions
|
@ -21,5 +21,6 @@ public interface Constants {
|
|||
public static final Integer CURRENT_SCHEMA_VERSION_CLIENT = 1;
|
||||
public static final Integer CURRENT_SCHEMA_VERSION_CLIENT_SCOPE = 1;
|
||||
public static final Integer CURRENT_SCHEMA_VERSION_GROUP = 1;
|
||||
public static final Integer CURRENT_SCHEMA_VERSION_REALM = 1;
|
||||
public static final Integer CURRENT_SCHEMA_VERSION_ROLE = 1;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ public abstract class JpaMapKeycloakTransaction<RE extends JpaRootEntity, E exte
|
|||
CriteriaQuery<RE> query = cb.createQuery(entityType);
|
||||
Root<RE> root = query.from(entityType);
|
||||
query.select(selectCbConstruct(cb, root));
|
||||
if (mcb.isDistinct()) query.distinct(true);
|
||||
|
||||
//ordering
|
||||
if (!queryParameters.getOrderBy().isEmpty()) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -51,14 +52,34 @@ import org.keycloak.connections.jpa.util.JpaUtils;
|
|||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.ClientScopeModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.map.storage.jpa.client.entity.JpaClientEntity;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.dblock.DBLockProvider;
|
||||
import org.keycloak.models.map.client.MapProtocolMapperEntity;
|
||||
import org.keycloak.models.map.client.MapProtocolMapperEntityImpl;
|
||||
import org.keycloak.models.map.common.DeepCloner;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationExecutionEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationExecutionEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationFlowEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationFlowEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticatorConfigEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticatorConfigEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapClientInitialAccessEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapClientInitialAccessEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderMapperEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderMapperEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapOTPPolicyEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapOTPPolicyEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntityImpl;
|
||||
import org.keycloak.models.map.storage.MapKeycloakTransaction;
|
||||
import org.keycloak.models.map.storage.MapStorageProvider;
|
||||
import org.keycloak.models.map.storage.MapStorageProviderFactory;
|
||||
|
@ -66,20 +87,25 @@ import org.keycloak.models.map.storage.jpa.authSession.JpaRootAuthenticationSess
|
|||
import org.keycloak.models.map.storage.jpa.authSession.entity.JpaAuthenticationSessionEntity;
|
||||
import org.keycloak.models.map.storage.jpa.authSession.entity.JpaRootAuthenticationSessionEntity;
|
||||
import org.keycloak.models.map.storage.jpa.client.JpaClientMapKeycloakTransaction;
|
||||
import org.keycloak.models.map.storage.jpa.client.entity.JpaClientEntity;
|
||||
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.group.JpaGroupMapKeycloakTransaction;
|
||||
import org.keycloak.models.map.storage.jpa.group.entity.JpaGroupEntity;
|
||||
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.realm.JpaRealmMapKeycloakTransaction;
|
||||
import org.keycloak.models.map.storage.jpa.realm.entity.JpaComponentEntity;
|
||||
import org.keycloak.models.map.storage.jpa.realm.entity.JpaRealmEntity;
|
||||
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;
|
||||
import static org.keycloak.models.map.storage.jpa.updater.MapJpaUpdaterProvider.Status.VALID;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
import org.keycloak.provider.EnvironmentDependentProviderFactory;
|
||||
import org.keycloak.sessions.RootAuthenticationSessionModel;
|
||||
|
||||
import static org.keycloak.models.map.storage.jpa.updater.MapJpaUpdaterProvider.Status.VALID;
|
||||
|
||||
public class JpaMapStorageProviderFactory implements
|
||||
AmphibianProviderFactory<MapStorageProvider>,
|
||||
MapStorageProviderFactory,
|
||||
|
@ -103,6 +129,19 @@ public class JpaMapStorageProviderFactory implements
|
|||
.constructor(JpaClientScopeEntity.class, JpaClientScopeEntity::new)
|
||||
//group
|
||||
.constructor(JpaGroupEntity.class, JpaGroupEntity::new)
|
||||
// realm
|
||||
.constructor(JpaRealmEntity.class, JpaRealmEntity::new)
|
||||
.constructor(JpaComponentEntity.class, JpaComponentEntity::new)
|
||||
.constructor(MapAuthenticationExecutionEntity.class, MapAuthenticationExecutionEntityImpl::new)
|
||||
.constructor(MapAuthenticationFlowEntity.class, MapAuthenticationFlowEntityImpl::new)
|
||||
.constructor(MapAuthenticatorConfigEntity.class, MapAuthenticatorConfigEntityImpl::new)
|
||||
.constructor(MapClientInitialAccessEntity.class, MapClientInitialAccessEntityImpl::new)
|
||||
.constructor(MapIdentityProviderEntity.class, MapIdentityProviderEntityImpl::new)
|
||||
.constructor(MapIdentityProviderMapperEntity.class, MapIdentityProviderMapperEntityImpl::new)
|
||||
.constructor(MapOTPPolicyEntity.class, MapOTPPolicyEntityImpl::new)
|
||||
.constructor(MapRequiredActionProviderEntity.class, MapRequiredActionProviderEntityImpl::new)
|
||||
.constructor(MapRequiredCredentialEntity.class, MapRequiredCredentialEntityImpl::new)
|
||||
.constructor(MapWebAuthnPolicyEntity.class, MapWebAuthnPolicyEntityImpl::new)
|
||||
//role
|
||||
.constructor(JpaRoleEntity.class, JpaRoleEntity::new)
|
||||
.build();
|
||||
|
@ -113,6 +152,7 @@ public class JpaMapStorageProviderFactory implements
|
|||
MODEL_TO_TX.put(ClientScopeModel.class, JpaClientScopeMapKeycloakTransaction::new);
|
||||
MODEL_TO_TX.put(ClientModel.class, JpaClientMapKeycloakTransaction::new);
|
||||
MODEL_TO_TX.put(GroupModel.class, JpaGroupMapKeycloakTransaction::new);
|
||||
MODEL_TO_TX.put(RealmModel.class, JpaRealmMapKeycloakTransaction::new);
|
||||
MODEL_TO_TX.put(RoleModel.class, JpaRoleMapKeycloakTransaction::new);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ public abstract class JpaModelCriteriaBuilder<E, M, Self extends JpaModelCriteri
|
|||
|
||||
private final Function<BiFunction<CriteriaBuilder, Root<E>, Predicate>, Self> instantiator;
|
||||
private BiFunction<CriteriaBuilder, Root<E>, Predicate> predicateFunc = null;
|
||||
private boolean isDistinct = false;
|
||||
|
||||
public JpaModelCriteriaBuilder(Function<BiFunction<CriteriaBuilder, Root<E>, Predicate>, Self> instantiator) {
|
||||
this.instantiator = instantiator;
|
||||
|
@ -51,6 +52,14 @@ public abstract class JpaModelCriteriaBuilder<E, M, Self extends JpaModelCriteri
|
|||
this.predicateFunc = predicateFunc;
|
||||
}
|
||||
|
||||
public JpaModelCriteriaBuilder(Function<BiFunction<CriteriaBuilder, Root<E>, Predicate>, Self> instantiator,
|
||||
BiFunction<CriteriaBuilder, Root<E>, Predicate> predicateFunc,
|
||||
boolean isDistinct) {
|
||||
this.instantiator = instantiator;
|
||||
this.predicateFunc = predicateFunc;
|
||||
this.isDistinct = isDistinct;
|
||||
}
|
||||
|
||||
protected void validateValue(Object[] value, SearchableModelField<? super M> field, ModelCriteriaBuilder.Operator op, Class<?>... expectedTypes) {
|
||||
if (value == null || expectedTypes == null || value.length != expectedTypes.length) {
|
||||
throw new CriterionNotSupportedException(field, op, "Invalid argument: " + Arrays.toString(value));
|
||||
|
@ -91,4 +100,8 @@ public abstract class JpaModelCriteriaBuilder<E, M, Self extends JpaModelCriteri
|
|||
public BiFunction<CriteriaBuilder, Root<E>, Predicate> getPredicateFunc() {
|
||||
return predicateFunc;
|
||||
}
|
||||
|
||||
public boolean isDistinct() {
|
||||
return this.isDistinct;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,11 +22,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_AUTH_SESSION;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_CLIENT;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_CLIENT_SCOPE;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_GROUP;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_ROLE;
|
||||
import org.keycloak.models.map.storage.jpa.authSession.entity.JpaAuthenticationSessionMetadata;
|
||||
import org.keycloak.models.map.storage.jpa.authSession.entity.JpaRootAuthenticationSessionMetadata;
|
||||
import org.keycloak.models.map.storage.jpa.client.entity.JpaClientMetadata;
|
||||
|
@ -35,12 +30,21 @@ import org.keycloak.models.map.storage.jpa.group.entity.JpaGroupMetadata;
|
|||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaAuthenticationSessionMigration;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaClientMigration;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaClientScopeMigration;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaComponentMigration;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaGroupMigration;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaRealmMigration;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaRoleMigration;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.migration.JpaRootAuthenticationSessionMigration;
|
||||
import org.keycloak.models.map.storage.jpa.realm.entity.JpaComponentMetadata;
|
||||
import org.keycloak.models.map.storage.jpa.realm.entity.JpaRealmMetadata;
|
||||
import org.keycloak.models.map.storage.jpa.role.entity.JpaRoleMetadata;
|
||||
|
||||
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_AUTH_SESSION;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_CLIENT;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_CLIENT_SCOPE;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_GROUP;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_REALM;
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_ROLE;
|
||||
|
||||
public class JpaEntityMigration {
|
||||
|
||||
|
@ -50,7 +54,9 @@ public class JpaEntityMigration {
|
|||
MIGRATIONS.put(JpaRootAuthenticationSessionMetadata.class, (tree, entityVersion) -> migrateTreeTo(entityVersion, CURRENT_SCHEMA_VERSION_AUTH_SESSION, tree, JpaRootAuthenticationSessionMigration.MIGRATORS));
|
||||
MIGRATIONS.put(JpaClientMetadata.class, (tree, entityVersion) -> migrateTreeTo(entityVersion, CURRENT_SCHEMA_VERSION_CLIENT, tree, JpaClientMigration.MIGRATORS));
|
||||
MIGRATIONS.put(JpaClientScopeMetadata.class, (tree, entityVersion) -> migrateTreeTo(entityVersion, CURRENT_SCHEMA_VERSION_CLIENT_SCOPE, tree, JpaClientScopeMigration.MIGRATORS));
|
||||
MIGRATIONS.put(JpaComponentMetadata.class, (tree, entityVersion) -> migrateTreeTo(entityVersion, CURRENT_SCHEMA_VERSION_REALM, tree, JpaComponentMigration.MIGRATORS));
|
||||
MIGRATIONS.put(JpaGroupMetadata.class, (tree, entityVersion) -> migrateTreeTo(entityVersion, CURRENT_SCHEMA_VERSION_GROUP, tree, JpaGroupMigration.MIGRATORS));
|
||||
MIGRATIONS.put(JpaRealmMetadata.class, (tree, entityVersion) -> migrateTreeTo(entityVersion, CURRENT_SCHEMA_VERSION_REALM, tree, JpaRealmMigration.MIGRATORS));
|
||||
MIGRATIONS.put(JpaRoleMetadata.class, (tree, entityVersion) -> migrateTreeTo(entityVersion, CURRENT_SCHEMA_VERSION_ROLE, tree, JpaRoleMigration.MIGRATORS));
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,27 @@ import org.keycloak.models.map.common.EntityWithAttributes;
|
|||
import org.keycloak.models.map.common.Serialization.IgnoreUpdatedMixIn;
|
||||
import org.keycloak.models.map.common.Serialization.IgnoredTypeMixIn;
|
||||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationExecutionEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationExecutionEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationFlowEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticationFlowEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticatorConfigEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapAuthenticatorConfigEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapClientInitialAccessEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapClientInitialAccessEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderMapperEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapIdentityProviderMapperEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapOTPPolicyEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapOTPPolicyEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredActionProviderEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapRequiredCredentialEntityImpl;
|
||||
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapWebAuthnPolicyEntityImpl;
|
||||
|
||||
import static org.keycloak.models.map.storage.jpa.hibernate.jsonb.JpaEntityMigration.MIGRATIONS;
|
||||
|
||||
public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> implements DynamicParameterizedType {
|
||||
|
@ -68,7 +89,18 @@ public class JsonbType extends AbstractSingleColumnStandardBasicType<Object> imp
|
|||
.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE)
|
||||
.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
|
||||
.activateDefaultTyping(new LaissezFaireSubTypeValidator(), ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.PROPERTY)
|
||||
.registerModule(new SimpleModule().addAbstractTypeMapping(MapProtocolMapperEntity.class, MapProtocolMapperEntityImpl.class))
|
||||
.registerModule(new SimpleModule().addAbstractTypeMapping(MapProtocolMapperEntity.class, MapProtocolMapperEntityImpl.class)
|
||||
// realm abstract type mappings
|
||||
.addAbstractTypeMapping(MapAuthenticationExecutionEntity.class, MapAuthenticationExecutionEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapAuthenticationFlowEntity.class, MapAuthenticationFlowEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapAuthenticatorConfigEntity.class, MapAuthenticatorConfigEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapClientInitialAccessEntity.class, MapClientInitialAccessEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapIdentityProviderEntity.class, MapIdentityProviderEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapIdentityProviderMapperEntity.class, MapIdentityProviderMapperEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapOTPPolicyEntity.class, MapOTPPolicyEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapRequiredActionProviderEntity.class, MapRequiredActionProviderEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapRequiredCredentialEntity.class, MapRequiredCredentialEntityImpl.class)
|
||||
.addAbstractTypeMapping(MapWebAuthnPolicyEntity.class, MapWebAuthnPolicyEntityImpl.class))
|
||||
.addMixIn(UpdatableEntity.class, IgnoreUpdatedMixIn.class)
|
||||
.addMixIn(DeepCloner.class, IgnoredTypeMixIn.class)
|
||||
.addMixIn(EntityWithAttributes.class, IgnoredMetadataFieldsMixIn.class);
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.jsonb.migration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
/**
|
||||
* Migration functions for components.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class JpaComponentMigration {
|
||||
|
||||
public static final List<Function<ObjectNode, ObjectNode>> MIGRATORS = Arrays.asList(
|
||||
o -> o // no migration yet
|
||||
);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.jsonb.migration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
/**
|
||||
* Migration functions for realms.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class JpaRealmMigration {
|
||||
|
||||
public static final List<Function<ObjectNode, ObjectNode>> MIGRATORS = Arrays.asList(
|
||||
o -> o // no migration yet
|
||||
);
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.realm;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.persistence.criteria.Selection;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.map.realm.MapRealmEntity;
|
||||
import org.keycloak.models.map.realm.MapRealmEntityDelegate;
|
||||
import org.keycloak.models.map.storage.jpa.JpaMapKeycloakTransaction;
|
||||
import org.keycloak.models.map.storage.jpa.JpaModelCriteriaBuilder;
|
||||
import org.keycloak.models.map.storage.jpa.JpaRootEntity;
|
||||
import org.keycloak.models.map.storage.jpa.realm.delegate.JpaRealmDelegateProvider;
|
||||
import org.keycloak.models.map.storage.jpa.realm.entity.JpaRealmEntity;
|
||||
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_REALM;
|
||||
|
||||
/**
|
||||
* A {@link org.keycloak.models.map.storage.MapKeycloakTransaction} implementation for realm entities.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class JpaRealmMapKeycloakTransaction extends JpaMapKeycloakTransaction<JpaRealmEntity, MapRealmEntity, RealmModel> {
|
||||
|
||||
public JpaRealmMapKeycloakTransaction(final EntityManager em) {
|
||||
super(JpaRealmEntity.class, em);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Selection<? extends JpaRealmEntity> selectCbConstruct(CriteriaBuilder cb, Root<JpaRealmEntity> root) {
|
||||
return cb.construct(JpaRealmEntity.class,
|
||||
root.get("id"),
|
||||
root.get("version"),
|
||||
root.get("entityVersion"),
|
||||
root.get("name"),
|
||||
root.get("displayName"),
|
||||
root.get("displayNameHtml"),
|
||||
root.get("enabled")
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setEntityVersion(JpaRootEntity entity) {
|
||||
entity.setEntityVersion(CURRENT_SCHEMA_VERSION_REALM);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JpaModelCriteriaBuilder createJpaModelCriteriaBuilder() {
|
||||
return new JpaRealmModelCriteriaBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MapRealmEntity mapToEntityDelegate(JpaRealmEntity original) {
|
||||
return new MapRealmEntityDelegate(new JpaRealmDelegateProvider(original, em));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.realm;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.map.storage.CriterionNotSupportedException;
|
||||
import org.keycloak.models.map.storage.jpa.JpaModelCriteriaBuilder;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.JsonbType;
|
||||
import org.keycloak.models.map.storage.jpa.realm.entity.JpaRealmEntity;
|
||||
import org.keycloak.storage.SearchableModelField;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link JpaModelCriteriaBuilder} implementation for realms.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class JpaRealmModelCriteriaBuilder extends JpaModelCriteriaBuilder<JpaRealmEntity, RealmModel, JpaRealmModelCriteriaBuilder> {
|
||||
|
||||
public JpaRealmModelCriteriaBuilder() {
|
||||
super(JpaRealmModelCriteriaBuilder::new);
|
||||
}
|
||||
|
||||
private JpaRealmModelCriteriaBuilder(final BiFunction<CriteriaBuilder, Root<JpaRealmEntity>, Predicate> predicateFunc) {
|
||||
super(JpaRealmModelCriteriaBuilder::new, predicateFunc);
|
||||
}
|
||||
|
||||
private JpaRealmModelCriteriaBuilder(final BiFunction<CriteriaBuilder, Root<JpaRealmEntity>, Predicate> predicateFUnc,
|
||||
final boolean isDistinct) {
|
||||
super(JpaRealmModelCriteriaBuilder::new, predicateFUnc, isDistinct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpaRealmModelCriteriaBuilder compare(SearchableModelField<? super RealmModel> modelField, Operator op, Object... value) {
|
||||
switch(op) {
|
||||
case EQ:
|
||||
if (modelField.equals(RealmModel.SearchableFields.NAME)) {
|
||||
validateValue(value, modelField, op, String.class);
|
||||
return new JpaRealmModelCriteriaBuilder((cb, root) ->
|
||||
cb.equal(root.get(modelField.getName()), value[0])
|
||||
);
|
||||
} else if (modelField.equals(RealmModel.SearchableFields.COMPONENT_PROVIDER_TYPE)) {
|
||||
validateValue(value, modelField, op, String.class);
|
||||
return new JpaRealmModelCriteriaBuilder((cb, root) ->
|
||||
cb.equal(root.join("components").get("providerType"), value[0]), true);
|
||||
} else {
|
||||
throw new CriterionNotSupportedException(modelField, op);
|
||||
}
|
||||
case EXISTS:
|
||||
if (modelField.equals(RealmModel.SearchableFields.CLIENT_INITIAL_ACCESS)) {
|
||||
return new JpaRealmModelCriteriaBuilder((cb, root) ->
|
||||
cb.isTrue(cb.function("->", JsonbType.class, root.get("metadata"),
|
||||
cb.literal("fClientInitialAccesses")).isNotNull())
|
||||
);
|
||||
} else {
|
||||
throw new CriterionNotSupportedException(modelField, op);
|
||||
}
|
||||
default:
|
||||
throw new CriterionNotSupportedException(modelField, op);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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.realm.delegate;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.keycloak.models.map.common.EntityField;
|
||||
import org.keycloak.models.map.common.delegate.DelegateProvider;
|
||||
import org.keycloak.models.map.realm.MapRealmEntity;
|
||||
import org.keycloak.models.map.realm.MapRealmEntityFields;
|
||||
import org.keycloak.models.map.storage.jpa.JpaDelegateProvider;
|
||||
import org.keycloak.models.map.storage.jpa.realm.entity.JpaRealmEntity;
|
||||
|
||||
/**
|
||||
* A {@link DelegateProvider} implementation for {@link JpaRealmEntity}.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class JpaRealmDelegateProvider extends JpaDelegateProvider<JpaRealmEntity> implements DelegateProvider<MapRealmEntity> {
|
||||
|
||||
private final EntityManager em;
|
||||
|
||||
public JpaRealmDelegateProvider(final JpaRealmEntity delegate, final EntityManager em) {
|
||||
super(delegate);
|
||||
this.em = em;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapRealmEntity getDelegate(boolean isRead, Enum<? extends EntityField<MapRealmEntity>> field, Object... parameters) {
|
||||
if (getDelegate().isMetadataInitialized()) return getDelegate();
|
||||
if (isRead) {
|
||||
if (field instanceof MapRealmEntityFields) {
|
||||
switch ((MapRealmEntityFields) field) {
|
||||
case ID:
|
||||
case NAME:
|
||||
case DISPLAY_NAME:
|
||||
case DISPLAY_NAME_HTML:
|
||||
case ENABLED:
|
||||
return getDelegate();
|
||||
|
||||
case ATTRIBUTES:
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<JpaRealmEntity> query = cb.createQuery(JpaRealmEntity.class);
|
||||
Root<JpaRealmEntity> root = query.from(JpaRealmEntity.class);
|
||||
root.fetch("attributes", JoinType.LEFT);
|
||||
query.select(root).where(cb.equal(root.get("id"), UUID.fromString(getDelegate().getId())));
|
||||
|
||||
setDelegate(em.createQuery(query).getSingleResult());
|
||||
break;
|
||||
|
||||
default:
|
||||
setDelegate(em.find(JpaRealmEntity.class, UUID.fromString(getDelegate().getId())));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Not a valid realm field: " + field);
|
||||
}
|
||||
} else {
|
||||
setDelegate(em.find(JpaRealmEntity.class, UUID.fromString(getDelegate().getId())));
|
||||
}
|
||||
return getDelegate(); }
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* 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.realm.entity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Version;
|
||||
|
||||
import org.hibernate.annotations.Type;
|
||||
import org.hibernate.annotations.TypeDef;
|
||||
import org.hibernate.annotations.TypeDefs;
|
||||
import org.keycloak.models.map.common.DeepCloner;
|
||||
import org.keycloak.models.map.common.UpdatableEntity;
|
||||
import org.keycloak.models.map.realm.entity.MapComponentEntity;
|
||||
import org.keycloak.models.map.storage.jpa.JpaRootVersionedEntity;
|
||||
import org.keycloak.models.map.storage.jpa.hibernate.jsonb.JsonbType;
|
||||
|
||||
import static org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_REALM;
|
||||
|
||||
/**
|
||||
* JPA {@link MapComponentEntity} implementation. Some fields are annotated with {@code @Column(insertable = false, updatable = false)}
|
||||
* to indicate that they are automatically generated from json fields. As such, these fields are non-insertable and non-updatable.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "kc_component")
|
||||
@TypeDefs({@TypeDef(name = "jsonb", typeClass = JsonbType.class)})
|
||||
public class JpaComponentEntity extends UpdatableEntity.Impl implements MapComponentEntity, JpaRootVersionedEntity {
|
||||
|
||||
@Id
|
||||
@Column
|
||||
private UUID id;
|
||||
|
||||
//used for implicit optimistic locking
|
||||
@Version
|
||||
@Column
|
||||
private int version;
|
||||
|
||||
@Column(insertable = false, updatable = false)
|
||||
@Basic(fetch = FetchType.LAZY)
|
||||
private String providerType;
|
||||
|
||||
@Type(type = "jsonb")
|
||||
@Column(columnDefinition = "jsonb")
|
||||
private final JpaComponentMetadata metadata;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name="fk_root")
|
||||
private JpaRealmEntity root;
|
||||
|
||||
/**
|
||||
* No-argument constructor, used by hibernate to instantiate entities.
|
||||
*/
|
||||
public JpaComponentEntity() {
|
||||
this.metadata = new JpaComponentMetadata();
|
||||
}
|
||||
|
||||
public JpaComponentEntity(DeepCloner cloner) {
|
||||
this.metadata = new JpaComponentMetadata(cloner);
|
||||
}
|
||||
|
||||
public void setParent(JpaRealmEntity root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
public boolean isMetadataInitialized() {
|
||||
return this.metadata != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.id == null ? null : this.id.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(String id) {
|
||||
this.id = id == null ? null : UUID.fromString(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getEntityVersion() {
|
||||
return this.metadata.getEntityVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEntityVersion(Integer version) {
|
||||
this.metadata.setEntityVersion(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getCurrentSchemaVersion() {
|
||||
return CURRENT_SCHEMA_VERSION_REALM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.metadata.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.metadata.setName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderId() {
|
||||
return this.metadata.getProviderId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProviderId(String providerId) {
|
||||
this.metadata.setProviderId(providerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProviderType() {
|
||||
if (this.isMetadataInitialized()) return this.metadata.getProviderType();
|
||||
return this.providerType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProviderType(String providerType) {
|
||||
this.metadata.setProviderType(providerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubType() {
|
||||
return this.metadata.getSubType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubType(String subType) {
|
||||
this.metadata.setSubType(subType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParentId() {
|
||||
return this.metadata.getParentId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParentId(String parentId) {
|
||||
this.metadata.setParentId(parentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getConfig() {
|
||||
return this.metadata.getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfig(Map<String, List<String>> config) {
|
||||
this.metadata.setConfig(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof JpaComponentEntity)) return false;
|
||||
return Objects.equals(getId(), ((JpaComponentEntity) obj).getId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.realm.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.keycloak.models.map.common.DeepCloner;
|
||||
import org.keycloak.models.map.realm.entity.MapComponentEntityImpl;
|
||||
|
||||
/**
|
||||
* Class that contains all the component metadata that is written as JSON into the database.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class JpaComponentMetadata extends MapComponentEntityImpl implements Serializable {
|
||||
|
||||
public JpaComponentMetadata(DeepCloner cloner) {
|
||||
super(cloner);
|
||||
}
|
||||
|
||||
public JpaComponentMetadata() {
|
||||
super();
|
||||
}
|
||||
|
||||
private Integer entityVersion;
|
||||
|
||||
public Integer getEntityVersion() {
|
||||
return entityVersion;
|
||||
}
|
||||
|
||||
public void setEntityVersion(Integer entityVersion) {
|
||||
this.entityVersion = entityVersion;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.realm.entity;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.keycloak.models.map.storage.jpa.JpaAttributeEntity;
|
||||
|
||||
/**
|
||||
* JPA implementation for realm attributes. This entity represents a realm attribute and has a many-to-one relationship
|
||||
* with the realm entity.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "kc_realm_attribute")
|
||||
public class JpaRealmAttributeEntity extends JpaAttributeEntity<JpaRealmEntity> {
|
||||
|
||||
public JpaRealmAttributeEntity() {
|
||||
}
|
||||
|
||||
public JpaRealmAttributeEntity(final JpaRealmEntity root, final String name, final String value) {
|
||||
super(root, name, value);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.realm.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.keycloak.models.map.common.DeepCloner;
|
||||
import org.keycloak.models.map.realm.MapRealmEntityImpl;
|
||||
|
||||
/**
|
||||
* Class that contains all the realm metadata that is written as JSON into the database.
|
||||
*
|
||||
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
|
||||
*/
|
||||
public class JpaRealmMetadata extends MapRealmEntityImpl implements Serializable {
|
||||
|
||||
public JpaRealmMetadata() {
|
||||
super();
|
||||
}
|
||||
|
||||
public JpaRealmMetadata(final DeepCloner cloner) {
|
||||
super(cloner);
|
||||
}
|
||||
|
||||
private Integer entityVersion;
|
||||
|
||||
public Integer getEntityVersion() {
|
||||
return entityVersion;
|
||||
}
|
||||
|
||||
public void setEntityVersion(Integer entityVersion) {
|
||||
this.entityVersion = entityVersion;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
<!-- format of id of changelog file names: jpa-realms-changelog-${org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_REALM}.xml -->
|
||||
<include file="META-INF/realms/jpa-realms-changelog-1.xml"/>
|
||||
</databaseChangeLog>
|
|
@ -13,6 +13,10 @@
|
|||
<!--groups-->
|
||||
<class>org.keycloak.models.map.storage.jpa.group.entity.JpaGroupEntity</class>
|
||||
<class>org.keycloak.models.map.storage.jpa.group.entity.JpaGroupAttributeEntity</class>
|
||||
<!-- realms -->
|
||||
<class>org.keycloak.models.map.storage.jpa.realm.entity.JpaComponentEntity</class>
|
||||
<class>org.keycloak.models.map.storage.jpa.realm.entity.JpaRealmEntity</class>
|
||||
<class>org.keycloak.models.map.storage.jpa.realm.entity.JpaRealmAttributeEntity</class>
|
||||
<!--roles-->
|
||||
<class>org.keycloak.models.map.storage.jpa.role.entity.JpaRoleEntity</class>
|
||||
<class>org.keycloak.models.map.storage.jpa.role.entity.JpaRoleAttributeEntity</class>
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
|
||||
|
||||
<!-- format of id of changeSet: realms-${org.keycloak.models.map.storage.jpa.Constants.CURRENT_SCHEMA_VERSION_REALM} -->
|
||||
<changeSet author="keycloak" id="realms-1">
|
||||
|
||||
<createTable tableName="kc_realm">
|
||||
<column name="id" type="UUID">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="version" type="INTEGER" defaultValueNumeric="0">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="metadata" type="json"/>
|
||||
</createTable>
|
||||
<ext:addGeneratedColumn tableName="kc_realm">
|
||||
<ext:column name="entityversion" type="INTEGER" jsonColumn="metadata" jsonProperty="entityVersion"/>
|
||||
<ext:column name="name" type="VARCHAR(255)" jsonColumn="metadata" jsonProperty="fName"/>
|
||||
<ext:column name="displayname" type="TEXT" jsonColumn="metadata" jsonProperty="fDisplayName"/>
|
||||
<ext:column name="displaynamehtml" type="TEXT" jsonColumn="metadata" jsonProperty="fDisplayNameHtml"/>
|
||||
<ext:column name="enabled" type="BOOLEAN" jsonColumn="metadata" jsonProperty="fEnabled"/>
|
||||
</ext:addGeneratedColumn>
|
||||
<createIndex tableName="kc_realm" indexName="realm_entityVersion">
|
||||
<column name="entityversion"/>
|
||||
</createIndex>
|
||||
<createIndex tableName="kc_realm" indexName="realm_name" unique="true">
|
||||
<column name="name"/>
|
||||
</createIndex>
|
||||
<ext:createJsonIndex tableName="kc_realm" indexName="realm_clientInitialAccesses">
|
||||
<ext:column jsonColumn="metadata" jsonProperty="fClientInitialAccesses"/>
|
||||
</ext:createJsonIndex>
|
||||
|
||||
<createTable tableName="kc_component">
|
||||
<column name="id" type="UUID">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="version" type="INTEGER" defaultValueNumeric="0">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="fk_root" type="UUID">
|
||||
<constraints foreignKeyName="component_fk_root_fkey" references="kc_realm(id)" deleteCascade="true"/>
|
||||
</column>
|
||||
<column name="metadata" type="json"/>
|
||||
</createTable>
|
||||
<ext:addGeneratedColumn tableName="kc_component">
|
||||
<ext:column name="providertype" type="VARCHAR(255)" jsonColumn="metadata" jsonProperty="fProviderType"/>
|
||||
</ext:addGeneratedColumn>
|
||||
<createIndex tableName="kc_component" indexName="component_fk_root">
|
||||
<column name="fk_root"/>
|
||||
</createIndex>
|
||||
<createIndex tableName="kc_component" indexName="component_componentType">
|
||||
<column name="providertype"/>
|
||||
</createIndex>
|
||||
|
||||
<createTable tableName="kc_realm_attribute">
|
||||
<column name="id" type="UUID">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="fk_root" type="UUID">
|
||||
<constraints foreignKeyName="realm_attr_fk_root_fkey" references="kc_realm(id)" deleteCascade="true"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(255)"/>
|
||||
<column name="value" type="TEXT"/>
|
||||
</createTable>
|
||||
<createIndex tableName="kc_realm_attribute" indexName="realm_attr_fk_root">
|
||||
<column name="fk_root"/>
|
||||
</createIndex>
|
||||
<createIndex tableName="kc_realm_attribute" indexName="realm_attr_name_value">
|
||||
<column name="name"/>
|
||||
<column name="VALUE(255)" valueComputed="VALUE(255)"/>
|
||||
</createIndex>
|
||||
<modifySql dbms="postgresql,cockroachdb">
|
||||
<replace replace="VALUE(255)" with="(value::varchar(250))"/>
|
||||
</modifySql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
|
@ -0,0 +1,2 @@
|
|||
package org.keycloak.utils;public class UuidValidator {
|
||||
}
|
Loading…
Reference in a new issue