Make it possible to set a custom user and cache providers when using legacy store
Closes #15008
This commit is contained in:
parent
09da4a211e
commit
f32e012c11
11 changed files with 177 additions and 10 deletions
|
@ -18,9 +18,11 @@
|
||||||
package org.keycloak.quarkus.runtime.configuration.mappers;
|
package org.keycloak.quarkus.runtime.configuration.mappers;
|
||||||
|
|
||||||
import static java.util.Optional.of;
|
import static java.util.Optional.of;
|
||||||
|
import static java.util.function.Predicate.not;
|
||||||
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption;
|
import static org.keycloak.quarkus.runtime.configuration.mappers.PropertyMapper.fromOption;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.keycloak.config.StorageOptions;
|
import org.keycloak.config.StorageOptions;
|
||||||
import org.keycloak.config.StorageOptions.StorageType;
|
import org.keycloak.config.StorageOptions.StorageType;
|
||||||
|
@ -301,11 +303,27 @@ final class StoragePropertyMappers {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Optional<String> getAreaStorage(Optional<String> storage, ConfigSourceInterceptorContext context) {
|
private static Optional<String> getAreaStorage(Optional<String> storage, ConfigSourceInterceptorContext context) {
|
||||||
return of(storage.isEmpty() ? "jpa" : "map");
|
if (storage.isEmpty()) {
|
||||||
|
return of("jpa");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Stream.of(StorageType.values()).map(Enum::name).anyMatch(storage.get()::equals)) {
|
||||||
|
return of("map");
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Optional<String> getCacheStorage(Optional<String> storage, ConfigSourceInterceptorContext context) {
|
private static Optional<String> getCacheStorage(Optional<String> storage, ConfigSourceInterceptorContext context) {
|
||||||
return of(storage.isEmpty() ? "infinispan" : "map");
|
if (storage.isEmpty()) {
|
||||||
|
return of("infinispan");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Stream.of(StorageType.values()).map(Enum::name).anyMatch(storage.get()::equals)) {
|
||||||
|
return of("map");
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Optional<String> getGlobalLockProvider(Optional<String> storage, ConfigSourceInterceptorContext context) {
|
private static Optional<String> getGlobalLockProvider(Optional<String> storage, ConfigSourceInterceptorContext context) {
|
||||||
|
|
|
@ -15,13 +15,13 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.acme.provider.user;
|
package com.acme.provider.legacy.jpa.entity;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.keycloak.it.TestProvider;
|
import org.keycloak.it.TestProvider;
|
||||||
|
|
||||||
public class CustomUserProvider implements TestProvider {
|
public class CustomLegacyJpaEntityProvider implements TestProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class[] getClasses() {
|
public Class[] getClasses() {
|
|
@ -15,7 +15,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.acme.provider.user;
|
package com.acme.provider.legacy.jpa.entity;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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 com.acme.provider.legacy.jpa.user;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.keycloak.it.TestProvider;
|
||||||
|
import com.acme.provider.legacy.jpa.entity.Realm;
|
||||||
|
|
||||||
|
public class CustomLegacyUserProvider implements TestProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class[] getClasses() {
|
||||||
|
return new Class[] { MyUserProvider.class, MyUserProviderFactory.class };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getManifestResources() {
|
||||||
|
return Collections.singletonMap("org.keycloak.models.UserProviderFactory", "services/org.keycloak.models.UserProviderFactory");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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 com.acme.provider.legacy.jpa.user;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.jpa.JpaUserProvider;
|
||||||
|
|
||||||
|
public class MyUserProvider extends JpaUserProvider {
|
||||||
|
|
||||||
|
public MyUserProvider(KeycloakSession session, EntityManager em) {
|
||||||
|
super(session, em);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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 com.acme.provider.legacy.jpa.user;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import org.keycloak.connections.jpa.JpaConnectionProvider;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.UserProvider;
|
||||||
|
import org.keycloak.models.jpa.JpaUserProviderFactory;
|
||||||
|
|
||||||
|
public class MyUserProviderFactory extends JpaUserProviderFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserProvider create(KeycloakSession session) {
|
||||||
|
EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
|
||||||
|
return new MyUserProvider(session, em);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "custom_jpa";
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,7 @@
|
||||||
http://java.sun.com/xml/ns/persistence
|
http://java.sun.com/xml/ns/persistence
|
||||||
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||||
<persistence-unit name="user-store" transaction-type="JTA">
|
<persistence-unit name="user-store" transaction-type="JTA">
|
||||||
<class>com.acme.provider.user.Realm</class>
|
<class>com.acme.provider.legacy.jpa.entity.Realm</class>
|
||||||
<properties>
|
<properties>
|
||||||
<property name="hibernate.dialect" value="io.quarkus.hibernate.orm.runtime.dialect.QuarkusH2Dialect" />
|
<property name="hibernate.dialect" value="io.quarkus.hibernate.orm.runtime.dialect.QuarkusH2Dialect" />
|
||||||
<!-- Sets the name of the datasource to be the same as the datasource name in quarkus.properties-->
|
<!-- Sets the name of the datasource to be the same as the datasource name in quarkus.properties-->
|
|
@ -0,0 +1 @@
|
||||||
|
com.acme.provider.legacy.jpa.user.MyUserProviderFactory
|
|
@ -23,7 +23,7 @@ import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
import org.keycloak.it.junit5.extension.LegacyStore;
|
import org.keycloak.it.junit5.extension.LegacyStore;
|
||||||
import org.keycloak.it.junit5.extension.RawDistOnly;
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
import org.keycloak.it.junit5.extension.TestProvider;
|
import org.keycloak.it.junit5.extension.TestProvider;
|
||||||
import com.acme.provider.user.CustomUserProvider;
|
import com.acme.provider.legacy.jpa.entity.CustomLegacyJpaEntityProvider;
|
||||||
|
|
||||||
import io.quarkus.test.junit.main.Launch;
|
import io.quarkus.test.junit.main.Launch;
|
||||||
import io.quarkus.test.junit.main.LaunchResult;
|
import io.quarkus.test.junit.main.LaunchResult;
|
||||||
|
@ -31,15 +31,15 @@ import io.quarkus.test.junit.main.LaunchResult;
|
||||||
@DistributionTest
|
@DistributionTest
|
||||||
@RawDistOnly(reason = "Containers are immutable")
|
@RawDistOnly(reason = "Containers are immutable")
|
||||||
@LegacyStore
|
@LegacyStore
|
||||||
public class CustomJpaUserProviderDistTest {
|
public class CustomLegacyJpaEntityProviderDistTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestProvider(CustomUserProvider.class)
|
@TestProvider(CustomLegacyJpaEntityProvider.class)
|
||||||
@Launch({ "start-dev", "--log-level=org.hibernate.jpa.internal.util.LogHelper:debug" })
|
@Launch({ "start-dev", "--log-level=org.hibernate.jpa.internal.util.LogHelper:debug" })
|
||||||
void testUserManagedEntityNotAddedToDefaultPU(LaunchResult result) {
|
void testUserManagedEntityNotAddedToDefaultPU(LaunchResult result) {
|
||||||
CLIResult cliResult = (CLIResult) result;
|
CLIResult cliResult = (CLIResult) result;
|
||||||
cliResult.assertStringCount("name: user-store", 1);
|
cliResult.assertStringCount("name: user-store", 1);
|
||||||
cliResult.assertStringCount("com.acme.provider.user.Realm", 1);
|
cliResult.assertStringCount("com.acme.provider.legacy.jpa.entity.Realm", 1);
|
||||||
cliResult.assertStartedDevMode();
|
cliResult.assertStartedDevMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 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.it.cli.dist;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.keycloak.it.junit5.extension.CLIResult;
|
||||||
|
import org.keycloak.it.junit5.extension.DistributionTest;
|
||||||
|
import org.keycloak.it.junit5.extension.LegacyStore;
|
||||||
|
import org.keycloak.it.junit5.extension.RawDistOnly;
|
||||||
|
import org.keycloak.it.junit5.extension.TestProvider;
|
||||||
|
import com.acme.provider.legacy.jpa.entity.CustomLegacyJpaEntityProvider;
|
||||||
|
import com.acme.provider.legacy.jpa.user.CustomLegacyUserProvider;
|
||||||
|
|
||||||
|
import io.quarkus.test.junit.main.Launch;
|
||||||
|
import io.quarkus.test.junit.main.LaunchResult;
|
||||||
|
|
||||||
|
@DistributionTest
|
||||||
|
@RawDistOnly(reason = "Containers are immutable")
|
||||||
|
@LegacyStore
|
||||||
|
public class CustomLegacyUserProviderDistTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestProvider(CustomLegacyUserProvider.class)
|
||||||
|
@Launch({ "start-dev", "--spi-user-provider=custom_jpa --spi-user-jpa-enabled=false" })
|
||||||
|
void testUserManagedEntityNotAddedToDefaultPU(LaunchResult result) {
|
||||||
|
CLIResult cliResult = (CLIResult) result;
|
||||||
|
cliResult.assertMessage("KC-SERVICES0047: custom_jpa (com.acme.provider.legacy.jpa.user.MyUserProviderFactory) is implementing the internal SPI user. This SPI is internal and may change without notice");
|
||||||
|
cliResult.assertStartedDevMode();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue