component model
This commit is contained in:
parent
3b3368eead
commit
09693eb108
92 changed files with 2097 additions and 1044 deletions
101
core/src/main/java/org/keycloak/representations/idm/ComponentRepresentation.java
Executable file
101
core/src/main/java/org/keycloak/representations/idm/ComponentRepresentation.java
Executable file
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -15,20 +15,36 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.models.entities;
|
||||
package org.keycloak.representations.idm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class StorageProviderEntity extends AbstractIdentifiableEntity {
|
||||
protected String providerName;
|
||||
protected Map<String, String> config;
|
||||
protected int priority;
|
||||
protected String displayName;
|
||||
public class StorageProviderRepresentation {
|
||||
|
||||
private String id;
|
||||
private String displayName;
|
||||
private String providerName;
|
||||
private Map<String, String> config;
|
||||
private int priority;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getProviderName() {
|
||||
return providerName;
|
||||
|
@ -38,6 +54,7 @@ public class StorageProviderEntity extends AbstractIdentifiableEntity {
|
|||
this.providerName = providerName;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
@ -54,12 +71,20 @@ public class StorageProviderEntity extends AbstractIdentifiableEntity {
|
|||
this.priority = priority;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
StorageProviderRepresentation that = (StorageProviderRepresentation) o;
|
||||
|
||||
if (!id.equals(that.id)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,5 +37,6 @@
|
|||
<module>authenticator</module>
|
||||
<module>rest</module>
|
||||
<module>domain-extension</module>
|
||||
<module>user-storage-jpa</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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>
|
|
@ -0,0 +1 @@
|
|||
org.keycloak.examples.storage.user.ExampleUserStorageProviderFactory
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -746,48 +745,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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,20 +14,29 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.changeset;
|
||||
package org.keycloak.connections.jpa;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserCredentialModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
|
||||
import java.util.List;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataCredentialValidator {
|
||||
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
||||
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input);
|
||||
public class JndiEntityManagerLookup {
|
||||
public static EntityManager getSessionEntityManager(KeycloakSession session, String entityManagerFactoryJndiName) {
|
||||
EntityManagerFactory factory = null;
|
||||
try {
|
||||
factory = (EntityManagerFactory)new InitialContext().lookup(entityManagerFactoryJndiName);
|
||||
} catch (NamingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
EntityManager em = factory.createEntityManager();
|
||||
session.getTransactionManager().enlist(new JpaKeycloakTransaction(em));
|
||||
return em;
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -1003,179 +1002,6 @@ public class RealmAdapter implements RealmModel, JpaModel<RealmEntity> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@ package org.keycloak.models.jpa.entities;
|
|||
|
||||
import javax.persistence.Access;
|
||||
import javax.persistence.AccessType;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.CollectionTable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.ElementCollection;
|
||||
|
@ -28,16 +29,28 @@ import javax.persistence.Id;
|
|||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.MapKeyColumn;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
|
||||
*/
|
||||
@NamedQueries({
|
||||
@NamedQuery(name="getComponents", query="select attr from ComponentEntity attr where attr.realm = :realm"),
|
||||
@NamedQuery(name="getComponentsByParentAndType", query="select attr from ComponentEntity attr where attr.realm = :realm and attr.providerType = :providerType and attr.parentId = :parentId"),
|
||||
@NamedQuery(name="getComponentIdsByParent", query="select attr.id from ComponentEntity attr where attr.realm = :realm and attr.parentId = :parentId"),
|
||||
@NamedQuery(name="deleteComponentByRealm", query="delete from ComponentEntity c where c.realm = :realm"),
|
||||
@NamedQuery(name="deleteComponentByParent", query="delete from ComponentEntity c where c.parentId = :parentId")
|
||||
})
|
||||
@Entity
|
||||
@Table(name="STORAGE_PROVIDER")
|
||||
public class StorageProviderEntity {
|
||||
@Table(name="COMPONENT")
|
||||
public class ComponentEntity {
|
||||
|
||||
@Id
|
||||
@Column(name="ID", length = 36)
|
||||
|
@ -48,19 +61,17 @@ public class StorageProviderEntity {
|
|||
@JoinColumn(name = "REALM_ID")
|
||||
protected RealmEntity realm;
|
||||
|
||||
@Column(name="PROVIDER_NAME")
|
||||
private String providerName;
|
||||
@Column(name="PRIORITY")
|
||||
private int priority;
|
||||
@Column(name="NAME")
|
||||
protected String name;
|
||||
|
||||
@ElementCollection
|
||||
@MapKeyColumn(name="name")
|
||||
@Column(name="VALUE")
|
||||
@CollectionTable(name="STORAGE_PROVIDER_CONFIG", joinColumns={ @JoinColumn(name="STORAGE_PROVIDER_ID") })
|
||||
private Map<String, String> config;
|
||||
@Column(name="PROVIDER_TYPE")
|
||||
protected String providerType;
|
||||
|
||||
@Column(name="DISPLAY_NAME")
|
||||
private String displayName;
|
||||
@Column(name="PROVIDER_ID")
|
||||
protected String providerId;
|
||||
|
||||
@Column(name="PARENT_ID")
|
||||
protected String parentId;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
|
@ -70,6 +81,38 @@ public class StorageProviderEntity {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getProviderType() {
|
||||
return providerType;
|
||||
}
|
||||
|
||||
public void setProviderType(String providerType) {
|
||||
this.providerType = providerType;
|
||||
}
|
||||
|
||||
public String getProviderId() {
|
||||
return providerId;
|
||||
}
|
||||
|
||||
public void setProviderId(String providerId) {
|
||||
this.providerId = providerId;
|
||||
}
|
||||
|
||||
public String getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(String parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public RealmEntity getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
@ -78,45 +121,13 @@ public class StorageProviderEntity {
|
|||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getProviderName() {
|
||||
return providerName;
|
||||
}
|
||||
|
||||
public void setProviderName(String providerName) {
|
||||
this.providerName = providerName;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, String> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
if (!(o instanceof StorageProviderEntity)) return false;
|
||||
if (!(o instanceof ComponentEntity)) return false;
|
||||
|
||||
StorageProviderEntity that = (StorageProviderEntity) o;
|
||||
ComponentEntity that = (ComponentEntity) o;
|
||||
|
||||
if (!id.equals(that.getId())) return false;
|
||||
|
|
@ -144,9 +144,6 @@ public class RealmEntity {
|
|||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "realm")
|
||||
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>();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="VALUE" type="VARCHAR(255)"/>
|
||||
<column name="NAME" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<createTable tableName="STORAGE_PROVIDER">
|
||||
<createTable tableName="COMPONENT_CONFIG">
|
||||
<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="COMPONENT_ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="NAME" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="VALUE" type="VARCHAR(4096)"/>
|
||||
</createTable>
|
||||
<createTable tableName="COMPONENT">
|
||||
<column name="ID" type="VARCHAR(36)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<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>
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -142,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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -1170,166 +1170,6 @@ public class RealmAdapter extends AbstractMongoAdapter<MongoRealmEntity> impleme
|
|||
updateRealm();
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,41 +14,30 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.storage;
|
||||
package org.keycloak.component;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.provider.ConfiguredProvider;
|
||||
import org.keycloak.provider.Provider;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
import org.keycloak.provider.ProviderFactory;
|
||||
import org.keycloak.storage.UserStorageProviderModel;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface StorageProviderFactory<T extends StorageProvider> extends ProviderFactory<StorageProvider> {
|
||||
/**
|
||||
* called per Keycloak transaction.
|
||||
*
|
||||
* @param session
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
T getInstance(KeycloakSession session, StorageProviderModel model);
|
||||
public interface ComponentFactory<CreatedType, ProviderType extends Provider> extends ProviderFactory<ProviderType>, ConfiguredProvider {
|
||||
CreatedType create(KeycloakSession session, ComponentModel model);
|
||||
|
||||
/**
|
||||
* This is the name of the provider and will be showed in the admin console as an option.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
String getId();
|
||||
default ProviderType create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
void validateConfiguration(KeycloakSession session, ComponentModel config) throws ComponentValidationException;
|
||||
|
||||
/**
|
||||
* This method is never called and is only an artifact of ProviderFactory. Returning null with no implementation is recommended.
|
||||
* @param session
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
StorageProvider create(KeycloakSession session);
|
||||
}
|
101
server-spi/src/main/java/org/keycloak/component/ComponentModel.java
Executable file
101
server-spi/src/main/java/org/keycloak/component/ComponentModel.java
Executable file
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -14,26 +14,29 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage;
|
||||
|
||||
import org.keycloak.models.ClientModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.provider.Provider;
|
||||
package org.keycloak.component;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface StorageProvider extends Provider {
|
||||
public class ComponentValidationException extends RuntimeException {
|
||||
public ComponentValidationException() {
|
||||
}
|
||||
|
||||
void preRemove(RealmModel realm);
|
||||
void preRemove(RealmModel realm, GroupModel group);
|
||||
void preRemove(RealmModel realm, RoleModel role);
|
||||
void preRemove(RealmModel realm, StorageProviderModel model);
|
||||
public ComponentValidationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ComponentValidationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ComponentValidationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public ComponentValidationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,18 +14,14 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.storage.changeset;
|
||||
package org.keycloak.component;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.entities.UserEntity;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.provider.ConfiguredProvider;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataLookup {
|
||||
UserData getUserById(RealmModel realm, StorageId id);
|
||||
UserData getUserByUsername(RealmModel realm, String username);
|
||||
UserData getUserByEmail(RealmModel realm, String email);
|
||||
public interface ConfiguredComponent extends ConfiguredProvider {
|
||||
}
|
|
@ -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,22 +101,40 @@ 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.
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
@ -604,6 +599,11 @@ public class UserFederationManager implements UserProvider {
|
|||
return (result != null) ? result : CredentialValidationOutput.failed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preRemove(RealmModel realm, ComponentModel component) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
75
server-spi/src/main/java/org/keycloak/models/entities/ComponentEntity.java
Executable file
75
server-spi/src/main/java/org/keycloak/models/entities/ComponentEntity.java
Executable file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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.entities;
|
||||
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ComponentEntity extends AbstractIdentifiableEntity {
|
||||
protected String name;
|
||||
protected String providerType;
|
||||
protected String providerId;
|
||||
protected String parentId;
|
||||
protected Map<String, List<String>> config = new MultivaluedHashMap<>();
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getProviderType() {
|
||||
return providerType;
|
||||
}
|
||||
|
||||
public void setProviderType(String providerType) {
|
||||
this.providerType = providerType;
|
||||
}
|
||||
|
||||
public String getProviderId() {
|
||||
return providerId;
|
||||
}
|
||||
|
||||
public void setProviderId(String providerId) {
|
||||
this.providerId = providerId;
|
||||
}
|
||||
|
||||
public String getParentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
||||
public void setParentId(String parentId) {
|
||||
this.parentId = parentId;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, List<String>> config) {
|
||||
this.config = config;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -342,43 +341,6 @@ public final class KeycloakModelUtils {
|
|||
}
|
||||
// USER FEDERATION RELATED STUFF
|
||||
|
||||
/**
|
||||
* 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, 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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ 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;
|
||||
|
@ -62,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;
|
||||
|
@ -1618,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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* 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 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 StorageProviderModel implements Serializable {
|
||||
|
||||
public static Comparator<StorageProviderModel> comparator = new Comparator<StorageProviderModel>() {
|
||||
@Override
|
||||
public int compare(StorageProviderModel o1, StorageProviderModel o2) {
|
||||
return o1.priority - o2.priority;
|
||||
}
|
||||
};
|
||||
|
||||
private String id;
|
||||
private String providerName;
|
||||
private Map<String, String> config = new HashMap<String, String>();
|
||||
private int priority;
|
||||
private String displayName;
|
||||
|
||||
public StorageProviderModel() {}
|
||||
|
||||
public StorageProviderModel(String id, String providerName, Map<String, String> config, int priority, String displayName) {
|
||||
this.id = id;
|
||||
this.providerName = providerName;
|
||||
if (config != null) {
|
||||
this.config.putAll(config);
|
||||
}
|
||||
this.priority = priority;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getProviderName() {
|
||||
return providerName;
|
||||
}
|
||||
|
||||
public void setProviderName(String providerName) {
|
||||
this.providerName = providerName;
|
||||
}
|
||||
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void setConfig(Map<String, String> config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
public void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* 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.Config;
|
||||
import org.keycloak.component.ComponentFactory;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.component.ComponentValidationException;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.KeycloakSessionFactory;
|
||||
import org.keycloak.provider.ProviderConfigProperty;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserStorageProviderFactory<T extends UserStorageProvider> extends ComponentFactory<T, UserStorageProvider> {
|
||||
|
||||
|
||||
/**
|
||||
* called per Keycloak transaction.
|
||||
*
|
||||
* @param session
|
||||
* @param model
|
||||
* @return
|
||||
*/
|
||||
T create(KeycloakSession session, ComponentModel model);
|
||||
|
||||
/**
|
||||
* This is the name of the provider and will be showed in the admin console as an option.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
String getId();
|
||||
|
||||
@Override
|
||||
default void init(Config.Scope config) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
default void postInit(KeycloakSessionFactory factory) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
default void close() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
default String getHelpText() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
default List<ProviderConfigProperty> getConfigProperties() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
default void validateConfiguration(KeycloakSession session, ComponentModel config) throws ComponentValidationException {
|
||||
|
||||
}
|
||||
|
||||
}
|
62
server-spi/src/main/java/org/keycloak/storage/UserStorageProviderModel.java
Executable file
62
server-spi/src/main/java/org/keycloak/storage/UserStorageProviderModel.java
Executable file
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ import org.keycloak.provider.Spi;
|
|||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class StorageProviderSpi implements Spi {
|
||||
public class UserStorageProviderSpi implements Spi {
|
||||
|
||||
@Override
|
||||
public boolean isInternal() {
|
||||
|
@ -38,12 +38,12 @@ public class StorageProviderSpi implements Spi {
|
|||
|
||||
@Override
|
||||
public Class<? extends Provider> getProviderClass() {
|
||||
return StorageProvider.class;
|
||||
return UserStorageProvider.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||
return StorageProviderFactory.class;
|
||||
return UserStorageProviderFactory.class;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* 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.changeset;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.entities.UserEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataQuery {
|
||||
|
||||
// Service account is included for counts
|
||||
int getUsersCount(RealmModel realm);
|
||||
|
||||
List<UserData> getUsers(RealmModel realm);
|
||||
List<UserData> searchForUser(String search, RealmModel realm);
|
||||
List<UserData> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm);
|
||||
|
||||
List<UserData> getUsers(RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserData> searchForUser(String search, RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserData> searchForUserByAttributes(Map<String, String> attributes, RealmModel realm, int firstResult, int maxResults);
|
||||
|
||||
|
||||
|
||||
// Searching by UserModel.attribute (not property)
|
||||
List<UserData> searchForUserByUserAttribute(String attrName, String attrValue, RealmModel realm);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* 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.changeset;
|
||||
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.models.entities.UserEntity;
|
||||
import org.keycloak.storage.StorageId;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface UserDataStore {
|
||||
void updateUser(RealmModel realm, UserData user);
|
||||
void addUser(RealmModel realm, UserData user);
|
||||
boolean removeUser(RealmModel realm, StorageId store);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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,26 @@ 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());
|
||||
rep.setProperties(ModelToRepresentation.toRepresentation(configured.getConfigProperties()));
|
||||
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 +239,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
@ -94,12 +99,6 @@ public class UserMapStorage implements UserLookupProvider, StorageProvider, User
|
|||
return null;
|
||||
}
|
||||
|
||||
@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, "");
|
||||
|
@ -131,11 +130,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) {
|
||||
|
@ -151,6 +145,7 @@ public class UserMapStorage implements UserLookupProvider, StorageProvider, User
|
|||
|
||||
@Override
|
||||
public void close() {
|
||||
closings.incrementAndGet();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -49,11 +46,6 @@ public class UserMapStorageFactory implements StorageProviderFactory<UserMapStor
|
|||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -116,11 +115,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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -55,11 +50,6 @@ public class UserPropertyFileStorageFactory implements StorageProviderFactory<Us
|
|||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StorageProvider create(KeycloakSession session) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.junit.ClassRule;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.models.GroupModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
|
@ -30,7 +31,7 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.models.cache.infinispan.UserAdapter;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.StorageProviderModel;
|
||||
import org.keycloak.storage.UserStorageProviderModel;
|
||||
import org.keycloak.testsuite.OAuthClient;
|
||||
import org.keycloak.testsuite.pages.AppPage;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
|
@ -47,31 +48,35 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class UserFederationStorageTest {
|
||||
public static StorageProviderModel memoryProvider = null;
|
||||
public class UserStorageTest {
|
||||
public static ComponentModel memoryProvider = null;
|
||||
@ClassRule
|
||||
public static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
|
||||
|
||||
@Override
|
||||
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||
StorageProviderModel model = new StorageProviderModel();
|
||||
model.setDisplayName("memory");
|
||||
UserStorageProviderModel model = new UserStorageProviderModel();
|
||||
model.setName("memory");
|
||||
model.setPriority(0);
|
||||
model.setProviderName(UserMapStorageFactory.PROVIDER_ID);
|
||||
memoryProvider = appRealm.addStorageProvider(model);
|
||||
model = new StorageProviderModel();
|
||||
model.setDisplayName("read-only-user-props");
|
||||
model.setProviderId(UserMapStorageFactory.PROVIDER_ID);
|
||||
model.setParentId(appRealm.getId());
|
||||
memoryProvider = appRealm.addComponentModel(model);
|
||||
|
||||
model = new UserStorageProviderModel();
|
||||
model.setName("read-only-user-props");
|
||||
model.setPriority(1);
|
||||
model.setProviderName(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
model.getConfig().put("property.file", "/storage-test/read-only-user-password.properties");
|
||||
appRealm.addStorageProvider(model);
|
||||
model = new StorageProviderModel();
|
||||
model.setDisplayName("user-props");
|
||||
model.setProviderId(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
model.setParentId(appRealm.getId());
|
||||
model.getConfig().putSingle("property.file", "/storage-test/read-only-user-password.properties");
|
||||
appRealm.addComponentModel(model);
|
||||
model = new UserStorageProviderModel();
|
||||
model.setName("user-props");
|
||||
model.setPriority(2);
|
||||
model.setProviderName(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
model.getConfig().put("property.file", "/storage-test/user-password.properties");
|
||||
model.getConfig().put("USER_FEDERATED_STORAGE", "true");
|
||||
appRealm.addStorageProvider(model);
|
||||
model.setParentId(appRealm.getId());
|
||||
model.setProviderId(UserPropertyFileStorageFactory.PROVIDER_ID);
|
||||
model.getConfig().putSingle("property.file", "/storage-test/user-password.properties");
|
||||
model.getConfig().putSingle("USER_FEDERATED_STORAGE", "true");
|
||||
appRealm.addComponentModel(model);
|
||||
}
|
||||
});
|
||||
@Rule
|
||||
|
@ -265,4 +270,27 @@ public class UserFederationStorageTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
UserMapStorage.allocations.set(0);
|
||||
UserMapStorage.closings.set(0);
|
||||
KeycloakSession session = keycloakRule.startSession();
|
||||
RealmModel realm = session.realms().getRealmByName("test");
|
||||
UserModel user = session.users().addUser(realm, "memuser");
|
||||
Assert.assertNotNull(user);
|
||||
user = session.users().getUserByUsername("nonexistent", realm);
|
||||
Assert.assertNull(user);
|
||||
keycloakRule.stopSession(session, true);
|
||||
Assert.assertEquals(1, UserMapStorage.allocations.get());
|
||||
Assert.assertEquals(1, UserMapStorage.closings.get());
|
||||
|
||||
session = keycloakRule.startSession();
|
||||
realm = session.realms().getRealmByName("test");
|
||||
user = session.users().getUserByUsername("memuser", realm);
|
||||
session.users().removeUser(realm, user);
|
||||
Assert.assertNull(session.users().getUserByUsername("memuser", realm));
|
||||
keycloakRule.stopSession(session, true);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
Assert.assertTrue(session.getTransactionManager().isActive());
|
||||
session.getTransactionManager().commit();
|
||||
Assert.assertFalse(session.getTransactionManager().isActive());
|
||||
|
||||
session.getTransaction().begin();
|
||||
Assert.assertTrue(session.getTransaction().isActive());
|
||||
session.getTransaction().rollback();
|
||||
Assert.assertFalse(session.getTransaction().isActive());
|
||||
session.getTransactionManager().begin();
|
||||
Assert.assertTrue(session.getTransactionManager().isActive());
|
||||
session.getTransactionManager().rollback();
|
||||
Assert.assertFalse(session.getTransactionManager().isActive());
|
||||
|
||||
session.close();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue