diff --git a/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/constant/OrgApplicationMgtConstants.java b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/constant/OrgApplicationMgtConstants.java index d31ed7254..2678dd5d8 100644 --- a/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/constant/OrgApplicationMgtConstants.java +++ b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/constant/OrgApplicationMgtConstants.java @@ -33,11 +33,13 @@ public class OrgApplicationMgtConstants { public static final String DELETE_MAIN_APPLICATION = "deleteMainApplication"; public static final String UPDATE_SP_METADATA_SHARE_WITH_ALL_CHILDREN = "updateShareWithAllChildren"; public static final String DELETE_SHARE_FOR_MAIN_APPLICATION = "deleteShareForMainApp"; + public static final String USER_CUSTOM_ATTRIBUTE_PROPERTY = "USER_CUSTOM_ATTRIBUTE"; public static final String USER_ORGANIZATION_CLAIM_URI = "http://wso2.org/claims/runtime/user_organization"; public static final String APP_ROLES_CLAIM_URI = "http://wso2.org/claims/applicationRoles"; public static final String USER_ORGANIZATION_CLAIM = "user_organization"; public static final String OIDC_CLAIM_DIALECT_URI = "http://wso2.org/oidc/claim"; + public static final String RUNTIME_CLAIM_URI_PREFIX = "http://wso2.org/claims/runtime/"; // Event constants related to shared application management. public static final String EVENT_PROP_PARENT_ORGANIZATION_ID = "PARENT_ORGANIZATION_ID"; @@ -47,6 +49,7 @@ public class OrgApplicationMgtConstants { public static final String EVENT_PROP_SHARED_APPLICATIONS_DATA = "SHARED_APPLICATIONS_DATA"; public static final String EVENT_PROP_SHARE_WITH_ALL_CHILDREN = "SHARE_WITH_ALL_CHILDREN"; public static final String EVENT_PROP_SHARED_ORGANIZATIONS = "SHARED_ORGANIZATIONS"; + public static final String EVENT_PROP_SHARED_USER_ATTRIBUTES = "SHARED_USER_ATTRIBUTES"; public static final String EVENT_PRE_SHARE_APPLICATION = "PRE_SHARE_APPLICATION"; public static final String EVENT_POST_SHARE_APPLICATION = "POST_SHARE_APPLICATION"; public static final String EVENT_PRE_DELETE_SHARED_APPLICATION = "PRE_DELETE_SHARED_APPLICATION"; diff --git a/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/handler/OrgClaimMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/handler/OrgClaimMgtHandler.java new file mode 100644 index 000000000..c7093cc8d --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/handler/OrgClaimMgtHandler.java @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.organization.management.application.handler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.common.model.ClaimMapping; +import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; +import org.wso2.carbon.identity.claim.metadata.mgt.exception.ClaimMetadataException; +import org.wso2.carbon.identity.claim.metadata.mgt.model.AttributeMapping; +import org.wso2.carbon.identity.claim.metadata.mgt.model.Claim; +import org.wso2.carbon.identity.claim.metadata.mgt.model.ExternalClaim; +import org.wso2.carbon.identity.claim.metadata.mgt.model.LocalClaim; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.event.IdentityEventConstants; +import org.wso2.carbon.identity.event.IdentityEventException; +import org.wso2.carbon.identity.event.event.Event; +import org.wso2.carbon.identity.event.handler.AbstractEventHandler; +import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; +import org.wso2.carbon.identity.organization.management.application.OrgApplicationManagerImpl; +import org.wso2.carbon.identity.organization.management.application.constant.OrgApplicationMgtConstants; +import org.wso2.carbon.identity.organization.management.application.internal.OrgApplicationMgtDataHolder; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; +import org.wso2.carbon.identity.organization.management.service.model.BasicOrganization; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; + +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT; + +/** + * This class contains the implementation of the handler for managing sub-organizations' user claims. + * This handler will be used to manage claims of sub organizations. + */ +public class OrgClaimMgtHandler extends AbstractEventHandler { + + private final ExecutorService executorService = Executors.newFixedThreadPool(1); + private static final Log LOG = LogFactory.getLog(OrgClaimMgtHandler.class); + + @Override + public void handleEvent(Event event) throws IdentityEventException { + + String eventName = event.getEventName(); + switch (eventName) { + case OrgApplicationMgtConstants.EVENT_POST_SHARE_APPLICATION: + handlePostShareApplication(event); + break; + case IdentityEventConstants.Event.POST_APP_USER_ATTRIBUTE_UPDATE: + handleAppUserAttributeUpdate(event); + break; + case IdentityEventConstants.Event.POST_DELETE_LOCAL_CLAIM: + handlePostDeleteLocalClaim(event); + break; + case IdentityEventConstants.Event.POST_DELETE_EXTERNAL_CLAIM: + handlePostDeleteExternalClaim(event); + break; + case IdentityEventConstants.Event.POST_UPDATE_LOCAL_CLAIM: + handleUpdateLocalClaim(event); + break; + case IdentityEventConstants.Event.POST_UPDATE_EXTERNAL_CLAIM: + handleUpdateExternalClaim(event); + break; + case IdentityEventConstants.Event.POST_ADD_EXTERNAL_CLAIM: + handleAddExternalClaim(event); + break; + default: + break; + } + } + + private void handlePostShareApplication(Event event) throws IdentityEventException { + + Map eventProperties = event.getEventProperties(); + String parentOrganizationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_ORGANIZATION_ID); + String sharedOrganizationID = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_ORGANIZATION_ID); + ClaimMapping[] claimMappings = + (ClaimMapping[]) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_USER_ATTRIBUTES); + + try { + String parentTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); + String sharedOrganizationTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationID); + List missingClaims = getMissingClaims(sharedOrganizationTenantDomain, claimMappings); + if (!missingClaims.isEmpty()) { + List parentOrgCustomLocalClaims = getClaimMetadataManagementService(). + getLocalClaims(parentTenantDomain); + addClaimsToSubOrganization(parentOrgCustomLocalClaims, sharedOrganizationTenantDomain, + missingClaims, parentTenantDomain); + } + } catch (OrganizationManagementException | ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while adding the claims.", e); + } + } + + private void handleAppUserAttributeUpdate(Event event) throws IdentityEventException { + + Map eventProperties = event.getEventProperties(); + List claimMappings = + (List) eventProperties.get(IdentityEventConstants.EventProperty.UPDATED_CLAIM_MAPPINGS); + String applicationId = + (String) eventProperties.get(IdentityEventConstants.EventProperty.APPLICATION_ID); + String tenantDomain = (String) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN); + try { + List sharedOrganizations = getOrgApplicationManager().getApplicationSharedOrganizations( + getOrganizationManager().resolveOrganizationId(tenantDomain), applicationId); + if (!sharedOrganizations.isEmpty()) { + ClaimMapping[] filteredClaimMappings = + claimMappings.stream().filter(claim -> !claim.getLocalClaim().getClaimUri() + .startsWith(OrgApplicationMgtConstants.RUNTIME_CLAIM_URI_PREFIX)) + .toArray(ClaimMapping[]::new); + + for (BasicOrganization organization : sharedOrganizations) { + List missingClaims = getMissingClaims(organization.getId(), filteredClaimMappings); + String sharedOrganizationTenantDomain = getOrganizationManager(). + resolveTenantDomain(organization.getId()); + List parentOrgCustomLocalClaims = getClaimMetadataManagementService(). + getLocalClaims(tenantDomain); + CompletableFuture.runAsync(() -> { + try { + addClaimsToSubOrganization(parentOrgCustomLocalClaims, sharedOrganizationTenantDomain, + missingClaims, tenantDomain); + } catch (IdentityEventException e) { + LOG.error("An error occurred while adding the claims:", e); + } + }, executorService); + } + } + } catch (OrganizationManagementException e) { + // This is to handle the scenario where the tenant is not modeled as an organization. + if (ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT.getCode().equals(e.getErrorCode())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Organization not found for the tenant: " + tenantDomain); + } + return; + } + throw new IdentityEventException("An error occurred while adding the claims.", e); + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while adding the claims.", e); + } + } + + private void handlePostDeleteExternalClaim(Event event) throws IdentityEventException { + + Map eventProperties = event.getEventProperties(); + String externalClaimDialectURI = + (String) eventProperties.get(IdentityEventConstants.EventProperty.CLAIM_DIALECT_URI); + String externalClaimURI = + (String) eventProperties.get(IdentityEventConstants.EventProperty.EXTERNAL_CLAIM_URI); + int tenantId = (int) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_ID); + String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId); + + try { + String organizationId = getOrganizationManager().resolveOrganizationId(tenantDomain); + List childOrganizations = getOrganizationManager(). + getChildOrganizations(organizationId, true); + for (BasicOrganization organization : childOrganizations) { + String sharedOrganizationTenantDomain = getOrganizationManager(). + resolveTenantDomain(organization.getId()); + if (isExistingExternalClaimURI(externalClaimDialectURI, externalClaimURI, + sharedOrganizationTenantDomain)) { + getClaimMetadataManagementService().removeExternalClaim(externalClaimDialectURI, externalClaimURI, + sharedOrganizationTenantDomain); + } + } + } catch (OrganizationManagementException e) { + // This is to handle the scenario where the tenant is not modeled as an organization. + if (ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT.getCode().equals(e.getErrorCode())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Organization not found for the tenant: " + tenantDomain); + } + return; + } + throw new IdentityEventException("An error occurred while deleting the external claim " + externalClaimURI, + e); + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while deleting the external claim " + externalClaimURI, + e); + } + } + + private void handlePostDeleteLocalClaim(Event event) throws IdentityEventException { + + Map eventProperties = event.getEventProperties(); + String localClaimUri = (String) eventProperties.get(IdentityEventConstants.EventProperty.LOCAL_CLAIM_URI); + int tenantId = (int) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_ID); + String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId); + + try { + String organizationId = getOrganizationManager().resolveOrganizationId(tenantDomain); + List childOrganizations = getOrganizationManager(). + getChildOrganizations(organizationId, true); + for (BasicOrganization organization : childOrganizations) { + String sharedOrganizationTenantDomain = getOrganizationManager(). + resolveTenantDomain(organization.getId()); + if (isExistingLocalClaimURI(localClaimUri, sharedOrganizationTenantDomain)) { + getClaimMetadataManagementService().removeLocalClaim(localClaimUri, sharedOrganizationTenantDomain); + } + } + } catch (OrganizationManagementException e) { + // This is to handle the scenario where the tenant is not modeled as an organization. + if (ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT.getCode().equals(e.getErrorCode())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Organization not found for the tenant: " + tenantDomain); + } + return; + } + throw new IdentityEventException("An error occurred while deleting local claim " + localClaimUri, e); + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while deleting local claim " + localClaimUri, e); + } + } + + private void handleUpdateLocalClaim(Event event) throws IdentityEventException { + + Map eventProperties = event.getEventProperties(); + int tenantId = (int) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_ID); + String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId); + String localClaimURI = (String) eventProperties.get(IdentityEventConstants.EventProperty.LOCAL_CLAIM_URI); + Map localClaimProperties = + (Map) eventProperties.get(IdentityEventConstants.EventProperty. + LOCAL_CLAIM_PROPERTIES); + List mappedAttributes = + (List) eventProperties.get(IdentityEventConstants.EventProperty. + MAPPED_ATTRIBUTES); + + try { + String organizationId = getOrganizationManager().resolveOrganizationId(tenantDomain); + List childOrganizations = getOrganizationManager(). + getChildOrganizations(organizationId, true); + for (BasicOrganization organization : childOrganizations) { + String sharedOrganizationTenantDomain = getOrganizationManager(). + resolveTenantDomain(organization.getId()); + if (isExistingLocalClaimURI(localClaimURI, sharedOrganizationTenantDomain)) { + getClaimMetadataManagementService().updateLocalClaim(new LocalClaim(localClaimURI, + mappedAttributes, localClaimProperties), sharedOrganizationTenantDomain); + } + } + } catch (OrganizationManagementException e) { + // This is to handle the scenario where the tenant is not modeled as an organization. + if (ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT.getCode().equals(e.getErrorCode())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Organization not found for the tenant: " + tenantDomain); + } + return; + } + throw new IdentityEventException("An error occurred while updating the local claim " + localClaimURI, e); + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while updating the local claim " + localClaimURI, e); + } + } + + private void handleUpdateExternalClaim(Event event) throws IdentityEventException { + + Map eventProperties = event.getEventProperties(); + int tenantId = (int) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_ID); + String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId); + String claimDialectURI = + (String) eventProperties.get(IdentityEventConstants.EventProperty.CLAIM_DIALECT_URI); + String claimURI = (String) eventProperties.get(IdentityEventConstants.EventProperty.EXTERNAL_CLAIM_URI); + String mappedLocalClaim = + (String) eventProperties.get(IdentityEventConstants.EventProperty.MAPPED_LOCAL_CLAIM_URI); + Map claimProperties = + (Map) eventProperties.get(IdentityEventConstants.EventProperty. + EXTERNAL_CLAIM_PROPERTIES); + + try { + String organizationId = getOrganizationManager().resolveOrganizationId(tenantDomain); + List childOrganizations = getOrganizationManager(). + getChildOrganizations(organizationId, true); + for (BasicOrganization organization : childOrganizations) { + String sharedOrganizationTenantDomain = getOrganizationManager(). + resolveTenantDomain(organization.getId()); + if (isExistingExternalClaimURI(claimDialectURI, claimURI, sharedOrganizationTenantDomain)) { + getClaimMetadataManagementService().updateExternalClaim(new ExternalClaim(claimDialectURI, + claimURI, mappedLocalClaim, claimProperties), sharedOrganizationTenantDomain); + } + } + } catch (OrganizationManagementException e) { + // This is to handle the scenario where the tenant is not modeled as an organization. + if (ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT.getCode().equals(e.getErrorCode())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Organization not found for the tenant: " + tenantDomain); + } + return; + } + throw new IdentityEventException("An error occurred while updating the external claim " + claimURI, e); + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while updating the external claim " + claimURI, e); + } + } + + private void handleAddExternalClaim(Event event) throws IdentityEventException { + + Map eventProperties = event.getEventProperties(); + int tenantId = (int) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_ID); + String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId); + String claimDialectURI = + (String) eventProperties.get(IdentityEventConstants.EventProperty.CLAIM_DIALECT_URI); + String claimURI = (String) eventProperties.get(IdentityEventConstants.EventProperty.EXTERNAL_CLAIM_URI); + String mappedLocalClaim = + (String) eventProperties.get(IdentityEventConstants.EventProperty.MAPPED_LOCAL_CLAIM_URI); + Map claimProperties = + (Map) eventProperties.get(IdentityEventConstants.EventProperty. + EXTERNAL_CLAIM_PROPERTIES); + try { + String organizationId = getOrganizationManager().resolveOrganizationId(tenantDomain); + List childOrganizations = getOrganizationManager(). + getChildOrganizations(organizationId, true); + for (BasicOrganization organization : childOrganizations) { + String sharedOrganizationTenantDomain = getOrganizationManager(). + resolveTenantDomain(organization.getId()); + /* This checks if the local claim exists within the organization. Local claims are added to + sub-organizations when updating application user attributes or when sharing applications with already + added requested attributes. */ + if (isExistingLocalClaimURI(mappedLocalClaim, sharedOrganizationTenantDomain)) { + getClaimMetadataManagementService().addExternalClaim(new ExternalClaim(claimDialectURI, + claimURI, mappedLocalClaim, claimProperties), sharedOrganizationTenantDomain); + } + } + } catch (OrganizationManagementException e) { + // This is to handle the scenario where the tenant is not modeled as an organization. + if (ERROR_CODE_ORGANIZATION_NOT_FOUND_FOR_TENANT.getCode().equals(e.getErrorCode())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Organization not found for the tenant: " + tenantDomain); + } + return; + } + throw new IdentityEventException("An error occurred while adding the external claim " + claimURI, e); + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while adding the external claim " + claimURI, e); + } + } + + private void addClaimsToSubOrganization(List parentOrgCustomLocalClaims, + String sharedOrganizationTenantDomain, + List missingClaims, String parentTenantDomain) + throws IdentityEventException { + + for (String claimURI : missingClaims) { + Optional matchingClaim = parentOrgCustomLocalClaims.stream() + .filter(claim -> claimURI.equals(claim.getClaimURI())) + .findFirst(); + if (matchingClaim.isPresent()) { + LocalClaim claim = matchingClaim.get(); + try { + getClaimMetadataManagementService().addLocalClaim(claim, sharedOrganizationTenantDomain); + + List externalClaimMappingsInParentOrg = + getMappedExternalClaims(claimURI, parentTenantDomain); + if (!externalClaimMappingsInParentOrg.isEmpty()) { + for (Claim externalClaim : externalClaimMappingsInParentOrg) { + getClaimMetadataManagementService().addExternalClaim((new ExternalClaim( + externalClaim.getClaimDialectURI(), externalClaim.getClaimURI(), claimURI)), + sharedOrganizationTenantDomain); + } + } + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while adding claims to the sub-organization", + e); + } + } + } + } + + private List getMissingClaims(String sharedOrganizationTenantDomain, ClaimMapping[] claimMappings) + throws IdentityEventException { + + try { + List subOrgLocalClaims = getClaimMetadataManagementService(). + getLocalClaims(sharedOrganizationTenantDomain); + Set subOrgClaimURIs = subOrgLocalClaims.stream().map(LocalClaim::getClaimURI) + .collect(Collectors.toSet()); + List missingClaims = new ArrayList<>(); + for (ClaimMapping claimMapping : claimMappings) { + String claimURI = claimMapping.getLocalClaim().getClaimUri(); + if (!subOrgClaimURIs.contains(claimURI)) { + missingClaims.add(claimURI); + } + } + return missingClaims; + } catch (ClaimMetadataException e) { + throw new IdentityEventException("An error occurred while getting claims from the sub-organization", e); + } + } + + private List getMappedExternalClaims(String localClaimURI, String tenantDomain) + throws ClaimMetadataException { + + return getClaimMetadataManagementService().getMappedExternalClaimsForLocalClaim(localClaimURI, tenantDomain); + } + + private ClaimMetadataManagementService getClaimMetadataManagementService() { + + return OrgApplicationMgtDataHolder.getInstance().getClaimMetadataManagementService(); + } + + private OrganizationManager getOrganizationManager() { + + return OrgApplicationMgtDataHolder.getInstance().getOrganizationManager(); + } + + private OrgApplicationManager getOrgApplicationManager() { + + return new OrgApplicationManagerImpl(); + } + + private boolean isExistingLocalClaimURI(String localClaimURI, String tenantDomain) throws ClaimMetadataException { + + return getClaimMetadataManagementService().getLocalClaims(tenantDomain).stream().filter( + claim -> claim.getClaimURI().equalsIgnoreCase(localClaimURI)).findFirst().isPresent(); + } + + private boolean isExistingExternalClaimURI(String externalClaimDialectURI, String externalClaimURI, + String tenantDomain) throws ClaimMetadataException { + + return getClaimMetadataManagementService().getExternalClaims(externalClaimDialectURI, tenantDomain).stream(). + filter(claim -> claim.getClaimURI().equalsIgnoreCase(externalClaimURI)).findFirst().isPresent(); + } +} diff --git a/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/internal/OrgApplicationMgtServiceComponent.java b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/internal/OrgApplicationMgtServiceComponent.java index bbe62ce9f..18b43c22f 100644 --- a/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/internal/OrgApplicationMgtServiceComponent.java +++ b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/internal/OrgApplicationMgtServiceComponent.java @@ -36,6 +36,7 @@ import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; import org.wso2.carbon.identity.organization.management.application.OrgApplicationManagerImpl; import org.wso2.carbon.identity.organization.management.application.dao.impl.OrgApplicationMgtDAOImpl; +import org.wso2.carbon.identity.organization.management.application.handler.OrgClaimMgtHandler; import org.wso2.carbon.identity.organization.management.application.listener.ApplicationSharingManagerListenerImpl; import org.wso2.carbon.identity.organization.management.application.listener.FragmentApplicationMgtListener; import org.wso2.carbon.identity.organization.management.application.listener.OrganizationCreationHandler; @@ -75,6 +76,7 @@ protected void activate(ComponentContext componentContext) { null); bundleContext.registerService(AbstractEventHandler.class.getName(), new OrganizationCreationHandler(), null); + bundleContext.registerService(AbstractEventHandler.class.getName(), new OrgClaimMgtHandler(), null); if (log.isDebugEnabled()) { log.debug("Organization Application Management component activated successfully."); } diff --git a/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/listener/ApplicationSharingManagerListenerImpl.java b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/listener/ApplicationSharingManagerListenerImpl.java index 491aacbb7..730a04a21 100644 --- a/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/listener/ApplicationSharingManagerListenerImpl.java +++ b/components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/listener/ApplicationSharingManagerListenerImpl.java @@ -18,6 +18,9 @@ package org.wso2.carbon.identity.organization.management.application.listener; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.ClaimMapping; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.event.IdentityEventClientException; import org.wso2.carbon.identity.event.IdentityEventException; import org.wso2.carbon.identity.event.event.Event; @@ -32,10 +35,13 @@ import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementServerException; import org.wso2.carbon.identity.organization.management.service.model.BasicOrganization; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import static org.wso2.carbon.identity.organization.management.service.util.Utils.getTenantDomain; + /** * Listener implementation for organization's application sharing operations. * Class implements {@link ApplicationSharingManagerListener}. @@ -66,6 +72,8 @@ public void postShareApplication(String parentOrganizationId, String parentAppli eventProperties.put(OrgApplicationMgtConstants.EVENT_PROP_SHARED_ORGANIZATION_ID, sharedOrganizationId); eventProperties.put(OrgApplicationMgtConstants.EVENT_PROP_SHARED_APPLICATION_ID, sharedApplicationId); eventProperties.put(OrgApplicationMgtConstants.EVENT_PROP_SHARE_WITH_ALL_CHILDREN, shareWithAllChildren); + eventProperties.put(OrgApplicationMgtConstants.EVENT_PROP_SHARED_USER_ATTRIBUTES, + getSharedUserAttributes(sharedApplicationId)); fireEvent(OrgApplicationMgtConstants.EVENT_POST_SHARE_APPLICATION, eventProperties); } @@ -174,4 +182,21 @@ private void fireEvent(String eventName, Map eventProperties) OrganizationManagementConstants.ErrorMessages.ERROR_CODE_ERROR_FIRING_EVENTS.getCode(), e); } } + + private ClaimMapping[] getSharedUserAttributes(String sharedApplicationId) throws OrganizationManagementException { + + try { + ServiceProvider application = OrgApplicationMgtDataHolder.getInstance().getApplicationManagementService(). + getApplicationByResourceId(sharedApplicationId, getTenantDomain()); + + ClaimMapping[] filteredClaimMappings = + Arrays.stream(application.getClaimConfig().getClaimMappings()) + .filter(claim -> !claim.getLocalClaim().getClaimUri() + .startsWith(OrgApplicationMgtConstants.RUNTIME_CLAIM_URI_PREFIX)). + toArray(ClaimMapping[]::new); + return filteredClaimMappings; + } catch (IdentityApplicationManagementException e) { + throw new OrganizationManagementException("An error occurred while getting the application."); + } + } } diff --git a/pom.xml b/pom.xml index ac2764ac3..8637501a6 100644 --- a/pom.xml +++ b/pom.xml @@ -475,7 +475,7 @@ [4.7.0,5.0.0) - 5.25.264 + 5.25.369 [5.20.0, 7.0.0)