Skip to content

Commit

Permalink
Allow sub org level application deletion when the application is a su…
Browse files Browse the repository at this point in the history
…b org app
  • Loading branch information
ShanChathusanda93 committed Jan 6, 2025
1 parent 3833c81 commit 81768f3
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com).
* Copyright (c) 2023-2024, 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
Expand Down Expand Up @@ -57,6 +57,7 @@
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;

/**
Expand Down Expand Up @@ -468,16 +469,26 @@ public boolean doPreDeleteApplication(String applicationName, String tenantDomai
throws IdentityApplicationManagementException {

try {
// If the deleting application is an application of tenant(i.e primary org) nothing to do here.
// If the tenant is not an organization, no need to handle shared roles.
if (!OrganizationManagementUtil.isOrganization(tenantDomain)) {
return true;
}

ServiceProvider sharedApplication = getApplicationByName(applicationName, tenantDomain);
if (sharedApplication == null) {
ServiceProvider serviceProvider = getApplicationByName(applicationName, tenantDomain);
if (serviceProvider == null) {
return false;
}
String sharedAppId = sharedApplication.getApplicationResourceId();

// If the application is not a fragment app in the sub organization level, no need to handle shared roles.
boolean isFragmentApp = Arrays.stream(serviceProvider.getSpProperties())
.anyMatch(property -> IS_FRAGMENT_APP.equals(property.getName()) &&
Boolean.parseBoolean(property.getValue()));
if (!isFragmentApp) {
// Given app is a sub org level application.
return true;
}

String sharedAppId = serviceProvider.getApplicationResourceId();
String sharedAppOrgId = organizationManager.resolveOrganizationId(tenantDomain);
// Resolve the main application details.
String mainAppId = orgApplicationManager.getMainApplicationIdForGivenSharedApp(sharedAppId, sharedAppOrgId);
Expand Down Expand Up @@ -583,22 +594,18 @@ public boolean doPostGetAllowedAudienceForRoleAssociation(AssociatedRolesConfig
String applicationUUID, String tenantDomain)
throws IdentityApplicationManagementException {

try {
if (!OrganizationManagementUtil.isOrganization(tenantDomain)) {
return true;
}
// Resolve the allowed audience for associated roles of shared application from main application details.
String mainAppId = applicationManagementService.getMainAppId(applicationUUID);
int mainAppTenantId = applicationManagementService.getTenantIdByApp(mainAppId);
String mainAppTenantDomain = IdentityTenantUtil.getTenantDomain(mainAppTenantId);
String resolvedAllowedAudienceFromMainApp =
applicationManagementService.getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain);
allowedAudienceForRoleAssociation.setAllowedAudience(resolvedAllowedAudienceFromMainApp);
} catch (OrganizationManagementException e) {
throw new IdentityApplicationManagementException(String.format(
"Error while fetching the allowed audience for role association of application with: %s.",
applicationUUID), e);
String mainAppId = applicationManagementService.getMainAppId(applicationUUID);
// If the main application id is null, then this is the main application. We can skip this operation
// based on that.
if (StringUtils.isEmpty(mainAppId)) {
return true;
}
// Resolve the allowed audience for associated roles of shared application from main application details.
int mainAppTenantId = applicationManagementService.getTenantIdByApp(mainAppId);
String mainAppTenantDomain = IdentityTenantUtil.getTenantDomain(mainAppTenantId);
String resolvedAllowedAudienceFromMainApp =
applicationManagementService.getAllowedAudienceForRoleAssociation(mainAppId, mainAppTenantDomain);
allowedAudienceForRoleAssociation.setAllowedAudience(resolvedAllowedAudienceFromMainApp);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright (c) 2024, 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.lang3.StringUtils;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.wso2.carbon.identity.application.common.model.AssociatedRolesConfig;
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.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.organization.management.handler.internal.OrganizationManagementHandlerDataHolder;
import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil;

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

/**
* Contains unit tests for SharedRoleMgtListener.
*/
public class SharedRoleMgtListenerTest {

@Mock
private ApplicationManagementService mockedApplicationManagementService;

private MockedStatic<OrganizationManagementUtil> organizationManagementUtilMockedStatic;
private MockedStatic<IdentityTenantUtil> identityTenantUtilMockedStatic;

@BeforeClass
public void setUpClass() {

MockitoAnnotations.openMocks(this);
OrganizationManagementHandlerDataHolder.getInstance().
setApplicationManagementService(mockedApplicationManagementService);
organizationManagementUtilMockedStatic = mockStatic(OrganizationManagementUtil.class);
identityTenantUtilMockedStatic = mockStatic(IdentityTenantUtil.class);
}

@DataProvider(name = "organizationTypeDataProvider")
public Object[][] organizationTypeDataProvider() {

// Create a ServiceProvider object for a main application.
ServiceProvider serviceProvider = new ServiceProvider();
serviceProvider.setApplicationName("sampleApplicationName");

return new Object[][]{
{false, null, true},
{true, serviceProvider, true},
{true, null, false},
};
}

@DataProvider(name = "applicationDataProvider")
public Object[][] applicationDataProvider() {

return new Object[][] {
{null},
{"main-app-id"}
};
}

@Test(dataProvider = "organizationTypeDataProvider")
public void testDoPreDeleteApplicationInOrgTypes(boolean isOrganization, ServiceProvider serviceProvider,
boolean expected) throws Exception {

organizationManagementUtilMockedStatic.when(() -> OrganizationManagementUtil.isOrganization(anyString()))
.thenReturn(isOrganization);
SharedRoleMgtListener sharedRoleMgtListener = new SharedRoleMgtListener();
if (!isOrganization) {
assertEquals(sharedRoleMgtListener.doPreDeleteApplication("sampleApplicationId", "sampleTenantDomain",
"sampleUsername"), expected);
} else {
when(mockedApplicationManagementService.getServiceProvider("sampleApplicationId", "sampleTenantDomain"))
.thenReturn(serviceProvider);
assertEquals(sharedRoleMgtListener.doPreDeleteApplication("sampleApplicationId", "sampleTenantDomain",
"sampleUsername"), expected);
}
}

@Test(dataProvider = "applicationDataProvider")
public void testDoPostGetAllowedAudienceForRoleAssociation(String mainAppId) throws Exception {

AssociatedRolesConfig associatedRolesConfig = new AssociatedRolesConfig();
RoleV2 roleV2 = new RoleV2();
roleV2.setName("sampleRoleName");
associatedRolesConfig.setRoles(new RoleV2[]{roleV2});
SharedRoleMgtListener sharedRoleMgtListener = new SharedRoleMgtListener();
when(mockedApplicationManagementService.getMainAppId("1234-1234")).thenReturn(mainAppId);
when(mockedApplicationManagementService.getTenantIdByApp(mainAppId)).thenReturn(12345);
identityTenantUtilMockedStatic.when(() -> IdentityTenantUtil.getTenantDomain(12345)).thenReturn("sampleTenant");
when(mockedApplicationManagementService.getAllowedAudienceForRoleAssociation(mainAppId, "sampleTenant")).thenReturn("organization");
assertTrue(sharedRoleMgtListener.doPostGetAllowedAudienceForRoleAssociation(associatedRolesConfig, "1234-1234",
"sampleUsername"));
if (StringUtils.isNotEmpty(mainAppId)) {
assertEquals(associatedRolesConfig.getAllowedAudience(), "organization");
}
}
}

0 comments on commit 81768f3

Please sign in to comment.