Skip to content

Commit

Permalink
handle organization audience role deletion on app unsharing and app d…
Browse files Browse the repository at this point in the history
…eletion
  • Loading branch information
AnuradhaSK committed Oct 18, 2023
1 parent cf84ea6 commit cca7636
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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}",
</Import-Package>
</instructions>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -222,8 +215,8 @@ private void createOrganizationRolesOnAppSharing(Map<String, Object> 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) {
Expand Down Expand Up @@ -271,4 +264,9 @@ private static OrgApplicationManager getOrgApplicationManager() {

return OrganizationManagementHandlerDataHolder.getInstance().getOrgApplicationManager();
}

private static ApplicationManagementService getApplicationMgtService() {

return OrganizationManagementHandlerDataHolder.getInstance().getApplicationManagementService();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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<RoleV2> associatedRolesOfMainApplication = getApplicationMgtService()
.getAssociatedRolesOfApplication(mainApplicationId, mainApplicationTenantDomain);
List<String> mainAppRoleIds =
associatedRolesOfMainApplication.stream().map(RoleV2::getId).collect(Collectors.toList());
Map<String, String> 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<AssociatedApplication> 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();
}
}

0 comments on commit cca7636

Please sign in to comment.