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 608618923..d7e9f1b50 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;