From a923f446192cf092ca7f5b16b933e9e89e9b9e8a Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Fri, 15 Nov 2013 16:38:28 +0000 Subject: [PATCH] KEYCLOAK-100 UI: Delete User does not work --- .../java/org/keycloak/models/RealmModel.java | 2 ++ .../org/keycloak/models/jpa/RealmAdapter.java | 20 +++++++++++++ .../models/jpa/entities/UserEntity.java | 6 +++- .../models/picketlink/RealmAdapter.java | 10 +++++++ .../resources/admin/UsersResource.java | 7 +++++ .../java/org/keycloak/test/AdapterTest.java | 30 +++++++++++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) diff --git a/model/api/src/main/java/org/keycloak/models/RealmModel.java b/model/api/src/main/java/org/keycloak/models/RealmModel.java index 3b0b14913e..724d3b5198 100755 --- a/model/api/src/main/java/org/keycloak/models/RealmModel.java +++ b/model/api/src/main/java/org/keycloak/models/RealmModel.java @@ -84,6 +84,8 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa UserModel addUser(String username); + boolean deleteUser(String name); + List getDefaultRoles(); void addDefaultRole(String name); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index 416d5eb8b5..0d4813a76d 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -11,6 +11,7 @@ import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.models.jpa.entities.ApplicationEntity; +import org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity; import org.keycloak.models.jpa.entities.CredentialEntity; import org.keycloak.models.jpa.entities.OAuthClientEntity; import org.keycloak.models.jpa.entities.RealmEntity; @@ -456,6 +457,25 @@ public class RealmAdapter implements RealmModel { return new UserAdapter(entity); } + @Override + public boolean deleteUser(String name) { + TypedQuery query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class); + query.setParameter("loginName", name); + query.setParameter("realm", realm); + List results = query.getResultList(); + if (results.size() == 0) return false; + + UserEntity user = results.get(0); + + for (Class r : UserEntity.RELATIONSHIPS) { + em.createQuery("delete from " + r.getSimpleName() + " where user = :user").setParameter("user", user).executeUpdate(); + } + + em.remove(user); + + return true; + } + @Override public List getDefaultRoles() { Collection entities = realm.getDefaultRoles(); diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java index d9c3a68afe..90d3341eee 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/entities/UserEntity.java @@ -2,6 +2,7 @@ package org.keycloak.models.jpa.entities; import org.keycloak.models.UserModel; +import javax.persistence.CascadeType; import javax.persistence.CollectionTable; import javax.persistence.Column; import javax.persistence.ElementCollection; @@ -33,6 +34,9 @@ import java.util.Set; }) @Entity public class UserEntity { + + public static final Class[] RELATIONSHIPS = new Class[] { ApplicationUserRoleMappingEntity.class, RealmUserRoleMappingEntity.class, SocialLinkEntity.class }; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected String id; @@ -66,7 +70,7 @@ public class UserEntity { @CollectionTable protected Set redirectUris = new HashSet(); - @OneToMany + @OneToMany(cascade = CascadeType.REMOVE, orphanRemoval = true) protected Collection credentials = new ArrayList(); public String getId() { diff --git a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java index 3279abf8da..83a60474fb 100755 --- a/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java +++ b/model/picketlink/src/main/java/org/keycloak/models/picketlink/RealmAdapter.java @@ -518,6 +518,16 @@ public class RealmAdapter implements RealmModel { return new UserAdapter(user, getIdm()); } + @Override + public boolean deleteUser(String name) { + User user = findPicketlinkUser(name); + if (user == null) { + return false; + } + getIdm().remove(user); + return true; + } + @Override public RoleAdapter getRole(String name) { Role role = SampleModel.getRole(getIdm(), name); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java index 830fef1fee..2f506b113b 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java @@ -107,6 +107,13 @@ public class UsersResource { return new RealmManager(session).toRepresentation(user); } + @Path("{username}") + @DELETE + @NoCache + public void deleteUser(final @PathParam("username") String username) { + realm.deleteUser(username); + } + @GET @NoCache @Produces("application/json") diff --git a/services/src/test/java/org/keycloak/test/AdapterTest.java b/services/src/test/java/org/keycloak/test/AdapterTest.java index 4810aa28a5..ce44f4c479 100755 --- a/services/src/test/java/org/keycloak/test/AdapterTest.java +++ b/services/src/test/java/org/keycloak/test/AdapterTest.java @@ -4,11 +4,13 @@ import org.junit.Assert; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; +import org.keycloak.models.ApplicationModel; import org.keycloak.models.Constants; import org.keycloak.models.OAuthClientModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RequiredCredentialModel; import org.keycloak.models.RoleModel; +import org.keycloak.models.SocialLinkModel; import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserModel; import org.keycloak.representations.idm.CredentialRepresentation; @@ -173,6 +175,34 @@ public class AdapterTest extends AbstractKeycloakTest { } + @Test + public void deleteUser() throws Exception { + test1CreateRealm(); + + UserModel user = realmModel.addUser("bburke"); + user.setAttribute("attr1", "val1"); + user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD); + + RoleModel testRole = realmModel.addRole("test"); + realmModel.grantRole(user, testRole); + + ApplicationModel app = realmModel.addApplication("test-app"); + RoleModel appRole = app.addRole("test"); + app.grantRole(user, appRole); + + SocialLinkModel socialLink = new SocialLinkModel("google", user.getLoginName()); + realmModel.addSocialLink(user, socialLink); + + UserCredentialModel cred = new UserCredentialModel(); + cred.setType(CredentialRepresentation.PASSWORD); + cred.setValue("password"); + realmModel.updateCredential(user, cred); + + Assert.assertTrue(realmModel.deleteUser("bburke")); + Assert.assertFalse(realmModel.deleteUser("bburke")); + Assert.assertNull(realmModel.getUser("bburke")); + } + @Test public void testUserSearch() throws Exception { test1CreateRealm();