From 25576b61faba73d3a86f328d1567c71d9b351b85 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 16 Oct 2023 10:47:37 +0530 Subject: [PATCH 01/17] resolve conflict --- .../pom.xml | 14 ++ .../handler/SharedRoleMgtHandler.java | 180 ++++++++++++++++++ ...ganizationManagementHandlerDataHolder.java | 46 ++++- ...tionManagementHandlerServiceComponent.java | 44 ++++- pom.xml | 6 +- 5 files changed, 284 insertions(+), 6 deletions(-) create mode 100644 components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java diff --git a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml index c35b6b52a..4b83187da 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml @@ -56,6 +56,18 @@ org.wso2.carbon.identity.governance org.wso2.carbon.identity.governance + + org.wso2.carbon.identity.organization.management + org.wso2.carbon.identity.organization.management.application + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.event + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.role.v2.mgt.core + @@ -115,6 +127,8 @@ org.wso2.carbon.identity.event.services; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.recovery.*; version="${identity.governance.imp.pkg.version.range}", org.wso2.carbon.identity.governance; version="${identity.governance.imp.pkg.version.range}", + org.wso2.carbon.identity.role.v2.mgt.core.*; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.organization.management.application.*; version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java new file mode 100644 index 000000000..e356491ee --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -0,0 +1,180 @@ +/* + * 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.handler; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +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.constant.OrgApplicationMgtConstants; +import org.wso2.carbon.identity.organization.management.application.model.SharedApplication; +import org.wso2.carbon.identity.organization.management.ext.Constants; +import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; +import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; +import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Event handler to manage shared roles in sub-organizations. + */ +public class SharedRoleMgtHandler extends AbstractEventHandler { + + private static final Log LOG = LogFactory.getLog(SharedRoleMgtHandler.class); + + @Override + public void handleEvent(Event event) throws IdentityEventException { + + String eventName = event.getEventName(); + Map eventProperties = event.getEventProperties(); + switch (eventName) { + case OrgApplicationMgtConstants.EVENT_POST_SHARE_APPLICATION: + /* + If the main application use application audienced roles, create the role for sub org space, + and add the relationship. + */ + createSubOrgRolesOnAppSharing(eventProperties); + break; + case OrgApplicationMgtConstants.EVENT_POST_DELETE_SHARED_APPLICATION: + // TODO: no need to handle here if application audienced roles get + // deleted if the application is deleted. + break; + case OrgApplicationMgtConstants.EVENT_POST_DELETE_ALL_SHARED_APPLICATIONS: + // TODO: no need to handle here if application audienced roles get + // deleted if the application is deleted. + break; + case IdentityEventConstants.Event.POST_ADD_ROLE_V2_EVENT: + createSubOrgRolesOnNewRoleCreation(eventProperties); + break; + case IdentityEventConstants.Event.POST_DELETE_ROLE_V2_EVENT: + // If the deleted role is a primary org's role, delete the shared roles. +// String roleId = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_ID); +// String roleTenantDomain = +// (String) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN); + + break; + case Constants.EVENT_POST_ADD_ORGANIZATION: + /* + If the org is a sub organization and if primary org has roles with organization audience, + create them in the sub org as well. + */ + break; + // TODO: role name update event. + } + } + + private void createSubOrgRolesOnNewRoleCreation(Map eventProperties) { + + try { + String roleName = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_NAME); + String roleTenantDomain = (String) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN); + String roleAudienceType = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE); + String roleAudienceId = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE_ID); + String roleOrgId = getOrganizationManager().resolveOrganizationId(roleTenantDomain); + boolean isPrimaryOrganization = getOrganizationManager().isPrimaryOrganization(roleOrgId); + if (!isPrimaryOrganization) { + return; + } + switch (roleAudienceType) { + case RoleConstants.APPLICATION: + // If the audienced application is a shared application, create the role in the shared apps. + List sharedApplications = + getOrgApplicationManager().getSharedApplications(roleOrgId, roleAudienceId); + for (SharedApplication sharedApplication : sharedApplications) { + String sharedApplicationId = sharedApplication.getSharedApplicationId(); + String sharedOrganizationId = sharedApplication.getOrganizationId(); + String shareAppTenantDomain = + getOrganizationManager().resolveTenantDomain(sharedOrganizationId); + RoleBasicInfo sharedRoleInfo = + getRoleManagementServiceV2().addRole(roleName, Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), RoleConstants.APPLICATION, sharedApplicationId, + shareAppTenantDomain); + // Add relationship between main role and shared role. + // TODO + String mainRoleUUID = "TODO"; + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, + sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); + } + break; + case RoleConstants.ORGANIZATION: + // If the audienced organization is a shared organization, create the role in the shared orgs. + break; + } + } catch (OrganizationManagementException e) { + LOG.debug(e.getMessage()); + } catch (IdentityRoleManagementException e) { + // TODO : handle exception + throw new RuntimeException(e); + } + } + + private void createSubOrgRolesOnAppSharing(Map eventProperties) { + + String parentOrganizationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_ORGANIZATION_ID); + String parentApplicationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_APPLICATION_ID); + String sharedOrganizationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_ORGANIZATION_ID); + String sharedApplicationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_APPLICATION_ID); + boolean hasAppAudiencedRoles = true; + // TODO: check application is using the application audience roles. + if (hasAppAudiencedRoles) { + // Create the role if not exists, and add the relationship. + try { + String mainApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); + String sharedApplicationTenantDomain = + getOrganizationManager().resolveTenantDomain(sharedOrganizationId); + RoleManagementService roleManagementServiceV2 = getRoleManagementServiceV2(); + roleManagementServiceV2.shareRoles(parentApplicationId, mainApplicationTenantDomain, + sharedApplicationId, + sharedApplicationTenantDomain); + } catch (OrganizationManagementException | IdentityRoleManagementException e) { + // TODO: handle exception + throw new RuntimeException(e); + } + } + } + + private static RoleManagementService getRoleManagementServiceV2() { + + return OrganizationManagementHandlerDataHolder.getInstance().getRoleManagementServiceV2(); + } + + private static OrganizationManager getOrganizationManager() { + + return OrganizationManagementHandlerDataHolder.getInstance().getOrganizationManager(); + } + + private static OrgApplicationManager getOrgApplicationManager() { + + return OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager(); + } +} diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java index dddbba7b9..1f7cd7f1c 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java @@ -20,7 +20,9 @@ import org.wso2.carbon.identity.event.services.IdentityEventService; import org.wso2.carbon.identity.governance.IdentityGovernanceService; +import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; /** * Organization management handler data holder. @@ -31,10 +33,10 @@ public class OrganizationManagementHandlerDataHolder { new OrganizationManagementHandlerDataHolder(); private IdentityEventService identityEventService; - private IdentityGovernanceService identityGovernanceService; - private OrganizationManager organizationManager; + private RoleManagementService roleManagementServiceV2; + private OrgApplicationManager orgApplicationManager; public static OrganizationManagementHandlerDataHolder getInstance() { @@ -100,5 +102,45 @@ public void setOrganizationManager(OrganizationManager organizationManager) { this.organizationManager = organizationManager; } + + /** + * Set {@link RoleManagementService}. + * + * @param roleManagementServiceV2 Instance of {@link RoleManagementService}. + */ + public void setRoleManagementServiceV2(RoleManagementService roleManagementServiceV2) { + + this.roleManagementServiceV2 = roleManagementServiceV2; + } + + /** + * Get {@link RoleManagementService}. + * + * @return role management service instance {@link RoleManagementService}. + */ + public RoleManagementService getRoleManagementServiceV2() { + + return roleManagementServiceV2; + } + + /** + * Get {@link OrgApplicationManager}. + * + * @return Org application manager instance {@link OrgApplicationManager}. + */ + public OrgApplicationManager getOrgApplicationManager() { + + return orgApplicationManager; + } + + /** + * Set {@link OrgApplicationManager}. + * + * @param orgApplicationManager Instance of {@link OrgApplicationManager}. + */ + public void setOrgApplicationManager(OrgApplicationManager orgApplicationManager) { + + this.orgApplicationManager = orgApplicationManager; + } } diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java index d2e77840c..fe5f5669e 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java @@ -30,8 +30,11 @@ import org.wso2.carbon.identity.event.handler.AbstractEventHandler; import org.wso2.carbon.identity.event.services.IdentityEventService; import org.wso2.carbon.identity.governance.IdentityGovernanceService; +import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; import org.wso2.carbon.identity.organization.management.handler.GovernanceConfigUpdateHandler; +import org.wso2.carbon.identity.organization.management.handler.SharedRoleMgtHandler; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; /** * Organization management handler service component. @@ -54,8 +57,8 @@ protected void activate(ComponentContext componentContext) { try { BundleContext bundleContext = componentContext.getBundleContext(); - bundleContext.registerService(AbstractEventHandler.class, new GovernanceConfigUpdateHandler(), - null); + bundleContext.registerService(AbstractEventHandler.class, new GovernanceConfigUpdateHandler(), null); + bundleContext.registerService(AbstractEventHandler.class, new SharedRoleMgtHandler(), null); LOG.debug("Organization management handler component activated successfully."); } catch (Throwable e) { LOG.error("Error while activating organization management handler module.", e); @@ -110,5 +113,40 @@ protected void unsetOrganizationManager(OrganizationManager organizationManager) OrganizationManagementHandlerDataHolder.getInstance().setOrganizationManager(null); } -} + @Reference( + name = "org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService", + service = org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetRoleManagementServiceV2") + protected void setRoleManagementServiceV2(RoleManagementService roleManagementService) { + + OrganizationManagementHandlerDataHolder.getInstance().setRoleManagementServiceV2(roleManagementService); + LOG.debug("RoleManagementServiceV2 set in OrganizationManagementHandlerService bundle."); + } + + protected void unsetRoleManagementServiceV2(RoleManagementService roleManagementService) { + + OrganizationManagementHandlerDataHolder.getInstance().setRoleManagementServiceV2(null); + LOG.debug("RoleManagementServiceV2 unset in OrganizationManagementHandlerService bundle."); + } + + @Reference( + name = "org.wso2.carbon.identity.organization.management.application.OrgApplicationManager", + service = org.wso2.carbon.identity.organization.management.application.OrgApplicationManager.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetOrgApplicationManagementService") + protected void setOrgApplicationManagementService(OrgApplicationManager orgApplicationManagementService) { + + OrganizationManagementHandlerDataHolder.getInstance().setOrgApplicationManager(orgApplicationManagementService); + LOG.debug("OrgApplication management service unset in OrganizationManagementHandlerService bundle."); + } + + protected void unsetOrgApplicationManagementService(OrgApplicationManager orgApplicationManagementService) { + + OrganizationManagementHandlerDataHolder.getInstance().setOrgApplicationManager(null); + LOG.debug("OrgApplication management service unset in OrganizationManagementHandlerService bundle."); + } +} diff --git a/pom.xml b/pom.xml index dccaf8bd4..c6852da49 100644 --- a/pom.xml +++ b/pom.xml @@ -240,7 +240,11 @@ org.wso2.carbon.identity.governance ${org.wso2.carbon.identity.governance.version} - + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.role.v2.mgt.core + ${carbon.identity.framework.version} + com.google.code.findbugs annotations From 3ffeb1cf74b2b7e472636e9278d6b24d538f8aba Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Tue, 10 Oct 2023 10:14:57 +0530 Subject: [PATCH 02/17] create roles on sub org creation event --- .../handler/SharedRoleMgtHandler.java | 60 +++++++++++++++---- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index e356491ee..8f48f0e98 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -31,6 +31,9 @@ import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; 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.exception.OrganizationManagementServerException; +import org.wso2.carbon.identity.organization.management.service.model.Organization; +import org.wso2.carbon.identity.organization.management.service.model.ParentOrganizationDO; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; @@ -70,28 +73,39 @@ public void handleEvent(Event event) throws IdentityEventException { break; case IdentityEventConstants.Event.POST_ADD_ROLE_V2_EVENT: createSubOrgRolesOnNewRoleCreation(eventProperties); - break; - case IdentityEventConstants.Event.POST_DELETE_ROLE_V2_EVENT: - // If the deleted role is a primary org's role, delete the shared roles. -// String roleId = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_ID); -// String roleTenantDomain = -// (String) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN); - break; case Constants.EVENT_POST_ADD_ORGANIZATION: /* If the org is a sub organization and if primary org has roles with organization audience, create them in the sub org as well. */ + createSubOrgRolesOnNewOrgCreation(eventProperties); break; - // TODO: role name update event. } } + private void createSubOrgRolesOnNewOrgCreation(Map eventProperties) { + + try { + Organization organization = (Organization) eventProperties.get(Constants.EVENT_PROP_ORGANIZATION); + String organizationId = organization.getId(); + String organizationName = organization.getName(); + ParentOrganizationDO parentOrg = organization.getParent(); + if (getOrganizationManager().isPrimaryOrganization(organizationId)) { + return; + } + + } catch (OrganizationManagementServerException e) { + throw new RuntimeException(e); + } + + } + private void createSubOrgRolesOnNewRoleCreation(Map eventProperties) { try { - String roleName = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_NAME); + String mainRoleUUID = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_ID); + String mainRoleName = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_NAME); String roleTenantDomain = (String) eventProperties.get(IdentityEventConstants.EventProperty.TENANT_DOMAIN); String roleAudienceType = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE); String roleAudienceId = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE_ID); @@ -111,22 +125,44 @@ private void createSubOrgRolesOnNewRoleCreation(Map eventPropert String shareAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationId); RoleBasicInfo sharedRoleInfo = - getRoleManagementServiceV2().addRole(roleName, Collections.emptyList(), + getRoleManagementServiceV2().addRole(mainRoleName, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, sharedApplicationId, shareAppTenantDomain); // Add relationship between main role and shared role. - // TODO - String mainRoleUUID = "TODO"; getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); } break; case RoleConstants.ORGANIZATION: // If the audienced organization is a shared organization, create the role in the shared orgs. + getOrganizationManager().getChildOrganizations(roleOrgId, true).forEach(childOrg -> { + try { + String sharedOrganizationId = childOrg.getId(); + String shareAppTenantDomain = + getOrganizationManager().resolveTenantDomain(sharedOrganizationId); + RoleBasicInfo sharedRoleInfo = + getRoleManagementServiceV2().addRole(mainRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), + RoleConstants.ORGANIZATION, sharedOrganizationId, + shareAppTenantDomain); + // Add relationship between main role and shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, + sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); + } catch (OrganizationManagementException e) { + //TODO : handle exception + throw new RuntimeException(e); + } catch (IdentityRoleManagementException e) { + //TODO : handle exception + throw new RuntimeException(e); + } + }); break; + default: + LOG.error("Unsupported audience type: " + roleAudienceType); } } catch (OrganizationManagementException e) { + // TODO : handle exception LOG.debug(e.getMessage()); } catch (IdentityRoleManagementException e) { // TODO : handle exception From c82ca3fdcafc43aca7a2279227542cf6d523f2c3 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 16 Oct 2023 10:48:45 +0530 Subject: [PATCH 03/17] resolve conflict --- .../handler/SharedRoleMgtHandler.java | 59 +++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index 8f48f0e98..772139108 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -31,7 +31,6 @@ import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; 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.exception.OrganizationManagementServerException; import org.wso2.carbon.identity.organization.management.service.model.Organization; import org.wso2.carbon.identity.organization.management.service.model.ParentOrganizationDO; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; @@ -63,14 +62,6 @@ public void handleEvent(Event event) throws IdentityEventException { */ createSubOrgRolesOnAppSharing(eventProperties); break; - case OrgApplicationMgtConstants.EVENT_POST_DELETE_SHARED_APPLICATION: - // TODO: no need to handle here if application audienced roles get - // deleted if the application is deleted. - break; - case OrgApplicationMgtConstants.EVENT_POST_DELETE_ALL_SHARED_APPLICATIONS: - // TODO: no need to handle here if application audienced roles get - // deleted if the application is deleted. - break; case IdentityEventConstants.Event.POST_ADD_ROLE_V2_EVENT: createSubOrgRolesOnNewRoleCreation(eventProperties); break; @@ -81,6 +72,9 @@ public void handleEvent(Event event) throws IdentityEventException { */ createSubOrgRolesOnNewOrgCreation(eventProperties); break; + default: + LOG.debug("Unsupported event: " + eventName); + break; } } @@ -89,13 +83,33 @@ private void createSubOrgRolesOnNewOrgCreation(Map eventProperti try { Organization organization = (Organization) eventProperties.get(Constants.EVENT_PROP_ORGANIZATION); String organizationId = organization.getId(); - String organizationName = organization.getName(); - ParentOrganizationDO parentOrg = organization.getParent(); if (getOrganizationManager().isPrimaryOrganization(organizationId)) { return; } - - } catch (OrganizationManagementServerException e) { + String subOrgTenantDomain = getOrganizationManager().resolveTenantDomain(organizationId); + ParentOrganizationDO parentOrg = organization.getParent(); + String parentOrgId = parentOrg.getId(); + // Get parent organization's roles which has organization audience. + String filter = "audienceId eq " + parentOrg.getId(); + String parenTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrgId); + List parentOrgRoles = + getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, parenTenantDomain); + for (RoleBasicInfo parentOrgRole : parentOrgRoles) { + String parentOrgRoleName = parentOrgRole.getName(); + // Create the role in the sub org. + RoleBasicInfo subOrgRole = + getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.ORGANIZATION, + organizationId, subOrgTenantDomain); + // Add relationship between parent org role and sub org role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), + subOrgRole.getId(), parenTenantDomain, subOrgTenantDomain); + } + } catch (OrganizationManagementException e) { + // TODO : handle exception + throw new RuntimeException(e); + } catch (IdentityRoleManagementException e) { + // TODO : handle exception throw new RuntimeException(e); } @@ -188,10 +202,21 @@ private void createSubOrgRolesOnAppSharing(Map eventProperties) String mainApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); String sharedApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationId); - RoleManagementService roleManagementServiceV2 = getRoleManagementServiceV2(); - roleManagementServiceV2.shareRoles(parentApplicationId, mainApplicationTenantDomain, - sharedApplicationId, - sharedApplicationTenantDomain); + // Get parent organization's roles which has application audience. + String filter = "audienceId eq " + parentApplicationId; + List parentOrgRoles = + getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, mainApplicationTenantDomain); + for (RoleBasicInfo parentOrgRole : parentOrgRoles) { + String parentOrgRoleName = parentOrgRole.getName(); + // Create the role in the sub org. + RoleBasicInfo subOrgRole = + getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, + sharedApplicationId, sharedApplicationTenantDomain); + // Add relationship between parent org role and sub org role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), + subOrgRole.getId(), mainApplicationTenantDomain, sharedApplicationTenantDomain); + } } catch (OrganizationManagementException | IdentityRoleManagementException e) { // TODO: handle exception throw new RuntimeException(e); From 57dc2c8b45d417f315a272c2e110424aecaea22d Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 16 Oct 2023 10:34:15 +0530 Subject: [PATCH 04/17] fix todos --- .../handler/SharedRoleMgtHandler.java | 82 ++++++++++--------- ...ganizationManagementHandlerDataHolder.java | 23 ++++++ ...tionManagementHandlerServiceComponent.java | 22 ++++- 3 files changed, 87 insertions(+), 40 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index 772139108..6dd8f8d3c 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -20,6 +20,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.event.IdentityEventConstants; import org.wso2.carbon.identity.event.IdentityEventException; import org.wso2.carbon.identity.event.event.Event; @@ -37,6 +38,7 @@ import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import java.util.Collections; import java.util.List; @@ -78,7 +80,7 @@ public void handleEvent(Event event) throws IdentityEventException { } } - private void createSubOrgRolesOnNewOrgCreation(Map eventProperties) { + private void createSubOrgRolesOnNewOrgCreation(Map eventProperties) throws IdentityEventException { try { Organization organization = (Organization) eventProperties.get(Constants.EVENT_PROP_ORGANIZATION); @@ -90,7 +92,7 @@ private void createSubOrgRolesOnNewOrgCreation(Map eventProperti ParentOrganizationDO parentOrg = organization.getParent(); String parentOrgId = parentOrg.getId(); // Get parent organization's roles which has organization audience. - String filter = "audienceId eq " + parentOrg.getId(); + String filter = RoleConstants.AUDIENCE_ID + " " + RoleConstants.EQ + " " + parentOrg.getId(); String parenTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrgId); List parentOrgRoles = getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, parenTenantDomain); @@ -106,16 +108,13 @@ private void createSubOrgRolesOnNewOrgCreation(Map eventProperti subOrgRole.getId(), parenTenantDomain, subOrgTenantDomain); } } catch (OrganizationManagementException e) { - // TODO : handle exception - throw new RuntimeException(e); + throw new IdentityEventException("Error occurred while resolving organization id from tenant domain.", e); } catch (IdentityRoleManagementException e) { - // TODO : handle exception - throw new RuntimeException(e); + throw new IdentityEventException("Error occurred while adding main role to shared role relationship.", e); } - } - private void createSubOrgRolesOnNewRoleCreation(Map eventProperties) { + private void createSubOrgRolesOnNewRoleCreation(Map eventProperties) throws IdentityEventException { try { String mainRoleUUID = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_ID); @@ -125,7 +124,7 @@ private void createSubOrgRolesOnNewRoleCreation(Map eventPropert String roleAudienceId = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE_ID); String roleOrgId = getOrganizationManager().resolveOrganizationId(roleTenantDomain); boolean isPrimaryOrganization = getOrganizationManager().isPrimaryOrganization(roleOrgId); - if (!isPrimaryOrganization) { + if (!isPrimaryOrganization && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(roleTenantDomain)) { return; } switch (roleAudienceType) { @@ -176,15 +175,13 @@ private void createSubOrgRolesOnNewRoleCreation(Map eventPropert LOG.error("Unsupported audience type: " + roleAudienceType); } } catch (OrganizationManagementException e) { - // TODO : handle exception - LOG.debug(e.getMessage()); + throw new IdentityEventException("Error occurred while retrieving shared applications.", e); } catch (IdentityRoleManagementException e) { - // TODO : handle exception - throw new RuntimeException(e); + throw new IdentityEventException("Error occurred while adding main role to shared role relationship.", e); } } - private void createSubOrgRolesOnAppSharing(Map eventProperties) { + private void createSubOrgRolesOnAppSharing(Map eventProperties) throws IdentityEventException { String parentOrganizationId = (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_ORGANIZATION_ID); @@ -194,33 +191,40 @@ private void createSubOrgRolesOnAppSharing(Map eventProperties) (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_ORGANIZATION_ID); String sharedApplicationId = (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_APPLICATION_ID); - boolean hasAppAudiencedRoles = true; - // TODO: check application is using the application audience roles. - if (hasAppAudiencedRoles) { + try { + String mainApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); + String allowedAudienceForRoleAssociation = + OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService() + .getAllowedAudienceForRoleAssociation(parentApplicationId, mainApplicationTenantDomain); + boolean hasAppAudiencedRoles = + RoleConstants.APPLICATION.equalsIgnoreCase(allowedAudienceForRoleAssociation); + if (!hasAppAudiencedRoles) { + return; + } // Create the role if not exists, and add the relationship. - try { - String mainApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); - String sharedApplicationTenantDomain = - getOrganizationManager().resolveTenantDomain(sharedOrganizationId); - // Get parent organization's roles which has application audience. - String filter = "audienceId eq " + parentApplicationId; - List parentOrgRoles = - getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, mainApplicationTenantDomain); - for (RoleBasicInfo parentOrgRole : parentOrgRoles) { - String parentOrgRoleName = parentOrgRole.getName(); - // Create the role in the sub org. - RoleBasicInfo subOrgRole = - getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), - Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, - sharedApplicationId, sharedApplicationTenantDomain); - // Add relationship between parent org role and sub org role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), - subOrgRole.getId(), mainApplicationTenantDomain, sharedApplicationTenantDomain); - } - } catch (OrganizationManagementException | IdentityRoleManagementException e) { - // TODO: handle exception - throw new RuntimeException(e); + String sharedApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationId); + // Get parent organization's roles which has application audience. + String filter = RoleConstants.AUDIENCE_ID + " " + RoleConstants.EQ + " " + parentApplicationId; + List parentOrgRoles = + getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, + mainApplicationTenantDomain); + for (RoleBasicInfo parentOrgRole : parentOrgRoles) { + String parentOrgRoleName = parentOrgRole.getName(); + // Create the role in the sub org. + RoleBasicInfo subOrgRole = + getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, + sharedApplicationId, sharedApplicationTenantDomain); + // Add relationship between parent org role and sub org role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), + subOrgRole.getId(), mainApplicationTenantDomain, sharedApplicationTenantDomain); } + } catch (IdentityApplicationManagementException e) { + throw new IdentityEventException("Error occurred checking main application allowed role audience.", e); + } catch (OrganizationManagementException e) { + throw new IdentityEventException("Error occurred while resolving tenant domain from organization id.", e); + } catch (IdentityRoleManagementException e) { + throw new IdentityEventException("Error occurred while adding main role to shared role relationship.", e); } } diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java index 1f7cd7f1c..41f1d52a3 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerDataHolder.java @@ -18,6 +18,7 @@ package org.wso2.carbon.identity.organization.management.handler.internal; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.event.services.IdentityEventService; import org.wso2.carbon.identity.governance.IdentityGovernanceService; import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; @@ -37,6 +38,7 @@ public class OrganizationManagementHandlerDataHolder { private OrganizationManager organizationManager; private RoleManagementService roleManagementServiceV2; private OrgApplicationManager orgApplicationManager; + private ApplicationManagementService applicationManagementService; public static OrganizationManagementHandlerDataHolder getInstance() { @@ -142,5 +144,26 @@ public void setOrgApplicationManager(OrgApplicationManager orgApplicationManager this.orgApplicationManager = orgApplicationManager; } + + /** + * Get {@link ApplicationManagementService}. + * + * @return Application management instance {@link ApplicationManagementService}. + */ + public ApplicationManagementService getApplicationManagementService() { + + return applicationManagementService; + } + + /** + * Set {@link ApplicationManagementService}. + * + * @param applicationManagementService Instance of {@link ApplicationManagementService}. + */ + public void setApplicationManagementService( + ApplicationManagementService applicationManagementService) { + + this.applicationManagementService = applicationManagementService; + } } diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java index fe5f5669e..9d13faabf 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java @@ -27,6 +27,7 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.event.handler.AbstractEventHandler; import org.wso2.carbon.identity.event.services.IdentityEventService; import org.wso2.carbon.identity.governance.IdentityGovernanceService; @@ -141,7 +142,7 @@ protected void unsetRoleManagementServiceV2(RoleManagementService roleManagement protected void setOrgApplicationManagementService(OrgApplicationManager orgApplicationManagementService) { OrganizationManagementHandlerDataHolder.getInstance().setOrgApplicationManager(orgApplicationManagementService); - LOG.debug("OrgApplication management service unset in OrganizationManagementHandlerService bundle."); + LOG.debug("OrgApplication management service set in OrganizationManagementHandlerService bundle."); } protected void unsetOrgApplicationManagementService(OrgApplicationManager orgApplicationManagementService) { @@ -149,4 +150,23 @@ protected void unsetOrgApplicationManagementService(OrgApplicationManager orgApp OrganizationManagementHandlerDataHolder.getInstance().setOrgApplicationManager(null); LOG.debug("OrgApplication management service unset in OrganizationManagementHandlerService bundle."); } + + @Reference( + name = "org.wso2.carbon.identity.application.mgt.ApplicationManagementService", + service = org.wso2.carbon.identity.application.mgt.ApplicationManagementService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetApplicationManagementService") + protected void setApplicationManagementService(ApplicationManagementService applicationManagementService) { + + OrganizationManagementHandlerDataHolder.getInstance() + .setApplicationManagementService(applicationManagementService); + LOG.debug("Application management service set in OrganizationManagementHandlerService bundle."); + } + + protected void unsetApplicationManagementService(ApplicationManagementService applicationManagementService) { + + OrganizationManagementHandlerDataHolder.getInstance().setApplicationManagementService(null); + LOG.debug("Application management service unset in OrganizationManagementHandlerService bundle."); + } } From aaba1590a416ab357d13f0cd4afd024d2208eb46 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 16 Oct 2023 10:57:05 +0530 Subject: [PATCH 05/17] fix unresolved todos --- .../handler/SharedRoleMgtHandler.java | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index 6dd8f8d3c..9b003f051 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -32,6 +32,7 @@ import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; 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 org.wso2.carbon.identity.organization.management.service.model.Organization; import org.wso2.carbon.identity.organization.management.service.model.ParentOrganizationDO; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; @@ -149,27 +150,21 @@ private void createSubOrgRolesOnNewRoleCreation(Map eventPropert break; case RoleConstants.ORGANIZATION: // If the audienced organization is a shared organization, create the role in the shared orgs. - getOrganizationManager().getChildOrganizations(roleOrgId, true).forEach(childOrg -> { - try { - String sharedOrganizationId = childOrg.getId(); - String shareAppTenantDomain = - getOrganizationManager().resolveTenantDomain(sharedOrganizationId); - RoleBasicInfo sharedRoleInfo = - getRoleManagementServiceV2().addRole(mainRoleName, Collections.emptyList(), - Collections.emptyList(), Collections.emptyList(), - RoleConstants.ORGANIZATION, sharedOrganizationId, - shareAppTenantDomain); - // Add relationship between main role and shared role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, - sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); - } catch (OrganizationManagementException e) { - //TODO : handle exception - throw new RuntimeException(e); - } catch (IdentityRoleManagementException e) { - //TODO : handle exception - throw new RuntimeException(e); - } - }); + List childOrganizations = + getOrganizationManager().getChildOrganizations(roleOrgId, true); + for (BasicOrganization childOrg : childOrganizations) { + String sharedOrganizationId = childOrg.getId(); + String shareAppTenantDomain = + getOrganizationManager().resolveTenantDomain(sharedOrganizationId); + RoleBasicInfo sharedRoleInfo = + getRoleManagementServiceV2().addRole(mainRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), + RoleConstants.ORGANIZATION, sharedOrganizationId, + shareAppTenantDomain); + // Add relationship between main role and shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, + sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); + } break; default: LOG.error("Unsupported audience type: " + roleAudienceType); From 5bfbc2d1ab3b5fdde11c9ab1c3292dbed09e90a6 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 16 Oct 2023 14:11:43 +0530 Subject: [PATCH 06/17] change org check --- .../management/handler/SharedRoleMgtHandler.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index 9b003f051..49a4627d3 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -35,11 +35,11 @@ import org.wso2.carbon.identity.organization.management.service.model.BasicOrganization; import org.wso2.carbon.identity.organization.management.service.model.Organization; import org.wso2.carbon.identity.organization.management.service.model.ParentOrganizationDO; +import org.wso2.carbon.identity.organization.management.service.util.Utils; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; -import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import java.util.Collections; import java.util.List; @@ -124,8 +124,7 @@ private void createSubOrgRolesOnNewRoleCreation(Map eventPropert String roleAudienceType = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE); String roleAudienceId = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE_ID); String roleOrgId = getOrganizationManager().resolveOrganizationId(roleTenantDomain); - boolean isPrimaryOrganization = getOrganizationManager().isPrimaryOrganization(roleOrgId); - if (!isPrimaryOrganization && !MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(roleTenantDomain)) { + if (Utils.isOrganization(roleTenantDomain)) { return; } switch (roleAudienceType) { From bdd9bd3ea52d7f8ac01631e314ae8bc8817a5600 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Tue, 17 Oct 2023 20:15:44 +0530 Subject: [PATCH 07/17] fix comments --- .../pom.xml | 7 +- .../handler/SharedRoleMgtHandler.java | 87 +++++++++++++------ 2 files changed, 67 insertions(+), 27 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml index 4b83187da..4a84f46be 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml @@ -128,7 +128,12 @@ org.wso2.carbon.identity.recovery.*; version="${identity.governance.imp.pkg.version.range}", org.wso2.carbon.identity.governance; version="${identity.governance.imp.pkg.version.range}", org.wso2.carbon.identity.role.v2.mgt.core.*; version="${carbon.identity.package.import.version.range}", - org.wso2.carbon.identity.organization.management.application.*; version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.management.application.*; + version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", + org.wso2.carbon.identity.application.mgt.*; + version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.application.common.*; + version="${carbon.identity.package.import.version.range}", diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index 49a4627d3..4478d80c0 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -35,7 +35,7 @@ import org.wso2.carbon.identity.organization.management.service.model.BasicOrganization; import org.wso2.carbon.identity.organization.management.service.model.Organization; import org.wso2.carbon.identity.organization.management.service.model.ParentOrganizationDO; -import org.wso2.carbon.identity.organization.management.service.util.Utils; +import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; @@ -44,6 +44,9 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Event handler to manage shared roles in sub-organizations. @@ -51,6 +54,7 @@ public class SharedRoleMgtHandler extends AbstractEventHandler { private static final Log LOG = LogFactory.getLog(SharedRoleMgtHandler.class); + private final ExecutorService executorService = Executors.newFixedThreadPool(5); @Override public void handleEvent(Event event) throws IdentityEventException { @@ -60,28 +64,33 @@ public void handleEvent(Event event) throws IdentityEventException { switch (eventName) { case OrgApplicationMgtConstants.EVENT_POST_SHARE_APPLICATION: /* - If the main application use application audienced roles, create the role for sub org space, - and add the relationship. + If the main application use application audienced roles, create the role for shared app's org space, + and add the relationship. If the main application use organization audienced roles, create the role in + shared app's org space, and add the relationship if already not exists. */ - createSubOrgRolesOnAppSharing(eventProperties); + createOrganizationRolesOnAppSharing(eventProperties); break; case IdentityEventConstants.Event.POST_ADD_ROLE_V2_EVENT: - createSubOrgRolesOnNewRoleCreation(eventProperties); + createOrganizationRolesOnNewRoleCreation(eventProperties); break; case Constants.EVENT_POST_ADD_ORGANIZATION: /* - If the org is a sub organization and if primary org has roles with organization audience, + If the created org's primary business org has roles with organization audience, create them in the sub org as well. */ - createSubOrgRolesOnNewOrgCreation(eventProperties); + // TODO: This might not required with new approach of handling org audience roles + createOrganizationRolesOnNewOrgCreation(eventProperties); break; default: - LOG.debug("Unsupported event: " + eventName); + if (LOG.isDebugEnabled()) { + LOG.debug("Unsupported event: " + eventName); + } break; } } - private void createSubOrgRolesOnNewOrgCreation(Map eventProperties) throws IdentityEventException { + private void createOrganizationRolesOnNewOrgCreation(Map eventProperties) + throws IdentityEventException { try { Organization organization = (Organization) eventProperties.get(Constants.EVENT_PROP_ORGANIZATION); @@ -115,7 +124,8 @@ private void createSubOrgRolesOnNewOrgCreation(Map eventProperti } } - private void createSubOrgRolesOnNewRoleCreation(Map eventProperties) throws IdentityEventException { + private void createOrganizationRolesOnNewRoleCreation(Map eventProperties) + throws IdentityEventException { try { String mainRoleUUID = (String) eventProperties.get(IdentityEventConstants.EventProperty.ROLE_ID); @@ -124,30 +134,53 @@ private void createSubOrgRolesOnNewRoleCreation(Map eventPropert String roleAudienceType = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE); String roleAudienceId = (String) eventProperties.get(IdentityEventConstants.EventProperty.AUDIENCE_ID); String roleOrgId = getOrganizationManager().resolveOrganizationId(roleTenantDomain); - if (Utils.isOrganization(roleTenantDomain)) { + if (OrganizationManagementUtil.isOrganization(roleTenantDomain)) { return; } switch (roleAudienceType) { case RoleConstants.APPLICATION: - // If the audienced application is a shared application, create the role in the shared apps. + /* + If the audienced application is a shared application, create the role in + the shared apps' org space. + */ List sharedApplications = getOrgApplicationManager().getSharedApplications(roleOrgId, roleAudienceId); - for (SharedApplication sharedApplication : sharedApplications) { - String sharedApplicationId = sharedApplication.getSharedApplicationId(); - String sharedOrganizationId = sharedApplication.getOrganizationId(); - String shareAppTenantDomain = - getOrganizationManager().resolveTenantDomain(sharedOrganizationId); - RoleBasicInfo sharedRoleInfo = - getRoleManagementServiceV2().addRole(mainRoleName, Collections.emptyList(), - Collections.emptyList(), - Collections.emptyList(), RoleConstants.APPLICATION, sharedApplicationId, - shareAppTenantDomain); - // Add relationship between main role and shared role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, - sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); + int noOfSharedApps = sharedApplications.size(); + CompletableFuture[] creations = new CompletableFuture[noOfSharedApps]; + for (int i = 0; i < noOfSharedApps; i++) { + final int taskId = i; + CompletableFuture sharedRoleCreation = CompletableFuture.runAsync(() -> { + try { + String sharedApplicationId = sharedApplications.get(taskId).getSharedApplicationId(); + String sharedOrganizationId = sharedApplications.get(taskId).getOrganizationId(); + String shareAppTenantDomain = + getOrganizationManager().resolveTenantDomain(sharedOrganizationId); + RoleBasicInfo sharedRoleInfo = + getRoleManagementServiceV2().addRole(mainRoleName, Collections.emptyList(), + Collections.emptyList(), + Collections.emptyList(), RoleConstants.APPLICATION, sharedApplicationId, + shareAppTenantDomain); + // Add relationship between main role and shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, + sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); + } catch (IdentityRoleManagementException | OrganizationManagementException e) { + LOG.error("Error occurred while creating shared role in organization with id: " + + sharedApplications.get(taskId).getOrganizationId(), e); + } + }, executorService); + creations[taskId] = sharedRoleCreation; } + CompletableFuture allOfCreations = CompletableFuture.allOf(creations); + allOfCreations.join(); break; case RoleConstants.ORGANIZATION: + /* + TODO: Need to create organization roles in suborgs only if the role is + attahced to at least on shared role + on new org role creation, this role can't be associated to an app. + therefore this logic can be removed + + */ // If the audienced organization is a shared organization, create the role in the shared orgs. List childOrganizations = getOrganizationManager().getChildOrganizations(roleOrgId, true); @@ -175,7 +208,8 @@ private void createSubOrgRolesOnNewRoleCreation(Map eventPropert } } - private void createSubOrgRolesOnAppSharing(Map eventProperties) throws IdentityEventException { + private void createOrganizationRolesOnAppSharing(Map eventProperties) + throws IdentityEventException { String parentOrganizationId = (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_ORGANIZATION_ID); @@ -193,6 +227,7 @@ private void createSubOrgRolesOnAppSharing(Map eventProperties) boolean hasAppAudiencedRoles = RoleConstants.APPLICATION.equalsIgnoreCase(allowedAudienceForRoleAssociation); if (!hasAppAudiencedRoles) { + // TODO: handle organization audience role creation if they doesn't exist in sub org. return; } // Create the role if not exists, and add the relationship. From c41aecbb1a74394f5efce034ff98b79c0ccf3089 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Wed, 18 Oct 2023 16:30:16 +0530 Subject: [PATCH 08/17] handle organization audience role deletion on app unsharing and app deletion --- .../pom.xml | 1 + .../handler/SharedRoleMgtHandler.java | 18 +- ...tionManagementHandlerServiceComponent.java | 3 + .../listener/SharedRoleMgtListener.java | 189 ++++++++++++++++++ 4 files changed, 201 insertions(+), 10 deletions(-) create mode 100644 components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java diff --git a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml index 4a84f46be..eaab42b05 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml @@ -134,6 +134,7 @@ version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.application.common.*; version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.core.util;version="${carbon.identity.package.import.version.range}", diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index 4478d80c0..ff2c66a3d 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -21,6 +21,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.event.IdentityEventConstants; import org.wso2.carbon.identity.event.IdentityEventException; import org.wso2.carbon.identity.event.event.Event; @@ -73,14 +74,6 @@ public void handleEvent(Event event) throws IdentityEventException { case IdentityEventConstants.Event.POST_ADD_ROLE_V2_EVENT: createOrganizationRolesOnNewRoleCreation(eventProperties); break; - case Constants.EVENT_POST_ADD_ORGANIZATION: - /* - If the created org's primary business org has roles with organization audience, - create them in the sub org as well. - */ - // TODO: This might not required with new approach of handling org audience roles - createOrganizationRolesOnNewOrgCreation(eventProperties); - break; default: if (LOG.isDebugEnabled()) { LOG.debug("Unsupported event: " + eventName); @@ -222,8 +215,8 @@ private void createOrganizationRolesOnAppSharing(Map eventProper try { String mainApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); String allowedAudienceForRoleAssociation = - OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService() - .getAllowedAudienceForRoleAssociation(parentApplicationId, mainApplicationTenantDomain); + getApplicationMgtService().getAllowedAudienceForRoleAssociation(parentApplicationId, + mainApplicationTenantDomain); boolean hasAppAudiencedRoles = RoleConstants.APPLICATION.equalsIgnoreCase(allowedAudienceForRoleAssociation); if (!hasAppAudiencedRoles) { @@ -271,4 +264,9 @@ private static OrgApplicationManager getOrgApplicationManager() { return OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager(); } + + private static ApplicationManagementService getApplicationMgtService() { + + return OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService(); + } } diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java index 9d13faabf..742934cdf 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/internal/OrganizationManagementHandlerServiceComponent.java @@ -28,12 +28,14 @@ import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.application.mgt.listener.ApplicationMgtListener; import org.wso2.carbon.identity.event.handler.AbstractEventHandler; import org.wso2.carbon.identity.event.services.IdentityEventService; import org.wso2.carbon.identity.governance.IdentityGovernanceService; import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; import org.wso2.carbon.identity.organization.management.handler.GovernanceConfigUpdateHandler; import org.wso2.carbon.identity.organization.management.handler.SharedRoleMgtHandler; +import org.wso2.carbon.identity.organization.management.handler.listener.SharedRoleMgtListener; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; @@ -60,6 +62,7 @@ protected void activate(ComponentContext componentContext) { BundleContext bundleContext = componentContext.getBundleContext(); bundleContext.registerService(AbstractEventHandler.class, new GovernanceConfigUpdateHandler(), null); bundleContext.registerService(AbstractEventHandler.class, new SharedRoleMgtHandler(), null); + bundleContext.registerService(ApplicationMgtListener.class.getName(), new SharedRoleMgtListener(), null); LOG.debug("Organization management handler component activated successfully."); } catch (Throwable e) { LOG.error("Error while activating organization management handler module.", e); diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java new file mode 100644 index 000000000..5b4e6a808 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -0,0 +1,189 @@ +/* + * 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.handler.listener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.RoleV2; +import org.wso2.carbon.identity.application.common.model.ServiceProvider; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.application.mgt.listener.AbstractApplicationMgtListener; +import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; +import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; +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.util.OrganizationManagementUtil; +import org.wso2.carbon.identity.role.v2.mgt.core.AssociatedApplication; +import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; +import org.wso2.carbon.identity.role.v2.mgt.core.Role; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.SUPER_ORG_ID; + +/** + * Application management listener to handle shared roles in organizations. + */ +public class SharedRoleMgtListener extends AbstractApplicationMgtListener { + + private static final Log LOG = LogFactory.getLog(SharedRoleMgtListener.class); + + @Override + public int getDefaultOrderId() { + + return 49; + } + + @Override + public boolean doPreDeleteApplication(String applicationName, String tenantDomain, String userName) + throws IdentityApplicationManagementException { + + try { + // If the deleting application is an application of tenant(i.e primary org) nothing to do here. + if (!OrganizationManagementUtil.isOrganization(tenantDomain)) { + return true; + } + + ServiceProvider sharedApplication = getApplicationByName(applicationName, tenantDomain); + if (sharedApplication == null) { + return false; + } + String sharedAppId = sharedApplication.getApplicationResourceId(); + // Get all the shared applications of the deleting app. + String sharedAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + // Resolve the main application details. + String mainAppId = + getOrgApplicationManager().getMainApplicationIdForGivenSharedApp(sharedAppId, sharedAppOrgId); + if (mainAppId == null) { + return false; + } + int mainAppTenantId = getApplicationMgtService().getTenantIdByApp(mainAppId); + String mainAppTenantDomain = IdentityTenantUtil.getTenantDomain(mainAppTenantId); + String mainAppOrgId = getOrganizationManager().resolveOrganizationId(mainAppTenantDomain); + if (mainAppOrgId == null) { + mainAppOrgId = SUPER_ORG_ID; + } + String allowedAudienceForRoleAssociationInMainApp = + getApplicationMgtService().getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain); + boolean hasAppAudiencedRoles = + RoleConstants.APPLICATION.equalsIgnoreCase(allowedAudienceForRoleAssociationInMainApp); + if (hasAppAudiencedRoles) { + // Handle role deletion in application deletion post actions. + return true; + } + + // Handing organization audienced roles associated case. + handleOrganizationAudiencedSharedRoleDeletion(mainAppId, mainAppTenantDomain, mainAppOrgId, tenantDomain, + sharedAppOrgId); + } catch (OrganizationManagementException | IdentityRoleManagementException e) { + throw new IdentityApplicationManagementException( + "Error while deleting organization roles associated to the app.", e); + } + return super.doPreDeleteApplication(applicationName, tenantDomain, userName); + } + + private void handleOrganizationAudiencedSharedRoleDeletion(String mainApplicationId, + String mainApplicationTenantDomain, + String mainApplicationOrgId, + String unsharedApplicationTenantDomain, + String appUnsharedOrgId) + throws IdentityRoleManagementException, IdentityApplicationManagementException, + OrganizationManagementException { + + List associatedRolesOfMainApplication = getApplicationMgtService() + .getAssociatedRolesOfApplication(mainApplicationId, mainApplicationTenantDomain); + List mainAppRoleIds = + associatedRolesOfMainApplication.stream().map(RoleV2::getId).collect(Collectors.toList()); + Map mainRoleToSharedRoleMappingsInSubOrg = getRoleManagementServiceV2() + .getMainRoleToSharedRoleMappingsBySubOrg(mainAppRoleIds, unsharedApplicationTenantDomain); + + // Get each role associated applications. + for (String mainAppRoleId : mainAppRoleIds) { + // TODO use a service which return only associated role ids. + Role role = getRoleManagementServiceV2().getRole(mainAppRoleId, mainApplicationTenantDomain); + List associatedApplications = role.getAssociatedApplications(); + + if (associatedApplications == null) { + continue; + } + /* + If the only associated application is the main app in this flow, delete the role in + the app unsharing org. + */ + if (associatedApplications.size() == 1 && mainApplicationId.equals(associatedApplications.get(0).getId())) { + // Delete the role in app unsharing org. + getRoleManagementServiceV2().deleteRole(mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId), + unsharedApplicationTenantDomain); + break; + } else if (associatedApplications.size() > 1) { + boolean isRoleUsedByAnotherSharedApp = false; + for (AssociatedApplication associatedApplication : associatedApplications) { + if (associatedApplication.getId().equals(mainApplicationId)) { + continue; + } + boolean applicationSharedWithGivenOrganization = + getOrgApplicationManager().isApplicationSharedWithGivenOrganization( + associatedApplication.getId(), mainApplicationOrgId, appUnsharedOrgId); + if (applicationSharedWithGivenOrganization) { + isRoleUsedByAnotherSharedApp = true; + break; + } + } + if (!isRoleUsedByAnotherSharedApp) { + // Delete the role in app unsharing org. + getRoleManagementServiceV2().deleteRole(mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId), + unsharedApplicationTenantDomain); + break; + } + } + } + } + + private ServiceProvider getApplicationByName(String name, String tenantDomain) + throws IdentityApplicationManagementException { + + return getApplicationMgtService().getServiceProvider(name, tenantDomain); + } + + private static OrganizationManager getOrganizationManager() { + + return OrganizationManagementHandlerDataHolder.getInstance().getOrganizationManager(); + } + + private static OrgApplicationManager getOrgApplicationManager() { + + return OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager(); + } + + private static ApplicationManagementService getApplicationMgtService() { + + return OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService(); + } + + private static RoleManagementService getRoleManagementServiceV2() { + + return OrganizationManagementHandlerDataHolder.getInstance().getRoleManagementServiceV2(); + } +} From 4a38511506695f78309c46d2b38b475a589f167e Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Fri, 20 Oct 2023 18:31:27 +0530 Subject: [PATCH 09/17] update shared role management on app associated role update --- .../pom.xml | 5 +- .../handler/SharedRoleMgtHandler.java | 143 +----- .../listener/SharedRoleMgtListener.java | 436 +++++++++++++++++- 3 files changed, 429 insertions(+), 155 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml index eaab42b05..19a1cc331 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml @@ -68,7 +68,10 @@ org.wso2.carbon.identity.framework org.wso2.carbon.identity.role.v2.mgt.core - + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.mgt + org.testng diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index ff2c66a3d..d47f38cb6 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -20,22 +20,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; -import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; 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.constant.OrgApplicationMgtConstants; import org.wso2.carbon.identity.organization.management.application.model.SharedApplication; -import org.wso2.carbon.identity.organization.management.ext.Constants; import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; 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 org.wso2.carbon.identity.organization.management.service.model.Organization; -import org.wso2.carbon.identity.organization.management.service.model.ParentOrganizationDO; import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; @@ -63,14 +56,6 @@ public void handleEvent(Event event) throws IdentityEventException { String eventName = event.getEventName(); Map eventProperties = event.getEventProperties(); switch (eventName) { - case OrgApplicationMgtConstants.EVENT_POST_SHARE_APPLICATION: - /* - If the main application use application audienced roles, create the role for shared app's org space, - and add the relationship. If the main application use organization audienced roles, create the role in - shared app's org space, and add the relationship if already not exists. - */ - createOrganizationRolesOnAppSharing(eventProperties); - break; case IdentityEventConstants.Event.POST_ADD_ROLE_V2_EVENT: createOrganizationRolesOnNewRoleCreation(eventProperties); break; @@ -82,41 +67,6 @@ public void handleEvent(Event event) throws IdentityEventException { } } - private void createOrganizationRolesOnNewOrgCreation(Map eventProperties) - throws IdentityEventException { - - try { - Organization organization = (Organization) eventProperties.get(Constants.EVENT_PROP_ORGANIZATION); - String organizationId = organization.getId(); - if (getOrganizationManager().isPrimaryOrganization(organizationId)) { - return; - } - String subOrgTenantDomain = getOrganizationManager().resolveTenantDomain(organizationId); - ParentOrganizationDO parentOrg = organization.getParent(); - String parentOrgId = parentOrg.getId(); - // Get parent organization's roles which has organization audience. - String filter = RoleConstants.AUDIENCE_ID + " " + RoleConstants.EQ + " " + parentOrg.getId(); - String parenTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrgId); - List parentOrgRoles = - getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, parenTenantDomain); - for (RoleBasicInfo parentOrgRole : parentOrgRoles) { - String parentOrgRoleName = parentOrgRole.getName(); - // Create the role in the sub org. - RoleBasicInfo subOrgRole = - getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), - Collections.emptyList(), Collections.emptyList(), RoleConstants.ORGANIZATION, - organizationId, subOrgTenantDomain); - // Add relationship between parent org role and sub org role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), - subOrgRole.getId(), parenTenantDomain, subOrgTenantDomain); - } - } catch (OrganizationManagementException e) { - throw new IdentityEventException("Error occurred while resolving organization id from tenant domain.", e); - } catch (IdentityRoleManagementException e) { - throw new IdentityEventException("Error occurred while adding main role to shared role relationship.", e); - } - } - private void createOrganizationRolesOnNewRoleCreation(Map eventProperties) throws IdentityEventException { @@ -139,10 +89,9 @@ private void createOrganizationRolesOnNewRoleCreation(Map eventP List sharedApplications = getOrgApplicationManager().getSharedApplications(roleOrgId, roleAudienceId); int noOfSharedApps = sharedApplications.size(); - CompletableFuture[] creations = new CompletableFuture[noOfSharedApps]; for (int i = 0; i < noOfSharedApps; i++) { final int taskId = i; - CompletableFuture sharedRoleCreation = CompletableFuture.runAsync(() -> { + CompletableFuture.runAsync(() -> { try { String sharedApplicationId = sharedApplications.get(taskId).getSharedApplicationId(); String sharedOrganizationId = sharedApplications.get(taskId).getOrganizationId(); @@ -160,93 +109,26 @@ private void createOrganizationRolesOnNewRoleCreation(Map eventP LOG.error("Error occurred while creating shared role in organization with id: " + sharedApplications.get(taskId).getOrganizationId(), e); } - }, executorService); - creations[taskId] = sharedRoleCreation; + }, executorService).exceptionally(throwable -> { + LOG.error(String.format( + "Exception occurred during creating a shared role: %s in organization: %s", + mainRoleName, sharedApplications.get(taskId).getOrganizationId()), throwable); + return null; + }); } - CompletableFuture allOfCreations = CompletableFuture.allOf(creations); - allOfCreations.join(); break; case RoleConstants.ORGANIZATION: /* - TODO: Need to create organization roles in suborgs only if the role is - attahced to at least on shared role - on new org role creation, this role can't be associated to an app. - therefore this logic can be removed - + Organization audience roles can't be attached to an application at the same time of role creation. + Organization audience role get shared to other application only if that role is associated with any + shared application in the organization. So nothing do in this case. */ - // If the audienced organization is a shared organization, create the role in the shared orgs. - List childOrganizations = - getOrganizationManager().getChildOrganizations(roleOrgId, true); - for (BasicOrganization childOrg : childOrganizations) { - String sharedOrganizationId = childOrg.getId(); - String shareAppTenantDomain = - getOrganizationManager().resolveTenantDomain(sharedOrganizationId); - RoleBasicInfo sharedRoleInfo = - getRoleManagementServiceV2().addRole(mainRoleName, Collections.emptyList(), - Collections.emptyList(), Collections.emptyList(), - RoleConstants.ORGANIZATION, sharedOrganizationId, - shareAppTenantDomain); - // Add relationship between main role and shared role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(mainRoleUUID, - sharedRoleInfo.getId(), roleTenantDomain, shareAppTenantDomain); - } break; default: LOG.error("Unsupported audience type: " + roleAudienceType); } } catch (OrganizationManagementException e) { throw new IdentityEventException("Error occurred while retrieving shared applications.", e); - } catch (IdentityRoleManagementException e) { - throw new IdentityEventException("Error occurred while adding main role to shared role relationship.", e); - } - } - - private void createOrganizationRolesOnAppSharing(Map eventProperties) - throws IdentityEventException { - - String parentOrganizationId = - (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_ORGANIZATION_ID); - String parentApplicationId = - (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_APPLICATION_ID); - String sharedOrganizationId = - (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_ORGANIZATION_ID); - String sharedApplicationId = - (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_APPLICATION_ID); - try { - String mainApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); - String allowedAudienceForRoleAssociation = - getApplicationMgtService().getAllowedAudienceForRoleAssociation(parentApplicationId, - mainApplicationTenantDomain); - boolean hasAppAudiencedRoles = - RoleConstants.APPLICATION.equalsIgnoreCase(allowedAudienceForRoleAssociation); - if (!hasAppAudiencedRoles) { - // TODO: handle organization audience role creation if they doesn't exist in sub org. - return; - } - // Create the role if not exists, and add the relationship. - String sharedApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationId); - // Get parent organization's roles which has application audience. - String filter = RoleConstants.AUDIENCE_ID + " " + RoleConstants.EQ + " " + parentApplicationId; - List parentOrgRoles = - getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, - mainApplicationTenantDomain); - for (RoleBasicInfo parentOrgRole : parentOrgRoles) { - String parentOrgRoleName = parentOrgRole.getName(); - // Create the role in the sub org. - RoleBasicInfo subOrgRole = - getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), - Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, - sharedApplicationId, sharedApplicationTenantDomain); - // Add relationship between parent org role and sub org role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), - subOrgRole.getId(), mainApplicationTenantDomain, sharedApplicationTenantDomain); - } - } catch (IdentityApplicationManagementException e) { - throw new IdentityEventException("Error occurred checking main application allowed role audience.", e); - } catch (OrganizationManagementException e) { - throw new IdentityEventException("Error occurred while resolving tenant domain from organization id.", e); - } catch (IdentityRoleManagementException e) { - throw new IdentityEventException("Error occurred while adding main role to shared role relationship.", e); } } @@ -264,9 +146,4 @@ private static OrgApplicationManager getOrgApplicationManager() { return OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager(); } - - private static ApplicationManagementService getApplicationMgtService() { - - return OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService(); - } } diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java index 5b4e6a808..c47191d8a 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -18,6 +18,8 @@ package org.wso2.carbon.identity.organization.management.handler.listener; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; @@ -26,7 +28,9 @@ import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; import org.wso2.carbon.identity.application.mgt.listener.AbstractApplicationMgtListener; import org.wso2.carbon.identity.core.util.IdentityTenantUtil; +import org.wso2.carbon.identity.core.util.IdentityUtil; import org.wso2.carbon.identity.organization.management.application.OrgApplicationManager; +import org.wso2.carbon.identity.organization.management.application.model.SharedApplication; import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; @@ -34,13 +38,20 @@ import org.wso2.carbon.identity.role.v2.mgt.core.AssociatedApplication; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; import org.wso2.carbon.identity.role.v2.mgt.core.Role; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; +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.application.constant.OrgApplicationMgtConstants.IS_FRAGMENT_APP; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.SUPER_ORG_ID; /** @@ -49,6 +60,12 @@ public class SharedRoleMgtListener extends AbstractApplicationMgtListener { private static final Log LOG = LogFactory.getLog(SharedRoleMgtListener.class); + private static final String REMOVED_APPLICATION_AUDIENCE_ROLES = "removedApplicationAudienceRoles"; + private static final String ADDED_APPLICATION_AUDIENCE_ROLES = "addedApplicationAudienceRoles"; + private static final String REMOVED_ORGANIZATION_AUDIENCE_ROLES = "removedOrganizationAudienceRoles"; + private static final String ADDED_ORGANIZATION_AUDIENCE_ROLES = "addedOrganizationAudienceRoles"; + + private final ExecutorService executorService = Executors.newFixedThreadPool(5); @Override public int getDefaultOrderId() { @@ -56,6 +73,385 @@ public int getDefaultOrderId() { return 49; } + @Override + public boolean doPostCreateApplication(ServiceProvider serviceProvider, String tenantDomain, String userName) + throws IdentityApplicationManagementException { + + // If the creating application is an application of tenant(i.e primary org) nothing to do here. + try { + if (!OrganizationManagementUtil.isOrganization(tenantDomain)) { + return true; + } + boolean isSharedAppInOrg = Arrays.stream(serviceProvider.getSpProperties()) + .anyMatch(p -> IS_FRAGMENT_APP.equalsIgnoreCase(p.getName()) && Boolean.parseBoolean(p.getValue())); + if (!isSharedAppInOrg) { + // This is not a valid case. Organization could only have shared applications. + return true; + } + ServiceProvider sharedApplication = + getApplicationByName(serviceProvider.getApplicationName(), tenantDomain); + if (sharedApplication == null) { + return false; + } + String sharedAppId = sharedApplication.getApplicationResourceId(); + String sharedAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + // Resolve the main application details. + String mainAppId = + getOrgApplicationManager().getMainApplicationIdForGivenSharedApp(sharedAppId, sharedAppOrgId); + if (mainAppId == null) { + return false; + } + int mainAppTenantId = getApplicationMgtService().getTenantIdByApp(mainAppId); + String mainAppTenantDomain = IdentityTenantUtil.getTenantDomain(mainAppTenantId); + String allowedAudienceForRoleAssociationInMainApp = + getApplicationMgtService().getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain); + + switch (allowedAudienceForRoleAssociationInMainApp) { + case RoleConstants.APPLICATION: + // Create the roles, and add the relationship. + createSharedRolesWithAppAudience(mainAppId, mainAppTenantDomain, sharedAppId, + sharedAppTenantDomain); + break; + default: + // Create the role if not exists, and add the relationship. + List associatedRolesOfApplication = + getApplicationMgtService().getAssociatedRolesOfApplication( + mainAppId, mainAppTenantDomain); + createSharedRolesWithOrgAudience(associatedRolesOfApplication, mainAppTenantDomain, sharedAppOrgId); + break; + } + } catch (OrganizationManagementException | IdentityRoleManagementException e) { + throw new IdentityApplicationManagementException( + String.format("Error while sharing roles related to application %s.", + serviceProvider.getApplicationID()), e); + } + return super.doPostCreateApplication(serviceProvider, tenantDomain, userName); + } + + private void createSharedRolesWithOrgAudience(List rolesList, String mainAppTenantDomain, + String sharedAppOrgId) + throws IdentityRoleManagementException, OrganizationManagementException { + + if (rolesList == null) { + return; + } + String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + for (RoleV2 role : rolesList) { + // Check if the role exists in the application shared org. + boolean roleExistsInSharedOrg = + getRoleManagementServiceV2().isExistingRoleName(role.getName(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + Map mainRoleToSharedRoleMappingInSharedOrg = + getRoleManagementServiceV2().getMainRoleToSharedRoleMappingsBySubOrg( + Collections.singletonList(role.getId()), sharedAppTenantDomain); + boolean roleRelationshipExistsInSharedOrg = + MapUtils.isNotEmpty(mainRoleToSharedRoleMappingInSharedOrg); + if (roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { + // Add relationship between main role and shared role. + String roleIdInSharedOrg = + getRoleManagementServiceV2().getRoleIdByName(role.getName(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + roleIdInSharedOrg, mainAppTenantDomain, sharedAppTenantDomain); + } else if (!roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { + // Create the role in the shared org. + RoleBasicInfo sharedRole = + getRoleManagementServiceV2().addRole(role.getName(), Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + // Add relationship between main role and shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + sharedRole.getId(), mainAppTenantDomain, sharedAppTenantDomain); + } + } + } + + private void createSharedRolesWithAppAudience(String mainAppId, String mainAppTenantDomain, String sharedAppId, + String sharedAppTenantDomain) throws IdentityRoleManagementException { + + // Get parent organization's roles which has application audience. + String filter = RoleConstants.AUDIENCE_ID + " " + RoleConstants.EQ + " " + mainAppId; + List parentOrgRoles = + getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, mainAppTenantDomain); + for (RoleBasicInfo parentOrgRole : parentOrgRoles) { + String parentOrgRoleName = parentOrgRole.getName(); + // Create the role in the shared org. + RoleBasicInfo subOrgRole = getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, sharedAppId, + sharedAppTenantDomain); + // Add relationship between main role and the shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), subOrgRole.getId(), + mainAppTenantDomain, sharedAppTenantDomain); + } + } + + @Override + public boolean doPreUpdateApplication(ServiceProvider serviceProvider, String tenantDomain, String userName) + throws IdentityApplicationManagementException { + + // Associated role changes on main applications in tenant need to be handled here. + try { + if (OrganizationManagementUtil.isOrganization(tenantDomain)) { + return true; + } + String applicationResourceId = serviceProvider.getApplicationResourceId(); + // Get the currently associated roles set from DB/cache. + String existingAllowedAudienceForRoleAssociation = + getApplicationMgtService().getAllowedAudienceForRoleAssociation(applicationResourceId, + tenantDomain); + List existingAssociatedRolesList = + getApplicationMgtService().getAssociatedRolesOfApplication(applicationResourceId, tenantDomain); + + String updatedAllowedAudienceForRoleAssociation = + serviceProvider.getAssociatedRolesConfig() == null ? RoleConstants.ORGANIZATION : + serviceProvider.getAssociatedRolesConfig().getAllowedAudience(); + List updatedAssociatedRolesList = + serviceProvider.getAssociatedRolesConfig() == null ? Collections.emptyList() : + serviceProvider.getAssociatedRolesConfig().getRoles(); + + if (CollectionUtils.isEmpty(existingAssociatedRolesList) && + CollectionUtils.isEmpty(updatedAssociatedRolesList)) { + // No change in roles list. + return true; + } + + /* + if old and new audiences are equals, need to handle the role diff. + */ + if (existingAllowedAudienceForRoleAssociation.equalsIgnoreCase(updatedAllowedAudienceForRoleAssociation)) { + switch (updatedAllowedAudienceForRoleAssociation) { + case RoleConstants.APPLICATION: + List addedApplicationAudienceRoles = updatedAssociatedRolesList.stream() + .filter(updatedRole -> !existingAssociatedRolesList.contains(updatedRole)) + .collect(Collectors.toList()); + + List removedApplicationAudienceRoles = existingAssociatedRolesList.stream() + .filter(existingRole -> !updatedAssociatedRolesList.contains(existingRole)) + .collect(Collectors.toList()); + // Add to threadLocal. + IdentityUtil.threadLocalProperties.get() + .put(ADDED_APPLICATION_AUDIENCE_ROLES, addedApplicationAudienceRoles); + IdentityUtil.threadLocalProperties.get() + .put(REMOVED_APPLICATION_AUDIENCE_ROLES, removedApplicationAudienceRoles); + return true; + default: + if (existingAssociatedRolesList.equals(updatedAssociatedRolesList)) { + // Nothing to change in shared applications' organizations. + return true; + } + // Get the added roles and removed roles. + List addedOrganizationAudienceRoles = updatedAssociatedRolesList.stream() + .filter(updatedRole -> !existingAssociatedRolesList.contains(updatedRole)) + .collect(Collectors.toList()); + + List removedOrganizationAudienceRoles = existingAssociatedRolesList.stream() + .filter(existingRole -> !updatedAssociatedRolesList.contains(existingRole)) + .collect(Collectors.toList()); + // Add to threadLocal. + IdentityUtil.threadLocalProperties.get() + .put(ADDED_ORGANIZATION_AUDIENCE_ROLES, addedOrganizationAudienceRoles); + IdentityUtil.threadLocalProperties.get() + .put(REMOVED_ORGANIZATION_AUDIENCE_ROLES, removedOrganizationAudienceRoles); + return true; + } + } + + /* + If audience has changed from application to organization, all previous associated roles will be deleted. + For updated organization roles, create shared role in organizations below if applicable. + */ + if (RoleConstants.APPLICATION.equalsIgnoreCase(existingAllowedAudienceForRoleAssociation) && + RoleConstants.ORGANIZATION.equalsIgnoreCase(updatedAllowedAudienceForRoleAssociation)) { + + // Add to thread local. + IdentityUtil.threadLocalProperties.get() + .put(REMOVED_APPLICATION_AUDIENCE_ROLES, existingAssociatedRolesList); + IdentityUtil.threadLocalProperties.get() + .put(ADDED_ORGANIZATION_AUDIENCE_ROLES, updatedAssociatedRolesList); + return true; + } + + /* + If audience has changed from organization to application, need to remove the organization roles. + Nothing to handle in application audience roles because they will be added/deleted in shared orgs + based on role creation/deletion. + */ + if (RoleConstants.ORGANIZATION.equalsIgnoreCase(existingAllowedAudienceForRoleAssociation) && + RoleConstants.APPLICATION.equalsIgnoreCase(updatedAllowedAudienceForRoleAssociation)) { + + // Add to thread local. + IdentityUtil.threadLocalProperties.get() + .put(REMOVED_ORGANIZATION_AUDIENCE_ROLES, existingAssociatedRolesList); + return true; + } + } catch (OrganizationManagementException e) { + throw new IdentityApplicationManagementException( + String.format("Error while checking shared roles to be updated related to application %s update.", + serviceProvider.getApplicationID()), e); + } + return true; + } + + @Override + public boolean doPostUpdateApplication(ServiceProvider serviceProvider, String tenantDomain, String userName) + throws IdentityApplicationManagementException { + + try { + if (OrganizationManagementUtil.isOrganization(tenantDomain)) { + return true; + } + Object addedAppRoles = IdentityUtil.threadLocalProperties.get().get(ADDED_APPLICATION_AUDIENCE_ROLES); + if (addedAppRoles != null) { + List addedAppRolesList = (List) addedAppRoles; + handleAddedApplicationAudienceRolesOnAppUpdate(addedAppRolesList, serviceProvider, tenantDomain); + } + + Object removedAppRoles = IdentityUtil.threadLocalProperties.get().get(REMOVED_APPLICATION_AUDIENCE_ROLES); + if (removedAppRoles != null) { + List removedAppRolesList = (List) removedAppRoles; + handleRemovedApplicationAudienceRolesOnAppUpdate(removedAppRolesList, tenantDomain); + } + + Object addedOrgRoles = IdentityUtil.threadLocalProperties.get().get(ADDED_ORGANIZATION_AUDIENCE_ROLES); + if (addedOrgRoles != null) { + List addedOrgRolesList = (List) addedOrgRoles; + handleAddedOrganizationAudienceRolesOnAppUpdate(addedOrgRolesList, serviceProvider, tenantDomain); + + } + + Object removedOrgRoles = IdentityUtil.threadLocalProperties.get().get(REMOVED_ORGANIZATION_AUDIENCE_ROLES); + if (removedOrgRoles != null) { + List removedOrgRolesList = (List) removedOrgRoles; + handleRemovedOrganizationAudienceRolesOnAppUpdate(removedOrgRolesList, serviceProvider, tenantDomain); + } + } catch (OrganizationManagementException | IdentityRoleManagementException e) { + throw new IdentityApplicationManagementException( + String.format("Error while updating shared roles related to application %s update.", + serviceProvider.getApplicationID()), e); + } finally { + IdentityUtil.threadLocalProperties.get().remove(ADDED_APPLICATION_AUDIENCE_ROLES); + IdentityUtil.threadLocalProperties.get().remove(REMOVED_APPLICATION_AUDIENCE_ROLES); + IdentityUtil.threadLocalProperties.get().remove(ADDED_ORGANIZATION_AUDIENCE_ROLES); + IdentityUtil.threadLocalProperties.get().remove(REMOVED_ORGANIZATION_AUDIENCE_ROLES); + } + return true; + } + + private void handleRemovedOrganizationAudienceRolesOnAppUpdate(List removedOrgRolesList, + ServiceProvider serviceProvider, String tenantDomain) + throws OrganizationManagementException, IdentityRoleManagementException { + + if (CollectionUtils.isEmpty(removedOrgRolesList)) { + return; + } + String mainAppId = serviceProvider.getApplicationResourceId(); + String mainAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + List sharedApplications = + getOrgApplicationManager().getSharedApplications(mainAppOrgId, mainAppId); + if (CollectionUtils.isEmpty(sharedApplications)) { + return; + } + for (SharedApplication sharedApplication : sharedApplications) { + CompletableFuture.runAsync(() -> { + String sharedAppOrgId = sharedApplication.getOrganizationId(); + try { + handleOrganizationAudiencedSharedRoleDeletion(removedOrgRolesList, + serviceProvider.getApplicationResourceId(), + tenantDomain, sharedAppOrgId); + } catch (IdentityRoleManagementException | OrganizationManagementException e) { + LOG.error(String.format("Exception occurred during deleting roles from organization %s", + sharedApplication.getOrganizationId()), e); + } + }, executorService).exceptionally(throwable -> { + LOG.error(String.format("Exception occurred during deleting roles from organization %s", + sharedApplication.getOrganizationId()), throwable); + return null; + }); + } + } + + private void handleAddedOrganizationAudienceRolesOnAppUpdate(List addedOrgRolesList, + ServiceProvider serviceProvider, String tenantDomain) + throws OrganizationManagementException, IdentityRoleManagementException { + + if (CollectionUtils.isEmpty(addedOrgRolesList)) { + return; + } + String mainAppId = serviceProvider.getApplicationResourceId(); + String mainAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + List sharedApplications = + getOrgApplicationManager().getSharedApplications(mainAppOrgId, mainAppId); + if (CollectionUtils.isEmpty(sharedApplications)) { + return; + } + + for (SharedApplication sharedApplication : sharedApplications) { + CompletableFuture.runAsync(() -> { + String sharedAppOrgId = sharedApplication.getOrganizationId(); + try { + createSharedRolesWithOrgAudience(addedOrgRolesList, tenantDomain, sharedAppOrgId); + } catch (IdentityRoleManagementException | OrganizationManagementException e) { + LOG.error(String.format("Exception occurred while adding shared roles to organization: %s", + sharedApplication.getOrganizationId()), e); + } + }, executorService).exceptionally(throwable -> { + LOG.error(String.format("Exception occurred while adding shared roles to organization: %s", + sharedApplication.getOrganizationId()), throwable); + return null; + }); + } + } + + private void handleRemovedApplicationAudienceRolesOnAppUpdate(List removedAppRolesList, String tenantDomain) + throws IdentityRoleManagementException { + + if (CollectionUtils.isEmpty(removedAppRolesList)) { + return; + } + /* + Delete the application audience roles from parent organization. Deleting their shared roles also handled inside. + */ + for (RoleV2 removedRole : removedAppRolesList) { + getRoleManagementServiceV2().deleteRole(removedRole.getId(), tenantDomain); + } + } + + private void handleAddedApplicationAudienceRolesOnAppUpdate(List addedAppRolesList, + ServiceProvider serviceProvider, String tenantDomain) + throws OrganizationManagementException, IdentityRoleManagementException { + + if (CollectionUtils.isEmpty(addedAppRolesList)) { + return; + } + // Get shared applications of the given main app, and share the role. + String mainAppId = serviceProvider.getApplicationResourceId(); + String mainAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + + List sharedApplications = + getOrgApplicationManager().getSharedApplications(mainAppOrgId, mainAppId); + if (CollectionUtils.isEmpty(sharedApplications)) { + return; + } + + for (RoleV2 parentRole : addedAppRolesList) { + for (SharedApplication sharedApplication : sharedApplications) { + String sharedAppOrgId = sharedApplication.getOrganizationId(); + String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + String parentAppRoleName = parentRole.getName(); + // Create the role in the shared org. + RoleBasicInfo subOrgRole = + getRoleManagementServiceV2().addRole(parentAppRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, + sharedApplication.getSharedApplicationId(), + sharedAppTenantDomain); + // Add relationship between main role and the shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentRole.getId(), subOrgRole.getId(), + tenantDomain, sharedAppTenantDomain); + } + } + } + @Override public boolean doPreDeleteApplication(String applicationName, String tenantDomain, String userName) throws IdentityApplicationManagementException { @@ -71,7 +467,6 @@ public boolean doPreDeleteApplication(String applicationName, String tenantDomai return false; } String sharedAppId = sharedApplication.getApplicationResourceId(); - // Get all the shared applications of the deleting app. String sharedAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); // Resolve the main application details. String mainAppId = @@ -81,10 +476,7 @@ public boolean doPreDeleteApplication(String applicationName, String tenantDomai } int mainAppTenantId = getApplicationMgtService().getTenantIdByApp(mainAppId); String mainAppTenantDomain = IdentityTenantUtil.getTenantDomain(mainAppTenantId); - String mainAppOrgId = getOrganizationManager().resolveOrganizationId(mainAppTenantDomain); - if (mainAppOrgId == null) { - mainAppOrgId = SUPER_ORG_ID; - } + String allowedAudienceForRoleAssociationInMainApp = getApplicationMgtService().getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain); boolean hasAppAudiencedRoles = @@ -95,8 +487,10 @@ public boolean doPreDeleteApplication(String applicationName, String tenantDomai } // Handing organization audienced roles associated case. - handleOrganizationAudiencedSharedRoleDeletion(mainAppId, mainAppTenantDomain, mainAppOrgId, tenantDomain, - sharedAppOrgId); + List associatedRolesOfMainApplication = getApplicationMgtService() + .getAssociatedRolesOfApplication(mainAppId, mainAppTenantDomain); + handleOrganizationAudiencedSharedRoleDeletion(associatedRolesOfMainApplication, mainAppId, + mainAppTenantDomain, sharedAppOrgId); } catch (OrganizationManagementException | IdentityRoleManagementException e) { throw new IdentityApplicationManagementException( "Error while deleting organization roles associated to the app.", e); @@ -104,18 +498,18 @@ public boolean doPreDeleteApplication(String applicationName, String tenantDomai return super.doPreDeleteApplication(applicationName, tenantDomain, userName); } - private void handleOrganizationAudiencedSharedRoleDeletion(String mainApplicationId, + private void handleOrganizationAudiencedSharedRoleDeletion(List rolesList, String mainApplicationId, String mainApplicationTenantDomain, - String mainApplicationOrgId, - String unsharedApplicationTenantDomain, - String appUnsharedOrgId) - throws IdentityRoleManagementException, IdentityApplicationManagementException, - OrganizationManagementException { - - List associatedRolesOfMainApplication = getApplicationMgtService() - .getAssociatedRolesOfApplication(mainApplicationId, mainApplicationTenantDomain); + String sharedAppOrgId) + throws IdentityRoleManagementException, OrganizationManagementException { + + String mainApplicationOrgId = getOrganizationManager().resolveOrganizationId(mainApplicationTenantDomain); + if (mainApplicationOrgId == null) { + mainApplicationOrgId = SUPER_ORG_ID; + } + String unsharedApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); List mainAppRoleIds = - associatedRolesOfMainApplication.stream().map(RoleV2::getId).collect(Collectors.toList()); + rolesList.stream().map(RoleV2::getId).collect(Collectors.toList()); Map mainRoleToSharedRoleMappingsInSubOrg = getRoleManagementServiceV2() .getMainRoleToSharedRoleMappingsBySubOrg(mainAppRoleIds, unsharedApplicationTenantDomain); @@ -130,10 +524,10 @@ private void handleOrganizationAudiencedSharedRoleDeletion(String mainApplicatio } /* If the only associated application is the main app in this flow, delete the role in - the app unsharing org. + the org. */ if (associatedApplications.size() == 1 && mainApplicationId.equals(associatedApplications.get(0).getId())) { - // Delete the role in app unsharing org. + // Delete the role in org. getRoleManagementServiceV2().deleteRole(mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId), unsharedApplicationTenantDomain); break; @@ -145,14 +539,14 @@ private void handleOrganizationAudiencedSharedRoleDeletion(String mainApplicatio } boolean applicationSharedWithGivenOrganization = getOrgApplicationManager().isApplicationSharedWithGivenOrganization( - associatedApplication.getId(), mainApplicationOrgId, appUnsharedOrgId); + associatedApplication.getId(), mainApplicationOrgId, sharedAppOrgId); if (applicationSharedWithGivenOrganization) { isRoleUsedByAnotherSharedApp = true; break; } } if (!isRoleUsedByAnotherSharedApp) { - // Delete the role in app unsharing org. + // Delete the role in org. getRoleManagementServiceV2().deleteRole(mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId), unsharedApplicationTenantDomain); break; From 22802a1e4253213ca1dfd1802b0fd77f2b5dbc3b Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Fri, 20 Oct 2023 20:28:19 +0530 Subject: [PATCH 10/17] move role creation on post sharing to event handler --- .../handler/SharedRoleMgtHandler.java | 113 ++++++++++- .../listener/SharedRoleMgtListener.java | 190 ++++++------------ 2 files changed, 169 insertions(+), 134 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index d47f38cb6..5e98df3e5 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -18,13 +18,18 @@ package org.wso2.carbon.identity.organization.management.handler; +import org.apache.commons.collections.MapUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; +import org.wso2.carbon.identity.application.common.model.RoleV2; +import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; 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.constant.OrgApplicationMgtConstants; import org.wso2.carbon.identity.organization.management.application.model.SharedApplication; import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; @@ -56,8 +61,11 @@ public void handleEvent(Event event) throws IdentityEventException { String eventName = event.getEventName(); Map eventProperties = event.getEventProperties(); switch (eventName) { + case OrgApplicationMgtConstants.EVENT_POST_SHARE_APPLICATION: + createSharedRolesOnApplicationSharing(eventProperties); + break; case IdentityEventConstants.Event.POST_ADD_ROLE_V2_EVENT: - createOrganizationRolesOnNewRoleCreation(eventProperties); + createSharedRolesOnNewRoleCreation(eventProperties); break; default: if (LOG.isDebugEnabled()) { @@ -67,7 +75,103 @@ public void handleEvent(Event event) throws IdentityEventException { } } - private void createOrganizationRolesOnNewRoleCreation(Map eventProperties) + private void createSharedRolesOnApplicationSharing(Map eventProperties) + throws IdentityEventException { + + String parentOrganizationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_ORGANIZATION_ID); + String parentApplicationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_PARENT_APPLICATION_ID); + String sharedOrganizationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_ORGANIZATION_ID); + String sharedApplicationId = + (String) eventProperties.get(OrgApplicationMgtConstants.EVENT_PROP_SHARED_APPLICATION_ID); + try { + String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationId); + String mainAppTenantDomain = getOrganizationManager().resolveTenantDomain(parentOrganizationId); + String allowedAudienceForRoleAssociationInMainApp = + getApplicationMgtService().getAllowedAudienceForRoleAssociation(parentApplicationId, + mainAppTenantDomain); + switch (allowedAudienceForRoleAssociationInMainApp) { + case RoleConstants.APPLICATION: + // Create the roles, and add the relationship. + createSharedRolesWithAppAudience(parentApplicationId, mainAppTenantDomain, sharedApplicationId, + sharedAppTenantDomain); + break; + default: + // Create the role if not exists, and add the relationship. + List associatedRolesOfApplication = + getApplicationMgtService().getAssociatedRolesOfApplication( + parentApplicationId, mainAppTenantDomain); + createSharedRolesWithOrgAudience(associatedRolesOfApplication, mainAppTenantDomain, + sharedOrganizationId); + break; + } + } catch (OrganizationManagementException | IdentityRoleManagementException | + IdentityApplicationManagementException e) { + throw new IdentityEventException( + String.format("Error while sharing roles related to application %s.", sharedApplicationId), e); + } + } + + private void createSharedRolesWithOrgAudience(List rolesList, String mainAppTenantDomain, + String sharedAppOrgId) + throws IdentityRoleManagementException, OrganizationManagementException { + + if (rolesList == null) { + return; + } + String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + for (RoleV2 role : rolesList) { + // Check if the role exists in the application shared org. + boolean roleExistsInSharedOrg = + getRoleManagementServiceV2().isExistingRoleName(role.getName(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + Map mainRoleToSharedRoleMappingInSharedOrg = + getRoleManagementServiceV2().getMainRoleToSharedRoleMappingsBySubOrg( + Collections.singletonList(role.getId()), sharedAppTenantDomain); + boolean roleRelationshipExistsInSharedOrg = + MapUtils.isNotEmpty(mainRoleToSharedRoleMappingInSharedOrg); + if (roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { + // Add relationship between main role and shared role. + String roleIdInSharedOrg = + getRoleManagementServiceV2().getRoleIdByName(role.getName(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + roleIdInSharedOrg, mainAppTenantDomain, sharedAppTenantDomain); + } else if (!roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { + // Create the role in the shared org. + RoleBasicInfo sharedRole = + getRoleManagementServiceV2().addRole(role.getName(), Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + // Add relationship between main role and shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + sharedRole.getId(), mainAppTenantDomain, sharedAppTenantDomain); + } + } + } + + private void createSharedRolesWithAppAudience(String mainAppId, String mainAppTenantDomain, String sharedAppId, + String sharedAppTenantDomain) throws IdentityRoleManagementException { + + // Get parent organization's roles which has application audience. + String filter = RoleConstants.AUDIENCE_ID + " " + RoleConstants.EQ + " " + mainAppId; + List parentOrgRoles = + getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, mainAppTenantDomain); + for (RoleBasicInfo parentOrgRole : parentOrgRoles) { + String parentOrgRoleName = parentOrgRole.getName(); + // Create the role in the shared org. + RoleBasicInfo subOrgRole = getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, sharedAppId, + sharedAppTenantDomain); + // Add relationship between main role and the shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), subOrgRole.getId(), + mainAppTenantDomain, sharedAppTenantDomain); + } + } + + private void createSharedRolesOnNewRoleCreation(Map eventProperties) throws IdentityEventException { try { @@ -146,4 +250,9 @@ private static OrgApplicationManager getOrgApplicationManager() { return OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager(); } + + private static ApplicationManagementService getApplicationMgtService() { + + return OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService(); + } } diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java index c47191d8a..b29f473a6 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -20,6 +20,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; @@ -42,7 +43,6 @@ import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -51,7 +51,6 @@ import java.util.concurrent.Executors; import java.util.stream.Collectors; -import static org.wso2.carbon.identity.organization.management.application.constant.OrgApplicationMgtConstants.IS_FRAGMENT_APP; import static org.wso2.carbon.identity.organization.management.service.constant.OrganizationManagementConstants.SUPER_ORG_ID; /** @@ -73,119 +72,6 @@ public int getDefaultOrderId() { return 49; } - @Override - public boolean doPostCreateApplication(ServiceProvider serviceProvider, String tenantDomain, String userName) - throws IdentityApplicationManagementException { - - // If the creating application is an application of tenant(i.e primary org) nothing to do here. - try { - if (!OrganizationManagementUtil.isOrganization(tenantDomain)) { - return true; - } - boolean isSharedAppInOrg = Arrays.stream(serviceProvider.getSpProperties()) - .anyMatch(p -> IS_FRAGMENT_APP.equalsIgnoreCase(p.getName()) && Boolean.parseBoolean(p.getValue())); - if (!isSharedAppInOrg) { - // This is not a valid case. Organization could only have shared applications. - return true; - } - ServiceProvider sharedApplication = - getApplicationByName(serviceProvider.getApplicationName(), tenantDomain); - if (sharedApplication == null) { - return false; - } - String sharedAppId = sharedApplication.getApplicationResourceId(); - String sharedAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); - String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); - // Resolve the main application details. - String mainAppId = - getOrgApplicationManager().getMainApplicationIdForGivenSharedApp(sharedAppId, sharedAppOrgId); - if (mainAppId == null) { - return false; - } - int mainAppTenantId = getApplicationMgtService().getTenantIdByApp(mainAppId); - String mainAppTenantDomain = IdentityTenantUtil.getTenantDomain(mainAppTenantId); - String allowedAudienceForRoleAssociationInMainApp = - getApplicationMgtService().getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain); - - switch (allowedAudienceForRoleAssociationInMainApp) { - case RoleConstants.APPLICATION: - // Create the roles, and add the relationship. - createSharedRolesWithAppAudience(mainAppId, mainAppTenantDomain, sharedAppId, - sharedAppTenantDomain); - break; - default: - // Create the role if not exists, and add the relationship. - List associatedRolesOfApplication = - getApplicationMgtService().getAssociatedRolesOfApplication( - mainAppId, mainAppTenantDomain); - createSharedRolesWithOrgAudience(associatedRolesOfApplication, mainAppTenantDomain, sharedAppOrgId); - break; - } - } catch (OrganizationManagementException | IdentityRoleManagementException e) { - throw new IdentityApplicationManagementException( - String.format("Error while sharing roles related to application %s.", - serviceProvider.getApplicationID()), e); - } - return super.doPostCreateApplication(serviceProvider, tenantDomain, userName); - } - - private void createSharedRolesWithOrgAudience(List rolesList, String mainAppTenantDomain, - String sharedAppOrgId) - throws IdentityRoleManagementException, OrganizationManagementException { - - if (rolesList == null) { - return; - } - String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); - for (RoleV2 role : rolesList) { - // Check if the role exists in the application shared org. - boolean roleExistsInSharedOrg = - getRoleManagementServiceV2().isExistingRoleName(role.getName(), RoleConstants.ORGANIZATION, - sharedAppOrgId, sharedAppTenantDomain); - Map mainRoleToSharedRoleMappingInSharedOrg = - getRoleManagementServiceV2().getMainRoleToSharedRoleMappingsBySubOrg( - Collections.singletonList(role.getId()), sharedAppTenantDomain); - boolean roleRelationshipExistsInSharedOrg = - MapUtils.isNotEmpty(mainRoleToSharedRoleMappingInSharedOrg); - if (roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { - // Add relationship between main role and shared role. - String roleIdInSharedOrg = - getRoleManagementServiceV2().getRoleIdByName(role.getName(), RoleConstants.ORGANIZATION, - sharedAppOrgId, sharedAppTenantDomain); - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), - roleIdInSharedOrg, mainAppTenantDomain, sharedAppTenantDomain); - } else if (!roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { - // Create the role in the shared org. - RoleBasicInfo sharedRole = - getRoleManagementServiceV2().addRole(role.getName(), Collections.emptyList(), - Collections.emptyList(), Collections.emptyList(), RoleConstants.ORGANIZATION, - sharedAppOrgId, sharedAppTenantDomain); - // Add relationship between main role and shared role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), - sharedRole.getId(), mainAppTenantDomain, sharedAppTenantDomain); - } - } - } - - private void createSharedRolesWithAppAudience(String mainAppId, String mainAppTenantDomain, String sharedAppId, - String sharedAppTenantDomain) throws IdentityRoleManagementException { - - // Get parent organization's roles which has application audience. - String filter = RoleConstants.AUDIENCE_ID + " " + RoleConstants.EQ + " " + mainAppId; - List parentOrgRoles = - getRoleManagementServiceV2().getRoles(filter, null, 0, null, null, mainAppTenantDomain); - for (RoleBasicInfo parentOrgRole : parentOrgRoles) { - String parentOrgRoleName = parentOrgRole.getName(); - // Create the role in the shared org. - RoleBasicInfo subOrgRole = getRoleManagementServiceV2().addRole(parentOrgRoleName, Collections.emptyList(), - Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, sharedAppId, - sharedAppTenantDomain); - // Add relationship between main role and the shared role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentOrgRole.getId(), subOrgRole.getId(), - mainAppTenantDomain, sharedAppTenantDomain); - } - } - @Override public boolean doPreUpdateApplication(ServiceProvider serviceProvider, String tenantDomain, String userName) throws IdentityApplicationManagementException { @@ -403,6 +289,44 @@ private void handleAddedOrganizationAudienceRolesOnAppUpdate(List addedO } } + private void createSharedRolesWithOrgAudience(List rolesList, String mainAppTenantDomain, + String sharedAppOrgId) + throws IdentityRoleManagementException, OrganizationManagementException { + + if (rolesList == null) { + return; + } + String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + for (RoleV2 role : rolesList) { + // Check if the role exists in the application shared org. + boolean roleExistsInSharedOrg = + getRoleManagementServiceV2().isExistingRoleName(role.getName(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + Map mainRoleToSharedRoleMappingInSharedOrg = + getRoleManagementServiceV2().getMainRoleToSharedRoleMappingsBySubOrg( + Collections.singletonList(role.getId()), sharedAppTenantDomain); + boolean roleRelationshipExistsInSharedOrg = + MapUtils.isNotEmpty(mainRoleToSharedRoleMappingInSharedOrg); + if (roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { + // Add relationship between main role and shared role. + String roleIdInSharedOrg = + getRoleManagementServiceV2().getRoleIdByName(role.getName(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + roleIdInSharedOrg, mainAppTenantDomain, sharedAppTenantDomain); + } else if (!roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { + // Create the role in the shared org. + RoleBasicInfo sharedRole = + getRoleManagementServiceV2().addRole(role.getName(), Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), RoleConstants.ORGANIZATION, + sharedAppOrgId, sharedAppTenantDomain); + // Add relationship between main role and shared role. + getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + sharedRole.getId(), mainAppTenantDomain, sharedAppTenantDomain); + } + } + } + private void handleRemovedApplicationAudienceRolesOnAppUpdate(List removedAppRolesList, String tenantDomain) throws IdentityRoleManagementException { @@ -507,39 +431,42 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis if (mainApplicationOrgId == null) { mainApplicationOrgId = SUPER_ORG_ID; } - String unsharedApplicationTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); List mainAppRoleIds = rolesList.stream().map(RoleV2::getId).collect(Collectors.toList()); Map mainRoleToSharedRoleMappingsInSubOrg = getRoleManagementServiceV2() - .getMainRoleToSharedRoleMappingsBySubOrg(mainAppRoleIds, unsharedApplicationTenantDomain); + .getMainRoleToSharedRoleMappingsBySubOrg(mainAppRoleIds, sharedAppTenantDomain); // Get each role associated applications. for (String mainAppRoleId : mainAppRoleIds) { - // TODO use a service which return only associated role ids. - Role role = getRoleManagementServiceV2().getRole(mainAppRoleId, mainApplicationTenantDomain); - List associatedApplications = role.getAssociatedApplications(); - - if (associatedApplications == null) { + List associatedApplicationsIds = + getRoleManagementServiceV2().getAssociatedApplicationByRoleId(mainAppRoleId, + mainApplicationTenantDomain); + if (associatedApplicationsIds == null) { + continue; + } + String sharedRoleId = mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId); + if (StringUtils.isBlank(sharedRoleId)) { + // There is no role available in the shared org. May be due to role creation issue. continue; } /* If the only associated application is the main app in this flow, delete the role in the org. */ - if (associatedApplications.size() == 1 && mainApplicationId.equals(associatedApplications.get(0).getId())) { + if (associatedApplicationsIds.size() == 1 && mainApplicationId.equals(associatedApplicationsIds.get(0))) { // Delete the role in org. - getRoleManagementServiceV2().deleteRole(mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId), - unsharedApplicationTenantDomain); + getRoleManagementServiceV2().deleteRole(sharedRoleId, sharedAppTenantDomain); break; - } else if (associatedApplications.size() > 1) { + } else if (associatedApplicationsIds.size() > 1) { boolean isRoleUsedByAnotherSharedApp = false; - for (AssociatedApplication associatedApplication : associatedApplications) { - if (associatedApplication.getId().equals(mainApplicationId)) { + for (String associatedApplicationId : associatedApplicationsIds) { + if (associatedApplicationId.equals(mainApplicationId)) { continue; } boolean applicationSharedWithGivenOrganization = - getOrgApplicationManager().isApplicationSharedWithGivenOrganization( - associatedApplication.getId(), mainApplicationOrgId, sharedAppOrgId); + getOrgApplicationManager().isApplicationSharedWithGivenOrganization(associatedApplicationId, + mainApplicationOrgId, sharedAppOrgId); if (applicationSharedWithGivenOrganization) { isRoleUsedByAnotherSharedApp = true; break; @@ -547,8 +474,7 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis } if (!isRoleUsedByAnotherSharedApp) { // Delete the role in org. - getRoleManagementServiceV2().deleteRole(mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId), - unsharedApplicationTenantDomain); + getRoleManagementServiceV2().deleteRole(sharedRoleId, sharedAppTenantDomain); break; } } From 42543aedbee0738b52c31e88516f2d60c546528e Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Fri, 20 Oct 2023 21:33:41 +0530 Subject: [PATCH 11/17] fix formatting --- .../management/handler/listener/SharedRoleMgtListener.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java index b29f473a6..87384936d 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -38,7 +38,6 @@ import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil; import org.wso2.carbon.identity.role.v2.mgt.core.AssociatedApplication; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; -import org.wso2.carbon.identity.role.v2.mgt.core.Role; import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; @@ -203,7 +202,6 @@ public boolean doPostUpdateApplication(ServiceProvider serviceProvider, String t if (addedOrgRoles != null) { List addedOrgRolesList = (List) addedOrgRoles; handleAddedOrganizationAudienceRolesOnAppUpdate(addedOrgRolesList, serviceProvider, tenantDomain); - } Object removedOrgRoles = IdentityUtil.threadLocalProperties.get().get(REMOVED_ORGANIZATION_AUDIENCE_ROLES); From 480aba28e7ce825d513bc6dee9a02b7f2ec9d4e3 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 21 Oct 2023 01:11:54 +0530 Subject: [PATCH 12/17] resolve NPE and malfunctioning shared role creation --- .../listener/SharedRoleMgtListener.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java index 87384936d..143eddd66 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -36,7 +36,6 @@ 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.util.OrganizationManagementUtil; -import org.wso2.carbon.identity.role.v2.mgt.core.AssociatedApplication; import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; @@ -45,6 +44,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -201,7 +201,26 @@ public boolean doPostUpdateApplication(ServiceProvider serviceProvider, String t Object addedOrgRoles = IdentityUtil.threadLocalProperties.get().get(ADDED_ORGANIZATION_AUDIENCE_ROLES); if (addedOrgRoles != null) { List addedOrgRolesList = (List) addedOrgRoles; - handleAddedOrganizationAudienceRolesOnAppUpdate(addedOrgRolesList, serviceProvider, tenantDomain); + List namesResolvedAddedRolesList = addedOrgRolesList.stream() + .map(role -> { + try { + String roleName = + getRoleManagementServiceV2().getRoleNameByRoleId(role.getId(), tenantDomain); + if (roleName != null) { + return new RoleV2(role.getId(), roleName); + } else { + return null; + } + } catch (Exception e) { + LOG.error("Failed to resolve role name of role id: " + role.getId()); + return null; + } + }) + .filter(Objects::nonNull) // Filter out null values (roles that couldn't be resolved) + .collect(Collectors.toList()); + + handleAddedOrganizationAudienceRolesOnAppUpdate(namesResolvedAddedRolesList, serviceProvider, + tenantDomain); } Object removedOrgRoles = IdentityUtil.threadLocalProperties.get().get(REMOVED_ORGANIZATION_AUDIENCE_ROLES); @@ -455,7 +474,6 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis if (associatedApplicationsIds.size() == 1 && mainApplicationId.equals(associatedApplicationsIds.get(0))) { // Delete the role in org. getRoleManagementServiceV2().deleteRole(sharedRoleId, sharedAppTenantDomain); - break; } else if (associatedApplicationsIds.size() > 1) { boolean isRoleUsedByAnotherSharedApp = false; for (String associatedApplicationId : associatedApplicationsIds) { From 5c2ed13e5e324c0ac7df58e209045f055446b36c Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sat, 21 Oct 2023 01:50:41 +0530 Subject: [PATCH 13/17] fix role deletion issue --- .../pom.xml | 1 + .../listener/SharedRoleMgtListener.java | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml index 19a1cc331..a33b5e461 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/pom.xml +++ b/components/org.wso2.carbon.identity.organization.management.handler/pom.xml @@ -138,6 +138,7 @@ org.wso2.carbon.identity.application.common.*; version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.core.util;version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.context;version="${carbon.kernel.package.import.version.range}", diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java index 143eddd66..74f40b538 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -23,6 +23,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.RoleV2; import org.wso2.carbon.identity.application.common.model.ServiceProvider; @@ -459,21 +460,28 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis List associatedApplicationsIds = getRoleManagementServiceV2().getAssociatedApplicationByRoleId(mainAppRoleId, mainApplicationTenantDomain); - if (associatedApplicationsIds == null) { - continue; - } String sharedRoleId = mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId); if (StringUtils.isBlank(sharedRoleId)) { // There is no role available in the shared org. May be due to role creation issue. continue; } /* - If the only associated application is the main app in this flow, delete the role in - the org. + If this private method is called from application update post listener, the role already removed + from the application. associatedApplicationsIds is empty means there are no any other applications. + + If this private method is called from application deletion post listener, + and if the only associated application is the main app in this flow, this condition is satisfied. + Hence, deleting the shared roles. */ - if (associatedApplicationsIds.size() == 1 && mainApplicationId.equals(associatedApplicationsIds.get(0))) { - // Delete the role in org. - getRoleManagementServiceV2().deleteRole(sharedRoleId, sharedAppTenantDomain); + if (CollectionUtils.isEmpty(associatedApplicationsIds) || (associatedApplicationsIds.size() == 1 && + mainApplicationId.equals(associatedApplicationsIds.get(0)))) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(sharedAppTenantDomain, true); + getRoleManagementServiceV2().deleteRole(sharedRoleId, sharedAppTenantDomain); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } } else if (associatedApplicationsIds.size() > 1) { boolean isRoleUsedByAnotherSharedApp = false; for (String associatedApplicationId : associatedApplicationsIds) { From e9f2c02f4ea2426a48a21c7f6b765e49856cf89c Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Sun, 22 Oct 2023 18:51:15 +0530 Subject: [PATCH 14/17] fix comments --- .../listener/SharedRoleMgtListener.java | 110 ++++++++---------- 1 file changed, 48 insertions(+), 62 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java index 74f40b538..c813fe528 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -37,11 +37,13 @@ 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.util.OrganizationManagementUtil; -import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; -import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; +import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleBasicInfo; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -64,6 +66,14 @@ public class SharedRoleMgtListener extends AbstractApplicationMgtListener { private static final String REMOVED_ORGANIZATION_AUDIENCE_ROLES = "removedOrganizationAudienceRoles"; private static final String ADDED_ORGANIZATION_AUDIENCE_ROLES = "addedOrganizationAudienceRoles"; + ApplicationManagementService applicationManagementService = + OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService(); + OrganizationManager organizationManager = + OrganizationManagementHandlerDataHolder.getInstance().getOrganizationManager(); + OrgApplicationManager orgApplicationManager = + OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager(); + RoleManagementService roleManagementService = + OrganizationManagementHandlerDataHolder.getInstance().getRoleManagementServiceV2(); private final ExecutorService executorService = Executors.newFixedThreadPool(5); @Override @@ -84,17 +94,17 @@ public boolean doPreUpdateApplication(ServiceProvider serviceProvider, String te String applicationResourceId = serviceProvider.getApplicationResourceId(); // Get the currently associated roles set from DB/cache. String existingAllowedAudienceForRoleAssociation = - getApplicationMgtService().getAllowedAudienceForRoleAssociation(applicationResourceId, + applicationManagementService.getAllowedAudienceForRoleAssociation(applicationResourceId, tenantDomain); List existingAssociatedRolesList = - getApplicationMgtService().getAssociatedRolesOfApplication(applicationResourceId, tenantDomain); + applicationManagementService.getAssociatedRolesOfApplication(applicationResourceId, tenantDomain); String updatedAllowedAudienceForRoleAssociation = serviceProvider.getAssociatedRolesConfig() == null ? RoleConstants.ORGANIZATION : serviceProvider.getAssociatedRolesConfig().getAllowedAudience(); List updatedAssociatedRolesList = serviceProvider.getAssociatedRolesConfig() == null ? Collections.emptyList() : - serviceProvider.getAssociatedRolesConfig().getRoles(); + new ArrayList<>(Arrays.asList(serviceProvider.getAssociatedRolesConfig().getRoles())); if (CollectionUtils.isEmpty(existingAssociatedRolesList) && CollectionUtils.isEmpty(updatedAssociatedRolesList)) { @@ -205,13 +215,11 @@ public boolean doPostUpdateApplication(ServiceProvider serviceProvider, String t List namesResolvedAddedRolesList = addedOrgRolesList.stream() .map(role -> { try { - String roleName = - getRoleManagementServiceV2().getRoleNameByRoleId(role.getId(), tenantDomain); + String roleName = roleManagementService.getRoleNameByRoleId(role.getId(), tenantDomain); if (roleName != null) { return new RoleV2(role.getId(), roleName); - } else { - return null; } + return null; } catch (Exception e) { LOG.error("Failed to resolve role name of role id: " + role.getId()); return null; @@ -250,9 +258,9 @@ private void handleRemovedOrganizationAudienceRolesOnAppUpdate(List remo return; } String mainAppId = serviceProvider.getApplicationResourceId(); - String mainAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + String mainAppOrgId = organizationManager.resolveOrganizationId(tenantDomain); List sharedApplications = - getOrgApplicationManager().getSharedApplications(mainAppOrgId, mainAppId); + orgApplicationManager.getSharedApplications(mainAppOrgId, mainAppId); if (CollectionUtils.isEmpty(sharedApplications)) { return; } @@ -283,9 +291,9 @@ private void handleAddedOrganizationAudienceRolesOnAppUpdate(List addedO return; } String mainAppId = serviceProvider.getApplicationResourceId(); - String mainAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + String mainAppOrgId = organizationManager.resolveOrganizationId(tenantDomain); List sharedApplications = - getOrgApplicationManager().getSharedApplications(mainAppOrgId, mainAppId); + orgApplicationManager.getSharedApplications(mainAppOrgId, mainAppId); if (CollectionUtils.isEmpty(sharedApplications)) { return; } @@ -314,32 +322,31 @@ private void createSharedRolesWithOrgAudience(List rolesList, String mai if (rolesList == null) { return; } - String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + String sharedAppTenantDomain = organizationManager.resolveTenantDomain(sharedAppOrgId); for (RoleV2 role : rolesList) { // Check if the role exists in the application shared org. boolean roleExistsInSharedOrg = - getRoleManagementServiceV2().isExistingRoleName(role.getName(), RoleConstants.ORGANIZATION, + roleManagementService.isExistingRoleName(role.getName(), RoleConstants.ORGANIZATION, sharedAppOrgId, sharedAppTenantDomain); Map mainRoleToSharedRoleMappingInSharedOrg = - getRoleManagementServiceV2().getMainRoleToSharedRoleMappingsBySubOrg( + roleManagementService.getMainRoleToSharedRoleMappingsBySubOrg( Collections.singletonList(role.getId()), sharedAppTenantDomain); boolean roleRelationshipExistsInSharedOrg = MapUtils.isNotEmpty(mainRoleToSharedRoleMappingInSharedOrg); if (roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { // Add relationship between main role and shared role. String roleIdInSharedOrg = - getRoleManagementServiceV2().getRoleIdByName(role.getName(), RoleConstants.ORGANIZATION, + roleManagementService.getRoleIdByName(role.getName(), RoleConstants.ORGANIZATION, sharedAppOrgId, sharedAppTenantDomain); - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + roleManagementService.addMainRoleToSharedRoleRelationship(role.getId(), roleIdInSharedOrg, mainAppTenantDomain, sharedAppTenantDomain); } else if (!roleExistsInSharedOrg && !roleRelationshipExistsInSharedOrg) { // Create the role in the shared org. - RoleBasicInfo sharedRole = - getRoleManagementServiceV2().addRole(role.getName(), Collections.emptyList(), + RoleBasicInfo sharedRole = roleManagementService.addRole(role.getName(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), RoleConstants.ORGANIZATION, sharedAppOrgId, sharedAppTenantDomain); // Add relationship between main role and shared role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(role.getId(), + roleManagementService.addMainRoleToSharedRoleRelationship(role.getId(), sharedRole.getId(), mainAppTenantDomain, sharedAppTenantDomain); } } @@ -355,7 +362,7 @@ private void handleRemovedApplicationAudienceRolesOnAppUpdate(List remov Delete the application audience roles from parent organization. Deleting their shared roles also handled inside. */ for (RoleV2 removedRole : removedAppRolesList) { - getRoleManagementServiceV2().deleteRole(removedRole.getId(), tenantDomain); + roleManagementService.deleteRole(removedRole.getId(), tenantDomain); } } @@ -368,10 +375,10 @@ private void handleAddedApplicationAudienceRolesOnAppUpdate(List addedAp } // Get shared applications of the given main app, and share the role. String mainAppId = serviceProvider.getApplicationResourceId(); - String mainAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + String mainAppOrgId = organizationManager.resolveOrganizationId(tenantDomain); List sharedApplications = - getOrgApplicationManager().getSharedApplications(mainAppOrgId, mainAppId); + orgApplicationManager.getSharedApplications(mainAppOrgId, mainAppId); if (CollectionUtils.isEmpty(sharedApplications)) { return; } @@ -379,16 +386,16 @@ private void handleAddedApplicationAudienceRolesOnAppUpdate(List addedAp for (RoleV2 parentRole : addedAppRolesList) { for (SharedApplication sharedApplication : sharedApplications) { String sharedAppOrgId = sharedApplication.getOrganizationId(); - String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + String sharedAppTenantDomain = organizationManager.resolveTenantDomain(sharedAppOrgId); String parentAppRoleName = parentRole.getName(); // Create the role in the shared org. RoleBasicInfo subOrgRole = - getRoleManagementServiceV2().addRole(parentAppRoleName, Collections.emptyList(), + roleManagementService.addRole(parentAppRoleName, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), RoleConstants.APPLICATION, sharedApplication.getSharedApplicationId(), sharedAppTenantDomain); // Add relationship between main role and the shared role. - getRoleManagementServiceV2().addMainRoleToSharedRoleRelationship(parentRole.getId(), subOrgRole.getId(), + roleManagementService.addMainRoleToSharedRoleRelationship(parentRole.getId(), subOrgRole.getId(), tenantDomain, sharedAppTenantDomain); } } @@ -409,18 +416,17 @@ public boolean doPreDeleteApplication(String applicationName, String tenantDomai return false; } String sharedAppId = sharedApplication.getApplicationResourceId(); - String sharedAppOrgId = getOrganizationManager().resolveOrganizationId(tenantDomain); + String sharedAppOrgId = organizationManager.resolveOrganizationId(tenantDomain); // Resolve the main application details. - String mainAppId = - getOrgApplicationManager().getMainApplicationIdForGivenSharedApp(sharedAppId, sharedAppOrgId); + String mainAppId = orgApplicationManager.getMainApplicationIdForGivenSharedApp(sharedAppId, sharedAppOrgId); if (mainAppId == null) { return false; } - int mainAppTenantId = getApplicationMgtService().getTenantIdByApp(mainAppId); + int mainAppTenantId = applicationManagementService.getTenantIdByApp(mainAppId); String mainAppTenantDomain = IdentityTenantUtil.getTenantDomain(mainAppTenantId); String allowedAudienceForRoleAssociationInMainApp = - getApplicationMgtService().getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain); + applicationManagementService.getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain); boolean hasAppAudiencedRoles = RoleConstants.APPLICATION.equalsIgnoreCase(allowedAudienceForRoleAssociationInMainApp); if (hasAppAudiencedRoles) { @@ -429,7 +435,7 @@ public boolean doPreDeleteApplication(String applicationName, String tenantDomai } // Handing organization audienced roles associated case. - List associatedRolesOfMainApplication = getApplicationMgtService() + List associatedRolesOfMainApplication = applicationManagementService .getAssociatedRolesOfApplication(mainAppId, mainAppTenantDomain); handleOrganizationAudiencedSharedRoleDeletion(associatedRolesOfMainApplication, mainAppId, mainAppTenantDomain, sharedAppOrgId); @@ -445,20 +451,20 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis String sharedAppOrgId) throws IdentityRoleManagementException, OrganizationManagementException { - String mainApplicationOrgId = getOrganizationManager().resolveOrganizationId(mainApplicationTenantDomain); + String mainApplicationOrgId = organizationManager.resolveOrganizationId(mainApplicationTenantDomain); if (mainApplicationOrgId == null) { mainApplicationOrgId = SUPER_ORG_ID; } - String sharedAppTenantDomain = getOrganizationManager().resolveTenantDomain(sharedAppOrgId); + String sharedAppTenantDomain = organizationManager.resolveTenantDomain(sharedAppOrgId); List mainAppRoleIds = rolesList.stream().map(RoleV2::getId).collect(Collectors.toList()); - Map mainRoleToSharedRoleMappingsInSubOrg = getRoleManagementServiceV2() - .getMainRoleToSharedRoleMappingsBySubOrg(mainAppRoleIds, sharedAppTenantDomain); + Map mainRoleToSharedRoleMappingsInSubOrg = + roleManagementService.getMainRoleToSharedRoleMappingsBySubOrg(mainAppRoleIds, sharedAppTenantDomain); // Get each role associated applications. for (String mainAppRoleId : mainAppRoleIds) { List associatedApplicationsIds = - getRoleManagementServiceV2().getAssociatedApplicationByRoleId(mainAppRoleId, + roleManagementService.getAssociatedApplicationByRoleId(mainAppRoleId, mainApplicationTenantDomain); String sharedRoleId = mainRoleToSharedRoleMappingsInSubOrg.get(mainAppRoleId); if (StringUtils.isBlank(sharedRoleId)) { @@ -478,7 +484,7 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis try { PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(sharedAppTenantDomain, true); - getRoleManagementServiceV2().deleteRole(sharedRoleId, sharedAppTenantDomain); + roleManagementService.deleteRole(sharedRoleId, sharedAppTenantDomain); } finally { PrivilegedCarbonContext.endTenantFlow(); } @@ -489,7 +495,7 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis continue; } boolean applicationSharedWithGivenOrganization = - getOrgApplicationManager().isApplicationSharedWithGivenOrganization(associatedApplicationId, + orgApplicationManager.isApplicationSharedWithGivenOrganization(associatedApplicationId, mainApplicationOrgId, sharedAppOrgId); if (applicationSharedWithGivenOrganization) { isRoleUsedByAnotherSharedApp = true; @@ -498,7 +504,7 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis } if (!isRoleUsedByAnotherSharedApp) { // Delete the role in org. - getRoleManagementServiceV2().deleteRole(sharedRoleId, sharedAppTenantDomain); + roleManagementService.deleteRole(sharedRoleId, sharedAppTenantDomain); break; } } @@ -508,26 +514,6 @@ private void handleOrganizationAudiencedSharedRoleDeletion(List rolesLis private ServiceProvider getApplicationByName(String name, String tenantDomain) throws IdentityApplicationManagementException { - return getApplicationMgtService().getServiceProvider(name, tenantDomain); - } - - private static OrganizationManager getOrganizationManager() { - - return OrganizationManagementHandlerDataHolder.getInstance().getOrganizationManager(); - } - - private static OrgApplicationManager getOrgApplicationManager() { - - return OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager(); - } - - private static ApplicationManagementService getApplicationMgtService() { - - return OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService(); - } - - private static RoleManagementService getRoleManagementServiceV2() { - - return OrganizationManagementHandlerDataHolder.getInstance().getRoleManagementServiceV2(); + return applicationManagementService.getServiceProvider(name, tenantDomain); } } From 0269fc7327605ab61496dc656457b862234540e5 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 23 Oct 2023 10:43:15 +0530 Subject: [PATCH 15/17] fix imports --- .../organization/management/handler/SharedRoleMgtHandler.java | 4 ++-- pom.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java index 5e98df3e5..01fb38905 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java @@ -35,10 +35,10 @@ 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.util.OrganizationManagementUtil; -import org.wso2.carbon.identity.role.v2.mgt.core.IdentityRoleManagementException; -import org.wso2.carbon.identity.role.v2.mgt.core.RoleBasicInfo; import org.wso2.carbon.identity.role.v2.mgt.core.RoleConstants; import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; +import org.wso2.carbon.identity.role.v2.mgt.core.model.RoleBasicInfo; import java.util.Collections; import java.util.List; diff --git a/pom.xml b/pom.xml index c6852da49..9a223a8f6 100644 --- a/pom.xml +++ b/pom.xml @@ -503,7 +503,7 @@ [4.7.0,5.0.0) - 5.25.400 + 5.25.424-SNAPSHOT [5.20.0, 7.0.0) From 6e97d74b3b53f9035bd05c7cf0185402f5d3bbac Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 23 Oct 2023 11:22:56 +0530 Subject: [PATCH 16/17] fix possible NPE --- .../handler/listener/SharedRoleMgtListener.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java index c813fe528..b873b34f9 100644 --- a/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java +++ b/components/org.wso2.carbon.identity.organization.management.handler/src/main/java/org/wso2/carbon/identity/organization/management/handler/listener/SharedRoleMgtListener.java @@ -102,9 +102,14 @@ public boolean doPreUpdateApplication(ServiceProvider serviceProvider, String te String updatedAllowedAudienceForRoleAssociation = serviceProvider.getAssociatedRolesConfig() == null ? RoleConstants.ORGANIZATION : serviceProvider.getAssociatedRolesConfig().getAllowedAudience(); - List updatedAssociatedRolesList = - serviceProvider.getAssociatedRolesConfig() == null ? Collections.emptyList() : - new ArrayList<>(Arrays.asList(serviceProvider.getAssociatedRolesConfig().getRoles())); + + List updatedAssociatedRolesList; + if (serviceProvider.getAssociatedRolesConfig() != null && + serviceProvider.getAssociatedRolesConfig().getRoles() != null) { + updatedAssociatedRolesList = Arrays.asList(serviceProvider.getAssociatedRolesConfig().getRoles()); + } else { + updatedAssociatedRolesList = new ArrayList<>(); + } if (CollectionUtils.isEmpty(existingAssociatedRolesList) && CollectionUtils.isEmpty(updatedAssociatedRolesList)) { From 6c20a44f8dba9d97875c5cd84dc88258120a5586 Mon Sep 17 00:00:00 2001 From: AnuradhaSK Date: Mon, 23 Oct 2023 19:50:02 +0530 Subject: [PATCH 17/17] bump framework --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 9a223a8f6..ba83675e4 100644 --- a/pom.xml +++ b/pom.xml @@ -503,7 +503,7 @@ [4.7.0,5.0.0) - 5.25.424-SNAPSHOT + 5.25.426 [5.20.0, 7.0.0)