Refactor Scim Event listener
This commit is contained in:
parent
f81001503d
commit
2e992dad44
3 changed files with 35 additions and 26 deletions
|
@ -89,14 +89,6 @@ public abstract class AbstractScimService<RMM extends RoleMapperModel, S extends
|
||||||
|
|
||||||
protected abstract ResourceNode toScimForReplace(RMM roleMapperModel, EntityOnRemoteScimId externalId);
|
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) {
|
public void delete(KeycloakId id) {
|
||||||
try {
|
try {
|
||||||
ScimResource resource = findById(id).get();
|
ScimResource resource = findById(id).get();
|
||||||
|
|
|
@ -40,6 +40,11 @@ public class KeycloakDao {
|
||||||
return getKeycloakSession().users().getUserById(getRealm(), userId.asString());
|
return getKeycloakSession().users().getUserById(getRealm(), userId.asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GroupModel getGroupById(KeycloakId groupId) {
|
||||||
|
return getKeycloakSession().groups().getGroupById(getRealm(), groupId.asString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Stream<GroupModel> getGroupsStream() {
|
public Stream<GroupModel> getGroupsStream() {
|
||||||
return getKeycloakSession().groups().getGroupsStream(getRealm());
|
return getKeycloakSession().groups().getGroupsStream(getRealm());
|
||||||
}
|
}
|
||||||
|
@ -71,4 +76,6 @@ public class KeycloakDao {
|
||||||
public UserModel addUser(String username) {
|
public UserModel addUser(String username) {
|
||||||
return getKeycloakSession().users().addUser(getRealm(), username);
|
return getKeycloakSession().users().addUser(getRealm(), username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,10 @@ import org.keycloak.events.admin.ResourceType;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.UserModel;
|
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.ScimDispatcher;
|
||||||
|
import sh.libre.scim.core.ScimResourceType;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -30,6 +33,8 @@ public class ScimEventListenerProvider implements EventListenerProvider {
|
||||||
|
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
|
|
||||||
|
private final KeycloakDao keycloackDao;
|
||||||
|
|
||||||
private final Map<ResourceType, Pattern> patterns = Map.of(
|
private final Map<ResourceType, Pattern> patterns = Map.of(
|
||||||
ResourceType.USER, Pattern.compile("users/(.+)"),
|
ResourceType.USER, Pattern.compile("users/(.+)"),
|
||||||
ResourceType.GROUP, Pattern.compile("groups/([\\w-]+)(/children)?"),
|
ResourceType.GROUP, Pattern.compile("groups/([\\w-]+)(/children)?"),
|
||||||
|
@ -40,15 +45,15 @@ public class ScimEventListenerProvider implements EventListenerProvider {
|
||||||
|
|
||||||
public ScimEventListenerProvider(KeycloakSession session) {
|
public ScimEventListenerProvider(KeycloakSession session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
|
this.keycloackDao = new KeycloakDao(session);
|
||||||
this.dispatcher = ScimDispatcher.createForSession(session);
|
this.dispatcher = ScimDispatcher.createForSession(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(Event event) {
|
public void onEvent(Event event) {
|
||||||
// React to User-related event : creation, deletion, update
|
// React to User-related event : creation, deletion, update
|
||||||
EventType eventType = event.getType();
|
EventType eventType = event.getType();
|
||||||
String eventUserId = event.getUserId();
|
KeycloakId eventUserId = new KeycloakId(event.getUserId());
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case REGISTER -> {
|
case REGISTER -> {
|
||||||
LOGGER.infof("[SCIM] Propagate User Registration - %s", eventUserId);
|
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
|
// Step 2: propagate event (if needed) according to its resource type
|
||||||
switch (event.getResourceType()) {
|
switch (event.getResourceType()) {
|
||||||
case USER -> {
|
case USER -> {
|
||||||
String userId = matcher.group(1);
|
KeycloakId userId = new KeycloakId(matcher.group(1));
|
||||||
handleUserEvent(event, userId);
|
handleUserEvent(event, userId);
|
||||||
}
|
}
|
||||||
case GROUP -> {
|
case GROUP -> {
|
||||||
String groupId = matcher.group(1);
|
KeycloakId groupId = new KeycloakId(matcher.group(1));
|
||||||
handleGroupEvent(event, groupId);
|
handleGroupEvent(event, groupId);
|
||||||
}
|
}
|
||||||
case GROUP_MEMBERSHIP -> {
|
case GROUP_MEMBERSHIP -> {
|
||||||
String userId = matcher.group(1);
|
KeycloakId userId = new KeycloakId(matcher.group(1));
|
||||||
String groupId = matcher.group(2);
|
KeycloakId groupId = new KeycloakId(matcher.group(2));
|
||||||
handleGroupMemberShipEvent(event, userId, groupId);
|
handleGroupMemberShipEvent(event, userId, groupId);
|
||||||
}
|
}
|
||||||
case REALM_ROLE_MAPPING -> {
|
case REALM_ROLE_MAPPING -> {
|
||||||
String type = matcher.group(1);
|
String rawResourceType = matcher.group(1);
|
||||||
String id = matcher.group(2);
|
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);
|
handleRoleMappingEvent(event, type, id);
|
||||||
}
|
}
|
||||||
case COMPONENT -> {
|
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);
|
LOGGER.infof("[SCIM] Propagate User %s - %s", userEvent.getOperationType(), userId);
|
||||||
switch (userEvent.getOperationType()) {
|
switch (userEvent.getOperationType()) {
|
||||||
case CREATE -> {
|
case CREATE -> {
|
||||||
|
@ -141,7 +151,7 @@ public class ScimEventListenerProvider implements EventListenerProvider {
|
||||||
* @param event the event to propagate
|
* @param event the event to propagate
|
||||||
* @param groupId event target's id
|
* @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);
|
LOGGER.infof("[SCIM] Propagate Group %s - %s", event.getOperationType(), groupId);
|
||||||
switch (event.getOperationType()) {
|
switch (event.getOperationType()) {
|
||||||
case CREATE -> {
|
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);
|
LOGGER.infof("[SCIM] Propagate GroupMemberShip %s - User %s Group %s", groupMemberShipEvent.getOperationType(), userId, groupId);
|
||||||
GroupModel group = getGroup(groupId);
|
GroupModel group = getGroup(groupId);
|
||||||
group.setSingleAttribute("scim-dirty", BooleanUtils.TRUE);
|
group.setSingleAttribute("scim-dirty", BooleanUtils.TRUE);
|
||||||
|
@ -167,14 +177,14 @@ public class ScimEventListenerProvider implements EventListenerProvider {
|
||||||
dispatcher.dispatchUserModificationToAll(client -> client.replace(user));
|
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);
|
LOGGER.infof("[SCIM] Propagate RoleMapping %s - %s %s", roleMappingEvent.getOperationType(), type, id);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "users" -> {
|
case USER -> {
|
||||||
UserModel user = getUser(id);
|
UserModel user = getUser(id);
|
||||||
dispatcher.dispatchUserModificationToAll(client -> client.replace(user));
|
dispatcher.dispatchUserModificationToAll(client -> client.replace(user));
|
||||||
}
|
}
|
||||||
case "groups" -> {
|
case GROUP -> {
|
||||||
GroupModel group = getGroup(id);
|
GroupModel group = getGroup(id);
|
||||||
session.users()
|
session.users()
|
||||||
.getGroupMembersStream(session.getContext().getRealm(), group)
|
.getGroupMembersStream(session.getContext().getRealm(), group)
|
||||||
|
@ -208,12 +218,12 @@ public class ScimEventListenerProvider implements EventListenerProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private UserModel getUser(String id) {
|
private UserModel getUser(KeycloakId id) {
|
||||||
return session.users().getUserById(session.getContext().getRealm(), id);
|
return keycloackDao.getUserById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupModel getGroup(String id) {
|
private GroupModel getGroup(KeycloakId id) {
|
||||||
return session.groups().getGroupById(session.getContext().getRealm(), id);
|
return keycloackDao.getGroupById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue