From 6948c4be94f60f7f2f2d1fefbcc3790b75cf282c Mon Sep 17 00:00:00 2001 From: dhaura Date: Fri, 11 Oct 2024 17:37:15 +0530 Subject: [PATCH] Fix tenant id addition of newly added scopes of exiting system APIs. --- .../impl/APIResourceManagementDAOImpl.java | 7 +- .../dao/APIResourceManagementDAOImplTest.java | 140 +++++++++++++++++- 2 files changed, 145 insertions(+), 2 deletions(-) diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java index 30756faaf818..f69704d0abdd 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/main/java/org/wso2/carbon/identity/api/resource/mgt/dao/impl/APIResourceManagementDAOImpl.java @@ -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 @@ -273,6 +273,11 @@ public void updateAPIResource(APIResource apiResource, List addedScopes, preparedStatement.setString(4, apiResource.getId()); preparedStatement.executeUpdate(); + // If the API resource is a system API, set the tenant id to 0 since they are not tenant specific. + if (APIResourceManagementUtil.isSystemAPI(apiResource.getType())) { + tenantId = 0; + } + if (CollectionUtils.isNotEmpty(removedScopes)) { // Delete Scopes. deleteScopes(dbConnection, removedScopes, tenantId); diff --git a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/test/java/org/wso2/carbon/identity/api/resource/mgt/dao/APIResourceManagementDAOImplTest.java b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/test/java/org/wso2/carbon/identity/api/resource/mgt/dao/APIResourceManagementDAOImplTest.java index 9e29ca8fa7e2..bb8cad66fd6b 100644 --- a/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/test/java/org/wso2/carbon/identity/api/resource/mgt/dao/APIResourceManagementDAOImplTest.java +++ b/components/api-resource-mgt/org.wso2.carbon.identity.api.resource.mgt/src/test/java/org/wso2/carbon/identity/api/resource/mgt/dao/APIResourceManagementDAOImplTest.java @@ -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 @@ -27,6 +27,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.wso2.carbon.identity.api.resource.mgt.constant.APIResourceManagementConstants; import org.wso2.carbon.identity.api.resource.mgt.dao.impl.APIResourceManagementDAOImpl; import org.wso2.carbon.identity.application.common.model.APIResource; import org.wso2.carbon.identity.application.common.model.Scope; @@ -39,6 +40,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -54,6 +56,9 @@ public class APIResourceManagementDAOImplTest { private static final String DB_NAME = "api_resource_mgt_dao_db"; public static final String APIRESOURCE_IDENTIFIER = "testAPIResource identifier "; public static final String TEST_SCOPE_1 = "testScope1 "; + private static final String TENANT_TYPE = "TENANT"; + private static final String ORGANIZATION_TYPE = "ORGANIZATION"; + private static final String CONSOLE_ORG_LEVEL_TYPE = "CONSOLE_ORG_LEVEL"; private static final Map dataSourceMap = new HashMap<>(); private APIResourceManagementDAOImpl daoImpl; @@ -393,6 +398,51 @@ public void testDeleteScope() throws Exception { } + @DataProvider + public Object[][] updateAPIResourceScopeAddition() { + + return new Object[][]{ + {APIResourceManagementConstants.BUSINESS_TYPE}, + {APIResourceManagementConstants.SYSTEM_TYPE}, + {ORGANIZATION_TYPE}, + {TENANT_TYPE}, + {CONSOLE_ORG_LEVEL_TYPE} + }; + } + + @Test(dataProvider = "updateAPIResourceScopeAddition", priority = 14) + public void testUpdateAPIResourceScopeAddition(String type) throws Exception { + + // Add API resource to database. + String apiNamePostFix = "update-scope-addition-test"; + List scopes = new ArrayList<>(); + scopes.add(createScope("test_scope_1_" + apiNamePostFix)); + scopes.add(createScope("test_scope_2_" + apiNamePostFix)); + APIResource apiResource = addAPIResourceToDB(apiNamePostFix, scopes, type, getConnection(), TENANT_ID); + + // Validate scopes count before update. + validateScopesCount(apiResource.getId(), 2); + + try (MockedStatic identityDatabaseUtil = mockStatic(IdentityDatabaseUtil.class)) { + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())) + .thenReturn(getConnection()); + Scope newScope = createScope("test_scope_3_" + apiNamePostFix); + apiResource.getScopes().add(newScope); + + List addedScopes = new ArrayList<>(); + addedScopes.add(newScope); + + // Update API resource with a new scope. + daoImpl.updateAPIResource(apiResource, addedScopes, Collections.emptyList(), TENANT_ID); + } + + // Validate updated scopes count. + validateScopesCount(apiResource.getId(), 3); + + // Delete API resource from database. + deleteAPIResourceFromDB(apiResource.getId(), TENANT_ID); + } + /** * Create scope with the given name. * @@ -431,6 +481,26 @@ private static APIResource createAPIResource(String postFix) { return apiResourceBuilder.build(); } + /** + * Create API resource with the given postfix, scopes and type. + * + * @param postFix Postfix to be appended to each API resource and scope information. + * @param scopes List of scopes. + * @param type API resource type. + * @return API resource. + */ + private static APIResource createAPIResource(String postFix, List scopes, String type) { + + APIResource.APIResourceBuilder apiResourceBuilder = new APIResource.APIResourceBuilder() + .name("Test API Resource Name " + postFix) + .identifier("/test/api/path/" + postFix) + .description("Test API Resource Description " + postFix) + .type(type) + .requiresAuthorization(true) + .scopes(scopes); + return apiResourceBuilder.build(); + } + /** * Add API resource to the database. * @@ -470,6 +540,74 @@ private APIResource addAPIResourceToDB(String namePostFix, Connection connection return daoImpl.addAPIResource(apiResource, tenantId); } + /** + * Add API resource to the database. + * + * @param namePostFix Postfix to be appended to each API resource and scope information. + * @param scopes List of scopes. + * @param type API resource type. + * @param connection Database connection. + * @param tenantId Tenant ID. + * @return API resource. + * @throws Exception Error when adding API resource. + */ + private APIResource addAPIResourceToDB(String namePostFix, List scopes, String type, Connection connection, + int tenantId) throws Exception { + + try (MockedStatic identityDatabaseUtil = mockStatic(IdentityDatabaseUtil.class)) { + APIResource apiResource = createAPIResource(namePostFix, scopes, type); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())).thenReturn(connection); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.commitTransaction(any(Connection.class))) + .thenAnswer((Answer) invocation -> { + connection.commit(); + return null; + }); + return daoImpl.addAPIResource(apiResource, tenantId); + } + + } + + /** + * Delete API resource from the database. + * + * @param apiId API resource ID. + * @param tenantId Tenant ID. + * @throws Exception Error when deleting API resource. + */ + private void deleteAPIResourceFromDB(String apiId, int tenantId) throws Exception { + + try (MockedStatic identityDatabaseUtil = mockStatic(IdentityDatabaseUtil.class)) { + Connection connection = getConnection(); + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())).thenReturn(connection); + + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.commitTransaction(any(Connection.class))) + .thenAnswer((Answer) invocation -> { + connection.commit(); + return null; + }); + daoImpl.deleteAPIResourceById(apiId, tenantId); + } + } + + /** + * Method to validate the number of scopes for a given API. + * + * @param apiId API resource ID. + * @param expectedNumberOfScopes Expected number of scopes. + * @throws Exception Error when validating scopes count. + */ + private void validateScopesCount(String apiId, int expectedNumberOfScopes) throws Exception { + + try (MockedStatic identityDatabaseUtil = mockStatic(IdentityDatabaseUtil.class)) { + identityDatabaseUtil.when(() -> IdentityDatabaseUtil.getDBConnection(anyBoolean())) + .thenReturn(getConnection()); + + List scopesList = daoImpl.getScopesByAPI(apiId, TENANT_ID); + Assert.assertNotNull(scopesList); + Assert.assertEquals(scopesList.size(), expectedNumberOfScopes); + } + } + private static Connection getConnection() throws SQLException { if (dataSourceMap.get(DB_NAME) != null) {