diff --git a/src/main/java/sh/libre/scim/core/AbstractScimService.java b/src/main/java/sh/libre/scim/core/AbstractScimService.java index 11d6276084770ae16351d670a54270f8305b803c..e32f178977e3306e6669ca52dca1bcae0922b791 100644 --- a/src/main/java/sh/libre/scim/core/AbstractScimService.java +++ b/src/main/java/sh/libre/scim/core/AbstractScimService.java @@ -89,14 +89,6 @@ public abstract class AbstractScimService<RMM extends RoleMapperModel, S extends protected abstract ResourceNode toScimForReplace(RMM roleMapperModel, EntityOnRemoteScimId externalId); - /** - * @deprecated use {@link #delete(KeycloakId)} - */ - @Deprecated - public void delete(String id) { - delete(new KeycloakId(id)); - } - public void delete(KeycloakId id) { try { ScimResource resource = findById(id).get(); diff --git a/src/main/java/sh/libre/scim/core/KeycloakDao.java b/src/main/java/sh/libre/scim/core/KeycloakDao.java index 1062e03e703d1fe7f30f122905378acf46a2d92a..67f58da9f9ad5091190def3b4d9d5f163a99a82a 100644 --- a/src/main/java/sh/libre/scim/core/KeycloakDao.java +++ b/src/main/java/sh/libre/scim/core/KeycloakDao.java @@ -40,6 +40,11 @@ public class KeycloakDao { return getKeycloakSession().users().getUserById(getRealm(), userId.asString()); } + public GroupModel getGroupById(KeycloakId groupId) { + return getKeycloakSession().groups().getGroupById(getRealm(), groupId.asString()); + } + + public Stream<GroupModel> getGroupsStream() { return getKeycloakSession().groups().getGroupsStream(getRealm()); } @@ -71,4 +76,6 @@ public class KeycloakDao { public UserModel addUser(String username) { return getKeycloakSession().users().addUser(getRealm(), username); } + + } diff --git a/src/main/java/sh/libre/scim/event/ScimEventListenerProvider.java b/src/main/java/sh/libre/scim/event/ScimEventListenerProvider.java index 6463853843ae978189e661490ae630c7464a9615..0a57d5afca976ed7d6a99cbbf0ec008b797ef839 100644 --- a/src/main/java/sh/libre/scim/event/ScimEventListenerProvider.java +++ b/src/main/java/sh/libre/scim/event/ScimEventListenerProvider.java @@ -11,7 +11,10 @@ import org.keycloak.events.admin.ResourceType; import org.keycloak.models.GroupModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.UserModel; +import sh.libre.scim.core.KeycloakDao; +import sh.libre.scim.core.KeycloakId; import sh.libre.scim.core.ScimDispatcher; +import sh.libre.scim.core.ScimResourceType; import java.util.Map; import java.util.regex.Matcher; @@ -30,6 +33,8 @@ public class ScimEventListenerProvider implements EventListenerProvider { private final KeycloakSession session; + private final KeycloakDao keycloackDao; + private final Map<ResourceType, Pattern> patterns = Map.of( ResourceType.USER, Pattern.compile("users/(.+)"), ResourceType.GROUP, Pattern.compile("groups/([\\w-]+)(/children)?"), @@ -40,15 +45,15 @@ public class ScimEventListenerProvider implements EventListenerProvider { public ScimEventListenerProvider(KeycloakSession session) { this.session = session; + this.keycloackDao = new KeycloakDao(session); this.dispatcher = ScimDispatcher.createForSession(session); } - @Override public void onEvent(Event event) { // React to User-related event : creation, deletion, update EventType eventType = event.getType(); - String eventUserId = event.getUserId(); + KeycloakId eventUserId = new KeycloakId(event.getUserId()); switch (eventType) { case REGISTER -> { LOGGER.infof("[SCIM] Propagate User Registration - %s", eventUserId); @@ -85,21 +90,26 @@ public class ScimEventListenerProvider implements EventListenerProvider { // Step 2: propagate event (if needed) according to its resource type switch (event.getResourceType()) { case USER -> { - String userId = matcher.group(1); + KeycloakId userId = new KeycloakId(matcher.group(1)); handleUserEvent(event, userId); } case GROUP -> { - String groupId = matcher.group(1); + KeycloakId groupId = new KeycloakId(matcher.group(1)); handleGroupEvent(event, groupId); } case GROUP_MEMBERSHIP -> { - String userId = matcher.group(1); - String groupId = matcher.group(2); + KeycloakId userId = new KeycloakId(matcher.group(1)); + KeycloakId groupId = new KeycloakId(matcher.group(2)); handleGroupMemberShipEvent(event, userId, groupId); } case REALM_ROLE_MAPPING -> { - String type = matcher.group(1); - String id = matcher.group(2); + String rawResourceType = matcher.group(1); + ScimResourceType type = switch (rawResourceType) { + case "users" -> ScimResourceType.USER; + case "groups" -> ScimResourceType.GROUP; + default -> throw new IllegalArgumentException("Unsuported resource type : " + rawResourceType); + }; + KeycloakId id = new KeycloakId(matcher.group(2)); handleRoleMappingEvent(event, type, id); } case COMPONENT -> { @@ -114,7 +124,7 @@ public class ScimEventListenerProvider implements EventListenerProvider { } - private void handleUserEvent(AdminEvent userEvent, String userId) { + private void handleUserEvent(AdminEvent userEvent, KeycloakId userId) { LOGGER.infof("[SCIM] Propagate User %s - %s", userEvent.getOperationType(), userId); switch (userEvent.getOperationType()) { case CREATE -> { @@ -141,7 +151,7 @@ public class ScimEventListenerProvider implements EventListenerProvider { * @param event the event to propagate * @param groupId event target's id */ - private void handleGroupEvent(AdminEvent event, String groupId) { + private void handleGroupEvent(AdminEvent event, KeycloakId groupId) { LOGGER.infof("[SCIM] Propagate Group %s - %s", event.getOperationType(), groupId); switch (event.getOperationType()) { case CREATE -> { @@ -159,7 +169,7 @@ public class ScimEventListenerProvider implements EventListenerProvider { } } - private void handleGroupMemberShipEvent(AdminEvent groupMemberShipEvent, String userId, String groupId) { + private void handleGroupMemberShipEvent(AdminEvent groupMemberShipEvent, KeycloakId userId, KeycloakId groupId) { LOGGER.infof("[SCIM] Propagate GroupMemberShip %s - User %s Group %s", groupMemberShipEvent.getOperationType(), userId, groupId); GroupModel group = getGroup(groupId); group.setSingleAttribute("scim-dirty", BooleanUtils.TRUE); @@ -167,14 +177,14 @@ public class ScimEventListenerProvider implements EventListenerProvider { dispatcher.dispatchUserModificationToAll(client -> client.replace(user)); } - private void handleRoleMappingEvent(AdminEvent roleMappingEvent, String type, String id) { + private void handleRoleMappingEvent(AdminEvent roleMappingEvent, ScimResourceType type, KeycloakId id) { LOGGER.infof("[SCIM] Propagate RoleMapping %s - %s %s", roleMappingEvent.getOperationType(), type, id); switch (type) { - case "users" -> { + case USER -> { UserModel user = getUser(id); dispatcher.dispatchUserModificationToAll(client -> client.replace(user)); } - case "groups" -> { + case GROUP -> { GroupModel group = getGroup(id); session.users() .getGroupMembersStream(session.getContext().getRealm(), group) @@ -208,12 +218,12 @@ public class ScimEventListenerProvider implements EventListenerProvider { } - private UserModel getUser(String id) { - return session.users().getUserById(session.getContext().getRealm(), id); + private UserModel getUser(KeycloakId id) { + return keycloackDao.getUserById(id); } - private GroupModel getGroup(String id) { - return session.groups().getGroupById(session.getContext().getRealm(), id); + private GroupModel getGroup(KeycloakId id) { + return keycloackDao.getGroupById(id); } @Override