From 55cd06fe321852ad2bf1c67062d07f2d0595c1e0 Mon Sep 17 00:00:00 2001 From: Boubaker Khanfir Date: Sun, 15 Sep 2024 09:52:23 +0100 Subject: [PATCH] fix: Update IdentityRegistry identities when memberships changes - MEED-7488 - Meeds-io/MIPs#147 Prior to this change, when the user memberships are updated, the list of memberships stored in Identity Registry isn't updated. This change adds a new Listener to update authenticated and registered user identities right after updating their roles. --- .../IdentityRegistryMembershipListener.java | 62 +++++++++++++++++++ .../mock/InMemoryMembershipHandler.java | 13 ++-- ...ortal.component.identity-configuration.xml | 10 +++ .../organization-configuration.xml | 6 ++ 4 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 component/identity/src/main/java/io/meeds/services/organization/listener/IdentityRegistryMembershipListener.java diff --git a/component/identity/src/main/java/io/meeds/services/organization/listener/IdentityRegistryMembershipListener.java b/component/identity/src/main/java/io/meeds/services/organization/listener/IdentityRegistryMembershipListener.java new file mode 100644 index 0000000000..05de9c0599 --- /dev/null +++ b/component/identity/src/main/java/io/meeds/services/organization/listener/IdentityRegistryMembershipListener.java @@ -0,0 +1,62 @@ +/** + * This file is part of the Meeds project (https://meeds.io/). + * + * Copyright (C) 2020 - 2024 Meeds Association contact@meeds.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package io.meeds.services.organization.listener; + +import java.util.Objects; + +import org.exoplatform.services.organization.Membership; +import org.exoplatform.services.organization.MembershipEventListener; +import org.exoplatform.services.security.Identity; +import org.exoplatform.services.security.IdentityRegistry; +import org.exoplatform.services.security.MembershipEntry; + +public class IdentityRegistryMembershipListener extends MembershipEventListener { + + private IdentityRegistry identityRegistry; + + public IdentityRegistryMembershipListener(IdentityRegistry identityRegistry) { + this.identityRegistry = identityRegistry; + } + + @Override + public void postDelete(Membership membership) throws Exception { + Identity identity = identityRegistry.getIdentity(membership.getUserName()); + if (identity != null) { + MembershipEntry membershipEntry = toMembershipEntry(membership); + identity.getMemberships() + .removeIf(m -> Objects.equals(m, membershipEntry)); + } + } + + @Override + public void postSave(Membership membership, boolean isNew) throws Exception { + Identity identity = identityRegistry.getIdentity(membership.getUserName()); + if (identity != null) { + MembershipEntry membershipEntry = toMembershipEntry(membership); + if (identity.getMemberships().stream().noneMatch(m -> m.equals(membershipEntry))) { + identity.getMemberships().add(membershipEntry); + } + } + } + + private MembershipEntry toMembershipEntry(Membership membership) { + return new MembershipEntry(membership.getGroupId(), membership.getMembershipType()); + } + +} diff --git a/component/identity/src/test/java/org/exoplatform/services/organization/mock/InMemoryMembershipHandler.java b/component/identity/src/test/java/org/exoplatform/services/organization/mock/InMemoryMembershipHandler.java index 45cd20c372..7468b98c37 100644 --- a/component/identity/src/test/java/org/exoplatform/services/organization/mock/InMemoryMembershipHandler.java +++ b/component/identity/src/test/java/org/exoplatform/services/organization/mock/InMemoryMembershipHandler.java @@ -16,7 +16,6 @@ package org.exoplatform.services.organization.mock; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -90,7 +89,7 @@ public Membership removeMembership(String membershipId, boolean broadcast) { public List removeMembershipByUser(String userName, boolean broadcast) { List memberships = userMemberships.compute(userName, (key, - existingMemberships) -> existingMemberships == null ? Collections.emptyList() + existingMemberships) -> existingMemberships == null ? new ArrayList<>() : new ArrayList<>(existingMemberships)); removeMemberships(memberships, broadcast); return memberships; @@ -99,7 +98,7 @@ public List removeMembershipByUser(String userName, boolean broadcas public List removeMembershipByGroup(String groupId, boolean broadcast) { List memberships = groupMemberships.compute(groupId, (key, - existingMemberships) -> existingMemberships == null ? Collections.emptyList() + existingMemberships) -> existingMemberships == null ? new ArrayList<>() : new ArrayList<>(existingMemberships)); removeMemberships(memberships, broadcast); return memberships; @@ -108,7 +107,7 @@ public List removeMembershipByGroup(String groupId, boolean broadcas public List removeMembershipByMembershipType(String membershipType, boolean broadcast) { List memberships = membershipTypeMemberships.compute(membershipType, (key, - existingMemberships) -> existingMemberships == null ? Collections.emptyList() + existingMemberships) -> existingMemberships == null ? new ArrayList<>() : new ArrayList<>(existingMemberships)); removeMemberships(memberships, broadcast); return memberships; @@ -142,7 +141,7 @@ public List findMembershipsByUserAndGroup(String userName, String gr @Override public List findMembershipsByUser(String userName) { - return userMemberships.computeIfAbsent(userName, key -> Collections.emptyList()); + return userMemberships.computeIfAbsent(userName, key -> new ArrayList<>()); } @Override @@ -152,11 +151,11 @@ public ListAccess findAllMembershipsByUser(User user) { @Override public List findMembershipsByGroup(Group group) { - return groupMemberships.computeIfAbsent(group.getId(), key -> Collections.emptyList()); + return groupMemberships.computeIfAbsent(group.getId(), key -> new ArrayList<>()); } public List findMembershipsByGroupId(String groupId) { - return groupMemberships.computeIfAbsent(groupId, key -> Collections.emptyList()); + return groupMemberships.computeIfAbsent(groupId, key -> new ArrayList<>()); } @Override diff --git a/component/identity/src/test/resources/conf/exo.portal.component.identity-configuration.xml b/component/identity/src/test/resources/conf/exo.portal.component.identity-configuration.xml index b791f55640..adfd8763a6 100644 --- a/component/identity/src/test/resources/conf/exo.portal.component.identity-configuration.xml +++ b/component/identity/src/test/resources/conf/exo.portal.component.identity-configuration.xml @@ -303,6 +303,16 @@ + + MembershipUpdateListener + addListenerPlugin + org.exoplatform.services.organization.impl.MembershipUpdateListener + + + MembershipUpdateListener + addListenerPlugin + io.meeds.services.organization.listener.IdentityRegistryMembershipListener + diff --git a/web/portal/src/main/webapp/WEB-INF/conf/organization/organization-configuration.xml b/web/portal/src/main/webapp/WEB-INF/conf/organization/organization-configuration.xml index e910a73654..2f6bcb3c86 100644 --- a/web/portal/src/main/webapp/WEB-INF/conf/organization/organization-configuration.xml +++ b/web/portal/src/main/webapp/WEB-INF/conf/organization/organization-configuration.xml @@ -331,5 +331,11 @@ addListenerPlugin org.exoplatform.services.organization.impl.MembershipUpdateListener + + + MembershipUpdateListener + addListenerPlugin + io.meeds.services.organization.listener.IdentityRegistryMembershipListener +