keycloak-uncached
Changes
adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java 2(+2 -0)
examples/providers/pom.xml 1(+1 -0)
examples/providers/user-storage-jpa/pom.xml 79(+79 -0)
examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProvider.java 118(+118 -0)
examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProviderFactory.java 60(+60 -0)
examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserAdapter.java 135(+135 -0)
examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserEntity.java 82(+82 -0)
examples/providers/user-storage-jpa/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory 1(+1 -0)
federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/TxAwareLDAPUserModelDelegate.java 2(+1 -1)
federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java 2(+1 -1)
model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java 2(+1 -1)
model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java 26(+16 -10)
model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java 2(+1 -1)
model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java 2(+1 -1)
model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java 4(+2 -2)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java 4(+2 -2)
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java 276(+113 -163)
server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java 7(+3 -4)
server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProviderSpi.java 2(+0 -2)
services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java 10(+5 -5)
services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java 4(+2 -2)
services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java 30(+19 -11)
services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java 4(+2 -2)
testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java 14(+7 -7)
testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java 4(+2 -2)
testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractAuthorizationTest.java 4(+2 -2)
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java 29(+12 -17)
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java 16(+4 -12)
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorage.java 18(+6 -12)
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorageFactory.java 20(+5 -15)
testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserStorageTest.java 64(+46 -18)
Details
diff --git a/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java b/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java
index fd8af9f..fc0e47f 100644
--- a/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java
+++ b/adapters/oidc/installed/src/main/java/org/keycloak/adapters/installed/KeycloakInstalled.java
@@ -119,6 +119,7 @@ public class KeycloakInstalled {
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
.queryParam(OAuth2Constants.STATE, state)
+ .queryParam(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
.build().toString();
Desktop.getDesktop().browse(new URI(authUrl));
@@ -175,6 +176,7 @@ public class KeycloakInstalled {
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
+ .queryParam(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
.build().toString();
printer.println("Open the following URL in a browser. After login copy/paste the code back and press <enter>");
diff --git a/core/src/main/java/org/keycloak/representations/idm/ComponentRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ComponentRepresentation.java
new file mode 100755
index 0000000..bbc4a42
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/ComponentRepresentation.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016 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.representations.idm;
+
+import org.keycloak.common.util.MultivaluedHashMap;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ComponentRepresentation {
+
+ private String id;
+ private String name;
+ private String providerId;
+ private String providerType;
+ private String parentId;
+ private MultivaluedHashMap<String, String> config;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getProviderId() {
+ return providerId;
+ }
+
+ public void setProviderId(String providerId) {
+ this.providerId = providerId;
+ }
+
+ public String getProviderType() {
+ return providerType;
+ }
+
+ public void setProviderType(String providerType) {
+ this.providerType = providerType;
+ }
+
+ public String getParentId() {
+ return parentId;
+ }
+
+ public void setParentId(String parentId) {
+ this.parentId = parentId;
+ }
+
+ public MultivaluedHashMap<String, String> getConfig() {
+ return config;
+ }
+
+ public void setConfig(MultivaluedHashMap<String, String> config) {
+ this.config = config;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ ComponentRepresentation that = (ComponentRepresentation) o;
+
+ if (!id.equals(that.id)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+}
diff --git a/core/src/main/java/org/keycloak/representations/idm/ComponentTypeRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ComponentTypeRepresentation.java
new file mode 100644
index 0000000..8ba0da6
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/ComponentTypeRepresentation.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016 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.representations.idm;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ */
+public class ComponentTypeRepresentation {
+ protected String id;
+ protected String helpText;
+ protected List<ConfigPropertyRepresentation> properties;
+
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getHelpText() {
+ return helpText;
+ }
+
+ public void setHelpText(String helpText) {
+ this.helpText = helpText;
+ }
+
+ public List<ConfigPropertyRepresentation> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(List<ConfigPropertyRepresentation> properties) {
+ this.properties = properties;
+ }
+}
diff --git a/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java b/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java
index c3aeeeb..59d400e 100755
--- a/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java
+++ b/core/src/main/java/org/keycloak/representations/info/ServerInfoRepresentation.java
@@ -17,6 +17,7 @@
package org.keycloak.representations.info;
+import org.keycloak.representations.idm.ComponentTypeRepresentation;
import org.keycloak.representations.idm.PasswordPolicyTypeRepresentation;
import org.keycloak.representations.idm.ProtocolMapperRepresentation;
import org.keycloak.representations.idm.ProtocolMapperTypeRepresentation;
@@ -43,6 +44,7 @@ public class ServerInfoRepresentation {
private Map<String, List<ProtocolMapperTypeRepresentation>> protocolMapperTypes;
private Map<String, List<ProtocolMapperRepresentation>> builtinProtocolMappers;
private Map<String, List<ClientInstallationRepresentation>> clientInstallations;
+ private Map<String, List<ComponentTypeRepresentation>> componentTypes;
private List<PasswordPolicyTypeRepresentation> passwordPolicies;
@@ -144,4 +146,11 @@ public class ServerInfoRepresentation {
this.passwordPolicies = passwordPolicies;
}
+ public Map<String, List<ComponentTypeRepresentation>> getComponentTypes() {
+ return componentTypes;
+ }
+
+ public void setComponentTypes(Map<String, List<ComponentTypeRepresentation>> componentTypes) {
+ this.componentTypes = componentTypes;
+ }
}
examples/providers/pom.xml 1(+1 -0)
diff --git a/examples/providers/pom.xml b/examples/providers/pom.xml
index 20b4eaa..fcde8b0 100755
--- a/examples/providers/pom.xml
+++ b/examples/providers/pom.xml
@@ -37,5 +37,6 @@
<module>authenticator</module>
<module>rest</module>
<module>domain-extension</module>
+ <module>user-storage-jpa</module>
</modules>
</project>
examples/providers/user-storage-jpa/pom.xml 79(+79 -0)
diff --git a/examples/providers/user-storage-jpa/pom.xml b/examples/providers/user-storage-jpa/pom.xml
new file mode 100755
index 0000000..b025900
--- /dev/null
+++ b/examples/providers/user-storage-jpa/pom.xml
@@ -0,0 +1,79 @@
+<!--
+ ~ Copyright 2016 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>keycloak-examples-providers-parent</artifactId>
+ <groupId>org.keycloak</groupId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+
+ <name>Properties Authentication Provider Example</name>
+ <description/>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>user-storage-jpa-example</artifactId>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-server-spi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-model-jpa</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.logging</groupId>
+ <artifactId>jboss-logging</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate.javax.persistence</groupId>
+ <artifactId>hibernate-jpa-2.1-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>user-storage-jpa-example</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProvider.java b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProvider.java
new file mode 100644
index 0000000..0705333
--- /dev/null
+++ b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProvider.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016 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.examples.storage.user;
+
+import org.keycloak.component.ComponentModel;
+import org.keycloak.models.GroupModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.storage.StorageId;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.user.UserLookupProvider;
+import org.keycloak.storage.user.UserRegistrationProvider;
+
+import javax.persistence.EntityManager;
+import javax.persistence.TypedQuery;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ExampleUserStorageProvider implements UserStorageProvider, UserLookupProvider, UserRegistrationProvider {
+ protected EntityManager em;
+ protected ComponentModel model;
+ protected KeycloakSession session;
+
+ public ExampleUserStorageProvider(EntityManager em, ComponentModel model, KeycloakSession session) {
+ this.em = em;
+ this.model = model;
+ this.session = session;
+ }
+
+ @Override
+ public void preRemove(RealmModel realm) {
+
+ }
+
+ @Override
+ public void preRemove(RealmModel realm, GroupModel group) {
+
+ }
+
+ @Override
+ public void preRemove(RealmModel realm, RoleModel role) {
+
+ }
+
+ @Override
+ public void close() {
+ em.close();
+ }
+
+ @Override
+ public UserModel getUserById(String id, RealmModel realm) {
+ String persistenceId = StorageId.externalId(id);
+ UserEntity entity = em.find(UserEntity.class, persistenceId);
+ if (entity == null) return null;
+ return new UserAdapter(session, realm, model, entity);
+ }
+
+ @Override
+ public UserModel getUserByUsername(String username, RealmModel realm) {
+ TypedQuery<UserEntity> query = em.createNamedQuery("getUserByUsername", UserEntity.class);
+ query.setParameter("username", username);
+ List<UserEntity> result = query.getResultList();
+ if (result.isEmpty()) return null;
+ return new UserAdapter(session, realm, model, result.get(0));
+ }
+
+ @Override
+ public UserModel getUserByEmail(String email, RealmModel realm) {
+ TypedQuery<UserEntity> query = em.createNamedQuery("getUserByEmail", UserEntity.class);
+ query.setParameter("email", email);
+ List<UserEntity> result = query.getResultList();
+ if (result.isEmpty()) return null;
+ return new UserAdapter(session, realm, model, result.get(0));
+ }
+
+ @Override
+ public UserModel addUser(RealmModel realm, String username) {
+ UserEntity entity = new UserEntity();
+ entity.setId(KeycloakModelUtils.generateId());
+ entity.setUsername(username);
+ em.persist(entity);
+ return new UserAdapter(session, realm, model, entity);
+ }
+
+ @Override
+ public boolean removeUser(RealmModel realm, UserModel user) {
+ String persistenceId = StorageId.externalId(user.getId());
+ UserEntity entity = em.find(UserEntity.class, persistenceId);
+ if (entity == null) return false;
+ em.remove(entity);
+ return true;
+ }
+
+ @Override
+ public void grantToAllUsers(RealmModel realm, RoleModel role) {
+
+ }
+}
diff --git a/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProviderFactory.java b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProviderFactory.java
new file mode 100644
index 0000000..963a558
--- /dev/null
+++ b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/ExampleUserStorageProviderFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 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.examples.storage.user;
+
+import org.keycloak.Config;
+import org.keycloak.component.ComponentModel;
+import org.keycloak.connections.jpa.JndiEntityManagerLookup;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.KeycloakSessionFactory;
+import org.keycloak.storage.UserStorageProviderFactory;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ExampleUserStorageProviderFactory implements UserStorageProviderFactory<ExampleUserStorageProvider> {
+ protected String jndiName = "java:jboss/ExampleUserEntityManagerFactory";
+
+ @Override
+ public ExampleUserStorageProvider create(KeycloakSession session, ComponentModel model) {
+ EntityManager em = JndiEntityManagerLookup.getSessionEntityManager(session, jndiName);
+ return new ExampleUserStorageProvider(em, model, session);
+ }
+
+ @Override
+ public String getId() {
+ return "example-user-storage";
+ }
+
+ @Override
+ public void init(Config.Scope config) {
+
+ }
+
+ @Override
+ public void postInit(KeycloakSessionFactory factory) {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+}
diff --git a/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserAdapter.java b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserAdapter.java
new file mode 100644
index 0000000..f851904
--- /dev/null
+++ b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserAdapter.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 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.examples.storage.user;
+
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserCredentialModel;
+import org.keycloak.storage.StorageId;
+import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserAdapter extends AbstractUserAdapterFederatedStorage {
+ protected UserEntity entity;
+ protected String keycloakId;
+
+ public UserAdapter(KeycloakSession session, RealmModel realm, ComponentModel model, UserEntity entity) {
+ super(session, realm, model);
+ this.entity = entity;
+ keycloakId = StorageId.keycloakId(model, entity.getId());
+ }
+
+ @Override
+ public String getUsername() {
+ return entity.getUsername();
+ }
+
+ @Override
+ public void setUsername(String username) {
+ entity.setUsername(username);
+
+ }
+
+ @Override
+ public void setEmail(String email) {
+ entity.setEmail(email);
+ }
+
+ @Override
+ public String getEmail() {
+ return entity.getEmail();
+ }
+
+ @Override
+ public String getId() {
+ return keycloakId;
+ }
+
+ @Override
+ public void updateCredential(UserCredentialModel cred) {
+ if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
+ entity.setPassword(cred.getValue());
+ } else {
+ super.updateCredential(cred);
+ }
+ }
+
+ @Override
+ public void setSingleAttribute(String name, String value) {
+ if (name.equals("phone")) {
+ entity.setPhone(value);
+ } else {
+ super.setSingleAttribute(name, value);
+ }
+ }
+
+ @Override
+ public void removeAttribute(String name) {
+ if (name.equals("phone")) {
+ entity.setPhone(null);
+ } else {
+ super.removeAttribute(name);
+ }
+ }
+
+ @Override
+ public void setAttribute(String name, List<String> values) {
+ if (name.equals("phone")) {
+ entity.setPhone(values.get(0));
+ } else {
+ super.setAttribute(name, values);
+ }
+ }
+
+ @Override
+ public String getFirstAttribute(String name) {
+ if (name.equals("phone")) {
+ return entity.getPhone();
+ } else {
+ return super.getFirstAttribute(name);
+ }
+ }
+
+ @Override
+ public Map<String, List<String>> getAttributes() {
+ Map<String, List<String>> attrs = super.getAttributes();
+ MultivaluedHashMap<String, String> all = new MultivaluedHashMap<>();
+ all.putAll(attrs);
+ all.add("phone", entity.getPhone());
+ return all;
+ }
+
+ @Override
+ public List<String> getAttribute(String name) {
+ if (name.equals("phone")) {
+ List<String> phone = new LinkedList<>();
+ phone.add(entity.getPhone());
+ return phone;
+ } else {
+ return super.getAttribute(name);
+ }
+ }
+}
diff --git a/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserEntity.java b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserEntity.java
new file mode 100644
index 0000000..c9227d2
--- /dev/null
+++ b/examples/providers/user-storage-jpa/src/main/java/org/keycloak/examples/storage/user/UserEntity.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 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.examples.storage.user;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+ @NamedQuery(name="getUserByUsername", query="select u from UserEntity u where u.username = :username"),
+ @NamedQuery(name="getUserByEmail", query="select u from UserEntity u where u.email = :email"),
+})
+@Entity
+public class UserEntity {
+ @Id
+ private String id;
+
+
+ private String username;
+ private String email;
+ private String password;
+ private String phone;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+}
diff --git a/examples/providers/user-storage-jpa/src/main/resources/META-INF/persistence.xml b/examples/providers/user-storage-jpa/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..5af362d
--- /dev/null
+++ b/examples/providers/user-storage-jpa/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="2.0"
+ xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://java.sun.com/xml/ns/persistence
+ http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+ <persistence-unit name="primary">
+ <non-jta-data-source>java:jboss/datasources/ExampleUserDS</non-jta-data-source>
+
+ <class>org.keycloak.examples.storage.user.UserEntity</class>
+
+ <properties>
+ <property name="jboss.entity.manager.factory.jndi.name" value="java:jboss/ExampleUserEntityManagerFactory" />
+ <property name="hibernate.hbm2ddl.auto" value="update" />
+ <property name="hibernate.show_sql" value="false" />
+ </properties>
+ </persistence-unit>
+</persistence>
diff --git a/examples/providers/user-storage-jpa/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory b/examples/providers/user-storage-jpa/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory
new file mode 100644
index 0000000..1634d11
--- /dev/null
+++ b/examples/providers/user-storage-jpa/src/main/resources/META-INF/services/org.keycloak.storage.UserStorageProviderFactory
@@ -0,0 +1 @@
+org.keycloak.examples.storage.user.ExampleUserStorageProviderFactory
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/TxAwareLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/TxAwareLDAPUserModelDelegate.java
index 622ebb6..9126a66 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/TxAwareLDAPUserModelDelegate.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/TxAwareLDAPUserModelDelegate.java
@@ -70,7 +70,7 @@ public abstract class TxAwareLDAPUserModelDelegate extends UserModelDelegate {
logger.trace("Starting and enlisting transaction for object " + ldapUser.getDn().toString());
}
- this.provider.getSession().getTransaction().enlistAfterCompletion(transaction);
+ this.provider.getSession().getTransactionManager().enlistAfterCompletion(transaction);
}
}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java
index af910a7..b577326 100644
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java
+++ b/federation/ldap/src/main/java/org/keycloak/federation/ldap/mappers/UserAttributeLDAPFederationMapper.java
@@ -163,7 +163,7 @@ public class UserAttributeLDAPFederationMapper extends AbstractLDAPFederationMap
UserModel that = session.userStorage().getUserByEmail(email, realm);
if (that != null && !that.getId().equals(user.getId())) {
- session.getTransaction().setRollbackOnly();
+ session.getTransactionManager().setRollbackOnly();
String exceptionMessage = String.format("Can't import user '%s' from LDAP because email '%s' already exists in Keycloak. Existing user with this email is '%s'", user.getUsername(), email, that.getUsername());
throw new ModelDuplicateException(exceptionMessage, UserModel.EMAIL);
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java
index cea4388..56a385f 100644
--- a/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/authorization/infinispan/InfinispanStoreFactoryProvider.java
@@ -40,7 +40,7 @@ public class InfinispanStoreFactoryProvider implements CachedStoreFactoryProvide
InfinispanStoreFactoryProvider(KeycloakSession delegate) {
this.session = delegate;
this.transaction = new CacheTransaction();
- this.session.getTransaction().enlistAfterCompletion(transaction);
+ this.session.getTransactionManager().enlistAfterCompletion(transaction);
}
@Override
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
index 6dcc0d9..80997c3 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/entities/CachedRealm.java
@@ -18,6 +18,7 @@
package org.keycloak.models.cache.infinispan.entities;
import org.keycloak.common.enums.SslRequired;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.AuthenticatorConfigModel;
@@ -29,20 +30,14 @@ import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.OTPPolicy;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
-import org.keycloak.models.RealmProvider;
import org.keycloak.models.RequiredActionProviderModel;
import org.keycloak.models.RequiredCredentialModel;
-import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationMapperModel;
import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.cache.infinispan.RealmCache;
import org.keycloak.common.util.MultivaluedHashMap;
-import org.keycloak.storage.StorageProviderModel;
-import java.io.Serializable;
import java.security.PrivateKey;
import java.security.PublicKey;
-import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
@@ -111,7 +106,8 @@ public class CachedRealm extends AbstractRevisioned {
protected List<RequiredCredentialModel> requiredCredentials;
protected List<UserFederationProviderModel> userFederationProviders;
- protected List<StorageProviderModel> storageProviders;
+ protected MultivaluedHashMap<String, ComponentModel> componentsByParent = new MultivaluedHashMap<>();
+ protected Map<String, ComponentModel> components = new HashMap<>();
protected MultivaluedHashMap<String, UserFederationMapperModel> userFederationMappers = new MultivaluedHashMap<String, UserFederationMapperModel>();
protected Set<UserFederationMapperModel> userFederationMapperSet;
protected List<IdentityProviderModel> identityProviders;
@@ -208,7 +204,6 @@ public class CachedRealm extends AbstractRevisioned {
requiredCredentials = model.getRequiredCredentials();
userFederationProviders = model.getUserFederationProviders();
- storageProviders = model.getStorageProviders();
userFederationMapperSet = model.getUserFederationMappers();
for (UserFederationMapperModel mapper : userFederationMapperSet) {
this.userFederationMappers.add(mapper.getFederationProviderId(), mapper);
@@ -279,6 +274,13 @@ public class CachedRealm extends AbstractRevisioned {
resetCredentialsFlow = model.getResetCredentialsFlow();
clientAuthenticationFlow = model.getClientAuthenticationFlow();
+ for (ComponentModel component : model.getComponents()) {
+ componentsByParent.add(component.getParentId() + component.getProviderType(), component);
+ }
+ for (ComponentModel component : model.getComponents()) {
+ components.put(component.getId(), component);
+ }
+
}
protected void cacheClientTemplates(RealmModel model) {
@@ -602,7 +604,11 @@ public class CachedRealm extends AbstractRevisioned {
return requiredActionProviderList;
}
- public List<StorageProviderModel> getStorageProviders() {
- return storageProviders;
+ public MultivaluedHashMap<String, ComponentModel> getComponentsByParent() {
+ return componentsByParent;
+ }
+
+ public Map<String, ComponentModel> getComponents() {
+ return components;
}
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
index 69f0510..ffaf469 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmAdapter.java
@@ -19,11 +19,10 @@ package org.keycloak.models.cache.infinispan;
import org.keycloak.Config;
import org.keycloak.common.enums.SslRequired;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.*;
-import org.keycloak.models.cache.CacheRealmProvider;
import org.keycloak.models.cache.infinispan.entities.CachedRealm;
import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.storage.StorageProviderModel;
import java.security.Key;
import java.security.PrivateKey;
@@ -747,48 +746,6 @@ public class RealmAdapter implements RealmModel {
}
@Override
- public StorageProviderModel addStorageProvider(StorageProviderModel provider) {
- getDelegateForUpdate();
- return updated.addStorageProvider(provider);
- }
-
- @Override
- public void updateStorageProvider(StorageProviderModel provider) {
- getDelegateForUpdate();
- updated.updateStorageProvider(provider);
-
- }
-
- @Override
- public void removeStorageProvider(StorageProviderModel provider) {
- getDelegateForUpdate();
- updated.removeStorageProvider(provider);
-
- }
-
- @Override
- public void setStorageProviders(List<StorageProviderModel> providers) {
- getDelegateForUpdate();
- updated.setStorageProviders(providers);
-
- }
-
- @Override
- public List<StorageProviderModel> getStorageProviders() {
- if (isUpdated()) return updated.getStorageProviders();
- return cached.getStorageProviders();
- }
-
- @Override
- public StorageProviderModel getStorageProvider(String id) {
- if (isUpdated()) return updated.getStorageProvider(id);
- for (StorageProviderModel model : cached.getStorageProviders()) {
- if (model.getId().equals(id)) return model;
- }
- return null;
- }
-
- @Override
public String getLoginTheme() {
if (isUpdated()) return updated.getLoginTheme();
return cached.getLoginTheme();
@@ -1451,6 +1408,52 @@ public class RealmAdapter implements RealmModel {
return cacheSession.getClientTemplateById(id, this);
}
+ @Override
+ public ComponentModel addComponentModel(ComponentModel model) {
+ getDelegateForUpdate();
+ return updated.addComponentModel(model);
+ }
+
+ @Override
+ public void updateComponent(ComponentModel component) {
+ getDelegateForUpdate();
+ updated.updateComponent(component);
+
+ }
+
+ @Override
+ public void removeComponent(ComponentModel component) {
+ getDelegateForUpdate();
+ updated.removeComponent(component);
+
+ }
+
+ @Override
+ public void removeComponents(String parentId) {
+ getDelegateForUpdate();
+ updated.removeComponents(parentId);
+ }
+ @Override
+ public List<ComponentModel> getComponents(String parentId, String providerType) {
+ if (isUpdated()) return updated.getComponents(parentId, providerType);
+ List<ComponentModel> components = cached.getComponentsByParent().getList(parentId + providerType);
+ if (components == null) return Collections.EMPTY_LIST;
+ return Collections.unmodifiableList(components);
+ }
+
+ @Override
+ public List<ComponentModel> getComponents() {
+ if (isUpdated()) return updated.getComponents();
+ List<ComponentModel> results = new LinkedList<>();
+ results.addAll(cached.getComponents().values());
+ return Collections.unmodifiableList(results);
+ }
+
+ @Override
+ public ComponentModel getComponent(String id) {
+ if (isUpdated()) return updated.getComponent(id);
+ return cached.getComponents().get(id);
+ }
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
index 2a3880d..7a72964 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/RealmCacheSession.java
@@ -132,8 +132,8 @@ public class RealmCacheSession implements CacheRealmProvider {
this.cache = cache;
this.session = session;
this.startupRevision = cache.getCurrentCounter();
- session.getTransaction().enlistPrepare(getPrepareTransaction());
- session.getTransaction().enlistAfterCompletion(getAfterTransaction());
+ session.getTransactionManager().enlistPrepare(getPrepareTransaction());
+ session.getTransactionManager().enlistAfterCompletion(getAfterTransaction());
}
public long getStartupRevision() {
diff --git a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
index c5e4c30..3016ae8 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/UserCacheSession.java
@@ -19,6 +19,7 @@ package org.keycloak.models.cache.infinispan;
import org.jboss.logging.Logger;
import org.keycloak.common.constants.ServiceAccountConstants;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.FederatedIdentityModel;
@@ -39,7 +40,6 @@ import org.keycloak.models.cache.infinispan.entities.CachedUser;
import org.keycloak.models.cache.infinispan.entities.CachedUserConsent;
import org.keycloak.models.cache.infinispan.entities.CachedUserConsents;
import org.keycloak.models.cache.infinispan.entities.UserListQuery;
-import org.keycloak.storage.StorageProviderModel;
import java.util.*;
@@ -65,7 +65,7 @@ public class UserCacheSession implements CacheUserProvider {
this.cache = cache;
this.session = session;
this.startupRevision = cache.getCurrentCounter();
- session.getTransaction().enlistAfterCompletion(getTransaction());
+ session.getTransactionManager().enlistAfterCompletion(getTransaction());
}
@Override
@@ -665,7 +665,8 @@ public class UserCacheSession implements CacheUserProvider {
}
@Override
- public void preRemove(RealmModel realm, StorageProviderModel provider) {
- getDelegate().preRemove(realm, provider);
+ public void preRemove(RealmModel realm, ComponentModel component) {
+ getDelegate().preRemove(realm, component);
+
}
}
diff --git a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
index 960ea25..614fa9f 100755
--- a/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
+++ b/model/infinispan/src/main/java/org/keycloak/models/sessions/infinispan/InfinispanUserSessionProvider.java
@@ -81,7 +81,7 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
this.loginFailureCache = loginFailureCache;
this.tx = new InfinispanKeycloakTransaction();
- session.getTransaction().enlistAfterCompletion(tx);
+ session.getTransactionManager().enlistAfterCompletion(tx);
}
protected Cache<String, SessionEntity> getCache(boolean offline) {
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
index 431a638..4272fb8 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
@@ -63,7 +63,7 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
EntityManager em = emf.createEntityManager();
em = PersistenceExceptionConverter.create(em);
- session.getTransaction().enlist(new JpaKeycloakTransaction(em));
+ session.getTransactionManager().enlist(new JpaKeycloakTransaction(em));
return new DefaultJpaConnectionProvider(em);
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ComponentConfigEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ComponentConfigEntity.java
new file mode 100755
index 0000000..bf141a8
--- /dev/null
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/ComponentConfigEntity.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2016 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.jpa.entities;
+
+import javax.persistence.Access;
+import javax.persistence.AccessType;
+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.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+@NamedQueries({
+ @NamedQuery(name="getComponentConfig", query="select attr from ComponentConfigEntity attr where attr.component = :component"),
+ @NamedQuery(name="deleteComponentConfigByComponent", query="delete from ComponentConfigEntity attr where attr.component = :component"),
+ @NamedQuery(name="deleteComponentConfigByRealm", query="delete from ComponentConfigEntity attr where attr.component IN (select u from ComponentEntity u where u.realm=:realm)"),
+ @NamedQuery(name="deleteComponentConfigByParent", query="delete from ComponentConfigEntity attr where attr.component IN (select u from ComponentEntity u where u.parentId=:parentId)"),
+})
+@Table(name="COMPONENT_CONFIG")
+@Entity
+public class ComponentConfigEntity {
+
+ @Id
+ @Column(name="ID", length = 36)
+ @Access(AccessType.PROPERTY) // we do this because relationships often fetch id, but not entity. This avoids an extra SQL
+ protected String id;
+
+ @ManyToOne(fetch= FetchType.LAZY)
+ @JoinColumn(name = "COMPONENT_ID")
+ protected ComponentEntity component;
+
+ @Column(name = "NAME")
+ protected String name;
+ @Column(name = "VALUE")
+ protected String value;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public ComponentEntity getComponent() {
+ return component;
+ }
+
+ public void setComponent(ComponentEntity component) {
+ this.component = component;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null) return false;
+ if (!(o instanceof ComponentConfigEntity)) return false;
+
+ ComponentConfigEntity that = (ComponentConfigEntity) o;
+
+ if (!id.equals(that.getId())) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
index 3c9ae5f..e45d819 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/RealmEntity.java
@@ -145,9 +145,6 @@ public class RealmEntity {
List<UserFederationProviderEntity> userFederationProviders = new ArrayList<>();
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
- List<StorageProviderEntity> storageProviders = new ArrayList<>();
-
- @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
Collection<UserFederationMapperEntity> userFederationMappers = new ArrayList<UserFederationMapperEntity>();
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
@@ -554,14 +551,6 @@ public class RealmEntity {
this.userFederationProviders = userFederationProviders;
}
- public List<StorageProviderEntity> getStorageProviders() {
- return storageProviders;
- }
-
- public void setStorageProviders(List<StorageProviderEntity> storageProviders) {
- this.storageProviders = storageProviders;
- }
-
public Collection<UserFederationMapperEntity> getUserFederationMappers() {
return userFederationMappers;
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
index 2cf74ad..f5d2666 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaRealmProvider.java
@@ -34,7 +34,6 @@ import org.keycloak.models.jpa.entities.GroupEntity;
import org.keycloak.models.jpa.entities.RealmEntity;
import org.keycloak.models.jpa.entities.RoleEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.storage.StorageProviderModel;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@@ -128,9 +127,6 @@ public class JpaRealmProvider implements RealmProvider {
em.refresh(realm);
final RealmAdapter adapter = new RealmAdapter(session, em, realm);
session.users().preRemove(adapter);
- for (StorageProviderModel provider : adapter.getStorageProviders()) {
- adapter.removeStorageProvider(provider);
- }
realm.getDefaultGroups().clear();
em.flush();
@@ -141,6 +137,10 @@ public class JpaRealmProvider implements RealmProvider {
.setParameter("realm", realm).executeUpdate();
num = em.createNamedQuery("deleteGroupsByRealm")
.setParameter("realm", realm).executeUpdate();
+ num = em.createNamedQuery("deleteComponentConfigByRealm")
+ .setParameter("realm", realm).executeUpdate();
+ num = em.createNamedQuery("deleteComponentByRealm")
+ .setParameter("realm", realm).executeUpdate();
TypedQuery<String> query = em.createNamedQuery("getClientIdsByRealm", String.class);
query.setParameter("realm", realm.getId());
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
index 02403ee..a928e58 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java
@@ -17,6 +17,7 @@
package org.keycloak.models.jpa;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.FederatedIdentityModel;
@@ -42,7 +43,6 @@ import org.keycloak.models.jpa.entities.UserEntity;
import org.keycloak.models.utils.CredentialValidation;
import org.keycloak.models.utils.DefaultRoles;
import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.storage.StorageProviderModel;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@@ -712,7 +712,7 @@ public class JpaUserProvider implements UserProvider {
}
@Override
- public void preRemove(RealmModel realm, StorageProviderModel link) {
+ public void preRemove(RealmModel realm, ComponentModel component) {
}
}
diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
index d6837aa..093ebf3 100755
--- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
+++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
@@ -18,7 +18,8 @@
package org.keycloak.models.jpa;
import org.jboss.logging.Logger;
-import org.keycloak.connections.jpa.util.JpaUtils;
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
import org.keycloak.common.enums.SslRequired;
import org.keycloak.jose.jwk.JWKBuilder;
import org.keycloak.models.AuthenticationExecutionModel;
@@ -43,8 +44,6 @@ import org.keycloak.models.UserFederationProviderCreationEventImpl;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.jpa.entities.*;
import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.storage.StorageProvider;
-import org.keycloak.storage.StorageProviderModel;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@@ -1004,179 +1003,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
}
@Override
- public StorageProviderModel getStorageProvider(String id) {
- StorageProviderEntity entity = em.find(StorageProviderEntity.class, id);
- if (entity == null) return null;
- return toModel(entity);
- }
-
- @Override
- public List<StorageProviderModel> getStorageProviders() {
- List<StorageProviderEntity> entities = realm.getStorageProviders();
- if (entities.isEmpty()) return Collections.EMPTY_LIST;
- List<StorageProviderEntity> copy = new LinkedList<>();
- for (StorageProviderEntity entity : entities) {
- copy.add(entity);
-
- }
- List<StorageProviderModel> result = new LinkedList<>();
- for (StorageProviderEntity entity : copy) {
- result.add(toModel(entity));
- }
- Collections.sort(result, StorageProviderModel.comparator);
-
- return Collections.unmodifiableList(result);
- }
-
- protected StorageProviderModel toModel(StorageProviderEntity entity) {
- StorageProviderModel model = new StorageProviderModel();
- model.setId(entity.getId());
- model.setProviderName(entity.getProviderName());
- model.getConfig().putAll(entity.getConfig());
- model.setPriority(entity.getPriority());
- model.setDisplayName(entity.getDisplayName());
- return model;
- }
-
- @Override
- public StorageProviderModel addStorageProvider(StorageProviderModel model) {
- KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), null, getStorageProviders());
-
- String id = KeycloakModelUtils.generateId();
- StorageProviderEntity entity = new StorageProviderEntity();
- entity.setId(id);
- entity.setRealm(realm);
- entity.setProviderName(model.getProviderName());
- entity.setConfig(model.getConfig());
- entity.setPriority(model.getPriority());
- String displayName = model.getDisplayName();
- if (model.getDisplayName() == null) {
- displayName = id;
- }
- entity.setDisplayName(displayName);
- em.persist(entity);
- realm.getStorageProviders().add(entity);
- em.flush();
- StorageProviderModel providerModel = toModel(entity);
-
- return providerModel;
- }
-
- @Override
- public void removeStorageProvider(StorageProviderModel provider) {
- Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
- while (it.hasNext()) {
- StorageProviderEntity entity = it.next();
- if (entity.getId().equals(provider.getId())) {
-
- session.users().preRemove(this, provider);
-
- it.remove();
- em.remove(entity);
- return;
- }
- }
- }
- @Override
- public void updateStorageProvider(StorageProviderModel model) {
- KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), model, getStorageProviders());
-
- Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
- while (it.hasNext()) {
- StorageProviderEntity entity = it.next();
- if (entity.getId().equals(model.getId())) {
- String displayName = model.getDisplayName();
- if (displayName != null) {
- entity.setDisplayName(model.getDisplayName());
- }
- entity.setConfig(model.getConfig());
- entity.setPriority(model.getPriority());
- entity.setProviderName(model.getProviderName());
- entity.setPriority(model.getPriority());
- break;
- }
- }
- }
-
- @Override
- public void setStorageProviders(List<StorageProviderModel> providers) {
- for (StorageProviderModel currentProvider : providers) {
- KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
- }
-
- Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
- while (it.hasNext()) {
- StorageProviderEntity entity = it.next();
- boolean found = false;
- for (StorageProviderModel model : providers) {
- if (entity.getId().equals(model.getId())) {
- entity.setConfig(model.getConfig());
- entity.setPriority(model.getPriority());
- entity.setProviderName(model.getProviderName());
- String displayName = model.getDisplayName();
- if (displayName != null) {
- entity.setDisplayName(displayName);
- }
- found = true;
- break;
- }
-
- }
- if (found) continue;
- session.users().preRemove(this, toModel(entity));
- removeFederationMappersForProvider(entity.getId());
-
- it.remove();
- em.remove(entity);
- }
-
- List<StorageProviderModel> add = new LinkedList<>();
- for (StorageProviderModel model : providers) {
- boolean found = false;
- for (StorageProviderEntity entity : realm.getStorageProviders()) {
- if (entity.getId().equals(model.getId())) {
- found = true;
- break;
- }
- }
- if (!found) add.add(model);
- }
-
- for (StorageProviderModel model : add) {
- StorageProviderEntity entity = new StorageProviderEntity();
- if (model.getId() != null) {
- entity.setId(model.getId());
- } else {
- String id = KeycloakModelUtils.generateId();
- entity.setId(id);
- model.setId(id);
- }
- entity.setConfig(model.getConfig());
- entity.setPriority(model.getPriority());
- entity.setProviderName(model.getProviderName());
- entity.setPriority(model.getPriority());
- String displayName = model.getDisplayName();
- if (displayName == null) {
- displayName = entity.getId();
- }
- entity.setDisplayName(displayName);
- entity.setRealm(realm);
- em.persist(entity);
- realm.getStorageProviders().add(entity);
-
- }
- }
-
- protected StorageProviderEntity getStorageProviderEntityById(String id) {
- for (StorageProviderEntity entity : realm.getStorageProviders()) {
- if (entity.getId().equals(id)) {
- return entity;
- }
- }
- return null;
- }
-
- @Override
public RoleModel getRole(String name) {
return session.realms().getRealmRole(this, name);
}
@@ -2280,4 +2106,131 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
return session.realms().getClientTemplateById(id, this);
}
+ @Override
+ public ComponentModel addComponentModel(ComponentModel model) {
+ ComponentEntity c = new ComponentEntity();
+ if (model.getId() == null) {
+ c.setId(KeycloakModelUtils.generateId());
+ } else {
+ c.setId(model.getId());
+ }
+ c.setName(model.getName());
+ c.setParentId(model.getParentId());
+ c.setProviderType(model.getProviderType());
+ c.setProviderId(model.getProviderId());
+ c.setRealm(realm);
+ em.persist(c);
+ setConfig(model, c);
+ model.setId(c.getId());
+ return model;
+ }
+
+ protected void setConfig(ComponentModel model, ComponentEntity c) {
+ for (String key : model.getConfig().keySet()) {
+ List<String> vals = model.getConfig().get(key);
+ for (String val : vals) {
+ ComponentConfigEntity config = new ComponentConfigEntity();
+ config.setId(KeycloakModelUtils.generateId());
+ config.setName(key);
+ config.setValue(val);
+ config.setComponent(c);
+ em.persist(config);
+ }
+ }
+ }
+
+ @Override
+ public void updateComponent(ComponentModel component) {
+ ComponentEntity c = em.find(ComponentEntity.class, component.getId());
+ if (c == null) return;
+ c.setName(component.getName());
+ c.setProviderId(component.getProviderId());
+ c.setProviderType(component.getProviderType());
+ c.setParentId(component.getParentId());
+ em.createNamedQuery("deleteComponentConfigByComponent").setParameter("component", c).executeUpdate();
+ em.flush();
+ setConfig(component, c);
+
+
+ }
+
+ @Override
+ public void removeComponent(ComponentModel component) {
+ ComponentEntity c = em.find(ComponentEntity.class, component.getId());
+ if (c == null) return;
+ session.users().preRemove(this, component);
+ em.createNamedQuery("deleteComponentConfigByComponent").setParameter("component", c).executeUpdate();
+ em.remove(c);
+ }
+
+ @Override
+ public void removeComponents(String parentId) {
+ TypedQuery<String> query = em.createNamedQuery("getComponentIdsByParent", String.class)
+ .setParameter("realm", realm)
+ .setParameter("parentId", parentId);
+ List<String> results = query.getResultList();
+ if (results.isEmpty()) return;
+ for (String id : results) {
+ session.users().preRemove(this, getComponent(id));
+ }
+ em.createNamedQuery("deleteComponentConfigByParent").setParameter("parentId", parentId).executeUpdate();
+ em.createNamedQuery("deleteComponentByParent").setParameter("parentId", parentId).executeUpdate();
+
+ }
+
+ @Override
+ public List<ComponentModel> getComponents(String parentId, String providerType) {
+ if (parentId == null) parentId = getId();
+ TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponentsByParentAndType", ComponentEntity.class)
+ .setParameter("realm", realm)
+ .setParameter("parentId", parentId)
+ .setParameter("providerType", providerType);
+ List<ComponentEntity> results = query.getResultList();
+ List<ComponentModel> rtn = new LinkedList<>();
+ for (ComponentEntity c : results) {
+ ComponentModel model = entityToModel(c);
+ rtn.add(model);
+
+ }
+ return rtn;
+ }
+
+ protected ComponentModel entityToModel(ComponentEntity c) {
+ ComponentModel model = new ComponentModel();
+ model.setId(c.getId());
+ model.setName(c.getName());
+ model.setProviderType(c.getProviderType());
+ model.setProviderId(c.getProviderId());
+ model.setParentId(c.getParentId());
+ MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
+ TypedQuery<ComponentConfigEntity> configQuery = em.createNamedQuery("getComponentConfig", ComponentConfigEntity.class)
+ .setParameter("component", c);
+ List<ComponentConfigEntity> configResults = configQuery.getResultList();
+ for (ComponentConfigEntity configEntity : configResults) {
+ config.add(configEntity.getName(), configEntity.getValue());
+ }
+ model.setConfig(config);
+ return model;
+ }
+
+ @Override
+ public List<ComponentModel> getComponents() {
+ TypedQuery<ComponentEntity> query = em.createNamedQuery("getComponents", ComponentEntity.class)
+ .setParameter("realm", realm);
+ List<ComponentEntity> results = query.getResultList();
+ List<ComponentModel> rtn = new LinkedList<>();
+ for (ComponentEntity c : results) {
+ ComponentModel model = entityToModel(c);
+ rtn.add(model);
+
+ }
+ return rtn;
+ }
+
+ @Override
+ public ComponentModel getComponent(String id) {
+ ComponentEntity c = em.find(ComponentEntity.class, id);
+ if (c == null) return null;
+ return entityToModel(c);
+ }
}
\ No newline at end of file
diff --git a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
index d64a3ea..f6710dd 100644
--- a/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
+++ b/model/jpa/src/main/java/org/keycloak/storage/jpa/JpaUserFederatedStorageProvider.java
@@ -17,6 +17,7 @@
package org.keycloak.storage.jpa;
import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.GroupModel;
@@ -31,11 +32,10 @@ import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
-import org.keycloak.models.jpa.entities.CredentialEntity;
import org.keycloak.models.utils.FederatedCredentials;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.StorageId;
-import org.keycloak.storage.StorageProviderModel;
+import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.federated.UserAttributeFederatedStorage;
import org.keycloak.storage.federated.UserBrokerLinkFederatedStorage;
import org.keycloak.storage.federated.UserConsentFederatedStorage;
@@ -719,7 +719,9 @@ public class JpaUserFederatedStorageProvider implements
}
@Override
- public void preRemove(RealmModel realm, StorageProviderModel model) {
+ public void preRemove(RealmModel realm, ComponentModel model) {
+ if (!model.getProviderType().equals(UserStorageProvider.class.getName())) return;
+
em.createNamedQuery("deleteBrokerLinkByStorageProvider")
.setParameter("storageProviderId", model.getId())
.executeUpdate();
diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.1.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.1.0.xml
index 988662d..9b01ace 100755
--- a/model/jpa/src/main/resources/META-INF/jpa-changelog-2.1.0.xml
+++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-2.1.0.xml
@@ -149,22 +149,26 @@
<column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)"/>
</createTable>
- <createTable tableName="STORAGE_PROVIDER_CONFIG">
- <column name="STORAGE_PROVIDER_ID" type="VARCHAR(36)">
+ <createTable tableName="COMPONENT_CONFIG">
+ <column name="ID" type="VARCHAR(36)">
+ <constraints nullable="false"/>
+ </column>
+ <column name="COMPONENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
- <column name="VALUE" type="VARCHAR(255)"/>
<column name="NAME" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
+ <column name="VALUE" type="VARCHAR(4096)"/>
</createTable>
- <createTable tableName="STORAGE_PROVIDER">
+ <createTable tableName="COMPONENT">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
</column>
- <column name="DISPLAY_NAME" type="VARCHAR(255)"/>
- <column name="PRIORITY" type="INT"/>
- <column name="PROVIDER_NAME" type="VARCHAR(255)"/>
+ <column name="NAME" type="VARCHAR(255)"/>
+ <column name="PARENT_ID" type="VARCHAR(36)"/>
+ <column name="PROVIDER_ID" type="VARCHAR(36)"/>
+ <column name="PROVIDER_TYPE" type="VARCHAR(255)"/>
<column name="REALM_ID" type="VARCHAR(36)"/>
</createTable>
@@ -185,10 +189,10 @@
<addPrimaryKey columnNames="ROLE_ID, USER_ID" constraintName="CONSTR_FED_USER_ROLE" tableName="FED_USER_ROLE_MAPPING"/>
<addPrimaryKey columnNames="REQUIRED_ACTION, USER_ID" constraintName="CONSTR_FED_REQUIRED_ACTION" tableName="FED_USER_REQUIRED_ACTION"/>
- <addPrimaryKey columnNames="ID" constraintName="CONSTR_STORAGE_PROVIDER_PK" tableName="STORAGE_PROVIDER"/>
- <addPrimaryKey columnNames="STORAGE_PROVIDER_ID, NAME" constraintName="CONSTR_STORAGE_CONFIG" tableName="STORAGE_PROVIDER_CONFIG"/>
- <!--
- <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="STORAGE_PROVIDER" constraintName="FK_STORAGE_PROVIDER_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
- -->
+ <addPrimaryKey columnNames="ID" constraintName="CONSTR_COMPONENT_PK" tableName="COMPONENT"/>
+ <addPrimaryKey columnNames="ID" constraintName="CONSTR_COMPONENT_CONFIG_PK" tableName="COMPONENT_CONFIG"/>
+ <addForeignKeyConstraint baseColumnNames="REALM_ID" baseTableName="COMPONENT" constraintName="FK_COMPONENT_REALM" referencedColumnNames="ID" referencedTableName="REALM"/>
+ <addForeignKeyConstraint baseColumnNames="COMPONENT_ID" baseTableName="COMPONENT_CONFIG" constraintName="FK_COMPONENT_CONFIG" referencedColumnNames="ID" referencedTableName="COMPONENT"/>
+
</changeSet>
</databaseChangeLog>
\ No newline at end of file
diff --git a/model/jpa/src/main/resources/META-INF/persistence.xml b/model/jpa/src/main/resources/META-INF/persistence.xml
index d912033..0b2ff23 100755
--- a/model/jpa/src/main/resources/META-INF/persistence.xml
+++ b/model/jpa/src/main/resources/META-INF/persistence.xml
@@ -25,7 +25,8 @@
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
<class>org.keycloak.models.jpa.entities.RealmAttributeEntity</class>
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
- <class>org.keycloak.models.jpa.entities.StorageProviderEntity</class>
+ <class>org.keycloak.models.jpa.entities.ComponentConfigEntity</class>
+ <class>org.keycloak.models.jpa.entities.ComponentEntity</class>
<class>org.keycloak.models.jpa.entities.UserFederationProviderEntity</class>
<class>org.keycloak.models.jpa.entities.UserFederationMapperEntity</class>
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
diff --git a/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java b/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
index d8d87f5..440886f 100755
--- a/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/connections/mongo/DefaultMongoConnectionFactoryProvider.java
@@ -22,7 +22,6 @@ import java.net.UnknownHostException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
import javax.net.ssl.SSLSocketFactory;
@@ -79,6 +78,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
"org.keycloak.models.entities.RequiredActionProviderEntity",
"org.keycloak.models.entities.PersistentUserSessionEntity",
"org.keycloak.models.entities.PersistentClientSessionEntity",
+ "org.keycloak.models.entities.StorageProviderEntity",
"org.keycloak.authorization.mongo.entities.PolicyEntity",
"org.keycloak.authorization.mongo.entities.ResourceEntity",
"org.keycloak.authorization.mongo.entities.ResourceServerEntity",
@@ -141,7 +141,7 @@ public class DefaultMongoConnectionFactoryProvider implements MongoConnectionPro
lazyInit(session);
TransactionMongoStoreInvocationContext invocationContext = new TransactionMongoStoreInvocationContext(mongoStore);
- session.getTransaction().enlist(new MongoKeycloakTransaction(invocationContext));
+ session.getTransactionManager().enlist(new MongoKeycloakTransaction(invocationContext));
return new DefaultMongoConnectionProvider(db, mongoStore, invocationContext);
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
index ad811d4..96d1f91 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoUserProvider.java
@@ -21,6 +21,7 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
+import org.keycloak.component.ComponentModel;
import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.models.ClientModel;
@@ -44,7 +45,6 @@ import org.keycloak.models.entities.UserConsentEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
import org.keycloak.models.utils.CredentialValidation;
-import org.keycloak.storage.StorageProviderModel;
import java.util.ArrayList;
import java.util.Collections;
@@ -632,7 +632,7 @@ public class MongoUserProvider implements UserProvider {
}
@Override
- public void preRemove(RealmModel realm, StorageProviderModel link) {
+ public void preRemove(RealmModel realm, ComponentModel component) {
}
}
diff --git a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
index cb6bba7..8b945ef 100755
--- a/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
+++ b/model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
@@ -20,6 +20,8 @@ package org.keycloak.models.mongo.keycloak.adapters;
import com.mongodb.DBObject;
import com.mongodb.QueryBuilder;
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
import org.keycloak.common.enums.SslRequired;
import org.keycloak.jose.jwk.JWKBuilder;
@@ -47,20 +49,18 @@ import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.entities.AuthenticationExecutionEntity;
import org.keycloak.models.entities.AuthenticationFlowEntity;
import org.keycloak.models.entities.AuthenticatorConfigEntity;
+import org.keycloak.models.entities.ComponentEntity;
import org.keycloak.models.entities.IdentityProviderEntity;
import org.keycloak.models.entities.IdentityProviderMapperEntity;
import org.keycloak.models.entities.RequiredActionProviderEntity;
import org.keycloak.models.entities.RequiredCredentialEntity;
-import org.keycloak.models.entities.StorageProviderEntity;
import org.keycloak.models.entities.UserFederationMapperEntity;
import org.keycloak.models.entities.UserFederationProviderEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoClientEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoClientTemplateEntity;
-import org.keycloak.models.mongo.keycloak.entities.MongoGroupEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRealmEntity;
import org.keycloak.models.mongo.keycloak.entities.MongoRoleEntity;
import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.storage.StorageProviderModel;
import java.security.Key;
import java.security.PrivateKey;
@@ -1171,166 +1171,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
}
@Override
- public StorageProviderModel addStorageProvider(StorageProviderModel model) {
- KeycloakModelUtils.ensureUniqueDisplayName(model.getDisplayName(), null, getStorageProviders());
-
- StorageProviderEntity entity = new StorageProviderEntity();
- entity.setId(KeycloakModelUtils.generateId());
- entity.setPriority(model.getPriority());
- entity.setProviderName(model.getProviderName());
- entity.setConfig(model.getConfig());
- String displayName = model.getDisplayName();
- if (displayName == null) {
- displayName = entity.getId();
- }
- entity.setDisplayName(displayName);
- realm.getStorageProviders().add(entity);
- updateRealm();
-
- StorageProviderModel providerModel = new StorageProviderModel(entity.getId(), model.getProviderName(),
- model.getConfig(), model.getPriority(), displayName);
-
-
- return providerModel;
- }
-
- @Override
- public void updateStorageProvider(StorageProviderModel provider) {
- KeycloakModelUtils.ensureUniqueDisplayName(provider.getDisplayName(), provider, getStorageProviders());
-
- Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
- while (it.hasNext()) {
- StorageProviderEntity entity = it.next();
- if (entity.getId().equals(provider.getId())) {
- entity.setProviderName(provider.getProviderName());
- entity.setConfig(provider.getConfig());
- entity.setPriority(provider.getPriority());
- String displayName = provider.getDisplayName();
- if (displayName != null) {
- entity.setDisplayName(provider.getDisplayName());
- }
- }
- }
- updateRealm();
-
- }
-
- @Override
- public void removeStorageProvider(StorageProviderModel provider) {
- Iterator<StorageProviderEntity> it = realm.getStorageProviders().iterator();
- while (it.hasNext()) {
- StorageProviderEntity entity = it.next();
- if (entity.getId().equals(provider.getId())) {
- session.users().preRemove(this, new StorageProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName()
- ));
-
- it.remove();
- }
- }
- updateRealm();
-
- }
-
- @Override
- public void setStorageProviders(List<StorageProviderModel> providers) {
- for (StorageProviderModel currentProvider : providers) {
- KeycloakModelUtils.ensureUniqueDisplayName(currentProvider.getDisplayName(), currentProvider, providers);
- }
-
- List<StorageProviderEntity> existingProviders = realm.getStorageProviders();
- List<StorageProviderEntity> toRemove = new LinkedList<>();
- for (StorageProviderEntity entity : existingProviders) {
- boolean found = false;
- for (StorageProviderModel model : providers) {
- if (entity.getId().equals(model.getId())) {
- entity.setConfig(model.getConfig());
- entity.setPriority(model.getPriority());
- entity.setProviderName(model.getProviderName());
- String displayName = model.getDisplayName();
- if (displayName != null) {
- entity.setDisplayName(displayName);
- }
- found = true;
- break;
- }
-
- }
- if (found) continue;
- session.users().preRemove(this, new StorageProviderModel(entity.getId(), entity.getProviderName(),
- entity.getConfig(), entity.getPriority(), entity.getDisplayName()));
- toRemove.add(entity);
- }
-
- for (StorageProviderEntity entity : toRemove) {
- realm.getStorageProviders().remove(entity);
- }
-
- List<StorageProviderModel> add = new LinkedList<>();
- for (StorageProviderModel model : providers) {
- boolean found = false;
- for (StorageProviderEntity entity : realm.getStorageProviders()) {
- if (entity.getId().equals(model.getId())) {
- found = true;
- break;
- }
- }
- if (!found) add.add(model);
- }
-
- for (StorageProviderModel model : add) {
- StorageProviderEntity entity = new StorageProviderEntity();
- if (model.getId() != null) {
- entity.setId(model.getId());
- } else {
- String id = KeycloakModelUtils.generateId();
- entity.setId(id);
- model.setId(id);
- }
- entity.setProviderName(model.getProviderName());
- entity.setConfig(model.getConfig());
- entity.setPriority(model.getPriority());
- String displayName = model.getDisplayName();
- if (displayName == null) {
- displayName = entity.getId();
- }
- entity.setDisplayName(displayName);
- realm.getStorageProviders().add(entity);
-
- }
-
- updateRealm();
-
- }
-
- @Override
- public List<StorageProviderModel> getStorageProviders() {
- List<StorageProviderEntity> entities = realm.getStorageProviders();
- if (entities.isEmpty()) return Collections.EMPTY_LIST;
- List<StorageProviderEntity> copy = new LinkedList<>();
- for (StorageProviderEntity entity : entities) {
- copy.add(entity);
-
- }
- List<StorageProviderModel> result = new LinkedList<>();
- for (StorageProviderEntity entity : copy) {
- result.add(new StorageProviderModel(entity.getId(), entity.getProviderName(), entity.getConfig(), entity.getPriority(), entity.getDisplayName()
- ));
- }
-
- Collections.sort(result, StorageProviderModel.comparator);
- return Collections.unmodifiableList(result);
- }
-
- @Override
- public StorageProviderModel getStorageProvider(String id) {
- for (StorageProviderEntity entity : realm.getStorageProviders()) {
- if (entity.getId().equals(id)) return new StorageProviderModel(entity.getId(), entity.getProviderName(),
- entity.getConfig(), entity.getPriority(), entity.getDisplayName());
- }
- return null;
- }
-
- @Override
public boolean isEventsEnabled() {
return realm.isEventsEnabled();
}
@@ -2217,5 +2057,115 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
return model.getClientTemplateById(id, this);
}
+ @Override
+ public ComponentModel addComponentModel(ComponentModel model) {
+ ComponentEntity entity = new ComponentEntity();
+ if (model.getId() == null) {
+ entity.setId(KeycloakModelUtils.generateId());
+ } else {
+ entity.setId(model.getId());
+ }
+ entity.setConfig(model.getConfig());
+ entity.setId(model.getId());
+ entity.setParentId(model.getParentId());
+ entity.setProviderType(model.getProviderType());
+ entity.setProviderId(model.getProviderId());
+ entity.setName(model.getName());
+ model.setId(entity.getId());
+ realm.getComponentEntities().add(entity);
+ updateRealm();
+
+ return model;
+ }
+
+ @Override
+ public void updateComponent(ComponentModel model) {
+ for (ComponentEntity entity : realm.getComponentEntities()) {
+ if (entity.getId().equals(model.getId())) {
+ entity.setConfig(model.getConfig());
+ entity.setId(model.getId());
+ entity.setParentId(model.getParentId());
+ entity.setProviderType(model.getProviderType());
+ entity.setProviderId(model.getProviderId());
+ entity.setName(model.getName());
+
+ }
+ }
+ updateRealm();
+
+ }
+
+ @Override
+ public void removeComponent(ComponentModel component) {
+ Iterator<ComponentEntity> it = realm.getComponentEntities().iterator();
+ while(it.hasNext()) {
+ if (it.next().getId().equals(component.getId())) {
+ session.users().preRemove(this, component);
+ it.remove();
+ break;
+ }
+ }
+ updateRealm();
+
+ }
+
+ @Override
+ public void removeComponents(String parentId) {
+ Iterator<ComponentEntity> it = realm.getComponentEntities().iterator();
+ while(it.hasNext()) {
+ ComponentEntity next = it.next();
+ if (next.getParentId().equals(parentId)) {
+ session.users().preRemove(this, entityToModel(next));
+ it.remove();
+ }
+ }
+ updateRealm();
+
+ }
+
+ @Override
+ public List<ComponentModel> getComponents(String parentId, String providerType) {
+ List<ComponentModel> results = new LinkedList<>();
+ for (ComponentEntity entity : realm.getComponentEntities()) {
+ if (entity.getParentId().equals(parentId) && entity.getProviderType().equals(providerType)) {
+ ComponentModel model = entityToModel(entity);
+ results.add(model);
+ }
+
+ }
+ return results;
+ }
+ protected ComponentModel entityToModel(ComponentEntity entity) {
+ ComponentModel model = new ComponentModel();
+ model.setId(entity.getId());
+ model.setName(entity.getName());
+ model.setParentId(entity.getParentId());
+ model.setProviderId(entity.getProviderId());
+ model.setProviderType(entity.getProviderType());
+ MultivaluedHashMap<String, String> map = new MultivaluedHashMap<>();
+ map.putAll(entity.getConfig());
+ model.setConfig(map);
+ return model;
+ }
+
+ @Override
+ public List<ComponentModel> getComponents() {
+ List<ComponentModel> results = new LinkedList<>();
+ for (ComponentEntity entity : realm.getComponentEntities()) {
+ ComponentModel model = entityToModel(entity);
+ results.add(model);
+ }
+ return results;
+ }
+
+ @Override
+ public ComponentModel getComponent(String id) {
+ for (ComponentEntity entity : realm.getComponentEntities()) {
+ if (entity.getId() == entity.getId()) {
+ return entityToModel(entity);
+ }
+ }
+ return null;
+ }
}
diff --git a/server-spi/src/main/java/org/keycloak/component/ComponentModel.java b/server-spi/src/main/java/org/keycloak/component/ComponentModel.java
new file mode 100755
index 0000000..338bc4b
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/component/ComponentModel.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2016 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.component;
+
+import org.keycloak.common.util.MultivaluedHashMap;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Stored configuration of a User Storage provider instance.
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ * @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
+ */
+public class ComponentModel implements Serializable {
+
+ private String id;
+ private String name;
+ private String providerId;
+ private String providerType;
+ private String parentId;
+ private MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
+
+ public ComponentModel() {}
+
+ public ComponentModel(ComponentModel copy) {
+ this.id = copy.id;
+ this.name = copy.name;
+ this.providerId = copy.providerId;
+ this.providerType = copy.providerType;
+ this.config = copy.config;
+ }
+
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public MultivaluedHashMap<String, String> getConfig() {
+ return config;
+ }
+
+ public void setConfig(MultivaluedHashMap<String, String> config) {
+ this.config = config;
+ }
+
+ public String getProviderId() {
+ return providerId;
+ }
+
+ public void setProviderId(String providerId) {
+ this.providerId = providerId;
+ }
+
+ public String getProviderType() {
+ return providerType;
+ }
+
+ public void setProviderType(String providerType) {
+ this.providerType = providerType;
+ }
+
+ public String getParentId() {
+ return parentId;
+ }
+
+ public void setParentId(String parentId) {
+ this.parentId = parentId;
+ }
+}
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
index 8ff3664..9e7b931 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrateTo2_1_0.java
@@ -52,11 +52,9 @@ public class MigrateTo2_1_0 {
private void migrateDefaultRequiredAction(RealmModel realm) {
RequiredActionProviderModel otpAction = realm.getRequiredActionProviderByAlias(UserModel.RequiredAction.CONFIGURE_TOTP.name());
- if (otpAction == null) return;
- if (!otpAction.getProviderId().equals(UserModel.RequiredAction.CONFIGURE_TOTP.name())) return;
- if (!otpAction.getName().equals("Configure Totp")) return;
+ MigrationUtils.updateOTPRequiredAction(otpAction);
- otpAction.setName("Configure OTP");
+ realm.updateRequiredActionProvider(otpAction);
}
// KEYCLOAK-3338: Changes to how role policy config is stored"
diff --git a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java
index 91f812e..08da081 100644
--- a/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java
+++ b/server-spi/src/main/java/org/keycloak/migration/migrators/MigrationUtils.java
@@ -47,4 +47,12 @@ public class MigrationUtils {
}
}
+ public static void updateOTPRequiredAction(RequiredActionProviderModel otpAction) {
+ if (otpAction == null) return;
+ if (!otpAction.getProviderId().equals(UserModel.RequiredAction.CONFIGURE_TOTP.name())) return;
+ if (!otpAction.getName().equals("Configure Totp")) return;
+
+ otpAction.setName("Configure OTP");
+ }
+
}
diff --git a/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java b/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java
index 6780498..c5a6ecf 100755
--- a/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java
+++ b/server-spi/src/main/java/org/keycloak/models/entities/RealmEntity.java
@@ -85,7 +85,7 @@ public class RealmEntity extends AbstractIdentifiableEntity {
private List<String> defaultGroups = new LinkedList<String>();
private List<RequiredCredentialEntity> requiredCredentials = new LinkedList<>();
- private List<StorageProviderEntity> storageProviders = new LinkedList<>();
+ private List<ComponentEntity> componentEntities = new LinkedList<>();
private List<UserFederationProviderEntity> userFederationProviders = new LinkedList<UserFederationProviderEntity>();
private List<UserFederationMapperEntity> userFederationMappers = new LinkedList<UserFederationMapperEntity>();
private List<IdentityProviderEntity> identityProviders = new LinkedList<IdentityProviderEntity>();
@@ -685,12 +685,12 @@ public class RealmEntity extends AbstractIdentifiableEntity {
this.defaultGroups = defaultGroups;
}
- public List<StorageProviderEntity> getStorageProviders() {
- return storageProviders;
+ public List<ComponentEntity> getComponentEntities() {
+ return componentEntities;
}
- public void setStorageProviders(List<StorageProviderEntity> storageProviders) {
- this.storageProviders = storageProviders;
+ public void setComponentEntities(List<ComponentEntity> componentEntities) {
+ this.componentEntities = componentEntities;
}
}
diff --git a/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java b/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
index 1d71b1f..8b6dcd3 100755
--- a/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
+++ b/server-spi/src/main/java/org/keycloak/models/KeycloakSession.java
@@ -32,16 +32,48 @@ public interface KeycloakSession {
KeycloakContext getContext();
- KeycloakTransactionManager getTransaction();
+ KeycloakTransactionManager getTransactionManager();
+ /**
+ * Get dedicated provider instance of provider type clazz that was created for this session. If one hasn't been created yet,
+ * find the factory and allocate by calling ProviderFactory.create(KeycloakSession). The provider to use is determined
+ * by the "provider" config entry in keycloak-server boot configuration. (keycloak-server.json)
+ *
+ *
+ *
+ * @param clazz
+ * @param <T>
+ * @return
+ */
<T extends Provider> T getProvider(Class<T> clazz);
+ /**
+ * Get dedicated provider instance for a specific provider factory of id of provider type clazz that was created for this session.
+ * If one hasn't been created yet,
+ * find the factory and allocate by calling ProviderFactory.create(KeycloakSession).
+
+ * @param clazz
+ * @param id
+ * @param <T>
+ * @return
+ */
<T extends Provider> T getProvider(Class<T> clazz, String id);
+ /**
+ * Get all provider factories that manage provider instances of class.
+ *
+ * @param clazz
+ * @param <T>
+ * @return
+ */
<T extends Provider> Set<String> listProviderIds(Class<T> clazz);
<T extends Provider> Set<T> getAllProviders(Class<T> clazz);
+ Object getAttribute(String attribute);
+ Object removeAttribute(String attribute);
+ void setAttribute(String name, Object value);
+
void enlistForClose(Provider provider);
KeycloakSessionFactory getKeycloakSessionFactory();
@@ -69,23 +101,41 @@ public interface KeycloakSession {
void close();
/**
- * Possibly both cached and federated view of users depending on configuration.
+ * A cached view of all users in system.
*
* @return
*/
UserFederationManager users();
+
+ /**
+ * Un-cached view of all users in system that does NOT include users available from the deprecated UserFederationProvider SPI.
+ *
+ * @return
+ */
UserProvider userStorageManager();
/**
- * Keycloak user storage. Non-federated, but possibly cache (if it is on) view of users.
+ * A cached view of all users in system that does NOT include users available from the deprecated UserFederationProvider SPI.
*/
UserProvider userStorage();
- UserFederatedStorageProvider userFederatedStorage();
+ /**
+ * Keycloak specific local storage for users. No cache in front, this api talks directly to database.
+ *
+ * @return
+ */
UserProvider userLocalStorage();
/**
+ * Hybrid storage for UserStorageProviders that can't store a specific piece of keycloak data in their external storage.
+ *
+ * @return
+ */
+ UserFederatedStorageProvider userFederatedStorage();
+
+
+ /**
* Keycloak scripting support.
*/
ScriptingProvider scripting();
diff --git a/server-spi/src/main/java/org/keycloak/models/RealmModel.java b/server-spi/src/main/java/org/keycloak/models/RealmModel.java
index af4d6d7..47692ac 100755
--- a/server-spi/src/main/java/org/keycloak/models/RealmModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/RealmModel.java
@@ -18,13 +18,17 @@
package org.keycloak.models;
import org.keycloak.common.enums.SslRequired;
+import org.keycloak.component.ComponentModel;
import org.keycloak.provider.ProviderEvent;
-import org.keycloak.storage.StorageProviderModel;
+import org.keycloak.storage.UserStorageProvider;
+import org.keycloak.storage.UserStorageProviderModel;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -282,12 +286,23 @@ public interface RealmModel extends RoleContainerModel {
public IdentityProviderMapperModel getIdentityProviderMapperByName(String brokerAlias, String name);
- StorageProviderModel addStorageProvider(StorageProviderModel model);
- void updateStorageProvider(StorageProviderModel provider);
- void removeStorageProvider(StorageProviderModel provider);
- void setStorageProviders(List<StorageProviderModel> providers);
- List<StorageProviderModel> getStorageProviders();
- StorageProviderModel getStorageProvider(String id);
+ ComponentModel addComponentModel(ComponentModel model);
+ void updateComponent(ComponentModel component);
+ void removeComponent(ComponentModel component);
+ void removeComponents(String parentId);
+ List<ComponentModel> getComponents(String parentId, String providerType);
+ List<ComponentModel> getComponents();
+ ComponentModel getComponent(String id);
+
+ default
+ List<UserStorageProviderModel> getUserStorageProviders() {
+ List<UserStorageProviderModel> list = new LinkedList<>();
+ for (ComponentModel component : getComponents(getId(), UserStorageProvider.class.getName())) {
+ list.add(new UserStorageProviderModel(component));
+ }
+ Collections.sort(list, UserStorageProviderModel.comparator);
+ return list;
+ }
// Should return list sorted by UserFederationProviderModel.priority
List<UserFederationProviderModel> getUserFederationProviders();
diff --git a/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java b/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
index 19db2e1..c48ae4d 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserFederationManager.java
@@ -18,11 +18,11 @@
package org.keycloak.models;
import org.jboss.logging.Logger;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.policy.PasswordPolicyManagerProvider;
import org.keycloak.policy.PolicyError;
import org.keycloak.services.managers.UserManager;
-import org.keycloak.storage.StorageProviderModel;
import java.util.ArrayList;
import java.util.Arrays;
@@ -487,11 +487,6 @@ public class UserFederationManager implements UserProvider {
session.userStorage().preRemove(protocolMapper);
}
- @Override
- public void preRemove(RealmModel realm, StorageProviderModel link) {
-
- }
-
public void updateCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
if (realm.getPasswordPolicy() != null) {
@@ -605,6 +600,11 @@ public class UserFederationManager implements UserProvider {
}
@Override
+ public void preRemove(RealmModel realm, ComponentModel component) {
+
+ }
+
+ @Override
public void close() {
}
}
diff --git a/server-spi/src/main/java/org/keycloak/models/UserProvider.java b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
index 24b6106..d6ef2cd 100755
--- a/server-spi/src/main/java/org/keycloak/models/UserProvider.java
+++ b/server-spi/src/main/java/org/keycloak/models/UserProvider.java
@@ -17,8 +17,8 @@
package org.keycloak.models;
+import org.keycloak.component.ComponentModel;
import org.keycloak.provider.Provider;
-import org.keycloak.storage.StorageProviderModel;
import org.keycloak.storage.user.UserCredentialValidatorProvider;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
@@ -56,10 +56,20 @@ public interface UserProvider extends Provider,
List<UserModel> getUsers(RealmModel realm, boolean includeServiceAccounts);
List<UserModel> getUsers(RealmModel realm, int firstResult, int maxResults, boolean includeServiceAccounts);
+ /**
+ * only used for local storage
+ *
+ * @param realm
+ * @param id
+ * @param username
+ * @param addDefaultRoles
+ * @param addDefaultRequiredActions
+ * @return
+ */
+ UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions);
void preRemove(RealmModel realm);
void preRemove(RealmModel realm, UserFederationProviderModel link);
- void preRemove(RealmModel realm, StorageProviderModel link);
void preRemove(RealmModel realm, RoleModel role);
void preRemove(RealmModel realm, GroupModel group);
@@ -73,4 +83,6 @@ public interface UserProvider extends Provider,
void close();
+
+ void preRemove(RealmModel realm, ComponentModel component);
}
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java b/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
index 55a7c02..bc20d49 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/KeycloakModelUtils.java
@@ -44,7 +44,6 @@ import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.CertificateRepresentation;
import org.keycloak.common.util.CertificateUtils;
import org.keycloak.common.util.PemUtils;
-import org.keycloak.storage.StorageProviderModel;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
@@ -282,7 +281,7 @@ public final class KeycloakModelUtils {
*/
public static void runJobInTransaction(KeycloakSessionFactory factory, KeycloakSessionTask task) {
KeycloakSession session = factory.create();
- KeycloakTransaction tx = session.getTransaction();
+ KeycloakTransaction tx = session.getTransactionManager();
try {
tx.begin();
task.run(session);
@@ -350,43 +349,6 @@ public final class KeycloakModelUtils {
* @param federationProviders
* @throws ModelDuplicateException if there is other provider with same displayName
*/
- public static void ensureUniqueDisplayName(String displayName, StorageProviderModel myProvider, List<StorageProviderModel> federationProviders) throws ModelDuplicateException {
- if (displayName != null) {
-
- for (StorageProviderModel federationProvider : federationProviders) {
- if (myProvider != null && (myProvider.equals(federationProvider) || (myProvider.getId() != null && myProvider.getId().equals(federationProvider.getId())))) {
- continue;
- }
-
- if (displayName.equals(federationProvider.getDisplayName())) {
- throw new ModelDuplicateException("There is already existing federation provider with display name: " + displayName);
- }
- }
- }
- }
-
-
- public static StorageProviderModel findStorageProviderByDisplayName(String displayName, RealmModel realm) {
- if (displayName == null) {
- return null;
- }
-
- for (StorageProviderModel provider : realm.getStorageProviders()) {
- if (displayName.equals(provider.getDisplayName())) {
- return provider;
- }
- }
- return null;
- }
-
- /**
- * Ensure that displayName of myProvider (if not null) is unique and there is no other provider with same displayName in the list.
- *
- * @param displayName to check for duplications
- * @param myProvider provider, which is excluded from the list (if present)
- * @param federationProviders
- * @throws ModelDuplicateException if there is other provider with same displayName
- */
public static void ensureUniqueDisplayName(String displayName, UserFederationProviderModel myProvider, List<UserFederationProviderModel> federationProviders) throws ModelDuplicateException {
if (displayName != null) {
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
index 203736f..f0c75b7 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java
@@ -17,6 +17,7 @@
package org.keycloak.models.utils;
+import org.keycloak.component.ComponentModel;
import org.keycloak.events.Event;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.AuthDetails;
@@ -44,6 +45,7 @@ import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
+import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.AuthDetailsRepresentation;
import org.keycloak.representations.idm.AuthenticationExecutionExportRepresentation;
@@ -51,6 +53,8 @@ import org.keycloak.representations.idm.AuthenticationFlowRepresentation;
import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
+import org.keycloak.representations.idm.ComponentRepresentation;
+import org.keycloak.representations.idm.ConfigPropertyRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
@@ -565,7 +569,7 @@ public class ModelToRepresentation {
return rep;
}
- public static UserFederationMapperRepresentation toRepresentation(RealmModel realm, UserFederationMapperModel model) {
+ public static UserFederationMapperRepresentation toRepresentation(RealmModel realm, UserFederationMapperModel model) {
UserFederationMapperRepresentation rep = new UserFederationMapperRepresentation();
rep.setId(model.getId());
rep.setName(model.getName());
@@ -736,4 +740,27 @@ public class ModelToRepresentation {
return rep;
}
+ public static List<ConfigPropertyRepresentation> toRepresentation(List<ProviderConfigProperty> configProperties) {
+ List<ConfigPropertyRepresentation> propertiesRep = new LinkedList<>();
+ for (ProviderConfigProperty prop : configProperties) {
+ ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
+ propRep.setName(prop.getName());
+ propRep.setLabel(prop.getLabel());
+ propRep.setType(prop.getType());
+ propRep.setDefaultValue(prop.getDefaultValue());
+ propRep.setHelpText(prop.getHelpText());
+ propertiesRep.add(propRep);
+ }
+ return propertiesRep;
+ }
+
+ public static ComponentRepresentation toRepresentation(ComponentModel component) {
+ ComponentRepresentation rep = new ComponentRepresentation();
+ rep.setId(component.getId());
+ rep.setName(component.getName());
+ rep.setProviderId(component.getProviderId());
+ rep.setProviderType(component.getProviderType());
+ rep.setConfig(component.getConfig());
+ return rep;
+ }
}
diff --git a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index 3efca79..a20adcf 100755
--- a/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/server-spi/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -20,7 +20,9 @@ package org.keycloak.models.utils;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.store.ResourceServerStore;
+import org.keycloak.component.ComponentModel;
import org.keycloak.hash.Pbkdf2PasswordHashProvider;
+import org.keycloak.migration.migrators.MigrationUtils;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.Constants;
import org.keycloak.common.util.Base64;
@@ -61,6 +63,7 @@ import org.keycloak.representations.idm.AuthenticatorConfigRepresentation;
import org.keycloak.representations.idm.ClaimRepresentation;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.ClientTemplateRepresentation;
+import org.keycloak.representations.idm.ComponentRepresentation;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.FederatedIdentityRepresentation;
import org.keycloak.representations.idm.GroupRepresentation;
@@ -204,6 +207,9 @@ public class RepresentationToModel {
if (rep.getRequiredActions() != null) {
for (RequiredActionProviderRepresentation action : rep.getRequiredActions()) {
RequiredActionProviderModel model = toModel(action);
+
+ MigrationUtils.updateOTPRequiredAction(model);
+
newRealm.addRequiredActionProvider(model);
}
} else {
@@ -1614,4 +1620,13 @@ public class RepresentationToModel {
}
+ public static ComponentModel toModel(ComponentRepresentation rep) {
+ ComponentModel model = new ComponentModel();
+ model.setParentId(rep.getParentId());
+ model.setProviderType(rep.getProviderType());
+ model.setProviderId(rep.getProviderId());
+ model.setConfig(rep.getConfig());
+ model.setName(rep.getName());
+ return model;
+ }
}
diff --git a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
index 45c6168..6a4e7d2 100644
--- a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
+++ b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapter.java
@@ -17,6 +17,7 @@
package org.keycloak.storage.adapter;
import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
@@ -29,7 +30,6 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.utils.DefaultRoles;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.StorageId;
-import org.keycloak.storage.StorageProviderModel;
import java.util.Collections;
import java.util.HashSet;
@@ -58,9 +58,9 @@ public abstract class AbstractUserAdapter implements UserModel {
}
protected KeycloakSession session;
protected RealmModel realm;
- protected StorageProviderModel storageProviderModel;
+ protected ComponentModel storageProviderModel;
- public AbstractUserAdapter(KeycloakSession session, RealmModel realm, StorageProviderModel storageProviderModel) {
+ public AbstractUserAdapter(KeycloakSession session, RealmModel realm, ComponentModel storageProviderModel) {
this.session = session;
this.realm = realm;
this.storageProviderModel = storageProviderModel;
diff --git a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
index b09ceae..bfe0b95 100644
--- a/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
+++ b/server-spi/src/main/java/org/keycloak/storage/adapter/AbstractUserAdapterFederatedStorage.java
@@ -16,6 +16,7 @@
*/
package org.keycloak.storage.adapter;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
@@ -28,11 +29,9 @@ import org.keycloak.models.UserModel;
import org.keycloak.models.utils.DefaultRoles;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.storage.StorageId;
-import org.keycloak.storage.StorageProviderModel;
import org.keycloak.storage.federated.UserFederatedStorageProvider;
import java.util.Collections;
-import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -60,9 +59,9 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
protected KeycloakSession session;
protected RealmModel realm;
- protected StorageProviderModel storageProviderModel;
+ protected ComponentModel storageProviderModel;
- public AbstractUserAdapterFederatedStorage(KeycloakSession session, RealmModel realm, StorageProviderModel storageProviderModel) {
+ public AbstractUserAdapterFederatedStorage(KeycloakSession session, RealmModel realm, ComponentModel storageProviderModel) {
this.session = session;
this.realm = realm;
this.storageProviderModel = storageProviderModel;
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
index 46ae9db..b604991 100755
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProvider.java
@@ -17,6 +17,7 @@
package org.keycloak.storage.federated;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.ProtocolMapperModel;
@@ -25,7 +26,6 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserFederationProviderModel;
import org.keycloak.models.UserModel;
import org.keycloak.provider.Provider;
-import org.keycloak.storage.StorageProviderModel;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -44,7 +44,7 @@ public interface UserFederatedStorageProvider extends Provider,
void preRemove(RealmModel realm, UserFederationProviderModel link);
- public void preRemove(RealmModel realm, GroupModel group);
+ void preRemove(RealmModel realm, GroupModel group);
void preRemove(RealmModel realm, RoleModel role);
@@ -54,5 +54,5 @@ public interface UserFederatedStorageProvider extends Provider,
void preRemove(RealmModel realm, UserModel user);
- void preRemove(RealmModel realm, StorageProviderModel model);
+ void preRemove(RealmModel realm, ComponentModel model);
}
diff --git a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProviderSpi.java b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProviderSpi.java
index 5475422..21b1ad0 100755
--- a/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProviderSpi.java
+++ b/server-spi/src/main/java/org/keycloak/storage/federated/UserFederatedStorageProviderSpi.java
@@ -20,8 +20,6 @@ package org.keycloak.storage.federated;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
-import org.keycloak.storage.StorageProvider;
-import org.keycloak.storage.StorageProviderFactory;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
diff --git a/server-spi/src/main/java/org/keycloak/storage/StorageId.java b/server-spi/src/main/java/org/keycloak/storage/StorageId.java
index 5620740..ab44e47 100644
--- a/server-spi/src/main/java/org/keycloak/storage/StorageId.java
+++ b/server-spi/src/main/java/org/keycloak/storage/StorageId.java
@@ -16,6 +16,7 @@
*/
package org.keycloak.storage;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.UserModel;
import java.io.Serializable;
@@ -27,27 +28,44 @@ import java.io.Serializable;
public class StorageId implements Serializable {
private String id;
private String providerId;
- private String storageId;
+ private String externalId;
public StorageId(String id) {
this.id = id;
if (!id.startsWith("f:")) {
- storageId = id;
+ externalId = id;
return;
}
int providerIndex = id.indexOf(':', 2);
providerId = id.substring(2, providerIndex);
- storageId = id.substring(providerIndex + 1);
+ externalId = id.substring(providerIndex + 1);
}
- public StorageId(String providerId, String storageId) {
- this.id = "f:" + providerId + ":" + storageId;
+ public StorageId(String providerId, String externalId) {
+ this.id = "f:" + providerId + ":" + externalId;
this.providerId = providerId;
- this.storageId = storageId;
+ this.externalId = externalId;
}
+ /**
+ * generate the id string that should be returned by UserModel.getId()
+ *
+ * @param model
+ * @param externalId id used to resolve user in external storage
+ * @return
+ */
+ public static String keycloakId(ComponentModel model, String externalId) {
+ return new StorageId(model.getId(), externalId).getId();
+ }
+
+ public static String externalId(String keycloakId) {
+ return new StorageId(keycloakId).getExternalId();
+ }
+
+
+
public static String resolveProviderId(UserModel user) {
return new StorageId(user.getId()).getProviderId();
}
@@ -63,8 +81,8 @@ public class StorageId implements Serializable {
return providerId;
}
- public String getStorageId() {
- return storageId;
+ public String getExternalId() {
+ return externalId;
}
diff --git a/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java b/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java
index 7b6922d..7697042 100644
--- a/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java
+++ b/server-spi/src/main/java/org/keycloak/storage/user/UserRegistrationProvider.java
@@ -25,7 +25,6 @@ import org.keycloak.models.UserModel;
* @version $Revision: 1 $
*/
public interface UserRegistrationProvider {
- UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions);
UserModel addUser(RealmModel realm, String username);
diff --git a/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java b/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
index b6e6028..72906b0 100755
--- a/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
+++ b/server-spi/src/main/java/org/keycloak/storage/UserStorageManager.java
@@ -19,6 +19,7 @@ package org.keycloak.storage;
import org.jboss.logging.Logger;
import org.keycloak.common.util.reflections.Types;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.CredentialValidationOutput;
import org.keycloak.models.FederatedIdentityModel;
@@ -62,10 +63,6 @@ public class UserStorageManager implements UserProvider {
protected KeycloakSession session;
- // Set of already validated/proxied federation users during this session. Key is user ID
- private Map<String, UserModel> managedUsers = new HashMap<>();
- private UserProvider localStorage = null;
-
public UserStorageManager(KeycloakSession session) {
this.session = session;
}
@@ -74,28 +71,37 @@ public class UserStorageManager implements UserProvider {
return session.userLocalStorage();
}
- protected List<StorageProviderModel> getStorageProviders(RealmModel realm) {
- return realm.getStorageProviders();
+ protected List<UserStorageProviderModel> getStorageProviders(RealmModel realm) {
+ return realm.getUserStorageProviders();
}
protected <T> T getFirstStorageProvider(RealmModel realm, Class<T> type) {
- for (StorageProviderModel model : getStorageProviders(realm)) {
- StorageProviderFactory factory = (StorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
+ for (UserStorageProviderModel model : getStorageProviders(realm)) {
+ UserStorageProviderFactory factory = (UserStorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, model.getProviderId());
- if (Types.supports(type, factory, StorageProviderFactory.class)) {
- return type.cast(factory.getInstance(session, model));
+ if (Types.supports(type, factory, UserStorageProviderFactory.class)) {
+ return type.cast(getStorageProviderInstance(model, factory));
}
}
return null;
}
+ private UserStorageProvider getStorageProviderInstance(UserStorageProviderModel model, UserStorageProviderFactory factory) {
+ UserStorageProvider instance = (UserStorageProvider)session.getAttribute(model.getId());
+ if (instance != null) return instance;
+ instance = factory.create(session, model);
+ session.enlistForClose(instance);
+ session.setAttribute(model.getId(), instance);
+ return instance;
+ }
+
protected <T> List<T> getStorageProviders(RealmModel realm, Class<T> type) {
List<T> list = new LinkedList<>();
- for (StorageProviderModel model : getStorageProviders(realm)) {
- StorageProviderFactory factory = (StorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
- if (Types.supports(type, factory, StorageProviderFactory.class)) {
- list.add(type.cast(factory.getInstance(session, model)));
+ for (UserStorageProviderModel model : getStorageProviders(realm)) {
+ UserStorageProviderFactory factory = (UserStorageProviderFactory) session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, model.getProviderId());
+ if (Types.supports(type, factory, UserStorageProviderFactory.class)) {
+ list.add(type.cast(getStorageProviderInstance(model, factory)));
}
@@ -106,10 +112,6 @@ public class UserStorageManager implements UserProvider {
@Override
public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
- UserRegistrationProvider registry = getFirstStorageProvider(realm, UserRegistrationProvider.class);
- if (registry != null) {
- return registry.addUser(realm, id, username, addDefaultRoles, addDefaultRequiredActions);
- }
return localStorage().addUser(realm, id, username.toLowerCase(), addDefaultRoles, addDefaultRequiredActions);
}
@@ -122,14 +124,14 @@ public class UserStorageManager implements UserProvider {
return localStorage().addUser(realm, username.toLowerCase());
}
- public StorageProvider getStorageProvider(RealmModel realm, String providerId) {
- StorageProviderModel model = realm.getStorageProvider(providerId);
+ public UserStorageProvider getStorageProvider(RealmModel realm, String componentId) {
+ ComponentModel model = realm.getComponent(componentId);
if (model == null) return null;
- StorageProviderFactory factory = (StorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(StorageProvider.class, model.getProviderName());
+ UserStorageProviderFactory factory = (UserStorageProviderFactory)session.getKeycloakSessionFactory().getProviderFactory(UserStorageProvider.class, model.getProviderId());
if (factory == null) {
- throw new ModelException("Could not find StorageProviderFactory for: " + model.getProviderName());
+ throw new ModelException("Could not find UserStorageProviderFactory for: " + model.getProviderId());
}
- return factory.getInstance(session, model);
+ return getStorageProviderInstance(new UserStorageProviderModel(model), factory);
}
@Override
@@ -481,7 +483,7 @@ public class UserStorageManager implements UserProvider {
public void preRemove(RealmModel realm) {
localStorage().preRemove(realm);
getFederatedStorage().preRemove(realm);
- for (StorageProvider provider : getStorageProviders(realm, StorageProvider.class)) {
+ for (UserStorageProvider provider : getStorageProviders(realm, UserStorageProvider.class)) {
provider.preRemove(realm);
}
}
@@ -496,7 +498,7 @@ public class UserStorageManager implements UserProvider {
public void preRemove(RealmModel realm, GroupModel group) {
localStorage().preRemove(realm, group);
getFederatedStorage().preRemove(realm, group);
- for (StorageProvider provider : getStorageProviders(realm, StorageProvider.class)) {
+ for (UserStorageProvider provider : getStorageProviders(realm, UserStorageProvider.class)) {
provider.preRemove(realm, group);
}
}
@@ -505,7 +507,7 @@ public class UserStorageManager implements UserProvider {
public void preRemove(RealmModel realm, RoleModel role) {
localStorage().preRemove(realm, role);
getFederatedStorage().preRemove(realm, role);
- for (StorageProvider provider : getStorageProviders(realm, StorageProvider.class)) {
+ for (UserStorageProvider provider : getStorageProviders(realm, UserStorageProvider.class)) {
provider.preRemove(realm, role);
}
}
@@ -557,7 +559,7 @@ public class UserStorageManager implements UserProvider {
if (toValidate.isEmpty()) return true;
- StorageProvider provider = getStorageProvider(realm, StorageId.resolveProviderId(user));
+ UserStorageProvider provider = getStorageProvider(realm, StorageId.resolveProviderId(user));
if (!(provider instanceof UserCredentialValidatorProvider)) {
return false;
}
@@ -601,7 +603,7 @@ public class UserStorageManager implements UserProvider {
}
@Override
- public void preRemove(RealmModel realm, StorageProviderModel link) {
+ public void preRemove(RealmModel realm, ComponentModel component) {
}
diff --git a/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java b/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java
index 58695c3..dbb4b3c 100644
--- a/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java
+++ b/server-spi/src/main/java/org/keycloak/storage/UserStorageProvider.java
@@ -16,13 +16,18 @@
*/
package org.keycloak.storage;
+import org.keycloak.models.GroupModel;
import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public interface UserStorageProvider {
+public interface UserStorageProvider extends Provider {
void preRemove(RealmModel realm);
-
+ void preRemove(RealmModel realm, GroupModel group);
+ void preRemove(RealmModel realm, RoleModel role);
}
+
diff --git a/server-spi/src/main/java/org/keycloak/storage/UserStorageProviderModel.java b/server-spi/src/main/java/org/keycloak/storage/UserStorageProviderModel.java
new file mode 100755
index 0000000..351107f
--- /dev/null
+++ b/server-spi/src/main/java/org/keycloak/storage/UserStorageProviderModel.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 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.storage;
+
+import org.keycloak.common.util.MultivaluedHashMap;
+import org.keycloak.component.ComponentModel;
+import org.keycloak.models.RealmModel;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Stored configuration of a User Storage provider instance.
+ *
+ * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
+ * @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
+ */
+public class UserStorageProviderModel extends ComponentModel {
+
+ public static Comparator<UserStorageProviderModel> comparator = new Comparator<UserStorageProviderModel>() {
+ @Override
+ public int compare(UserStorageProviderModel o1, UserStorageProviderModel o2) {
+ return o1.getPriority() - o2.getPriority();
+ }
+ };
+
+ public UserStorageProviderModel() {
+ setProviderType(UserStorageProvider.class.getName());
+ }
+
+ public UserStorageProviderModel(ComponentModel copy) {
+ super(copy);
+ }
+
+ public int getPriority() {
+ String priority = getConfig().getFirst("priority");
+ if (priority == null) return 0;
+ return Integer.valueOf(priority);
+
+ }
+
+ public void setPriority(int priority) {
+ getConfig().putSingle("priority", Integer.toString(priority));
+ }
+}
diff --git a/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi b/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi
index 696bb4d..d2431d8 100755
--- a/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi
+++ b/server-spi/src/main/resources/META-INF/services/org.keycloak.provider.Spi
@@ -16,7 +16,7 @@
#
org.keycloak.models.UserFederationSpi
-org.keycloak.storage.StorageProviderSpi
+org.keycloak.storage.UserStorageProviderSpi
org.keycloak.storage.federated.UserFederatedStorageProviderSpi
org.keycloak.mappers.UserFederationMapperSpi
org.keycloak.models.RealmSpi
diff --git a/services/src/main/java/org/keycloak/partialimport/PartialImportManager.java b/services/src/main/java/org/keycloak/partialimport/PartialImportManager.java
index 59d6217..705d230 100644
--- a/services/src/main/java/org/keycloak/partialimport/PartialImportManager.java
+++ b/services/src/main/java/org/keycloak/partialimport/PartialImportManager.java
@@ -62,7 +62,7 @@ public class PartialImportManager {
try {
partialImport.prepare(rep, realm, session);
} catch (ErrorResponseException error) {
- if (session.getTransaction().isActive()) session.getTransaction().setRollbackOnly();
+ if (session.getTransactionManager().isActive()) session.getTransactionManager().setRollbackOnly();
return error.getResponse();
}
}
@@ -72,7 +72,7 @@ public class PartialImportManager {
partialImport.removeOverwrites(realm, session);
results.addAllResults(partialImport.doImport(rep, realm, session));
} catch (ErrorResponseException error) {
- if (session.getTransaction().isActive()) session.getTransaction().setRollbackOnly();
+ if (session.getTransactionManager().isActive()) session.getTransactionManager().setRollbackOnly();
return error.getResponse();
}
}
@@ -84,8 +84,8 @@ public class PartialImportManager {
}
}
- if (session.getTransaction().isActive()) {
- session.getTransaction().commit();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().commit();
}
return Response.ok(results).build();
diff --git a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
index 8eb2a56..1fae787 100644
--- a/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
+++ b/services/src/main/java/org/keycloak/services/DefaultKeycloakSession.java
@@ -36,6 +36,7 @@ public class DefaultKeycloakSession implements KeycloakSession {
private final Map<Integer, Provider> providers = new HashMap<>();
private final List<Provider> closable = new LinkedList<Provider>();
private final DefaultKeycloakTransactionManager transactionManager;
+ private final Map<String, Object> attributes = new HashMap<>();
private RealmProvider model;
private UserProvider userModel;
private UserStorageManager userStorageManager;
@@ -81,7 +82,22 @@ public class DefaultKeycloakSession implements KeycloakSession {
}
@Override
- public KeycloakTransactionManager getTransaction() {
+ public Object getAttribute(String attribute) {
+ return attributes.get(attribute);
+ }
+
+ @Override
+ public Object removeAttribute(String attribute) {
+ return attributes.remove(attribute);
+ }
+
+ @Override
+ public void setAttribute(String name, Object value) {
+ attributes.put(name, value);
+ }
+
+ @Override
+ public KeycloakTransactionManager getTransactionManager() {
return transactionManager;
}
diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
index 40c1ac6..4187645 100755
--- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
+++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java
@@ -82,7 +82,7 @@ public class KeycloakSessionServletFilter implements Filter {
session.getContext().setConnection(connection);
ResteasyProviderFactory.pushContext(ClientConnection.class, connection);
- KeycloakTransaction tx = session.getTransaction();
+ KeycloakTransaction tx = session.getTransactionManager();
ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
tx.begin();
@@ -123,8 +123,8 @@ public class KeycloakSessionServletFilter implements Filter {
private void closeSession(KeycloakSession session) {
// KeycloakTransactionCommitter is responsible for committing the transaction, but if an exception is thrown it's not invoked and transaction
// should be rolled back
- if (session.getTransaction() != null && session.getTransaction().isActive()) {
- session.getTransaction().rollback();
+ if (session.getTransactionManager() != null && session.getTransactionManager().isActive()) {
+ session.getTransactionManager().rollback();
}
session.close();
diff --git a/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
index fa3b1d5..28fc29d 100644
--- a/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
+++ b/services/src/main/java/org/keycloak/services/managers/DefaultBruteForceProtector.java
@@ -177,7 +177,7 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
queue.drainTo(events, TRANSACTION_SIZE);
Collections.sort(events); // we sort to avoid deadlock due to ordered updates. Maybe I'm overthinking this.
KeycloakSession session = factory.create();
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
for (LoginEvent event : events) {
if (event instanceof FailedLogin) {
@@ -186,9 +186,9 @@ public class DefaultBruteForceProtector implements Runnable, BruteForceProtector
run = false;
}
}
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} catch (Exception e) {
- session.getTransaction().rollback();
+ session.getTransactionManager().rollback();
throw e;
} finally {
for (LoginEvent event : events) {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
index 94203d7..82e65fb 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AuthenticationManagementResource.java
@@ -536,7 +536,7 @@ public class AuthenticationManagementResource {
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(rep.getId());
if (model == null) {
- session.getTransaction().setRollbackOnly();
+ session.getTransactionManager().setRollbackOnly();
throw new NotFoundException("Illegal execution");
}
@@ -596,7 +596,7 @@ public class AuthenticationManagementResource {
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
- session.getTransaction().setRollbackOnly();
+ session.getTransactionManager().setRollbackOnly();
throw new NotFoundException("Illegal execution");
}
@@ -642,7 +642,7 @@ public class AuthenticationManagementResource {
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
- session.getTransaction().setRollbackOnly();
+ session.getTransactionManager().setRollbackOnly();
throw new NotFoundException("Illegal execution");
}
@@ -682,7 +682,7 @@ public class AuthenticationManagementResource {
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
- session.getTransaction().setRollbackOnly();
+ session.getTransactionManager().setRollbackOnly();
throw new NotFoundException("Illegal execution");
}
@@ -718,7 +718,7 @@ public class AuthenticationManagementResource {
AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution);
if (model == null) {
- session.getTransaction().setRollbackOnly();
+ session.getTransactionManager().setRollbackOnly();
throw new NotFoundException("Illegal execution");
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
index a2c35d8..de4d49b 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientInitialAccessResource.java
@@ -73,8 +73,8 @@ public class ClientInitialAccessResource {
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, clientInitialAccessModel.getId()).representation(config).success();
- if (session.getTransaction().isActive()) {
- session.getTransaction().commit();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().commit();
}
ClientInitialAccessPresentation rep = wrap(clientInitialAccessModel);
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
new file mode 100644
index 0000000..0097b19
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ComponentResource.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2016 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.services.resources.admin;
+
+import org.jboss.resteasy.spi.NotFoundException;
+import org.keycloak.common.ClientConnection;
+import org.keycloak.component.ComponentModel;
+import org.keycloak.events.admin.OperationType;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.protocol.oidc.TokenManager;
+import org.keycloak.representations.idm.ComponentRepresentation;
+import org.keycloak.services.ServicesLogger;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class ComponentResource {
+ protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
+
+ protected RealmModel realm;
+
+ private RealmAuth auth;
+
+ private AdminEventBuilder adminEvent;
+
+ @Context
+ protected ClientConnection clientConnection;
+
+ @Context
+ protected UriInfo uriInfo;
+
+ @Context
+ protected KeycloakSession session;
+
+ @Context
+ protected HttpHeaders headers;
+
+ public ComponentResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
+ this.auth = auth;
+ this.realm = realm;
+ this.adminEvent = adminEvent;
+
+ auth.init(RealmAuth.Resource.USER);
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public List<ComponentRepresentation> getComponents(@QueryParam("parent") String parent, @QueryParam("type") String type) {
+ auth.requireManage();
+ if (parent == null) parent = realm.getId();
+ List<ComponentModel> components = realm.getComponents(parent, type);
+ List<ComponentRepresentation> reps = new LinkedList<>();
+ for (ComponentModel component : components) {
+ ComponentRepresentation rep = ModelToRepresentation.toRepresentation(component);
+ reps.add(rep);
+ }
+ return reps;
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response create(ComponentRepresentation rep) {
+ auth.requireManage();
+ ComponentModel model = RepresentationToModel.toModel(rep);
+ if (model.getParentId() == null) model.setParentId(realm.getId());
+ adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
+
+
+
+ model = realm.addComponentModel(model);
+ return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build();
+ }
+
+ @GET
+ @Path("{id}")
+ public ComponentRepresentation getComponent(@PathParam("id") String id) {
+ auth.requireManage();
+ ComponentModel model = realm.getComponent(id);
+ if (model == null) {
+ throw new NotFoundException("Could not find component");
+ }
+ return ModelToRepresentation.toRepresentation(model);
+
+
+ }
+
+ @PUT
+ @Path("{id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public void updateComponent(@PathParam("id") String id, ComponentRepresentation rep) {
+ auth.requireManage();
+ ComponentModel model = realm.getComponent(id);
+ if (model == null) {
+ throw new NotFoundException("Could not find component");
+ }
+ model = RepresentationToModel.toModel(rep);
+ model.setId(id);
+ adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo, model.getId()).representation(rep).success();
+ realm.updateComponent(model);
+
+ }
+ @DELETE
+ @Path("{id}")
+ public void removeComponent(@PathParam("id") String id) {
+ auth.requireManage();
+ ComponentModel model = realm.getComponent(id);
+ if (model == null) {
+ throw new NotFoundException("Could not find component");
+ }
+ adminEvent.operation(OperationType.DELETE).resourcePath(uriInfo, model.getId()).success();
+ realm.removeComponent(model);
+
+ }
+
+
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
index 1a67fb0..1a1d2bf 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java
@@ -25,7 +25,6 @@ import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.ServiceLoader;
import javax.ws.rs.GET;
import javax.ws.rs.WebApplicationException;
@@ -33,12 +32,13 @@ import javax.ws.rs.core.Context;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
+import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.OperationType;
-import org.keycloak.models.PasswordPolicy;
import org.keycloak.policy.PasswordPolicyProvider;
import org.keycloak.policy.PasswordPolicyProviderFactory;
import org.keycloak.provider.*;
+import org.keycloak.representations.idm.ComponentTypeRepresentation;
import org.keycloak.representations.idm.PasswordPolicyTypeRepresentation;
import org.keycloak.theme.Theme;
import org.keycloak.theme.ThemeProvider;
@@ -115,12 +115,28 @@ public class ServerInfoAdminResource {
Map<String, ProviderRepresentation> providers = new HashMap<>();
if (providerIds != null) {
+ info.setComponentTypes(new HashMap<>());
for (String name : providerIds) {
ProviderRepresentation provider = new ProviderRepresentation();
ProviderFactory<?> pi = session.getKeycloakSessionFactory().getProviderFactory(spi.getProviderClass(), name);
if (ServerInfoAwareProviderFactory.class.isAssignableFrom(pi.getClass())) {
provider.setOperationalInfo(((ServerInfoAwareProviderFactory) pi).getOperationalInfo());
}
+ if (pi instanceof ConfiguredProvider) {
+ ComponentTypeRepresentation rep = new ComponentTypeRepresentation();
+ rep.setId(pi.getId());
+ ConfiguredProvider configured = (ConfiguredProvider)pi;
+ rep.setHelpText(configured.getHelpText());
+ List<ProviderConfigProperty> configProperties = configured.getConfigProperties();
+ if (configProperties == null) configProperties = Collections.EMPTY_LIST;
+ rep.setProperties(ModelToRepresentation.toRepresentation(configProperties));
+ List<ComponentTypeRepresentation> reps = info.getComponentTypes().get(spi.getProviderClass().getName());
+ if (reps == null) {
+ reps = new LinkedList<>();
+ info.getComponentTypes().put(spi.getProviderClass().getName(), reps);
+ }
+ reps.add(rep);
+ }
providers.put(name, provider);
}
}
@@ -225,15 +241,7 @@ public class ServerInfoAdminResource {
rep.setCategory(mapper.getDisplayCategory());
rep.setProperties(new LinkedList<ConfigPropertyRepresentation>());
List<ProviderConfigProperty> configProperties = mapper.getConfigProperties();
- for (ProviderConfigProperty prop : configProperties) {
- ConfigPropertyRepresentation propRep = new ConfigPropertyRepresentation();
- propRep.setName(prop.getName());
- propRep.setLabel(prop.getLabel());
- propRep.setType(prop.getType());
- propRep.setDefaultValue(prop.getDefaultValue());
- propRep.setHelpText(prop.getHelpText());
- rep.getProperties().add(propRep);
- }
+ rep.setProperties(ModelToRepresentation.toRepresentation(configProperties));
types.add(rep);
}
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index 4594bdd..8270ed4 100644
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -321,7 +321,7 @@ public class RealmAdminResource {
*/
@Path("users")
public UsersResource users() {
- UsersResource users = new UsersResource(realm, auth, tokenManager, adminEvent);
+ UsersResource users = new UsersResource(realm, auth, adminEvent);
ResteasyProviderFactory.getInstance().injectProperties(users);
//resourceContext.initResource(users);
return users;
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
index 5788b42..aa6aa68 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java
@@ -127,7 +127,7 @@ public class UsersResource {
@Context
protected HttpHeaders headers;
- public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager, AdminEventBuilder adminEvent) {
+ public UsersResource(RealmModel realm, RealmAuth auth, AdminEventBuilder adminEvent) {
this.auth = auth;
this.realm = realm;
this.adminEvent = adminEvent;
@@ -172,8 +172,8 @@ public class UsersResource {
updateUserFromRep(user, rep, attrsToRemove, realm, session, true);
adminEvent.operation(OperationType.UPDATE).resourcePath(uriInfo).representation(rep).success();
- if (session.getTransaction().isActive()) {
- session.getTransaction().commit();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().commit();
}
return Response.noContent().build();
} catch (ModelDuplicateException e) {
@@ -214,19 +214,19 @@ public class UsersResource {
adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo, user.getId()).representation(rep).success();
- if (session.getTransaction().isActive()) {
- session.getTransaction().commit();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().commit();
}
return Response.created(uriInfo.getAbsolutePathBuilder().path(user.getId()).build()).build();
} catch (ModelDuplicateException e) {
- if (session.getTransaction().isActive()) {
- session.getTransaction().setRollbackOnly();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().setRollbackOnly();
}
return ErrorResponse.exists("User exists with same username or email");
} catch (ModelException me){
- if (session.getTransaction().isActive()) {
- session.getTransaction().setRollbackOnly();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().setRollbackOnly();
}
return ErrorResponse.exists("Could not create user");
}
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index c7cbc62..9181817 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -835,17 +835,17 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
private void fireErrorEvent(String message, Throwable throwable) {
if (!this.event.getEvent().getType().toString().endsWith("_ERROR")) {
- boolean newTransaction = !this.session.getTransaction().isActive();
+ boolean newTransaction = !this.session.getTransactionManager().isActive();
try {
if (newTransaction) {
- this.session.getTransaction().begin();
+ this.session.getTransactionManager().begin();
}
this.event.error(message);
if (newTransaction) {
- this.session.getTransaction().commit();
+ this.session.getTransactionManager().commit();
}
} catch (Exception e) {
logger.couldNotFireEvent(e);
@@ -869,8 +869,8 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
private void rollback() {
- if (this.session.getTransaction().isActive()) {
- this.session.getTransaction().rollback();
+ if (this.session.getTransactionManager().isActive()) {
+ this.session.getTransactionManager().rollback();
}
}
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index 0385281..5e1cd9f 100644
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -119,10 +119,10 @@ public class KeycloakApplication extends Application {
boolean bootstrapAdminUser = false;
KeycloakSession session = sessionFactory.create();
try {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
bootstrapAdminUser = new ApplianceBootstrap(session).isNoMasterUser();
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} finally {
session.close();
}
@@ -142,7 +142,7 @@ public class KeycloakApplication extends Application {
KeycloakSession session = sessionFactory.create();
try {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
ApplianceBootstrap applianceBootstrap = new ApplianceBootstrap(session);
exportImportManager = new ExportImportManager(session);
@@ -155,10 +155,10 @@ public class KeycloakApplication extends Application {
if (createMasterRealm) {
applianceBootstrap.createMasterRealm(contextPath);
}
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} catch (RuntimeException re) {
- if (session.getTransaction().isActive()) {
- session.getTransaction().rollback();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().rollback();
}
throw re;
} finally {
@@ -180,11 +180,11 @@ public class KeycloakApplication extends Application {
protected void migrateModel() {
KeycloakSession session = sessionFactory.create();
try {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
MigrationModelManager.migrate(session);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} catch (Exception e) {
- session.getTransaction().rollback();
+ session.getTransactionManager().rollback();
logger.migrationFailure(e);
throw e;
} finally {
@@ -294,7 +294,7 @@ public class KeycloakApplication extends Application {
KeycloakSession session = sessionFactory.create();
boolean exists = false;
try {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
RealmManager manager = new RealmManager(session);
@@ -313,9 +313,9 @@ public class KeycloakApplication extends Application {
RealmModel realm = manager.importRealm(rep);
logger.importedRealm(realm.getName(), from);
}
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} catch (Throwable t) {
- session.getTransaction().rollback();
+ session.getTransactionManager().rollback();
if (!exists) {
logger.unableToImportRealm(t, rep.getRealm(), from);
}
@@ -345,7 +345,7 @@ public class KeycloakApplication extends Application {
for (UserRepresentation userRep : realmRep.getUsers()) {
KeycloakSession session = sessionFactory.create();
try {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
RealmModel realm = session.realms().getRealmByName(realmRep.getRealm());
if (realm == null) {
@@ -357,13 +357,13 @@ public class KeycloakApplication extends Application {
RepresentationToModel.createRoleMappings(userRep, user, realm);
}
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
logger.addUserSuccess(userRep.getUsername(), realmRep.getRealm());
} catch (ModelDuplicateException e) {
- session.getTransaction().rollback();
+ session.getTransactionManager().rollback();
logger.addUserFailedUserExists(userRep.getUsername(), realmRep.getRealm());
} catch (Throwable t) {
- session.getTransaction().rollback();
+ session.getTransactionManager().rollback();
logger.addUserFailed(t, userRep.getUsername(), realmRep.getRealm());
} finally {
session.close();
diff --git a/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java b/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java
index 94db9c9..b2a8bf7 100644
--- a/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java
+++ b/services/src/main/java/org/keycloak/services/scheduled/ClusterAwareScheduledTaskRunner.java
@@ -41,7 +41,7 @@ public class ClusterAwareScheduledTaskRunner extends ScheduledTaskRunner {
@Override
protected void runTask(final KeycloakSession session) {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
ClusterProvider clusterProvider = session.getProvider(ClusterProvider.class);
String taskKey = task.getClass().getSimpleName();
@@ -56,7 +56,7 @@ public class ClusterAwareScheduledTaskRunner extends ScheduledTaskRunner {
});
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
if (result.isExecuted()) {
logger.debugf("Executed scheduled task %s", taskKey);
diff --git a/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java b/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
index b49300f..81ff5f6 100644
--- a/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
+++ b/services/src/main/java/org/keycloak/services/scheduled/ScheduledTaskRunner.java
@@ -45,7 +45,7 @@ public class ScheduledTaskRunner implements Runnable {
} catch (Throwable t) {
logger.failedToRunScheduledTask(t, task.getClass().getSimpleName());
- session.getTransaction().rollback();
+ session.getTransactionManager().rollback();
} finally {
try {
session.close();
@@ -56,9 +56,9 @@ public class ScheduledTaskRunner implements Runnable {
}
protected void runTask(KeycloakSession session) {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
task.run(session);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
logger.debug("Executed scheduled task " + task.getClass().getSimpleName());
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
index 507c0fe..adea44e 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/AdapterTestStrategy.java
@@ -265,7 +265,7 @@ public class AdapterTestStrategy extends ExternalResource {
RealmModel realm = session.realms().getRealmByName("demo");
int originalIdle = realm.getSsoSessionIdleTimeout();
realm.setSsoSessionIdleTimeout(1);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
Time.setOffset(2);
@@ -278,7 +278,7 @@ public class AdapterTestStrategy extends ExternalResource {
session = keycloakRule.startSession();
realm = session.realms().getRealmByName("demo");
realm.setSsoSessionIdleTimeout(originalIdle);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
Time.setOffset(0);
@@ -300,7 +300,7 @@ public class AdapterTestStrategy extends ExternalResource {
RealmModel realm = session.realms().getRealmByName("demo");
int originalIdle = realm.getSsoSessionIdleTimeout();
realm.setSsoSessionIdleTimeout(1);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
Time.setOffset(2);
@@ -308,7 +308,7 @@ public class AdapterTestStrategy extends ExternalResource {
session = keycloakRule.startSession();
realm = session.realms().getRealmByName("demo");
session.sessions().removeExpired(realm);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
// test SSO
@@ -321,7 +321,7 @@ public class AdapterTestStrategy extends ExternalResource {
UserModel user = session.users().getUserByUsername("bburke@redhat.com", realm);
new ResourceAdminManager(session).logoutUser(null, realm, user, session);
realm.setSsoSessionIdleTimeout(originalIdle);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
Time.setOffset(0);
@@ -343,7 +343,7 @@ public class AdapterTestStrategy extends ExternalResource {
RealmModel realm = session.realms().getRealmByName("demo");
int original = realm.getSsoSessionMaxLifespan();
realm.setSsoSessionMaxLifespan(1);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
Time.setOffset(2);
@@ -356,7 +356,7 @@ public class AdapterTestStrategy extends ExternalResource {
session = keycloakRule.startSession();
realm = session.realms().getRealmByName("demo");
realm.setSsoSessionMaxLifespan(original);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
Time.setOffset(0);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java
index 936dfe9..02e34a7 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/adapter/CookieTokenStoreAdapterTest.java
@@ -125,7 +125,7 @@ public class CookieTokenStoreAdapterTest {
RealmModel realm = session.realms().getRealmByName("demo");
int originalTokenTimeout = realm.getAccessTokenLifespan();
realm.setAccessTokenLifespan(3);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
// login to customer-cookie-portal
@@ -164,7 +164,7 @@ public class CookieTokenStoreAdapterTest {
session = keycloakRule.startSession();
realm = session.realms().getRealmByName("demo");
realm.setAccessTokenLifespan(originalTokenTimeout);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
} finally {
Time.setOffset(0);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractAuthorizationTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractAuthorizationTest.java
index 301adca..fbf602e 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractAuthorizationTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/authorization/AbstractAuthorizationTest.java
@@ -58,7 +58,7 @@ public abstract class AbstractAuthorizationTest {
protected <R> R onAuthorizationSession(Function<AuthorizationProvider, R> function) {
KeycloakSession keycloakSession = startKeycloakSession();
- KeycloakTransactionManager transaction = keycloakSession.getTransaction();
+ KeycloakTransactionManager transaction = keycloakSession.getTransactionManager();
try {
AuthorizationProvider authorizationProvider = keycloakSession.getProvider(AuthorizationProvider.class);
@@ -80,7 +80,7 @@ public abstract class AbstractAuthorizationTest {
protected void onAuthorizationSession(Consumer<AuthorizationProvider> consumer) {
KeycloakSession keycloakSession = startKeycloakSession();
- KeycloakTransactionManager transaction = keycloakSession.getTransaction();
+ KeycloakTransactionManager transaction = keycloakSession.getTransactionManager();
try {
AuthorizationProvider authorizationProvider = keycloakSession.getProvider(AuthorizationProvider.class);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java
index daed4ad..a53479c 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorage.java
@@ -16,6 +16,7 @@
*/
package org.keycloak.testsuite.federation.storage;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -23,8 +24,7 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.StorageId;
-import org.keycloak.storage.StorageProvider;
-import org.keycloak.storage.StorageProviderModel;
+import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
import org.keycloak.storage.user.UserCredentialValidatorProvider;
import org.keycloak.storage.user.UserLookupProvider;
@@ -32,28 +32,33 @@ import org.keycloak.storage.user.UserRegistrationProvider;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class UserMapStorage implements UserLookupProvider, StorageProvider, UserCredentialValidatorProvider, UserRegistrationProvider {
+public class UserMapStorage implements UserLookupProvider, UserStorageProvider, UserCredentialValidatorProvider, UserRegistrationProvider {
protected Map<String, String> userPasswords;
- protected StorageProviderModel model;
+ protected ComponentModel model;
protected KeycloakSession session;
- public UserMapStorage(KeycloakSession session, StorageProviderModel model, Map<String, String> userPasswords) {
+ public static final AtomicInteger allocations = new AtomicInteger(0);
+ public static final AtomicInteger closings = new AtomicInteger(0);
+
+ public UserMapStorage(KeycloakSession session, ComponentModel model, Map<String, String> userPasswords) {
this.session = session;
this.model = model;
this.userPasswords = userPasswords;
+ allocations.incrementAndGet();
}
@Override
public UserModel getUserById(String id, RealmModel realm) {
StorageId storageId = new StorageId(id);
- final String username = storageId.getStorageId();
+ final String username = storageId.getExternalId();
if (!userPasswords.containsKey(username)) return null;
return createUser(realm, username);
@@ -95,12 +100,6 @@ public class UserMapStorage implements UserLookupProvider, StorageProvider, User
}
@Override
- public UserModel addUser(RealmModel realm, String id, String username, boolean addDefaultRoles, boolean addDefaultRequiredActions) {
- userPasswords.put(username, "");
- return createUser(realm, username);
- }
-
- @Override
public UserModel addUser(RealmModel realm, String username) {
userPasswords.put(username, "");
return createUser(realm, username);
@@ -132,11 +131,6 @@ public class UserMapStorage implements UserLookupProvider, StorageProvider, User
}
@Override
- public void preRemove(RealmModel realm, StorageProviderModel model) {
-
- }
-
- @Override
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
for (UserCredentialModel cred : input) {
if (!cred.getType().equals(UserCredentialModel.PASSWORD)) return false;
@@ -151,6 +145,7 @@ public class UserMapStorage implements UserLookupProvider, StorageProvider, User
@Override
public void close() {
+ closings.incrementAndGet();
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java
index f80a11d..79e9261 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserMapStorageFactory.java
@@ -17,22 +17,19 @@
package org.keycloak.testsuite.federation.storage;
import org.keycloak.Config;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.storage.StorageProvider;
-import org.keycloak.storage.StorageProviderFactory;
-import org.keycloak.storage.StorageProviderModel;
+import org.keycloak.storage.UserStorageProviderFactory;
-import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
-import java.util.Properties;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class UserMapStorageFactory implements StorageProviderFactory<UserMapStorage> {
+public class UserMapStorageFactory implements UserStorageProviderFactory<UserMapStorage> {
public static final String PROVIDER_ID = "user-password-map";
@@ -40,7 +37,7 @@ public class UserMapStorageFactory implements StorageProviderFactory<UserMapStor
protected Map<String, String> userPasswords = new Hashtable<>();
@Override
- public UserMapStorage getInstance(KeycloakSession session, StorageProviderModel model) {
+ public UserMapStorage create(KeycloakSession session, ComponentModel model) {
return new UserMapStorage(session, model, userPasswords);
}
@@ -50,11 +47,6 @@ public class UserMapStorageFactory implements StorageProviderFactory<UserMapStor
}
@Override
- public StorageProvider create(KeycloakSession session) {
- return null;
- }
-
- @Override
public void init(Config.Scope config) {
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorage.java
index cf237e4..644dcb8 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorage.java
@@ -16,6 +16,7 @@
*/
package org.keycloak.testsuite.federation.storage;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@@ -23,11 +24,9 @@ import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.StorageId;
-import org.keycloak.storage.StorageProvider;
-import org.keycloak.storage.StorageProviderModel;
+import org.keycloak.storage.UserStorageProvider;
import org.keycloak.storage.adapter.AbstractUserAdapter;
import org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage;
-import org.keycloak.storage.federated.UserFederatedStorageProvider;
import org.keycloak.storage.user.UserCredentialValidatorProvider;
import org.keycloak.storage.user.UserLookupProvider;
import org.keycloak.storage.user.UserQueryProvider;
@@ -42,14 +41,14 @@ import java.util.Properties;
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class UserPropertyFileStorage implements UserLookupProvider, StorageProvider, UserCredentialValidatorProvider, UserQueryProvider {
+public class UserPropertyFileStorage implements UserLookupProvider, UserStorageProvider, UserCredentialValidatorProvider, UserQueryProvider {
protected Properties userPasswords;
- protected StorageProviderModel model;
+ protected ComponentModel model;
protected KeycloakSession session;
protected boolean federatedStorageEnabled;
- public UserPropertyFileStorage(KeycloakSession session, StorageProviderModel model, Properties userPasswords) {
+ public UserPropertyFileStorage(KeycloakSession session, ComponentModel model, Properties userPasswords) {
this.session = session;
this.model = model;
this.userPasswords = userPasswords;
@@ -60,7 +59,7 @@ public class UserPropertyFileStorage implements UserLookupProvider, StorageProvi
@Override
public UserModel getUserById(String id, RealmModel realm) {
StorageId storageId = new StorageId(id);
- final String username = storageId.getStorageId();
+ final String username = storageId.getExternalId();
if (!userPasswords.containsKey(username)) return null;
return createUser(realm, username);
@@ -117,11 +116,6 @@ public class UserPropertyFileStorage implements UserLookupProvider, StorageProvi
}
@Override
- public void preRemove(RealmModel realm, StorageProviderModel model) {
-
- }
-
- @Override
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
for (UserCredentialModel cred : input) {
if (!cred.getType().equals(UserCredentialModel.PASSWORD)) return false;
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorageFactory.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorageFactory.java
index 82d91cf..0dec2bb 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorageFactory.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/federation/storage/UserPropertyFileStorageFactory.java
@@ -17,33 +17,28 @@
package org.keycloak.testsuite.federation.storage;
import org.keycloak.Config;
+import org.keycloak.component.ComponentModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.provider.ProviderFactory;
-import org.keycloak.storage.StorageProvider;
-import org.keycloak.storage.StorageProviderFactory;
-import org.keycloak.storage.StorageProviderModel;
+import org.keycloak.storage.UserStorageProviderFactory;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
import java.util.Properties;
-import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
-public class UserPropertyFileStorageFactory implements StorageProviderFactory<UserPropertyFileStorage> {
+public class UserPropertyFileStorageFactory implements UserStorageProviderFactory<UserPropertyFileStorage> {
public static final String PROVIDER_ID = "user-password-props";
@Override
- public UserPropertyFileStorage getInstance(KeycloakSession session, StorageProviderModel model) {
+ public UserPropertyFileStorage create(KeycloakSession session, ComponentModel model) {
Properties props = new Properties();
try {
- props.load(getClass().getResourceAsStream(model.getConfig().get("property.file")));
+ props.load(getClass().getResourceAsStream(model.getConfig().getFirst("property.file")));
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -56,11 +51,6 @@ public class UserPropertyFileStorageFactory implements StorageProviderFactory<Us
}
@Override
- public StorageProvider create(KeycloakSession session) {
- return null;
- }
-
- @Override
public void init(Config.Scope config) {
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
index 7791c91..3b8d68b 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
@@ -39,7 +39,6 @@ import org.keycloak.testsuite.util.cli.TestsuiteCLI;
import org.keycloak.util.JsonSerialization;
import javax.servlet.DispatcherType;
-import javax.ws.rs.core.Application;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -249,7 +248,7 @@ public class KeycloakServer {
public void importRealm(RealmRepresentation rep) {
KeycloakSession session = sessionFactory.create();;
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
RealmManager manager = new RealmManager(session);
@@ -268,7 +267,7 @@ public class KeycloakServer {
info("Imported realm " + realm.getName());
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} finally {
session.close();
}
@@ -278,11 +277,11 @@ public class KeycloakServer {
if (System.getProperty("keycloak.createAdminUser", "true").equals("true")) {
KeycloakSession session = sessionFactory.create();
try {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
if (new ApplianceBootstrap(session).isNoMasterUser()) {
new ApplianceBootstrap(session).createMasterRealmUser("admin", "admin");
}
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} finally {
session.close();
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AbstractModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AbstractModelTest.java
index 0befa7c..f1409f4 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AbstractModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AbstractModelTest.java
@@ -81,16 +81,16 @@ public class AbstractModelTest {
protected void commit(boolean rollback) {
if (rollback) {
- session.getTransaction().rollback();
+ session.getTransactionManager().rollback();
} else {
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
}
resetSession();
}
protected void resetSession() {
- if (session.getTransaction().isActive()) {
- session.getTransaction().rollback();
+ if (session.getTransactionManager().isActive()) {
+ session.getTransactionManager().rollback();
}
kc.stopSession(session, false);
session = kc.startSession();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
index a28af56..eecf8c9 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/AdapterTest.java
@@ -74,7 +74,7 @@ public class AdapterTest extends AbstractModelTest {
realmModel.setAccessTokenLifespan(1000);
realmModel.addDefaultRole("foo");
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
resetSession();
realmModel = realmManager.getRealm(realmModel.getId());
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
index 0d7c9b0..c478375 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/CacheTest.java
@@ -105,7 +105,7 @@ public class CacheTest {
assertNotNull(user2.getLastName());
} finally {
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
}
}
@@ -121,7 +121,7 @@ public class CacheTest {
RoleModel fooRole = client.addRole("foo-role");
user.grantRole(fooRole);
} finally {
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
}
@@ -136,7 +136,7 @@ public class CacheTest {
ClientModel client = realm.getClientByClientId("foo");
realm.removeClient(client.getId());
} finally {
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
}
@@ -152,7 +152,7 @@ public class CacheTest {
Assert.assertEquals(roles.size(), grantedRolesCount - 1);
} finally {
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
session.close();
}
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/TransactionsTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/TransactionsTest.java
index 0d7e9e2..2edcfaa 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/TransactionsTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/TransactionsTest.java
@@ -35,14 +35,14 @@ public class TransactionsTest {
public void testTransactionActive() {
KeycloakSession session = kc.startSession();
- Assert.assertTrue(session.getTransaction().isActive());
- session.getTransaction().commit();
- Assert.assertFalse(session.getTransaction().isActive());
-
- session.getTransaction().begin();
- Assert.assertTrue(session.getTransaction().isActive());
- session.getTransaction().rollback();
- Assert.assertFalse(session.getTransaction().isActive());
+ Assert.assertTrue(session.getTransactionManager().isActive());
+ session.getTransactionManager().commit();
+ Assert.assertFalse(session.getTransactionManager().isActive());
+
+ session.getTransactionManager().begin();
+ Assert.assertTrue(session.getTransactionManager().isActive());
+ session.getTransactionManager().rollback();
+ Assert.assertFalse(session.getTransactionManager().isActive());
session.close();
}
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
index 83ea5ad..01f99fb 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserModelTest.java
@@ -217,7 +217,7 @@ public class UserModelTest extends AbstractModelTest {
UserModel user1 = session.users().addUser(realm, "user1");
commit();
-
+ realm = session.realms().getRealmByName("original");
List<UserModel> users = session.users().searchForUser("user", realm, 0, 7);
Assert.assertTrue(users.contains(user1));
}
@@ -238,6 +238,7 @@ public class UserModelTest extends AbstractModelTest {
user3.setSingleAttribute("key2", "value21");
commit();
+ realm = session.realms().getRealmByName("original");
List<UserModel> users = session.users().searchForUserByUserAttribute("key1", "value1", realm);
Assert.assertEquals(2, users.size());
@@ -284,6 +285,7 @@ public class UserModelTest extends AbstractModelTest {
// Search and assert service account user not found
realm = realmManager.getRealmByName("original");
+ client = realm.getClientByClientId("foo");
UserModel searched = session.users().getServiceAccount(client);
Assert.assertEquals(searched, user1);
users = session.users().searchForUser("John Doe", realm);
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
index 172c517..8315331 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/AbstractKeycloakRule.java
@@ -85,12 +85,12 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
public UserRepresentation getUser(String realm, String name) {
KeycloakSession session = server.getSessionFactory().create();
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
RealmModel realmByName = session.realms().getRealmByName(realm);
UserModel user = session.users().getUserByUsername(name, realmByName);
UserRepresentation userRep = user != null ? ModelToRepresentation.toRepresentation(user) : null;
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
return userRep;
} finally {
session.close();
@@ -99,11 +99,11 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
public UserRepresentation getUserById(String realm, String id) {
KeycloakSession session = server.getSessionFactory().create();
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
RealmModel realmByName = session.realms().getRealmByName(realm);
UserRepresentation userRep = ModelToRepresentation.toRepresentation(session.users().getUserById(id, realmByName));
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
return userRep;
} finally {
session.close();
@@ -112,7 +112,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
protected void setupKeycloak() {
KeycloakSession session = server.getSessionFactory().create();
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
RealmManager manager = new RealmManager(session);
@@ -121,7 +121,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
configure(session, manager, adminstrationRealm);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} finally {
session.close();
}
@@ -129,7 +129,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
public void update(KeycloakRule.KeycloakSetup configurer, String realmId) {
KeycloakSession session = server.getSessionFactory().create();
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
RealmManager manager = new RealmManager(session);
@@ -141,7 +141,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
configurer.session = session;
configurer.config(manager, adminstrationRealm, appRealm);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} finally {
session.close();
}
@@ -221,7 +221,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
protected void removeTestRealms() {
KeycloakSession session = server.getSessionFactory().create();
try {
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
RealmManager realmManager = new RealmManager(session);
for (String realmName : getTestRealms()) {
RealmModel realm = realmManager.getRealmByName(realmName);
@@ -229,7 +229,7 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
realmManager.removeRealm(realm);
}
}
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} finally {
session.close();
}
@@ -248,12 +248,12 @@ public abstract class AbstractKeycloakRule extends ExternalResource {
public KeycloakSession startSession() {
KeycloakSession session = server.getSessionFactory().create();
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
return session;
}
public void stopSession(KeycloakSession session, boolean commit) {
- KeycloakTransaction transaction = session.getTransaction();
+ KeycloakTransaction transaction = session.getTransactionManager();
if (commit && !transaction.getRollbackOnly()) {
transaction.commit();
} else {
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
index 8e48177..050bcf3 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/rule/KeycloakRule.java
@@ -58,7 +58,7 @@ public class KeycloakRule extends AbstractKeycloakRule {
public void configure(KeycloakSetup configurer) {
KeycloakSession session = server.getSessionFactory().create();
- session.getTransaction().begin();
+ session.getTransactionManager().begin();
try {
RealmManager manager = new RealmManager(session);
@@ -70,7 +70,7 @@ public class KeycloakRule extends AbstractKeycloakRule {
configurer.session = session;
configurer.config(manager, adminstrationRealm, appRealm);
- session.getTransaction().commit();
+ session.getTransactionManager().commit();
} finally {
session.close();
}