package org.keycloak.models.users.jpa;
import org.keycloak.models.KeycloakTransaction;
import org.keycloak.models.users.Credentials;
import org.keycloak.models.users.Feature;
import org.keycloak.models.users.User;
import org.keycloak.models.users.UserProvider;
import org.keycloak.models.users.jpa.entities.UserEntity;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class JpaUserProvider implements UserProvider {
protected final EntityManager em;
public JpaUserProvider(EntityManager em) {
this.em = PersistenceExceptionConverter.create(em);
}
@Override
public KeycloakTransaction getTransaction() {
return new JpaKeycloakTransaction(em);
}
@Override
public User addUser(String id, String username, Set<String> initialRoles, String realm) {
UserEntity entity = new UserEntity();
entity.setId(id);
entity.setUsername(username);
entity.setEmailConstraint(id);
entity.setRealm(realm);
em.persist(entity);
UserAdapter adapter = new UserAdapter(realm, em, entity);
if (initialRoles != null && !initialRoles.isEmpty()) {
for (String role : initialRoles) {
adapter.grantRole(role);
}
}
return adapter;
}
@Override
public boolean removeUser(String name, String realm) {
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
query.setParameter("username", name);
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
if (results.size() == 0) return false;
em.remove(results.get(0));
return true;
}
@Override
public User getUserById(String id, String realm) {
UserEntity user = em.find(UserEntity.class, new UserEntity.Key(id, realm));
return user != null ? new UserAdapter(realm, em, user) : null;
}
@Override
public User getUserByUsername(String username, String realm) {
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByUsername", UserEntity.class);
query.setParameter("username", username);
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
if (results.size() == 0) return null;
return new UserAdapter(realm, em, results.get(0));
}
@Override
public User getUserByEmail(String email, String realm) {
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByEmail", UserEntity.class);
query.setParameter("email", email);
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
return results.isEmpty() ? null : new UserAdapter(realm, em, results.get(0));
}
@Override
public User getUserByAttribute(String name, String value, String realm) {
List<UserEntity> results = em.createNamedQuery("getRealmUserByAttribute", UserEntity.class)
.setParameter("realm", realm)
.setParameter("name", name)
.setParameter("value", value)
.getResultList();
return results.isEmpty() ? null : new UserAdapter(realm, em, results.get(0));
}
@Override
public void close() {
if (em.getTransaction().isActive()) em.getTransaction().rollback();
if (em.isOpen()) em.close();
}
@Override
public List<User> getUsers(String realm) {
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class);
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
List<User> users = new ArrayList<User>();
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
return users;
}
@Override
public List<User> searchForUser(String search, String realm) {
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm and ( lower(u.username) like :search or lower(concat(u.firstName, ' ', u.lastName)) like :search or u.email like :search )", UserEntity.class);
query.setParameter("realm", realm);
query.setParameter("search", "%" + search.toLowerCase() + "%");
List<UserEntity> results = query.getResultList();
List<User> users = new ArrayList<User>();
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
return users;
}
@Override
public List<User> searchForUserByAttributes(Map<String, String> attributes, String realm) {
StringBuilder builder = new StringBuilder("select u from UserEntity u");
boolean first = true;
for (Map.Entry<String, String> entry : attributes.entrySet()) {
String attribute = null;
if (entry.getKey().equals(User.USERNAME)) {
attribute = "lower(username)";
} else if (entry.getKey().equalsIgnoreCase(User.FIRST_NAME)) {
attribute = "lower(firstName)";
} else if (entry.getKey().equalsIgnoreCase(User.LAST_NAME)) {
attribute = "lower(lastName)";
} else if (entry.getKey().equalsIgnoreCase(User.EMAIL)) {
attribute = "lower(email)";
}
if (attribute == null) continue;
if (first) {
first = false;
builder.append(" where realm = :realm");
} else {
builder.append(" and ");
}
builder.append(attribute).append(" like '%").append(entry.getValue().toLowerCase()).append("%'");
}
String q = builder.toString();
TypedQuery<UserEntity> query = em.createQuery(q, UserEntity.class);
query.setParameter("realm", realm);
List<UserEntity> results = query.getResultList();
List<User> users = new ArrayList<User>();
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
return users;
}
@Override
public boolean supports(Feature feature) {
return (feature == Feature.READ_CREDENTIALS || feature == Feature.UPDATE_CREDENTIALS);
}
@Override
public boolean verifyCredentials(User user, Credentials... credentials) {
return false;
}
@Override
public void onRealmRemoved(String realm) {
TypedQuery<UserEntity> query = em.createQuery("select u from UserEntity u where u.realm = :realm", UserEntity.class);
query.setParameter("realm", realm);
for (UserEntity u : query.getResultList()) {
em.remove(u);
}
}
@Override
public void onRoleRemoved(String role) {
em.createQuery("delete from RoleEntity r where r.role = :role").setParameter("role", role).executeUpdate();
}
}