From 3f8b1c8e7096d3c42e3c8f9c54bbfbd7a2c30818 Mon Sep 17 00:00:00 2001 From: Alexander Schwartz Date: Tue, 17 Feb 2026 11:32:57 +0100 Subject: [PATCH] Optimize user joining group or role Closes #45689 Signed-off-by: Alexander Schwartz --- .../org/keycloak/models/jpa/UserAdapter.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java index 6254fc4ecb0..1c247e48603 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java @@ -442,9 +442,21 @@ public class UserAdapter implements UserModel, JpaModel { joinGroup(group, null); } + private boolean hasDirectGroup(GroupModel group) { + UserGroupMembershipEntity membership = em.createNamedQuery("userMemberOf", UserGroupMembershipEntity.class) + .setParameter("user", user) + .setParameter("groupId", group.getId()) + .getSingleResultOrNull(); + // Avoid keeping it in the persistence context, as the user might be detached for example in a bulk delete + if (membership != null) { + em.detach(membership); + } + return membership != null; + } + @Override public void joinGroup(GroupModel group, MembershipMetadata metadata) { - if (RoleUtils.isDirectMember(getGroupsStream(), group)) return; + if (hasDirectGroup(group)) return; joinGroupImpl(group, metadata); } @@ -513,6 +525,19 @@ public class UserAdapter implements UserModel, JpaModel { RoleGrantedEvent.fire(role, this, session); } + @Override + public boolean hasDirectRole(RoleModel role) { + UserRoleMappingEntity membership = em.createNamedQuery("userHasRole", UserRoleMappingEntity.class) + .setParameter("user", user) + .setParameter("roleId", role.getId()) + .getSingleResultOrNull(); + // Avoid keeping it in the persistence context, as the user might be detached for example in a bulk delete + if (membership != null) { + em.detach(membership); + } + return membership != null; + } + public void grantRoleImpl(RoleModel role) { UserRoleMappingEntity entity = new UserRoleMappingEntity(); entity.setUser(getEntity());