diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/pom.xml b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/pom.xml new file mode 100644 index 000000000..48215ca4a --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/pom.xml @@ -0,0 +1,151 @@ + + + + + org.wso2.carbon.identity.organization.management + identity-organization-management + 1.4.61-SNAPSHOT + ../../pom.xml + + + 4.0.0 + org.wso2.carbon.identity.organization.resource.sharing.policy.management + WSO2 - Organization Resource Sharing Policy Management Service + bundle + + + 11 + 11 + UTF-8 + + + + + org.wso2.carbon + org.wso2.carbon.utils + + + org.wso2.carbon.identity.organization.management.core + org.wso2.carbon.identity.organization.management.service + + + org.wso2.carbon.utils + org.wso2.carbon.database.utils + + + org.wso2.carbon + org.wso2.carbon.user.core + + + + org.testng + testng + test + + + org.mockito + mockito-core + test + + + com.h2database + h2 + test + + + org.wso2.carbon.multitenancy + org.wso2.carbon.tenant.mgt + test + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + Organization Resource Sharing Policy Service Bundle + + org.wso2.carbon.identity.organization.resource.sharing.policy.management.internal + org.wso2.carbon.identity.organization.resource.sharing.policy.management.dao + + + org.wso2.carbon.identity.organization.resource.sharing.policy.management, + org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant, + org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception, + org.wso2.carbon.identity.organization.resource.sharing.policy.management.model, + org.wso2.carbon.identity.organization.resource.sharing.policy.management.util; + version="${identity.organization.management.exp.pkg.version}", + + + javax.sql, + org.apache.commons.logging; version="${org.apache.commons.logging.imp.pkg.version.range}", + org.apache.commons.collections; version="${org.apache.commons.collections.imp.pkg.version.range}", + org.apache.commons.lang;version="${org.apache.commons.lang.imp.pkg.version.range}", + org.osgi.framework; version="${osgi.framework.imp.pkg.version.range}", + org.osgi.service.component; version="${osgi.service.component.imp.pkg.version.range}", + org.wso2.carbon.context;version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.database.utils.jdbc;version="${org.wso2.carbon.database.utils.version.range}", + org.wso2.carbon.database.utils.jdbc.exceptions;version="${org.wso2.carbon.database.utils.version.range}", + org.wso2.carbon.identity.organization.management.service;version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.management.service.util;version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", + org.wso2.carbon;version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.user.core.util;version="${carbon.kernel.package.import.version.range}", + + + + + + org.jacoco + jacoco-maven-plugin + ${jacoco.version} + + + org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/*.class + org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/*.class + org/wso2/carbon/identity/organization/resource/sharing/policy/management/internal/*.class + org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/*.class + org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerService.class + + + + + + prepare-agent + + + + + report + test + + report + + + + + + + + diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerService.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerService.java new file mode 100644 index 000000000..075ac35b6 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerService.java @@ -0,0 +1,245 @@ +/* + * 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.resource.sharing.policy.management; + +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.SharedAttributeType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.ResourceSharingPolicy; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.SharedResourceAttribute; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * Service interface for managing resource sharing policies across organizations. + *

+ * This interface provides methods for adding, retrieving, and deleting resource sharing policies. + * It also allows managing shared resource attributes, offering capabilities to add, retrieve, and delete + * these attributes. + *

+ */ +public interface ResourceSharingPolicyHandlerService { + + /** + * Creates a new resource sharing policy record and returns its unique identifier. + * + * @param resourceSharingPolicy The {@link ResourceSharingPolicy} containing details such as resource type, + * initiating organization, policy holding organization, and sharing policy. + * Must not be {@code null}. + * @return The unique identifier of the newly created resource sharing policy. + * @throws ResourceSharingPolicyMgtException If an error occurs during the creation of the resource sharing policy. + */ + int addResourceSharingPolicy(ResourceSharingPolicy resourceSharingPolicy) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves a resource sharing policy by its unique identifier, if present. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy to be retrieved. + * Must be a valid ID greater than zero. + * @return An {@link Optional} containing the {@link ResourceSharingPolicy} if found, + * or an empty {@link Optional} if no matching resource sharing policy exists. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the resource sharing policy. + */ + Optional getResourceSharingPolicyById(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves a list of resource sharing policies associated with the given policy holding organization IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose policies need to be retrieved. + * Must not be {@code null} or empty. + * @return A list of {@link ResourceSharingPolicy} objects for the specified organization IDs. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the resource sharing policies. + */ + List getResourceSharingPolicies(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves a map of resource sharing policies grouped by resource type for the given organization IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose policies need to be retrieved. + * Must not be {@code null} or empty. + * @return A map where each key is a {@link ResourceType} and the corresponding value is a list of + * {@link ResourceSharingPolicy}. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the resource sharing policies. + */ + Map> getResourceSharingPoliciesGroupedByResourceType( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtException; + + /** + * Retrieves a map of resource sharing policies grouped by policy holding organization ID for the given IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose policies need to be retrieved. + * Must not be {@code null} or empty. + * @return A map where each key is an organization ID, and the value is a list of {@link ResourceSharingPolicy}. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the resource sharing policies. + */ + Map> getResourceSharingPoliciesGroupedByPolicyHoldingOrgId( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtException; + + /** + * Deletes a resource sharing policy by its unique identifier if the specified organization has permission. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete sharing policies. + * Must not be {@code null}. + * @throws ResourceSharingPolicyMgtException If an error occurs while deleting the resource sharing policy. + */ + void deleteResourceSharingPolicyRecordById(int resourceSharingPolicyId, String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException; + + /** + * Deletes a resource sharing policy based on its resource type and resource ID if permitted. + * + * @param resourceType The {@link ResourceType} of the resource. + * @param resourceId The unique identifier of the resource whose sharing policy is to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete sharing policies. + * @throws ResourceSharingPolicyMgtException If an error occurs while deleting the resource sharing policy. + */ + void deleteResourceSharingPolicyByResourceTypeAndId(ResourceType resourceType, String resourceId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException; + + /** + * Adds shared resource attributes to an existing resource sharing policy. + * + * @param sharedResourceAttributes A list of {@link SharedResourceAttribute} objects to be added. + * Must not be {@code null} or empty. + * @return {@code true} if the shared resource attributes were added successfully. + * @throws ResourceSharingPolicyMgtException If an error occurs while adding the shared resource attributes. + */ + boolean addSharedResourceAttributes(List sharedResourceAttributes) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves shared resource attributes for a given resource sharing policy. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy. + * @return A list of {@link SharedResourceAttribute} associated with the given policy. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the shared resource attributes. + */ + List getSharedResourceAttributesBySharingPolicyId(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves shared resource attributes based on attribute type. + * + * @param attributeType The {@link SharedAttributeType} of the resource attribute to be retrieved. + * @return A list of {@link SharedResourceAttribute} objects for the specified type. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the shared resource attributes. + */ + List getSharedResourceAttributesByType(SharedAttributeType attributeType) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves shared resource attributes based on attribute ID. + * + * @param attributeId The unique identifier of the resource attribute to be retrieved. + * @return A list of {@link SharedResourceAttribute} objects for the specified attribute ID. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the shared resource attributes. + */ + List getSharedResourceAttributesById(String attributeId) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves shared resource attributes based on attribute type and ID. + * + * @param attributeType The {@link SharedAttributeType} of the resource attribute to be retrieved. + * @param attributeId The unique identifier of the attribute to be retrieved. + * @return A list of {@link SharedResourceAttribute} objects for the specified type and ID. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the shared resource attributes. + */ + List getSharedResourceAttributesByTypeAndId(SharedAttributeType attributeType, + String attributeId) + throws ResourceSharingPolicyMgtException; + + /** + * Deletes shared resource attributes for a given resource sharing policy and attribute type if the specified + * organization has permission. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy. + * @param sharedAttributeType The {@link SharedAttributeType} to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete shared attributes. + * @throws ResourceSharingPolicyMgtException If an error occurs while deleting the shared resource attributes. + */ + void deleteSharedResourceAttributesByResourceSharingPolicyId(int resourceSharingPolicyId, + SharedAttributeType sharedAttributeType, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException; + + /** + * Deletes a shared resource attribute based on its attribute type and unique identifier if the specified + * organization has permission. + * + * @param attributeType The {@link SharedAttributeType} of the attribute to be deleted. + * @param attributeId The unique identifier of the attribute to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete shared attributes. + * @throws ResourceSharingPolicyMgtException If an error occurs while deleting the shared resource attribute. + */ + void deleteSharedResourceAttributeByAttributeTypeAndId(SharedAttributeType attributeType, String attributeId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException; + + /** + * Adds a resource sharing policy along with its associated shared resource attributes in a single transaction. + * + * @param resourceSharingPolicy The {@link ResourceSharingPolicy} containing details such as resource type, + * initiating organization, policy holding organization, and sharing policy. + * Must not be {@code null}. + * @param sharedResourceAttributes A list of {@link SharedResourceAttribute} objects associated with the resource + * sharing policy. Must not be {@code null} or empty. + * @return {@code true} if both the resource sharing policy and the shared resource attributes were added + * successfully. + * @throws ResourceSharingPolicyMgtException If an error occurs while adding the resource sharing policy or the + * shared resource attributes. + */ + boolean addResourceSharingPolicyWithAttributes(ResourceSharingPolicy resourceSharingPolicy, + List sharedResourceAttributes) + throws ResourceSharingPolicyMgtException; + + /** + * Retrieves a map of resource sharing policies along with their associated shared resource attributes + * for the given list of policy holding organization IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose resource sharing policies along with + * shared resource attributes need to be retrieved. + * Must not be {@code null} or empty. + * @return A nested map where: + * - The first key is the organization ID. + * - The second key is the {@link ResourceSharingPolicy}. + * - The value is a list of {@link SharedResourceAttribute} associated with the policy. + * If no matching policies or attributes are found, an empty map will be returned. + * @throws ResourceSharingPolicyMgtException If an error occurs while retrieving the resource sharing + * policies or shared attributes. + */ + Map>> + getResourceSharingPoliciesWithSharedAttributes(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtException; +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerServiceImpl.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerServiceImpl.java new file mode 100644 index 000000000..801798cd5 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerServiceImpl.java @@ -0,0 +1,263 @@ +/* + * 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.resource.sharing.policy.management; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.SharedAttributeType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.dao.ResourceSharingPolicyHandlerDAO; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.dao.ResourceSharingPolicyHandlerDAOImpl; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtClientException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.ResourceSharingPolicy; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.SharedResourceAttribute; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_INAPPLICABLE_RESOURCE_TYPE_TO_POLICY; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_INVALID_ID; + +/** + * Implementation of the core service for managing resource sharing policies. + */ +public class ResourceSharingPolicyHandlerServiceImpl implements ResourceSharingPolicyHandlerService { + + private static final Log LOG = LogFactory.getLog(ResourceSharingPolicyHandlerServiceImpl.class); + private static final ResourceSharingPolicyHandlerDAO RESOURCE_SHARING_POLICY_HANDLER_DAO = + new ResourceSharingPolicyHandlerDAOImpl(); + + @Override + public int addResourceSharingPolicy(ResourceSharingPolicy resourceSharingPolicy) + throws ResourceSharingPolicyMgtException { + + List applicableResources = resourceSharingPolicy.getSharingPolicy().getApplicableResources(); + if (!applicableResources.contains(resourceSharingPolicy.getResourceType())) { + throw new ResourceSharingPolicyMgtClientException(ERROR_CODE_INAPPLICABLE_RESOURCE_TYPE_TO_POLICY.getCode(), + ERROR_CODE_INAPPLICABLE_RESOURCE_TYPE_TO_POLICY.getMessage(), + ERROR_CODE_INAPPLICABLE_RESOURCE_TYPE_TO_POLICY.getDescription()); + } + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.addResourceSharingPolicy(resourceSharingPolicy); + } + + @Override + public Optional getResourceSharingPolicyById(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtException { + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getResourceSharingPolicyById(resourceSharingPolicyId); + } + + @Override + public List getResourceSharingPolicies(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(policyHoldingOrganizationIds); + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getResourceSharingPolicies(policyHoldingOrganizationIds); + } + + @Override + public Map> getResourceSharingPoliciesGroupedByResourceType( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtException { + + validateIdFormat(policyHoldingOrganizationIds); + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getResourceSharingPoliciesGroupedByResourceType( + policyHoldingOrganizationIds); + } + + @Override + public Map> getResourceSharingPoliciesGroupedByPolicyHoldingOrgId( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtException { + + validateIdFormat(policyHoldingOrganizationIds); + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getResourceSharingPoliciesGroupedByPolicyHoldingOrgId( + policyHoldingOrganizationIds); + } + + @Override + public void deleteResourceSharingPolicyRecordById(int resourceSharingPolicyId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(sharingPolicyInitiatedOrgId); + + RESOURCE_SHARING_POLICY_HANDLER_DAO.deleteResourceSharingPolicyRecordById(resourceSharingPolicyId, + sharingPolicyInitiatedOrgId); + } + + @Override + public void deleteResourceSharingPolicyByResourceTypeAndId(ResourceType resourceType, String resourceId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(Arrays.asList(resourceId, sharingPolicyInitiatedOrgId)); + + RESOURCE_SHARING_POLICY_HANDLER_DAO.deleteResourceSharingPolicyByResourceTypeAndId(resourceType, + resourceId, sharingPolicyInitiatedOrgId); + } + + @Override + public boolean addSharedResourceAttributes(List sharedResourceAttributes) + throws ResourceSharingPolicyMgtException { + + List addableSharedResourceAttributes = new ArrayList<>(); + List invalidPolicyIds = new ArrayList<>(); + + for (SharedResourceAttribute sharedResourceAttribute : sharedResourceAttributes) { + Optional resourceSharingPolicy = + getResourceSharingPolicyById(sharedResourceAttribute.getResourceSharingPolicyId()); + if (resourceSharingPolicy.isPresent()) { + if (isValidAttributeForTheResource(resourceSharingPolicy.get(), sharedResourceAttribute)) { + addableSharedResourceAttributes.add(sharedResourceAttribute); + } + } else { + invalidPolicyIds.add(sharedResourceAttribute.getResourceSharingPolicyId()); + } + } + + if (!invalidPolicyIds.isEmpty()) { + String warnMessage = "Some attributes were skipped due to invalid ResourceSharingPolicy IDs: " + + invalidPolicyIds.stream().map(String::valueOf).collect(Collectors.joining(", ", "{", "}")); + LOG.warn(warnMessage); + } + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.addSharedResourceAttributes(addableSharedResourceAttributes); + } + + @Override + public List getSharedResourceAttributesBySharingPolicyId(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtException { + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getSharedResourceAttributesBySharingPolicyId( + resourceSharingPolicyId); + } + + @Override + public List getSharedResourceAttributesByType(SharedAttributeType attributeType) + throws ResourceSharingPolicyMgtException { + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getSharedResourceAttributesByType(attributeType); + } + + @Override + public List getSharedResourceAttributesById(String attributeId) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(attributeId); + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getSharedResourceAttributesById(attributeId); + } + + @Override + public List getSharedResourceAttributesByTypeAndId(SharedAttributeType attributeType, + String attributeId) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(attributeId); + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getSharedResourceAttributesByTypeAndId(attributeType, attributeId); + } + + @Override + public void deleteSharedResourceAttributesByResourceSharingPolicyId(int resourceSharingPolicyId, + SharedAttributeType sharedAttributeType, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(sharingPolicyInitiatedOrgId); + + RESOURCE_SHARING_POLICY_HANDLER_DAO.deleteSharedResourceAttributesByResourceSharingPolicyId( + resourceSharingPolicyId, sharedAttributeType, sharingPolicyInitiatedOrgId); + } + + @Override + public void deleteSharedResourceAttributeByAttributeTypeAndId(SharedAttributeType attributeType, + String attributeId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(sharingPolicyInitiatedOrgId); + + RESOURCE_SHARING_POLICY_HANDLER_DAO.deleteSharedResourceAttributeByAttributeTypeAndId(attributeType, + attributeId, sharingPolicyInitiatedOrgId); + } + + @Override + public boolean addResourceSharingPolicyWithAttributes(ResourceSharingPolicy resourceSharingPolicy, + List sharedResourceAttributes) + throws ResourceSharingPolicyMgtException { + + List addableSharedResourceAttributes = new ArrayList<>(); + + for (SharedResourceAttribute sharedResourceAttribute : sharedResourceAttributes) { + if (isValidAttributeForTheResource(resourceSharingPolicy, sharedResourceAttribute)) { + addableSharedResourceAttributes.add(sharedResourceAttribute); + } + } + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.addResourceSharingPolicyWithAttributes(resourceSharingPolicy, + addableSharedResourceAttributes); + } + + @Override + public Map>> + getResourceSharingPoliciesWithSharedAttributes(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtException { + + validateIdFormat(policyHoldingOrganizationIds); + + return RESOURCE_SHARING_POLICY_HANDLER_DAO.getResourceSharingPoliciesWithSharedAttributes( + policyHoldingOrganizationIds); + } + + private boolean isValidAttributeForTheResource(ResourceSharingPolicy resourceSharingPolicy, + SharedResourceAttribute sharedResourceAttribute) { + + return resourceSharingPolicy.getResourceType() + .isApplicableAttributeType(sharedResourceAttribute.getSharedAttributeType()); + } + + private void validateIdFormat(String id) throws ResourceSharingPolicyMgtClientException { + + if (isInvalidId(id)) { + throw new ResourceSharingPolicyMgtClientException(ERROR_CODE_INVALID_ID.getCode(), + ERROR_CODE_INVALID_ID.getMessage(), ERROR_CODE_INVALID_ID.getDescription()); + } + } + + private void validateIdFormat(List ids) throws ResourceSharingPolicyMgtClientException { + + for (String id : ids) { + validateIdFormat(id); + } + } + + private boolean isInvalidId(String id) { + + return id == null || id.isEmpty(); + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/OrganizationScope.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/OrganizationScope.java new file mode 100644 index 000000000..4035ec023 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/OrganizationScope.java @@ -0,0 +1,28 @@ +/* + * 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.resource.sharing.policy.management.constant; + +/** + * Enum representing the organization scope for which a given policy is shared with. + */ +public enum OrganizationScope { + EXISTING_ORGS_ONLY, + EXISTING_ORGS_AND_FUTURE_ORGS_ONLY, + FUTURE_ORGS_ONLY, + NO_ORG, +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/PolicyEnum.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/PolicyEnum.java new file mode 100644 index 000000000..2ee9bccbf --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/PolicyEnum.java @@ -0,0 +1,306 @@ +/* + * 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.resource.sharing.policy.management.constant; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +/** + * Enum representing user sharing policies with additional fields for code, name, value, organization scope, applicable + * resources, and details. + */ +public enum PolicyEnum { + + ALL_EXISTING_ORGS_ONLY( + "GENERAL-001", + "AllExistingOrgsOnly", + "ALL_EXISTING_ORGS_ONLY", + OrganizationScope.EXISTING_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy applies when the resource needs to be shared with all existing organizations at " + + "the current time. Newly created organizations after the policy is applied will not be included " + + "under this policy."), + ALL_EXISTING_AND_FUTURE_ORGS( + "GENERAL-002", + "AllExistingAndFutureOrgs", + "ALL_EXISTING_AND_FUTURE_ORGS", + OrganizationScope.EXISTING_ORGS_AND_FUTURE_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy allows sharing the resource with all current and any future organizations. It " + + "ensures that any new organizations created after the policy is set are automatically included."), + IMMEDIATE_EXISTING_ORGS_ONLY( + "GENERAL-003", + "ImmediateExistingOrgsOnly", + "IMMEDIATE_EXISTING_ORGS_ONLY", + OrganizationScope.EXISTING_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy is used to share the resource exclusively with all immediate existing child " + + "organizations. Newly created immediate child organizations after the policy is applied are " + + "not included."), + IMMEDIATE_EXISTING_AND_FUTURE_ORGS( + "GENERAL-004", + "ImmediateExistingAndFutureOrgs", + "IMMEDIATE_EXISTING_AND_FUTURE_ORGS", + OrganizationScope.EXISTING_ORGS_AND_FUTURE_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy is used to share the resource exclusively with all immediate existing child " + + "organizations. Newly created immediate child organizations after the policy is applied are " + + "not included."), + SELECTED_ORG_ONLY( + "SELECTIVE-001", + "SelectedOrgOnly", + "SELECTED_ORG_ONLY", + OrganizationScope.EXISTING_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy applies when the resource is to be shared with a single, specific organization " + + "only. Newly created child organizations under this selected organization will not be included."), + SELECTED_ORG_WITH_ALL_EXISTING_CHILDREN_ONLY( + "SELECTIVE-002", + "SelectedOrgWithAllExistingChildrenOnly", + "SELECTED_ORG_WITH_ALL_EXISTING_CHILDREN_ONLY", + OrganizationScope.EXISTING_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy ensures the resource is shared with a selected organization and all of its " + + "existing child organizations. New child organizations created under this selected organization " + + "after the policy is applied will not be included."), + SELECTED_ORG_WITH_ALL_EXISTING_AND_FUTURE_CHILDREN( + "SELECTIVE-003", + "SelectedOrgWithAllExistingAndFutureChildren", + "SELECTED_ORG_WITH_ALL_EXISTING_AND_FUTURE_CHILDREN", + OrganizationScope.EXISTING_ORGS_AND_FUTURE_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy ensures the resource is shared with a selected organization and all of its child " + + "organizations, including those created in the future."), + SELECTED_ORG_WITH_EXISTING_IMMEDIATE_CHILDREN_ONLY( + "SELECTIVE-004", + "SelectedOrgWithExistingImmediateChildrenOnly", + "SELECTED_ORG_WITH_EXISTING_IMMEDIATE_CHILDREN_ONLY", + OrganizationScope.EXISTING_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy shares the resource with a selected organization and all of its existing " + + "immediate child organizations. Newly created immediate children will not be included after " + + "the policy is applied."), + SELECTED_ORG_WITH_EXISTING_IMMEDIATE_AND_FUTURE_CHILDREN( + "SELECTIVE-005", + "SelectedOrgWithExistingImmediateAndFutureChildren", + "SELECTED_ORG_WITH_EXISTING_IMMEDIATE_AND_FUTURE_CHILDREN", + OrganizationScope.EXISTING_ORGS_AND_FUTURE_ORGS_ONLY, + Collections.singletonList(ResourceType.USER), + "This policy allows sharing the resource with a selected organization and all of its " + + "immediate child organizations, including those created in the future."), + NO_SHARING( + "NONE-000", + "NoSharing", + "NO_SHARING", + OrganizationScope.NO_ORG, + Collections.emptyList(), + "This policy specifies that no sharing will occur. The resource remains restricted to its " + + "current context and is not shared with any organization." + ); + + private final String policyCode; + private final String policyName; + private final String value; + private final OrganizationScope organizationScope; + private final List applicableResources; + private final String description; + + /** + * Constructor to initialize the user sharing policy enum. + * + * @param policyCode Unique code representing the sharing policy. + * @param policyName Name of the sharing policy. + * @param value The value of the sharing policy. + * @param applicableResources Type of resources to which the policy applies. + * @param description Short description of the sharing policy. + */ + PolicyEnum(String policyCode, String policyName, String value, OrganizationScope organizationScope, + List applicableResources, String description) { + + this.policyCode = policyCode; + this.policyName = policyName; + this.value = value; + this.organizationScope = organizationScope; + this.applicableResources = applicableResources; + this.description = description; + } + + /** + * Get the unique code of the sharing policy. + * + * @return Unique code of the sharing policy. + */ + public String getPolicyCode() { + + return policyCode; + } + + /** + * Get the name of the sharing policy. + * + * @return Name of the sharing policy. + */ + public String getPolicyName() { + + return policyName; + } + + /** + * Get the value of the sharing policy. + * + * @return Value of the sharing policy. + */ + public String getValue() { + + return value; + } + + /** + * Get the organization scope of the sharing policy. + * + * @return {@link OrganizationScope} of the sharing policy. + */ + public OrganizationScope getOrganizationScope() { + + return organizationScope; + } + + /** + * Get the applicable resource type for the sharing policy. + * + * @return Types of the applicable resources. + */ + public List getApplicableResources() { + + return applicableResources; + } + + /** + * Get the short description of the sharing policy. + * + * @return Description of the sharing policy. + */ + public String getDescription() { + + return description; + } + + /** + * Get the PolicyEnum based on the given policy code. + * + * @param policyCode Code of the sharing policy. + * @return Corresponding PolicyEnum, wrapped in Optional. + */ + public static Optional getByPolicyCode(String policyCode) { + + for (PolicyEnum policy : PolicyEnum.values()) { + if (policy.policyCode.equals(policyCode)) { + return Optional.of(policy); + } + } + return Optional.empty(); + } + + /** + * Get the PolicyEnum based on the given policy value. + * + * @param value Code of the sharing policy. + * @return Corresponding PolicyEnum, wrapped in Optional. + */ + public static Optional getByValue(String value) { + + for (PolicyEnum policy : PolicyEnum.values()) { + if (policy.value.equals(value)) { + return Optional.of(policy); + } + } + return Optional.empty(); + } + + /** + * Validate and get the PolicyEnum based on the given requested policy. + * + * @param requestedPolicy Requested policy as an Object (should be an instance of String). + * @return Corresponding PolicyEnum. + * @throws IllegalArgumentException if the requested policy is invalid or not found. + */ + public static PolicyEnum validateAndGetPolicyEnum(String requestedPolicy) { + + for (PolicyEnum policy : PolicyEnum.values()) { + if (policy.value.equalsIgnoreCase(requestedPolicy) || + policy.policyCode.equalsIgnoreCase(requestedPolicy) || + policy.policyName.equalsIgnoreCase(requestedPolicy)) { + return policy; + } + } + // Handle the case where no matching policy is found + throw new IllegalArgumentException("Invalid policy: " + requestedPolicy); + } + + /** + * Get the PolicyEnum by matching value. + * + * @param value Policy value to match. + * @return Corresponding PolicyEnum. + * @throws IllegalArgumentException if the policy value is not found. + */ + public static PolicyEnum getPolicyByValue(String value) { + + for (PolicyEnum policy : PolicyEnum.values()) { + if (policy.value.equalsIgnoreCase(value)) { + return policy; + } + } + throw new IllegalArgumentException("Invalid policy value: " + value); + } + + /** + * Get the PolicyEnum by matching policy code. + * + * @param policyCode Policy code to match. + * @return Corresponding PolicyEnum. + * @throws IllegalArgumentException if the policy code is not found. + */ + public static PolicyEnum getPolicyByPolicyCode(String policyCode) { + + for (PolicyEnum policy : PolicyEnum.values()) { + if (policy.policyCode.equalsIgnoreCase(policyCode)) { + return policy; + } + } + throw new IllegalArgumentException("Invalid policy code: " + policyCode); + } + + /** + * Get the PolicyEnum by matching policy name. + * + * @param policyName Policy name to match. + * @return Corresponding PolicyEnum. + * @throws IllegalArgumentException if the policy name is not found. + */ + public static PolicyEnum getPolicyByPolicyName(String policyName) { + + for (PolicyEnum policy : PolicyEnum.values()) { + if (policy.policyName.equalsIgnoreCase(policyName)) { + return policy; + } + } + throw new IllegalArgumentException("Invalid policy name: " + policyName); + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceSharingConstants.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceSharingConstants.java new file mode 100644 index 000000000..3f716b9b5 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceSharingConstants.java @@ -0,0 +1,116 @@ +/* + * 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.resource.sharing.policy.management.constant; + +/** + * Constants for organization user sharing. + */ +public class ResourceSharingConstants { + + public static final String SHARING_ERROR_PREFIX = "RSPM-"; + + /** + * Error messages for organization user sharing management related errors. + */ + public enum ErrorMessage { + + // Client Errors. + ERROR_CODE_MISSING_MANDATORY_FIELDS("60001", + "All fields are mandatory and must be provided.", + "One or more mandatory field is empty."), + ERROR_CODE_INAPPLICABLE_RESOURCE_TYPE_TO_POLICY("60002", + "The specified resource type is not supported by the selected sharing policy.", + "The resource sharing policy does not allow sharing for the provided resource type."), + ERROR_CODE_INVALID_ID("60003", + "ID is invalid.", + "ID cannot be null or empty."), + + // Server Errors. + ERROR_CODE_RESOURCE_SHARING_POLICY_CREATION_FAILED("65001", + "Failed to create resource sharing policy.", + "An error occurred while creating the resource sharing policy in the database."), + ERROR_CODE_RESOURCE_SHARING_POLICY_DELETION_FAILED("65002", + "Failed to delete resource sharing policy.", + "An error occurred while deleting the resource sharing policy from the database."), + ERROR_CODE_RESOURCE_SHARED_RESOURCE_ATTRIBUTE_CREATION_FAILED("65003", + "Failed to add shared resource attributes for policy ID: %d. Failed attributes: %s", + "An error occurred while creating the shared resource attributes in the database."), + ERROR_CODE_RESOURCE_SHARED_RESOURCE_ATTRIBUTE_DELETION_FAILED("65004", + "Failed to delete shared resource attributes for policy ID: %d. Failed attributes: %s", + "An error occurred while deleting the shared resource attributes in the database."), + ERROR_CODE_RESOURCE_SHARING_POLICY_AND_SHARED_RESOURCE_ATTRIBUTE_CREATION_FAILED("65005", + "Failed to create resource sharing policy and shared resource attributes.", + "An error occurred while creating the resource sharing policy and shared resource " + + "attributes in the database."), + ERROR_CODE_RETRIEVING_SHARED_RESOURCE_ATTRIBUTES_FAILED("65006", + "Failed to retrieve shared resource attributes.", + "An error occurred while retrieving the shared resource attributes from the database."), + ERROR_CODE_CREATION_OF_SHARED_RESOURCE_ATTRIBUTE_BUILDER_FAILED("65007", + "Failed to create shared resource attributes builder.", + "An error occurred while creating the shared resource attributes builder from the database."), + ERROR_CODE_RETRIEVING_RESOURCE_SHARING_POLICY_FAILED("65008", + "Failed to retrieve resource sharing policies.", + "An error occurred while retrieving the resource sharing policies from the database."), + ERROR_CODE_RETRIEVING_SHARED_RESOURCE_ATTRIBUTES_BY_RESOURCE_ID_AND_TYPE_FAILED("65009", + "Failed to retrieve shared resource attributes by resource ID and type.", + "An error occurred while retrieving shared resource attributes from the database by " + + "resource ID and type."), + ERROR_CODE_RESOURCE_SHARING_POLICY_DELETION_BY_RESOURCE_TYPE_AND_ID_FAILED("65010", + "Failed to delete resource sharing policy by type and ID.", + "An error occurred while deleting the resource sharing policy by resource type and ID " + + "from the database."), + ERROR_CODE_SHARED_RESOURCE_ATTRIBUTE_DELETION_BY_ATTRIBUTE_TYPE_AND_ID_FAILED("65011", + "Failed to delete shared resource attribute by type and ID.", + "An error occurred while deleting the shared resource attribute by attribute type and ID " + + "from the database."); + + private final String code; + private final String message; + private final String description; + + ErrorMessage(String code, String message, String description) { + + this.code = code; + this.message = message; + this.description = description; + } + + public String getCode() { + + return SHARING_ERROR_PREFIX + code; + } + + public String getMessage() { + + return message; + } + + public String getDescription() { + + return description; + } + + @Override + public String toString() { + + return String.format("ErrorMessage{code='%s', message='%s', description='%s'}", + getCode(), getMessage(), getDescription()); + } + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceSharingSQLConstants.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceSharingSQLConstants.java new file mode 100644 index 000000000..08846f66c --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceSharingSQLConstants.java @@ -0,0 +1,165 @@ +/* + * 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.resource.sharing.policy.management.constant; + +/** + * SQL constants for resource sharing policy management. + */ +public class ResourceSharingSQLConstants { + + // SQL for creating a resource sharing policy. + public static final String CREATE_RESOURCE_SHARING_POLICY = + "INSERT INTO UM_RESOURCE_SHARING_POLICY (UM_RESOURCE_ID, UM_RESOURCE_TYPE, " + + "UM_INITIATING_ORG_ID, UM_POLICY_HOLDING_ORG_ID, UM_SHARING_POLICY) VALUES (" + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_ID + ";, " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_TYPE + ";, " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID + ";, " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_POLICY_HOLDING_ORG_ID + ";, " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARING_POLICY + ";)"; + + // SQL for retrieving resource sharing policy by resource sharing policy ID. + public static final String GET_RESOURCE_SHARING_POLICY_BY_ID = + "SELECT UM_ID, UM_RESOURCE_ID, UM_RESOURCE_TYPE, UM_INITIATING_ORG_ID, " + + "UM_POLICY_HOLDING_ORG_ID, UM_SHARING_POLICY " + + "FROM UM_RESOURCE_SHARING_POLICY WHERE UM_ID = " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_UM_ID + ";"; + + // SQL HEAD constant for retrieving resource sharing policies by organization IDs. + public static final String GET_RESOURCE_SHARING_POLICIES_BY_ORG_IDS_HEAD = + "SELECT UM_ID, UM_RESOURCE_ID, UM_RESOURCE_TYPE, UM_INITIATING_ORG_ID, UM_POLICY_HOLDING_ORG_ID," + + " UM_SHARING_POLICY FROM UM_RESOURCE_SHARING_POLICY WHERE UM_POLICY_HOLDING_ORG_ID IN "; + + public static final String GET_RESOURCE_SHARING_POLICIES_WITH_SHARED_ATTRIBUTES_BY_POLICY_HOLDING_ORGS_HEAD = + "SELECT rsp.UM_POLICY_HOLDING_ORG_ID, " + + "rsp.UM_ID AS " + + SQLPlaceholders.JOIN_COLUMN_UM_ID_OF_UM_RESOURCE_SHARING_POLICY_TABLE + ", " + + "rsp.UM_RESOURCE_ID, rsp.UM_RESOURCE_TYPE, rsp.UM_INITIATING_ORG_ID, " + + "rsp.UM_POLICY_HOLDING_ORG_ID, rsp.UM_SHARING_POLICY, " + + "attr.UM_ID AS " + + SQLPlaceholders.JOIN_COLUMN_UM_ID_OF_UM_SHARED_RESOURCE_ATTRIBUTES_TABLE + ", " + + "attr.UM_RESOURCE_SHARING_POLICY_ID, attr.UM_SHARED_ATTRIBUTE_TYPE, attr.UM_SHARED_ATTRIBUTE_ID " + + "FROM " + + "UM_RESOURCE_SHARING_POLICY rsp LEFT JOIN UM_SHARED_RESOURCE_ATTRIBUTES attr " + + "ON rsp.UM_ID = attr.UM_RESOURCE_SHARING_POLICY_ID " + + "WHERE rsp.UM_POLICY_HOLDING_ORG_ID IN (%s)"; + + // SQL for deleting resource sharing policy. + public static final String DELETE_RESOURCE_SHARING_POLICY = + "DELETE FROM UM_RESOURCE_SHARING_POLICY WHERE " + + "UM_ID = :" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_UM_ID + "; AND " + + "UM_INITIATING_ORG_ID = :" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID + ";"; + + // SQL for deleting resource sharing policy by resource type and ID. + public static final String DELETE_RESOURCE_SHARING_POLICY_BY_RESOURCE_TYPE_AND_ID = + "DELETE FROM UM_RESOURCE_SHARING_POLICY WHERE " + + "UM_RESOURCE_TYPE = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_TYPE + "; AND " + + "UM_RESOURCE_ID = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_ID + "; AND " + + "UM_INITIATING_ORG_ID = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID + ";"; + + // SQL constant for inserting a shared resource attribute. + public static final String CREATE_SHARED_RESOURCE_ATTRIBUTE = + "INSERT INTO UM_SHARED_RESOURCE_ATTRIBUTES " + + "(UM_RESOURCE_SHARING_POLICY_ID, UM_SHARED_ATTRIBUTE_ID, UM_SHARED_ATTRIBUTE_TYPE) VALUES (" + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID + ";, " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID + ";, " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE + ";)"; + + // SQL for retrieving shared resource attributes. + public static final String GET_SHARED_RESOURCE_ATTRIBUTES = + "SELECT UM_ID, UM_RESOURCE_SHARING_POLICY_ID, UM_SHARED_ATTRIBUTE_TYPE, UM_SHARED_ATTRIBUTE_ID " + + "FROM UM_SHARED_RESOURCE_ATTRIBUTES WHERE UM_RESOURCE_SHARING_POLICY_ID = " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID + ";"; + + // SQL for retrieving shared resource attributes by attribute type. + public static final String GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_TYPE = + "SELECT UM_ID, UM_RESOURCE_SHARING_POLICY_ID, UM_SHARED_ATTRIBUTE_TYPE, UM_SHARED_ATTRIBUTE_ID " + + "FROM UM_SHARED_RESOURCE_ATTRIBUTES WHERE " + + "UM_SHARED_ATTRIBUTE_TYPE = " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE + ";"; + + // SQL for retrieving shared resource attributes by attribute ID. + public static final String GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_ID = + "SELECT UM_ID, UM_RESOURCE_SHARING_POLICY_ID, UM_SHARED_ATTRIBUTE_TYPE, UM_SHARED_ATTRIBUTE_ID " + + "FROM UM_SHARED_RESOURCE_ATTRIBUTES WHERE " + + "UM_SHARED_ATTRIBUTE_ID = " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID + ";"; + + // SQL for retrieving shared resource attributes by attribute type and ID. + public static final String GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_TYPE_AND_ID = + "SELECT UM_ID, UM_RESOURCE_SHARING_POLICY_ID, UM_SHARED_ATTRIBUTE_TYPE, UM_SHARED_ATTRIBUTE_ID " + + "FROM UM_SHARED_RESOURCE_ATTRIBUTES WHERE " + + "UM_SHARED_ATTRIBUTE_TYPE = " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE + "; AND " + + "UM_SHARED_ATTRIBUTE_ID = " + + ":" + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID + ";"; + + // SQL for deleting shared resource attributes. + public static final String DELETE_SHARED_RESOURCE_ATTRIBUTE = + "DELETE FROM UM_SHARED_RESOURCE_ATTRIBUTES WHERE " + + "UM_RESOURCE_SHARING_POLICY_ID = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID + "; AND " + + "UM_SHARED_ATTRIBUTE_TYPE = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE + "; AND " + + "UM_RESOURCE_SHARING_POLICY_ID IN (SELECT UM_ID FROM UM_RESOURCE_SHARING_POLICY WHERE " + + "UM_INITIATING_ORG_ID = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID + ";)"; + + // SQL for deleting shared resource attribute by attribute type and ID. + public static final String DELETE_SHARED_RESOURCE_ATTRIBUTE_BY_ATTRIBUTE_TYPE_AND_ID = + "DELETE FROM UM_SHARED_RESOURCE_ATTRIBUTES WHERE " + + "UM_SHARED_ATTRIBUTE_TYPE = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE + "; AND " + + "UM_SHARED_ATTRIBUTE_ID = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID + "; AND " + + "UM_RESOURCE_SHARING_POLICY_ID IN (SELECT UM_ID FROM UM_RESOURCE_SHARING_POLICY WHERE " + + "UM_INITIATING_ORG_ID = :" + + SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID + ";)"; + + private ResourceSharingSQLConstants() { + + } + + /** + * SQL Placeholders. + */ + public static final class SQLPlaceholders { + + public static final String DB_SCHEMA_COLUMN_NAME_UM_ID = "UM_ID"; + public static final String DB_SCHEMA_COLUMN_NAME_RESOURCE_ID = "UM_RESOURCE_ID"; + public static final String DB_SCHEMA_COLUMN_NAME_RESOURCE_TYPE = "UM_RESOURCE_TYPE"; + public static final String DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID = "UM_INITIATING_ORG_ID"; + public static final String DB_SCHEMA_COLUMN_NAME_POLICY_HOLDING_ORG_ID = "UM_POLICY_HOLDING_ORG_ID"; + public static final String DB_SCHEMA_COLUMN_NAME_SHARING_POLICY = "UM_SHARING_POLICY"; + public static final String DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID = "UM_RESOURCE_SHARING_POLICY_ID"; + public static final String DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID = "UM_SHARED_ATTRIBUTE_ID"; + public static final String DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE = "UM_SHARED_ATTRIBUTE_TYPE"; + + public static final String JOIN_COLUMN_UM_ID_OF_UM_RESOURCE_SHARING_POLICY_TABLE = "POLICY_ID"; + public static final String JOIN_COLUMN_UM_ID_OF_UM_SHARED_RESOURCE_ATTRIBUTES_TABLE = "ATTRIBUTE_ID"; + + private SQLPlaceholders() { + + } + } + +} + diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceType.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceType.java new file mode 100644 index 000000000..a9b0a550d --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/ResourceType.java @@ -0,0 +1,56 @@ +/* + * 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.resource.sharing.policy.management.constant; + +import java.util.Collections; +import java.util.List; + +/** + * Enum representing the type of resource being shared. + */ +public enum ResourceType { + USER(Collections.singletonList(SharedAttributeType.ROLE)); + + private final List applicableAttributes; + + ResourceType(List applicableAttributes) { + + this.applicableAttributes = applicableAttributes; + } + + /** + * Checks if the given SharedAttributeType is applicable for this ResourceType. + * + * @param attributeType The shared attribute type to be checked. + * @return True if the attribute type is applicable, false otherwise. + */ + public boolean isApplicableAttributeType(SharedAttributeType attributeType) { + + return applicableAttributes.contains(attributeType); + } + + /** + * Returns the list of applicable shared attribute types for this resource type. + * + * @return List of applicable shared attribute types. + */ + public List getApplicableAttributes() { + + return applicableAttributes; + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/SharedAttributeType.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/SharedAttributeType.java new file mode 100644 index 000000000..41a58e35d --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constant/SharedAttributeType.java @@ -0,0 +1,25 @@ +/* + * 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.resource.sharing.policy.management.constant; + +/** + * Enum representing the type of shared attribute. + */ +public enum SharedAttributeType { + ROLE +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/dao/ResourceSharingPolicyHandlerDAO.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/dao/ResourceSharingPolicyHandlerDAO.java new file mode 100644 index 000000000..9cb862073 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/dao/ResourceSharingPolicyHandlerDAO.java @@ -0,0 +1,255 @@ +/* + * 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.resource.sharing.policy.management.dao; + +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.SharedAttributeType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtServerException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.ResourceSharingPolicy; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.SharedResourceAttribute; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * DAO interface for handling resource sharing policies across organizations. + *

+ * This interface provides methods for adding, retrieving, and deleting resource sharing policies. + * It also allows managing shared resource attributes, offering capabilities to add, retrieve, and delete + * these attributes. + *

+ */ +public interface ResourceSharingPolicyHandlerDAO { + + /** + * Adds a new resource sharing policy to the database and returns its unique identifier. + * + * @param resourceSharingPolicy The {@link ResourceSharingPolicy} containing details such as resource type, + * initiating organization, policy holding organization, and sharing policy. + * Must not be {@code null}. + * @return The unique identifier of the newly created resource sharing policy. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while adding the resource sharing policy. + */ + int addResourceSharingPolicy(ResourceSharingPolicy resourceSharingPolicy) + throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves a resource sharing policy by its unique identifier, if present. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy to be retrieved. + * Must be a valid ID greater than zero. + * @return An {@link Optional} containing the {@link ResourceSharingPolicy} if found, + * or an empty {@link Optional} if no matching resource sharing policy exists. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the resource sharing policy. + */ + Optional getResourceSharingPolicyById(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtServerException; + + + /** + * Retrieves a list of resource sharing policies associated with the given policy holding organization IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose policies need to be retrieved. + * Must not be {@code null} or empty. + * @return A list of {@link ResourceSharingPolicy} objects for the specified organization IDs. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the resource sharing + * policies. + */ + List getResourceSharingPolicies(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves a map of resource sharing policies grouped by resource type for the given policy holding + * organization IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose policies need to be retrieved. + * Must not be {@code null} or empty. + * @return A map where each key is a {@link ResourceType} and the corresponding value is a list of + * {@link ResourceSharingPolicy}. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the resource sharing + * policies. + */ + Map> getResourceSharingPoliciesGroupedByResourceType( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves a map of resource sharing policies grouped by policy holding organization ID for the given policy + * holding organization IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose policies need to be retrieved. + * Must not be {@code null} or empty. + * @return A map where each key is an organization ID, and the value is a list of {@link ResourceSharingPolicy}. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the resource sharing + * policies. + */ + Map> getResourceSharingPoliciesGroupedByPolicyHoldingOrgId( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtServerException; + + /** + * Deletes a resource sharing policy by its unique identifier if the specified organization has permission. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete sharing policies. + * Must not be {@code null}. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while deleting the resource sharing policy. + */ + void deleteResourceSharingPolicyRecordById(int resourceSharingPolicyId, String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException; + + /** + * Deletes a resource sharing policy based on its resource type and resource ID if permitted. + * + * @param resourceType The {@link ResourceType} of the resource. + * @param resourceId The unique identifier of the resource whose sharing policy is to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete sharing policies. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while deleting the resource sharing policy. + */ + void deleteResourceSharingPolicyByResourceTypeAndId(ResourceType resourceType, String resourceId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException; + + /** + * Adds shared resource attributes to an existing resource sharing policy. + * + * @param sharedResourceAttributes A list of {@link SharedResourceAttribute} objects to be added. + * Must not be {@code null} or empty. + * @return {@code true} if the shared resource attributes were added successfully. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while adding the shared resource attributes. + */ + boolean addSharedResourceAttributes(List sharedResourceAttributes) + throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves shared resource attributes for a given resource sharing policy. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy. + * @return A list of {@link SharedResourceAttribute} associated with the given policy. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the shared resource + * attributes. + */ + List getSharedResourceAttributesBySharingPolicyId(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves shared resource attributes based on attribute type. + * + * @param attributeType The {@link SharedAttributeType} of the resource attribute to be retrieved. + * @return A list of {@link SharedResourceAttribute} objects for the specified type. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the shared resource + * attributes. + */ + List getSharedResourceAttributesByType(SharedAttributeType attributeType) + throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves shared resource attributes based on attribute ID. + * + * @param attributeId The unique identifier of the resource attribute to be retrieved. + * @return A list of {@link SharedResourceAttribute} objects for the specified attribute ID. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the shared resource + * attributes. + */ + List getSharedResourceAttributesById(String attributeId) + throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves shared resource attributes based on attribute type and ID. + * + * @param attributeType The {@link SharedAttributeType} of the resource attribute to be retrieved. + * @param attributeId The unique identifier of the attribute to be retrieved. + * @return A list of {@link SharedResourceAttribute} objects for the specified type and ID. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the shared resource + * attributes. + */ + List getSharedResourceAttributesByTypeAndId(SharedAttributeType attributeType, + String attributeId) + throws ResourceSharingPolicyMgtServerException; + + /** + * Deletes shared resource attributes for a given resource sharing policy and attribute type if the specified + * organization has permission. + * + * @param resourceSharingPolicyId The unique identifier of the resource sharing policy. + * @param sharedAttributeType The {@link SharedAttributeType} to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete shared attributes. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while deleting the shared resource attributes. + */ + void deleteSharedResourceAttributesByResourceSharingPolicyId(int resourceSharingPolicyId, + SharedAttributeType sharedAttributeType, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException; + + /** + * Deletes a shared resource attribute based on its attribute type and unique identifier if the specified + * organization has permission. + * + * @param attributeType The {@link SharedAttributeType} of the attribute to be deleted. + * @param attributeId The unique identifier of the attribute to be deleted. + * @param sharingPolicyInitiatedOrgId The ID of the organization initiating the share request. + * The deletion will only be successful if the initiating organization + * has permission to delete shared attributes. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while deleting the shared resource attribute. + */ + void deleteSharedResourceAttributeByAttributeTypeAndId(SharedAttributeType attributeType, String attributeId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException; + + /** + * Adds a resource sharing policy along with its associated shared resource attributes in a single transaction. + * + * @param resourceSharingPolicy The {@link ResourceSharingPolicy} containing details such as resource type, + * initiating organization, policy holding organization, and sharing policy. + * Must not be {@code null}. + * @param sharedResourceAttributes A list of {@link SharedResourceAttribute} objects associated with the resource + * sharing policy. Must not be {@code null} or empty. + * @return {@code true} if both the resource sharing policy and the shared resource attributes were added + * successfully. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while adding the resource sharing policy or + * the shared resource attributes. + */ + boolean addResourceSharingPolicyWithAttributes(ResourceSharingPolicy resourceSharingPolicy, + List sharedResourceAttributes) + throws ResourceSharingPolicyMgtServerException; + + /** + * Retrieves a map of resource sharing policies along with their associated shared resource attributes + * for the given list of policy holding organization IDs. + * + * @param policyHoldingOrganizationIds A list of organization IDs whose resource sharing policies along with + * shared resource attributes need to be retrieved. + * Must not be {@code null} or empty. + * @return A nested map where: + * - The first key is the organization ID. + * - The second key is the {@link ResourceSharingPolicy}. + * - The value is a list of {@link SharedResourceAttribute} associated with the policy. + * If no matching policies or attributes are found, an empty map will be returned. + * @throws ResourceSharingPolicyMgtServerException If an error occurs while retrieving the resource sharing + * policies or shared attributes. + */ + Map>> + getResourceSharingPoliciesWithSharedAttributes(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtServerException; +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/dao/ResourceSharingPolicyHandlerDAOImpl.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/dao/ResourceSharingPolicyHandlerDAOImpl.java new file mode 100644 index 000000000..6b452ba6a --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/dao/ResourceSharingPolicyHandlerDAOImpl.java @@ -0,0 +1,443 @@ +/* + * 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.resource.sharing.policy.management.dao; + +import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.NamedPreparedStatement; +import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; +import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.PolicyEnum; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.SharedAttributeType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtServerException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.ResourceSharingPolicy; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.ResourceSharingPolicyWithAttributes; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.SharedResourceAttribute; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.wso2.carbon.identity.organization.management.service.util.Utils.getNewTemplate; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RESOURCE_SHARED_RESOURCE_ATTRIBUTE_CREATION_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RESOURCE_SHARED_RESOURCE_ATTRIBUTE_DELETION_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RESOURCE_SHARING_POLICY_AND_SHARED_RESOURCE_ATTRIBUTE_CREATION_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RESOURCE_SHARING_POLICY_CREATION_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RESOURCE_SHARING_POLICY_DELETION_BY_RESOURCE_TYPE_AND_ID_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RESOURCE_SHARING_POLICY_DELETION_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RETRIEVING_RESOURCE_SHARING_POLICY_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RETRIEVING_SHARED_RESOURCE_ATTRIBUTES_BY_RESOURCE_ID_AND_TYPE_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_RETRIEVING_SHARED_RESOURCE_ATTRIBUTES_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_SHARED_RESOURCE_ATTRIBUTE_DELETION_BY_ATTRIBUTE_TYPE_AND_ID_FAILED; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.CREATE_RESOURCE_SHARING_POLICY; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.CREATE_SHARED_RESOURCE_ATTRIBUTE; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.DELETE_RESOURCE_SHARING_POLICY; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.DELETE_RESOURCE_SHARING_POLICY_BY_RESOURCE_TYPE_AND_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.DELETE_SHARED_RESOURCE_ATTRIBUTE; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.DELETE_SHARED_RESOURCE_ATTRIBUTE_BY_ATTRIBUTE_TYPE_AND_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.GET_RESOURCE_SHARING_POLICIES_BY_ORG_IDS_HEAD; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.GET_RESOURCE_SHARING_POLICIES_WITH_SHARED_ATTRIBUTES_BY_POLICY_HOLDING_ORGS_HEAD; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.GET_RESOURCE_SHARING_POLICY_BY_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.GET_SHARED_RESOURCE_ATTRIBUTES; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_TYPE; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_TYPE_AND_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_POLICY_HOLDING_ORG_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_RESOURCE_TYPE; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_SHARING_POLICY; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.DB_SCHEMA_COLUMN_NAME_UM_ID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingSQLConstants.SQLPlaceholders.JOIN_COLUMN_UM_ID_OF_UM_SHARED_RESOURCE_ATTRIBUTES_TABLE; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.util.ResourceSharingUtils.handleServerException; + +/** + * DAO implementation for handling resource sharing policies. + */ +public class ResourceSharingPolicyHandlerDAOImpl implements ResourceSharingPolicyHandlerDAO { + + @Override + public int addResourceSharingPolicy(ResourceSharingPolicy resourceSharingPolicy) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + try { + return namedJdbcTemplate.executeInsert(CREATE_RESOURCE_SHARING_POLICY, namedPreparedStatement -> { + setResourceSharingPolicyParameters(namedPreparedStatement, resourceSharingPolicy); + }, null, true, DB_SCHEMA_COLUMN_NAME_UM_ID); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RESOURCE_SHARING_POLICY_CREATION_FAILED, e, + resourceSharingPolicy.getResourceType(), resourceSharingPolicy.getResourceId()); + } + } + + @Override + public Optional getResourceSharingPolicyById(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + + try { + return Optional.ofNullable(namedJdbcTemplate.fetchSingleRecord( + GET_RESOURCE_SHARING_POLICY_BY_ID, + (resultSet, rowNum) -> retrieveResourceSharingPolicyRecordFromDB(resultSet), + namedPreparedStatement -> + namedPreparedStatement.setInt(DB_SCHEMA_COLUMN_NAME_UM_ID, resourceSharingPolicyId))); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RETRIEVING_RESOURCE_SHARING_POLICY_FAILED); + } + } + + @Override + public List getResourceSharingPolicies(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + + // Dynamically build placeholders for the query + String placeholders = policyHoldingOrganizationIds.stream() + .map(id -> "?") + .collect(Collectors.joining(",")); + String query = GET_RESOURCE_SHARING_POLICIES_BY_ORG_IDS_HEAD + "(" + placeholders + ");"; + + try { + return namedJdbcTemplate.executeQuery(query, + (resultSet, rowNumber) -> retrieveResourceSharingPolicyRecordFromDB(resultSet), + preparedStatement -> { + for (int i = 0; i < policyHoldingOrganizationIds.size(); i++) { + preparedStatement.setString(i + 1, policyHoldingOrganizationIds.get(i)); + } + }); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RETRIEVING_RESOURCE_SHARING_POLICY_FAILED); + } + } + + @Override + public Map> getResourceSharingPoliciesGroupedByResourceType( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtServerException { + + List resourceSharingPolicies = getResourceSharingPolicies(policyHoldingOrganizationIds); + return resourceSharingPolicies.stream().collect(Collectors.groupingBy(ResourceSharingPolicy::getResourceType)); + } + + @Override + public Map> getResourceSharingPoliciesGroupedByPolicyHoldingOrgId( + List policyHoldingOrganizationIds) throws ResourceSharingPolicyMgtServerException { + + List resourceSharingPolicies = getResourceSharingPolicies(policyHoldingOrganizationIds); + return resourceSharingPolicies.stream() + .collect(Collectors.groupingBy(ResourceSharingPolicy::getPolicyHoldingOrgId)); + } + + @Override + public void deleteResourceSharingPolicyRecordById(int resourceSharingPolicyId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + try { + namedJdbcTemplate.executeUpdate(DELETE_RESOURCE_SHARING_POLICY, + namedPreparedStatement -> { + namedPreparedStatement.setInt(DB_SCHEMA_COLUMN_NAME_UM_ID, resourceSharingPolicyId); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID, + sharingPolicyInitiatedOrgId); + }); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RESOURCE_SHARING_POLICY_DELETION_FAILED); + } + } + + @Override + public void deleteResourceSharingPolicyByResourceTypeAndId(ResourceType resourceType, String resourceId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + try { + namedJdbcTemplate.executeUpdate(DELETE_RESOURCE_SHARING_POLICY_BY_RESOURCE_TYPE_AND_ID, + namedPreparedStatement -> { + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_RESOURCE_TYPE, + resourceType.name()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_RESOURCE_ID, + resourceId); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID, + sharingPolicyInitiatedOrgId); + }); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RESOURCE_SHARING_POLICY_DELETION_BY_RESOURCE_TYPE_AND_ID_FAILED); + } + } + + @Override + public boolean addSharedResourceAttributes(List sharedResourceAttributes) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + + try { + namedJdbcTemplate.withTransaction(template -> { + template.executeBatchInsert(CREATE_SHARED_RESOURCE_ATTRIBUTE, (namedPreparedStatement -> { + for (SharedResourceAttribute sharedResourceAttribute : sharedResourceAttributes) { + setSharedResourceAttributeParameters(namedPreparedStatement, sharedResourceAttribute); + } + }), null); + return true; + }); + } catch (TransactionException e) { + throw handleServerException(ERROR_CODE_RESOURCE_SHARED_RESOURCE_ATTRIBUTE_CREATION_FAILED); + } + return true; + } + + @Override + public List getSharedResourceAttributesBySharingPolicyId(int resourceSharingPolicyId) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + List sharedResourceAttributes = new ArrayList<>(); + + try { + namedJdbcTemplate.executeQuery(GET_SHARED_RESOURCE_ATTRIBUTES, (resultSet, rowNumber) -> { + sharedResourceAttributes.add(retrieveSharedResourceAttributeRecordFromDB(resultSet)); + return null; + }, namedPreparedStatement -> namedPreparedStatement.setInt( + DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID, + resourceSharingPolicyId)); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RETRIEVING_SHARED_RESOURCE_ATTRIBUTES_FAILED); + } + return sharedResourceAttributes; + } + + @Override + public List getSharedResourceAttributesByType(SharedAttributeType attributeType) + throws ResourceSharingPolicyMgtServerException { + + return getSharedResourceAttributes(GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_TYPE, attributeType, null); + } + + @Override + public List getSharedResourceAttributesById(String attributeId) + throws ResourceSharingPolicyMgtServerException { + + return getSharedResourceAttributes(GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_ID, null, attributeId); + } + + @Override + public List getSharedResourceAttributesByTypeAndId(SharedAttributeType attributeType, + String attributeId) + throws ResourceSharingPolicyMgtServerException { + + return getSharedResourceAttributes(GET_SHARED_RESOURCE_ATTRIBUTES_BY_ATTRIBUTE_TYPE_AND_ID, attributeType, + attributeId); + } + + @Override + public void deleteSharedResourceAttributesByResourceSharingPolicyId(int resourceSharingPolicyId, + SharedAttributeType sharedAttributeType, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + try { + namedJdbcTemplate.executeUpdate(DELETE_SHARED_RESOURCE_ATTRIBUTE, namedPreparedStatement -> { + namedPreparedStatement.setInt(DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID, + resourceSharingPolicyId); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE, + sharedAttributeType.name()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID, + sharingPolicyInitiatedOrgId); + }); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RESOURCE_SHARED_RESOURCE_ATTRIBUTE_DELETION_FAILED); + } + } + + @Override + public void deleteSharedResourceAttributeByAttributeTypeAndId(SharedAttributeType attributeType, + String attributeId, + String sharingPolicyInitiatedOrgId) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + try { + namedJdbcTemplate.executeUpdate(DELETE_SHARED_RESOURCE_ATTRIBUTE_BY_ATTRIBUTE_TYPE_AND_ID, + namedPreparedStatement -> { + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE, + attributeType.name()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID, + attributeId); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID, + sharingPolicyInitiatedOrgId); + }); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_SHARED_RESOURCE_ATTRIBUTE_DELETION_BY_ATTRIBUTE_TYPE_AND_ID_FAILED); + } + } + + @Override + public boolean addResourceSharingPolicyWithAttributes(ResourceSharingPolicy resourceSharingPolicy, + List sharedResourceAttributes) + throws ResourceSharingPolicyMgtServerException { + + int resourceSharingPolicyId = addResourceSharingPolicy(resourceSharingPolicy); + + sharedResourceAttributes.forEach(attribute -> attribute.setResourceSharingPolicyId(resourceSharingPolicyId)); + + try { + addSharedResourceAttributes(sharedResourceAttributes); + } catch (ResourceSharingPolicyMgtServerException e) { + deleteResourceSharingPolicyRecordById(resourceSharingPolicyId, resourceSharingPolicy.getInitiatingOrgId()); + throw handleServerException( + ERROR_CODE_RESOURCE_SHARING_POLICY_AND_SHARED_RESOURCE_ATTRIBUTE_CREATION_FAILED); + } + + return true; + } + + @Override + public Map>> + getResourceSharingPoliciesWithSharedAttributes(List policyHoldingOrganizationIds) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + + String placeholders = policyHoldingOrganizationIds.stream().map(id -> "?").collect(Collectors.joining(",")); + String query = String.format(GET_RESOURCE_SHARING_POLICIES_WITH_SHARED_ATTRIBUTES_BY_POLICY_HOLDING_ORGS_HEAD, + placeholders); + + try { + List result = namedJdbcTemplate.executeQuery(query, + (resultSet, rowNumber) -> { + ResourceSharingPolicy policy = retrieveResourceSharingPolicyRecordFromDB(resultSet); + SharedResourceAttribute attribute = null; + if (resultSet.getString(JOIN_COLUMN_UM_ID_OF_UM_SHARED_RESOURCE_ATTRIBUTES_TABLE) != null) { + attribute = retrieveSharedResourceAttributeRecordFromDB(resultSet); + } + return new ResourceSharingPolicyWithAttributes( + resultSet.getString(DB_SCHEMA_COLUMN_NAME_POLICY_HOLDING_ORG_ID), policy, attribute); + }, + namedPreparedStatement -> { + for (int i = 0; i < policyHoldingOrganizationIds.size(); i++) { + namedPreparedStatement.setString(i + 1, policyHoldingOrganizationIds.get(i)); + } + }); + + return result.stream() + .collect(Collectors.groupingBy( + ResourceSharingPolicyWithAttributes::getPolicyHoldingOrgId, + Collectors.groupingBy( + ResourceSharingPolicyWithAttributes::getPolicy, + Collectors.mapping(ResourceSharingPolicyWithAttributes::getAttribute, + Collectors.toList()) + ) + )); + } catch (DataAccessException e) { + throw handleServerException(ERROR_CODE_RETRIEVING_RESOURCE_SHARING_POLICY_FAILED); + } + } + + private List getSharedResourceAttributes(String query, SharedAttributeType attributeType, + String attributeId) + throws ResourceSharingPolicyMgtServerException { + + NamedJdbcTemplate namedJdbcTemplate = getNewTemplate(); + List sharedResourceAttributes = new ArrayList<>(); + + try { + namedJdbcTemplate.executeQuery(query, (resultSet, rowNumber) -> { + sharedResourceAttributes.add(retrieveSharedResourceAttributeRecordFromDB(resultSet)); + return null; + }, namedPreparedStatement -> { + if (attributeType != null) { + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE, attributeType.name()); + } + if (attributeId != null) { + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID, attributeId); + } + }); + } catch (DataAccessException e) { + throw handleServerException( + ERROR_CODE_RETRIEVING_SHARED_RESOURCE_ATTRIBUTES_BY_RESOURCE_ID_AND_TYPE_FAILED); + } + return sharedResourceAttributes; + } + + private ResourceSharingPolicy retrieveResourceSharingPolicyRecordFromDB(ResultSet resultSet) throws SQLException { + + ResourceSharingPolicy policy = new ResourceSharingPolicy(); + policy.setResourceSharingPolicyId( + resultSet.getInt(DB_SCHEMA_COLUMN_NAME_UM_ID)); + policy.setResourceType(ResourceType.valueOf( + resultSet.getString(DB_SCHEMA_COLUMN_NAME_RESOURCE_TYPE))); + policy.setResourceId( + resultSet.getString(DB_SCHEMA_COLUMN_NAME_RESOURCE_ID)); + policy.setInitiatingOrgId( + resultSet.getString(DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID)); + policy.setPolicyHoldingOrgId( + resultSet.getString(DB_SCHEMA_COLUMN_NAME_POLICY_HOLDING_ORG_ID)); + policy.setSharingPolicy( + PolicyEnum.getPolicyByPolicyCode(resultSet.getString(DB_SCHEMA_COLUMN_NAME_SHARING_POLICY))); + return policy; + } + + private SharedResourceAttribute retrieveSharedResourceAttributeRecordFromDB(ResultSet resultSet) + throws SQLException { + + SharedResourceAttribute attributes = new SharedResourceAttribute(); + attributes.setResourceSharingPolicyId( + resultSet.getInt(DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID)); + attributes.setSharedAttributeType(SharedAttributeType.valueOf( + resultSet.getString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE))); + attributes.setSharedAttributeId( + resultSet.getString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID)); + attributes.setSharedResourceAttributeId( + resultSet.getInt(DB_SCHEMA_COLUMN_NAME_UM_ID)); + return attributes; + } + + private void setResourceSharingPolicyParameters(NamedPreparedStatement namedPreparedStatement, + ResourceSharingPolicy policy) throws SQLException { + + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_RESOURCE_TYPE, policy.getResourceType().name()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_RESOURCE_ID, policy.getResourceId()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_INITIATING_ORG_ID, policy.getInitiatingOrgId()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_POLICY_HOLDING_ORG_ID, policy.getPolicyHoldingOrgId()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARING_POLICY, + policy.getSharingPolicy().getPolicyCode()); + } + + private void setSharedResourceAttributeParameters(NamedPreparedStatement namedPreparedStatement, + SharedResourceAttribute attribute) throws SQLException { + + namedPreparedStatement.setInt(DB_SCHEMA_COLUMN_NAME_RESOURCE_SHARING_POLICY_ID, + attribute.getResourceSharingPolicyId()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_TYPE, + attribute.getSharedAttributeType().name()); + namedPreparedStatement.setString(DB_SCHEMA_COLUMN_NAME_SHARED_ATTRIBUTE_ID, attribute.getSharedAttributeId()); + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtClientException.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtClientException.java new file mode 100644 index 000000000..6002fe649 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtClientException.java @@ -0,0 +1,43 @@ +/* + * 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.resource.sharing.policy.management.exception; + +/** + * Exception class for resource sharing policy management for client exceptions. + */ +public class ResourceSharingPolicyMgtClientException extends ResourceSharingPolicyMgtException { + + public ResourceSharingPolicyMgtClientException(String errorCode, String message, String description) { + + super(errorCode, message, description); + } + + public ResourceSharingPolicyMgtClientException(String errorCode, String message, String description, + Throwable cause) { + + super(errorCode, message, description, cause); + } + + public ResourceSharingPolicyMgtClientException(String errorCode, String message, String description, + Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + + super(errorCode, message, description, cause, enableSuppression, writableStackTrace); + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtException.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtException.java new file mode 100644 index 000000000..09e4bf0e3 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtException.java @@ -0,0 +1,60 @@ +/* + * 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.resource.sharing.policy.management.exception; + +/** + * Exception class for resource sharing policy management. + */ +public class ResourceSharingPolicyMgtException extends Exception { + + private final String errorCode; + private final String description; + + public ResourceSharingPolicyMgtException(String errorCode, String message, String description) { + + super(message); + this.errorCode = errorCode; + this.description = description; + } + + public ResourceSharingPolicyMgtException(String errorCode, String message, String description, Throwable cause) { + + super(message, cause); + this.errorCode = errorCode; + this.description = description; + } + + public ResourceSharingPolicyMgtException(String errorCode, String message, String description, Throwable cause, + boolean enableSuppression, boolean writableStackTrace) { + + super(message, cause, enableSuppression, writableStackTrace); + this.errorCode = errorCode; + this.description = description; + } + + public String getErrorCode() { + + return errorCode; + } + + public String getDescription() { + + return description; + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtServerException.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtServerException.java new file mode 100644 index 000000000..367595167 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/exception/ResourceSharingPolicyMgtServerException.java @@ -0,0 +1,43 @@ +/* + * 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.resource.sharing.policy.management.exception; + +/** + * Exception class for resource sharing policy management for server exceptions. + */ +public class ResourceSharingPolicyMgtServerException extends ResourceSharingPolicyMgtException { + + public ResourceSharingPolicyMgtServerException(String errorCode, String message, String description) { + + super(errorCode, message, description); + } + + public ResourceSharingPolicyMgtServerException(String errorCode, String message, String description, + Throwable cause) { + + super(errorCode, message, description, cause); + } + + public ResourceSharingPolicyMgtServerException(String errorCode, String message, String description, + Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + + super(errorCode, message, description, cause, enableSuppression, writableStackTrace); + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/internal/ResourceSharingPolicyHandlerServiceComponent.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/internal/ResourceSharingPolicyHandlerServiceComponent.java new file mode 100644 index 000000000..cb3f9c575 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/internal/ResourceSharingPolicyHandlerServiceComponent.java @@ -0,0 +1,57 @@ +/* + * 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.resource.sharing.policy.management.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.framework.BundleContext; +import org.osgi.service.component.ComponentContext; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.ResourceSharingPolicyHandlerService; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.ResourceSharingPolicyHandlerServiceImpl; + +/** + * OSGi service component for Resource Sharing Policy Handler bundle. + */ +@Component( + name = "identity.organization.resource.sharing.policy.management.component", + immediate = true +) +public class ResourceSharingPolicyHandlerServiceComponent { + + private static final Log LOG = LogFactory.getLog(ResourceSharingPolicyHandlerServiceComponent.class); + + /** + * Register the Resource Sharing Policy Mgt service in the OSGI context. + * + * @param componentContext OSGi service component context. + */ + @Activate + protected void activate(ComponentContext componentContext) { + + BundleContext bundleContext = componentContext.getBundleContext(); + ResourceSharingPolicyHandlerService resourceSharingPolicyHandlerService = + new ResourceSharingPolicyHandlerServiceImpl(); + bundleContext.registerService(ResourceSharingPolicyHandlerService.class.getName(), + resourceSharingPolicyHandlerService, null); + if (LOG.isDebugEnabled()) { + LOG.debug("ResourceSharingPolicyHandlerServiceComponent activated successfully."); + } + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/ResourceSharingPolicy.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/ResourceSharingPolicy.java new file mode 100644 index 000000000..1d504436c --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/ResourceSharingPolicy.java @@ -0,0 +1,175 @@ +/* + * 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.resource.sharing.policy.management.model; + +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.PolicyEnum; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtException; + +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_MISSING_MANDATORY_FIELDS; + +/** + * Model representing the Resource Sharing Policy. + */ +public class ResourceSharingPolicy { + + private int resourceSharingPolicyId; + private ResourceType resourceType; + private String resourceId; + private String initiatingOrgId; + private String policyHoldingOrgId; + private PolicyEnum sharingPolicy; + + public int getResourceSharingPolicyId() { + + return resourceSharingPolicyId; + } + + public void setResourceSharingPolicyId(int resourceSharingPolicyId) { + + this.resourceSharingPolicyId = resourceSharingPolicyId; + } + + public String getResourceId() { + + return resourceId; + } + + public void setResourceType(ResourceType resourceType) { + + this.resourceType = resourceType; + } + + public String getInitiatingOrgId() { + + return initiatingOrgId; + } + + public void setResourceId(String resourceId) { + + this.resourceId = resourceId; + } + + public ResourceType getResourceType() { + + return resourceType; + } + + public void setInitiatingOrgId(String initiatingOrgId) { + + this.initiatingOrgId = initiatingOrgId; + } + + public String getPolicyHoldingOrgId() { + + return policyHoldingOrgId; + } + + public void setPolicyHoldingOrgId(String policyHoldingOrgId) { + + this.policyHoldingOrgId = policyHoldingOrgId; + } + + public PolicyEnum getSharingPolicy() { + + return sharingPolicy; + } + + public void setSharingPolicy(PolicyEnum sharingPolicy) { + + this.sharingPolicy = sharingPolicy; + } + + @Override + public String toString() { + + return "{" + + "\"resourceSharingPolicyId\": " + resourceSharingPolicyId + ", " + + "\"resourceType\": \"" + resourceType + "\", " + + "\"resourceId\": \"" + resourceId + "\", " + + "\"initiatingOrgId\": \"" + initiatingOrgId + "\", " + + "\"policyHoldingOrgId\": \"" + policyHoldingOrgId + "\", " + + "\"sharingPolicy\": \"" + sharingPolicy + "\"" + + "}"; + } + + public static Builder builder() { + + return new Builder(); + } + + /** + * Builder for constructing {@link ResourceSharingPolicy} instances. + */ + public static class Builder { + + private ResourceType resourceType; + private String resourceId; + private String initiatingOrgId; + private String policyHoldingOrgId; + private PolicyEnum sharingPolicy; + + public Builder withResourceType(ResourceType resourceType) { + + this.resourceType = resourceType; + return this; + } + + public Builder withResourceId(String resourceId) { + + this.resourceId = resourceId; + return this; + } + + public Builder withInitiatingOrgId(String initiatingOrgId) { + + this.initiatingOrgId = initiatingOrgId; + return this; + } + + public Builder withPolicyHoldingOrgId(String policyHoldingOrgId) { + + this.policyHoldingOrgId = policyHoldingOrgId; + return this; + } + + public Builder withSharingPolicy(PolicyEnum sharingPolicy) { + + this.sharingPolicy = sharingPolicy; + return this; + } + + public ResourceSharingPolicy build() throws ResourceSharingPolicyMgtException { + + if (resourceType == null || resourceId == null || initiatingOrgId == null || policyHoldingOrgId == null || + sharingPolicy == null) { + + throw new ResourceSharingPolicyMgtException(ERROR_CODE_MISSING_MANDATORY_FIELDS.getCode(), + ERROR_CODE_MISSING_MANDATORY_FIELDS.getMessage(), + ERROR_CODE_MISSING_MANDATORY_FIELDS.getDescription()); + } + ResourceSharingPolicy policy = new ResourceSharingPolicy(); + policy.setResourceType(this.resourceType); + policy.setResourceId(this.resourceId); + policy.setInitiatingOrgId(this.initiatingOrgId); + policy.setPolicyHoldingOrgId(this.policyHoldingOrgId); + policy.setSharingPolicy(this.sharingPolicy); + return policy; + } + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/ResourceSharingPolicyWithAttributes.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/ResourceSharingPolicyWithAttributes.java new file mode 100644 index 000000000..e75f1e723 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/ResourceSharingPolicyWithAttributes.java @@ -0,0 +1,51 @@ +/* + * 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.resource.sharing.policy.management.model; + +/** + * Model representing the Shared Resource Attribute with respective policies and policy holding orgs. + */ +public class ResourceSharingPolicyWithAttributes { + + private final String policyHoldingOrgId; + private final ResourceSharingPolicy policy; + private final SharedResourceAttribute attribute; + + public ResourceSharingPolicyWithAttributes(String policyHoldingOrgId, ResourceSharingPolicy policy, + SharedResourceAttribute attribute) { + + this.policyHoldingOrgId = policyHoldingOrgId; + this.policy = policy; + this.attribute = attribute; + } + + public String getPolicyHoldingOrgId() { + + return policyHoldingOrgId; + } + + public ResourceSharingPolicy getPolicy() { + + return policy; + } + + public SharedResourceAttribute getAttribute() { + + return attribute; + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/SharedResourceAttribute.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/SharedResourceAttribute.java new file mode 100644 index 000000000..649cea4af --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/model/SharedResourceAttribute.java @@ -0,0 +1,133 @@ +/* + * 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.resource.sharing.policy.management.model; + +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.SharedAttributeType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtException; + +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage.ERROR_CODE_MISSING_MANDATORY_FIELDS; + +/** + * Model representing the Shared Resource Attribute. + */ +public class SharedResourceAttribute { + + private int sharedResourceAttributeId; + private int resourceSharingPolicyId; + private SharedAttributeType sharedAttributeType; + private String sharedAttributeId; + + public int getSharedResourceAttributeId() { + + return sharedResourceAttributeId; + } + + public void setSharedResourceAttributeId(int sharedResourceAttributeId) { + + this.sharedResourceAttributeId = sharedResourceAttributeId; + } + + public int getResourceSharingPolicyId() { + + return resourceSharingPolicyId; + } + + public void setResourceSharingPolicyId(int resourceSharingPolicyId) { + + this.resourceSharingPolicyId = resourceSharingPolicyId; + } + + public SharedAttributeType getSharedAttributeType() { + + return sharedAttributeType; + } + + public void setSharedAttributeType( + SharedAttributeType sharedAttributeType) { + + this.sharedAttributeType = sharedAttributeType; + } + + public String getSharedAttributeId() { + + return sharedAttributeId; + } + + public void setSharedAttributeId(String sharedAttributeId) { + + this.sharedAttributeId = sharedAttributeId; + } + + @Override + public String toString() { + + return "{" + + "\"sharedResourceAttributeId\": " + sharedResourceAttributeId + ", " + + "\"resourceSharingPolicyId\": " + resourceSharingPolicyId + ", " + + "\"sharedAttributeType\": \"" + sharedAttributeType + "\", " + + "\"sharedAttributeId\": \"" + sharedAttributeId + "\"" + + "}"; + } + + public static Builder builder() { + + return new Builder(); + } + + /** + * Builder for constructing {@link SharedResourceAttribute} instances. + */ + public static class Builder { + + private int resourceSharingPolicyId; + private SharedAttributeType sharedAttributeType; + private String sharedAttributeId; + + public Builder withResourceSharingPolicyId(int resourceSharingPolicyId) { + + this.resourceSharingPolicyId = resourceSharingPolicyId; + return this; + } + + public Builder withSharedAttributeType(SharedAttributeType sharedAttributeType) { + + this.sharedAttributeType = sharedAttributeType; + return this; + } + + public Builder withSharedAttributeId(String sharedAttributeId) { + + this.sharedAttributeId = sharedAttributeId; + return this; + } + + public SharedResourceAttribute build() throws ResourceSharingPolicyMgtException { + + if (sharedAttributeType == null || sharedAttributeId == null) { + throw new ResourceSharingPolicyMgtException(ERROR_CODE_MISSING_MANDATORY_FIELDS.getCode(), + ERROR_CODE_MISSING_MANDATORY_FIELDS.getMessage(), + ERROR_CODE_MISSING_MANDATORY_FIELDS.getDescription()); + } + SharedResourceAttribute attributes = new SharedResourceAttribute(); + attributes.setResourceSharingPolicyId(this.resourceSharingPolicyId); + attributes.setSharedAttributeType(this.sharedAttributeType); + attributes.setSharedAttributeId(this.sharedAttributeId); + return attributes; + } + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/util/ResourceSharingUtils.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/util/ResourceSharingUtils.java new file mode 100644 index 000000000..ce08cb7fd --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/main/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/util/ResourceSharingUtils.java @@ -0,0 +1,60 @@ +/* + * 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.wso2.com/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.resource.sharing.policy.management.util; + +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceSharingConstants.ErrorMessage; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtServerException; + +/** + * Utility class for resource sharing util management. + */ +public class ResourceSharingUtils { + + /** + * Handle server exception by generating a relevant description message. + * + * @param error The ErrorMessage enum containing error details. + * @param e The Throwable cause of the exception. + * @param resourceType The type of the resource (as an enum). + * @param resourceId The UUID of the resource. + * @return A ResourceSharingPolicyMgtServerException. + */ + public static ResourceSharingPolicyMgtServerException handleServerException(ErrorMessage error, Throwable e, + ResourceType resourceType, + String resourceId) { + + String description = String.format("%s (Resource Type: %s, Resource ID: %s)", + error.getDescription(), resourceType.name(), resourceId); + + return new ResourceSharingPolicyMgtServerException(error.getCode(), error.getMessage(), description, e); + } + + /** + * Handle server exception for failed shared resource attributes. + * + * @param error The ErrorMessage enum containing error details. + * @return A ResourceSharingPolicyMgtServerException. + */ + public static ResourceSharingPolicyMgtServerException handleServerException(ErrorMessage error) { + + return new ResourceSharingPolicyMgtServerException(error.getCode(), error.getMessage(), error.getDescription()); + } + + private ResourceSharingUtils() {} +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerServiceImplTest.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerServiceImplTest.java new file mode 100644 index 000000000..fa25e3142 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/ResourceSharingPolicyHandlerServiceImplTest.java @@ -0,0 +1,889 @@ +/* + * 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.resource.sharing.policy.management; + +import org.mockito.MockedStatic; +import org.testng.Assert; +import org.testng.TestException; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.wso2.carbon.database.utils.jdbc.NamedJdbcTemplate; +import org.wso2.carbon.database.utils.jdbc.exceptions.DataAccessException; +import org.wso2.carbon.database.utils.jdbc.exceptions.TransactionException; +import org.wso2.carbon.identity.organization.management.service.util.Utils; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.PolicyEnum; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.SharedAttributeType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtClientException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.exception.ResourceSharingPolicyMgtServerException; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.ResourceSharingPolicy; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.model.SharedResourceAttribute; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.util.TestUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.openMocks; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType.USER; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.MOCKED_DATA_ACCESS_EXCEPTION; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.MOCKED_TRANSACTION_EXCEPTION; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.RESOURCE_TYPE_RESOURCE_1; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_ORGANIZATION_INVALID; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_ORGANIZATION_INVALID_FORMAT; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_ORGANIZATION_ORG_ALL; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_ORGANIZATION_ORG_ALL_CHILD1; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_ORGANIZATION_ORG_IMMEDIATE; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_ORGANIZATION_ORG_IMMEDIATE_CHILD1; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_ORGANIZATION_SUPER; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_RESOURCE_1; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_RESOURCE_2; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_RESOURCE_3; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_RESOURCE_4; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_RESOURCE_ATTRIBUTE_1; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.constants.TestResourceSharingConstants.UM_ID_RESOURCE_ATTRIBUTE_2; +import static org.wso2.carbon.identity.organization.resource.sharing.policy.management.util.TestUtils.closeH2Base; + +public class ResourceSharingPolicyHandlerServiceImplTest { + + private ResourceSharingPolicyHandlerServiceImpl resourceSharingPolicyHandlerService; + + @BeforeClass + public void setUp() throws Exception { + + resourceSharingPolicyHandlerService = new ResourceSharingPolicyHandlerServiceImpl(); + openMocks(this); + TestUtils.initiateH2Base(); + TestUtils.mockDataSource(); + } + + @AfterClass + public void tearDown() throws Exception { + + closeH2Base(); + } + + // Tests: CREATE Resource Sharing Policy Records. + @DataProvider(name = "resourceSharingPolicyProvider") + public Object[][] resourceSharingPolicyProvider() throws ResourceSharingPolicyMgtException { + + return new Object[][]{ + {new ResourceSharingPolicy.Builder() + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withResourceId(UM_ID_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_SUPER) + .withSharingPolicy(PolicyEnum.ALL_EXISTING_AND_FUTURE_ORGS).build()}, + {new ResourceSharingPolicy.Builder() + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withResourceId(UM_ID_RESOURCE_3) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_SUPER) + .withSharingPolicy(PolicyEnum.IMMEDIATE_EXISTING_AND_FUTURE_ORGS).build()}, + {new ResourceSharingPolicy.Builder() + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withResourceId(UM_ID_RESOURCE_2) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_ORG_ALL) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_WITH_ALL_EXISTING_AND_FUTURE_CHILDREN).build()}, + {new ResourceSharingPolicy.Builder() + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withResourceId(UM_ID_RESOURCE_4) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_ORG_IMMEDIATE) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_WITH_EXISTING_IMMEDIATE_AND_FUTURE_CHILDREN).build()} + }; + + } + + @Test(dataProvider = "resourceSharingPolicyProvider", priority = 1) + public void testAddResourceSharingPolicySuccess(ResourceSharingPolicy testData) throws Exception { + + ResourceSharingPolicy resourceSharingPolicy = new ResourceSharingPolicy.Builder() + .withResourceId(testData.getResourceId()) + .withResourceType(testData.getResourceType()) + .withInitiatingOrgId(testData.getInitiatingOrgId()) + .withPolicyHoldingOrgId(testData.getPolicyHoldingOrgId()) + .withSharingPolicy(testData.getSharingPolicy()) + .build(); + + int addedPolicyId = resourceSharingPolicyHandlerService.addResourceSharingPolicy(resourceSharingPolicy); + + Assert.assertTrue(addedPolicyId > 0, + "Expected a positive non-zero integer as the result for a clean record insertion to the database."); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 2) + public void testAddResourceSharingPolicyFailure() throws Exception { + + ResourceSharingPolicy resourceSharingPolicy = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_1) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_INVALID) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_ORG_ALL) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_WITH_ALL_EXISTING_AND_FUTURE_CHILDREN) + .build(); + + resourceSharingPolicyHandlerService.addResourceSharingPolicy(resourceSharingPolicy); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtClientException.class, priority = 3) + public void testAddResourceSharingPolicyFailureForNotApplicableResource() throws Exception { + + ResourceSharingPolicy resourceSharingPolicy = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_1) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_INVALID) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_ORG_ALL) + .withSharingPolicy(PolicyEnum.NO_SHARING) + .build(); + + resourceSharingPolicyHandlerService.addResourceSharingPolicy(resourceSharingPolicy); + } + + // Tests: GET Resource Sharing Policy Records. + @Test(priority = 4) + public void testGetResourceSharingPolicyByIdSuccess() throws ResourceSharingPolicyMgtException { + + ResourceSharingPolicy resourceSharingPolicy = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_1) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_ORG_ALL) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_ONLY) + .build(); + + int recordId = resourceSharingPolicyHandlerService.addResourceSharingPolicy(resourceSharingPolicy); + Optional optionalResource = + resourceSharingPolicyHandlerService.getResourceSharingPolicyById(recordId); + + Assert.assertTrue(optionalResource.isPresent(), "ResourceSharingPolicy should be present."); + ResourceSharingPolicy resource = optionalResource.get(); + Assert.assertNotNull(resource, "ResourceSharingPolicy object should not be null."); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 5) + public void testGetResourceSharingPolicyByIdFailure() throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .fetchSingleRecord(anyString(), any(), any()); + + resourceSharingPolicyHandlerService.getResourceSharingPolicyById(1); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + @DataProvider(name = "organizationIdsProvider") + public Object[][] organizationIdsProvider() { + + return new Object[][]{ + {Arrays.asList(UM_ID_ORGANIZATION_SUPER, UM_ID_ORGANIZATION_ORG_ALL)}, + {Arrays.asList(UM_ID_ORGANIZATION_ORG_IMMEDIATE, UM_ID_ORGANIZATION_ORG_IMMEDIATE_CHILD1)}, + {Arrays.asList(UM_ID_ORGANIZATION_ORG_ALL, UM_ID_ORGANIZATION_ORG_ALL_CHILD1)} + }; + } + + @Test(dataProvider = "organizationIdsProvider", priority = 6) + public void testGetResourceSharingPoliciesSuccess(List organizationIds) throws Exception { + + addAndAssertResourceSharingPolicy(Arrays.asList(organizationIds.get(0), organizationIds.get(1))); + + List actualPolicies = + resourceSharingPolicyHandlerService.getResourceSharingPolicies(organizationIds); + + for (ResourceSharingPolicy policy : actualPolicies) { + Assert.assertTrue(organizationIds.contains(policy.getPolicyHoldingOrgId())); + } + } + + @Test(dataProvider = "organizationIdsProvider", priority = 7) + public void testGetResourceSharingPoliciesGroupedByResourceTypeSuccess(List organizationIds) + throws Exception { + + addAndAssertResourceSharingPolicy(Arrays.asList(organizationIds.get(0), organizationIds.get(1))); + + Map> actualPoliciesGroupedByType = + resourceSharingPolicyHandlerService.getResourceSharingPoliciesGroupedByResourceType(organizationIds); + + Assert.assertTrue(actualPoliciesGroupedByType.containsKey(RESOURCE_TYPE_RESOURCE_1)); + Assert.assertTrue(actualPoliciesGroupedByType.containsKey(RESOURCE_TYPE_RESOURCE_1)); + + for (Map.Entry> entry : actualPoliciesGroupedByType.entrySet()) { + ResourceType resourceType = entry.getKey(); + List policies = entry.getValue(); + + switch (resourceType) { + case USER: + for (ResourceSharingPolicy policy : policies) { + Assert.assertEquals(policy.getResourceType(), USER); + Assert.assertTrue(organizationIds.contains(policy.getPolicyHoldingOrgId())); + } + break; + + default: + Assert.fail("Unexpected resource type found: " + resourceType); + break; + } + } + } + + @Test(dataProvider = "organizationIdsProvider", priority = 8) + public void testGetResourceSharingPoliciesGroupedByPolicyHoldingOrgIdSuccess(List organizationIds) + throws Exception { + + addAndAssertResourceSharingPolicy(Arrays.asList(organizationIds.get(0), organizationIds.get(1))); + + Map> actualPoliciesGroupedByOrgId = + resourceSharingPolicyHandlerService.getResourceSharingPoliciesGroupedByPolicyHoldingOrgId( + organizationIds); + + for (String policyHoldingOrgId : actualPoliciesGroupedByOrgId.keySet()) { + Assert.assertTrue(organizationIds.contains(policyHoldingOrgId)); + } + + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtClientException.class, priority = 9) + public void testGetResourceSharingPoliciesFailureForNullOrgIdInList() throws Exception { + + List actualPolicies = + resourceSharingPolicyHandlerService.getResourceSharingPolicies(Collections.singletonList(null)); + + Assert.assertTrue(actualPolicies.isEmpty()); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtClientException.class, priority = 9) + public void testGetResourceSharingPoliciesFailureForEmptyOrgIdInList() throws Exception { + + List actualPolicies = + resourceSharingPolicyHandlerService.getResourceSharingPolicies(Collections.singletonList("")); + + Assert.assertTrue(actualPolicies.isEmpty()); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 10) + public void testGetResourceSharingPoliciesFailureForInvalidOrgId() throws Exception { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeQuery(anyString(), any(), any()); + + resourceSharingPolicyHandlerService.getResourceSharingPolicies( + Collections.singletonList(UM_ID_ORGANIZATION_INVALID_FORMAT)); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtClientException.class, priority = 11) + public void testGetResourceSharingPoliciesFailureForNullOrgs() throws Exception { + + List policyHoldingOrgIds = new ArrayList<>(); + policyHoldingOrgIds.add(UM_ID_RESOURCE_1); + policyHoldingOrgIds.add(null); + + List actualPolicies = + resourceSharingPolicyHandlerService.getResourceSharingPolicies(policyHoldingOrgIds); + + Assert.assertTrue(actualPolicies.isEmpty()); + } + + // Tests: DELETE Resource Sharing Policy Records. + @Test(dataProvider = "organizationIdsProvider", priority = 12) + public void testDeleteResourceSharingPolicyRecordByIdSuccess(List organizationIds) throws Exception { + + List addedResourceSharingPolyIds = + addAndAssertResourceSharingPolicy(Arrays.asList(organizationIds.get(0), organizationIds.get(1))); + + for (int addedResourceSharingPolyId : addedResourceSharingPolyIds) { + resourceSharingPolicyHandlerService.deleteResourceSharingPolicyRecordById( + addedResourceSharingPolyId, UM_ID_ORGANIZATION_SUPER); + Optional resourceSharingPolicyById = + resourceSharingPolicyHandlerService.getResourceSharingPolicyById(addedResourceSharingPolyId); + Assert.assertFalse(resourceSharingPolicyById.isPresent()); + } + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 13) + public void testDeleteResourceSharingPolicyRecordByIdFailure() + throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeUpdate(anyString(), any()); + + resourceSharingPolicyHandlerService.deleteResourceSharingPolicyRecordById(1, UM_ID_ORGANIZATION_SUPER); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtClientException.class, priority = 21) + public void testDeleteResourceSharingPolicyRecordByIdAndEmptySharingInitiatedOrgIdFailure() + throws ResourceSharingPolicyMgtException { + + resourceSharingPolicyHandlerService.deleteResourceSharingPolicyRecordById(1, ""); + } + + @DataProvider(name = "organizationsAndResourceTypesAndIdsProvider") + public Object[][] organizationsAndResourceTypesAndIdsProvider() { + + return new Object[][]{ + {Arrays.asList(UM_ID_ORGANIZATION_SUPER, UM_ID_ORGANIZATION_ORG_ALL), + RESOURCE_TYPE_RESOURCE_1, UM_ID_RESOURCE_1}, + {Arrays.asList(UM_ID_ORGANIZATION_ORG_IMMEDIATE, UM_ID_ORGANIZATION_ORG_IMMEDIATE_CHILD1), + RESOURCE_TYPE_RESOURCE_1, UM_ID_RESOURCE_2}, + {Arrays.asList(UM_ID_ORGANIZATION_ORG_ALL, UM_ID_ORGANIZATION_ORG_ALL_CHILD1), + RESOURCE_TYPE_RESOURCE_1, UM_ID_RESOURCE_3}, + {Arrays.asList(UM_ID_ORGANIZATION_SUPER, UM_ID_ORGANIZATION_SUPER), + RESOURCE_TYPE_RESOURCE_1, UM_ID_RESOURCE_4}, + }; + } + + @Test(priority = 14) + public void testDeleteResourceSharingPolicyByResourceTypeAndIdSuccess() throws Exception { + + ResourceSharingPolicy resourceSharingPolicy = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_1) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_SUPER) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_WITH_EXISTING_IMMEDIATE_AND_FUTURE_CHILDREN) + .build(); + + int addedPolicyId = resourceSharingPolicyHandlerService.addResourceSharingPolicy(resourceSharingPolicy); + + // Deleting the added policy + resourceSharingPolicyHandlerService.deleteResourceSharingPolicyByResourceTypeAndId( + RESOURCE_TYPE_RESOURCE_1, UM_ID_RESOURCE_1, UM_ID_ORGANIZATION_SUPER); + + // Verifying that the policy is deleted + Optional deletedPolicy = + resourceSharingPolicyHandlerService.getResourceSharingPolicyById(addedPolicyId); + Assert.assertFalse(deletedPolicy.isPresent()); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 15) + public void testDeleteResourceSharingPolicyByResourceTypeAndIdFailure() throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeUpdate(anyString(), any()); + + resourceSharingPolicyHandlerService.deleteResourceSharingPolicyByResourceTypeAndId(RESOURCE_TYPE_RESOURCE_1, + UM_ID_RESOURCE_1, UM_ID_ORGANIZATION_SUPER); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + // Tests: CREATE Shared Resource Attributes Records. + @Test(priority = 16) + public void testAddSharedResourceAttributesSuccess() throws Exception { + + List sharedResourceAttributes = Arrays.asList( + new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(1) + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_1) + .build(), + new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(1) + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_2) + .build()); + + boolean isAdded = resourceSharingPolicyHandlerService.addSharedResourceAttributes(sharedResourceAttributes); + Assert.assertTrue(isAdded, "Added shared resource attributes."); + + } + + @Test(priority = 17) + public void testAddSharedResourceAttributesSuccessWithIgnoringInvalidAttributes() throws Exception { + + List sharedResourceAttributes = Arrays.asList( + new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(Integer.MIN_VALUE) + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_1) + .build(), + new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(1) + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_2) + .build()); + + boolean isAdded = resourceSharingPolicyHandlerService.addSharedResourceAttributes(sharedResourceAttributes); + Assert.assertTrue(isAdded, "Skipped the invalid attributes and added the rest."); + + } + + @Test(priority = 18) + public void testAddSharedResourceAttributesSuccessWithInapplicableAttribute() throws Exception { + + ResourceSharingPolicy resourceSharingPolicyMock = mock(ResourceSharingPolicy.class); + ResourceType resourceTypeMock = mock(ResourceType.class); + + when(resourceSharingPolicyMock.getResourceType()).thenReturn(resourceTypeMock); + when(resourceTypeMock.isApplicableAttributeType(any(SharedAttributeType.class))).thenReturn(false); + + // Valid attribute + SharedResourceAttribute validSharedResourceAttribute = new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(1) + .withSharedAttributeType(SharedAttributeType.ROLE) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_1) + .build(); + + // Invalid attribute + SharedResourceAttribute invalidSharedResourceAttribute = new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(-1) + .withSharedAttributeType(SharedAttributeType.ROLE) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_2) + .build(); + + ResourceSharingPolicyHandlerService resourceSharingPolicyHandlerServiceMock = + spy(new ResourceSharingPolicyHandlerServiceImpl()); + + doReturn(Optional.of(resourceSharingPolicyMock)).when(resourceSharingPolicyHandlerServiceMock) + .getResourceSharingPolicyById(validSharedResourceAttribute.getResourceSharingPolicyId()); + + doReturn(Optional.empty()).when(resourceSharingPolicyHandlerServiceMock) + .getResourceSharingPolicyById(invalidSharedResourceAttribute.getResourceSharingPolicyId()); + + List sharedResourceAttributes = + Arrays.asList(validSharedResourceAttribute, invalidSharedResourceAttribute); + + boolean isAdded = resourceSharingPolicyHandlerServiceMock.addSharedResourceAttributes(sharedResourceAttributes); + + Assert.assertTrue(isAdded, "Skipped the inapplicable attributes and added the rest."); + verify(resourceSharingPolicyHandlerServiceMock, times(1)) + .getResourceSharingPolicyById(validSharedResourceAttribute.getResourceSharingPolicyId()); + verify(resourceSharingPolicyHandlerServiceMock, times(1)) + .getResourceSharingPolicyById(invalidSharedResourceAttribute.getResourceSharingPolicyId()); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 19) + public void testAddSharedResourceAttributesFailure() throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new TransactionException(MOCKED_TRANSACTION_EXCEPTION)).when(mockJdbcTemplate) + .withTransaction(any()); + + resourceSharingPolicyHandlerService.addSharedResourceAttributes( + Collections.singletonList(new SharedResourceAttribute())); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (TransactionException e) { + throw new TestException(e); + } + } + + // Tests: GET Shared Resource Attributes Records. + @Test(priority = 20) + public void testGetSharedResourceAttributesBySharingPolicyIdSuccess() throws Exception { + + addAndAssertSharedResourceAttributes(); + List sharedResourceAttributes = + resourceSharingPolicyHandlerService.getSharedResourceAttributesBySharingPolicyId(1); + Assert.assertNotNull(sharedResourceAttributes, + "Expected non-null list of shared resource attributes."); + Assert.assertFalse(sharedResourceAttributes.isEmpty(), + "Expected non-empty list of shared resource attributes."); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 21) + public void testGetSharedResourceAttributesBySharingPolicyIdFailure() throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeQuery(anyString(), any(), any()); + + resourceSharingPolicyHandlerService.getSharedResourceAttributesBySharingPolicyId(1); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + @Test(priority = 22) + public void testGetSharedResourceAttributesByTypeSuccess() throws Exception { + + List sharedResourceAttributes = + resourceSharingPolicyHandlerService.getSharedResourceAttributesByType( + SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1); + Assert.assertNotNull(sharedResourceAttributes, + "Expected non-null list of shared resource attributes by type."); + Assert.assertFalse(sharedResourceAttributes.isEmpty(), + "Expected non-empty list of shared resource attributes by type."); + } + + @Test(priority = 24) + public void testGetSharedResourceAttributesByIdSuccess() throws Exception { + + addAndAssertSharedResourceAttributes(); + List sharedResourceAttributes = + resourceSharingPolicyHandlerService.getSharedResourceAttributesById(UM_ID_RESOURCE_ATTRIBUTE_1); + Assert.assertNotNull(sharedResourceAttributes, + "Expected non-null list of shared resource attributes by ID."); + Assert.assertFalse(sharedResourceAttributes.isEmpty(), + "Expected non-empty list of shared resource attributes by ID."); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtClientException.class, priority = 25) + public void testGetSharedResourceAttributesByIdFailureForNull() throws Exception { + + resourceSharingPolicyHandlerService.getSharedResourceAttributesById(null); + } + + @Test(priority = 26) + public void testGetSharedResourceAttributesByTypeAndIdSuccess() throws Exception { + + addAndAssertSharedResourceAttributes(); + List sharedResourceAttributes = + resourceSharingPolicyHandlerService.getSharedResourceAttributesByTypeAndId( + SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1, UM_ID_RESOURCE_ATTRIBUTE_1); + Assert.assertNotNull(sharedResourceAttributes, + "Expected non-null list of shared resource attributes by type and ID."); + Assert.assertFalse(sharedResourceAttributes.isEmpty(), + "Expected non-empty list of shared resource attributes by type and ID."); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtClientException.class, priority = 27) + public void testGetSharedResourceAttributesByTypeAndIdFailureForNull() throws Exception { + + resourceSharingPolicyHandlerService.getSharedResourceAttributesByTypeAndId(null, null); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 28) + public void testGetSharedResourceAttributesByTypeAndIdFailure() + throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeQuery(anyString(), any(), any()); + + resourceSharingPolicyHandlerService.getSharedResourceAttributesByTypeAndId( + SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1, UM_ID_RESOURCE_ATTRIBUTE_1); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + // Tests: DELETE Shared Resource Attributes Records. + @Test(priority = 29) + public void testDeleteSharedResourceAttributesByResourceSharingPolicyIdSuccess() throws Exception { + + resourceSharingPolicyHandlerService.deleteSharedResourceAttributesByResourceSharingPolicyId + (1, SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1, UM_ID_ORGANIZATION_SUPER); + List sharedResourceAttributes = + resourceSharingPolicyHandlerService.getSharedResourceAttributesBySharingPolicyId(1); + Assert.assertEquals(sharedResourceAttributes.size(), 0); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 30) + public void testDeleteSharedResourceAttributesByResourceSharingPolicyIdFailure() + throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeUpdate(anyString(), any()); + + resourceSharingPolicyHandlerService.deleteSharedResourceAttributesByResourceSharingPolicyId(1, + SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1, UM_ID_ORGANIZATION_SUPER); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + @Test(priority = 31) + public void testDeleteSharedResourceAttributeByAttributeTypeAndIdSuccess() throws Exception { + + resourceSharingPolicyHandlerService.deleteSharedResourceAttributeByAttributeTypeAndId( + SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1, UM_ID_RESOURCE_ATTRIBUTE_1, UM_ID_ORGANIZATION_SUPER); + List sharedResourceAttributes = + resourceSharingPolicyHandlerService.getSharedResourceAttributesByTypeAndId( + SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1, UM_ID_RESOURCE_ATTRIBUTE_1); + Assert.assertEquals(sharedResourceAttributes.size(), 0); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 32) + public void testDeleteSharedResourceAttributeByAttributeTypeAndIdFailure() + throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeUpdate(anyString(), any()); + + resourceSharingPolicyHandlerService.deleteSharedResourceAttributeByAttributeTypeAndId( + SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1, UM_ID_RESOURCE_1, UM_ID_ORGANIZATION_SUPER); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + @Test(priority = 33) + public void testAddResourceSharingPolicyWithAttributesSuccess() throws ResourceSharingPolicyMgtException { + + ResourceSharingPolicy resourceSharingPolicy = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_1) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_ORG_ALL) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_WITH_ALL_EXISTING_AND_FUTURE_CHILDREN) + .build(); + + List sharedResourceAttributes = Arrays.asList( + new SharedResourceAttribute.Builder() + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_1) + .build(), + new SharedResourceAttribute.Builder() + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_2) + .build()); + + boolean result = + resourceSharingPolicyHandlerService.addResourceSharingPolicyWithAttributes(resourceSharingPolicy, + sharedResourceAttributes); + + Assert.assertTrue(result, "Expected the method to successfully add valid attributes."); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 34) + public void testAddResourceSharingPolicyWithAttributesFailure() throws ResourceSharingPolicyMgtException { + + ResourceSharingPolicy resourceSharingPolicy = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_1) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(UM_ID_ORGANIZATION_ORG_ALL) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_WITH_ALL_EXISTING_AND_FUTURE_CHILDREN) + .build(); + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new TransactionException(MOCKED_TRANSACTION_EXCEPTION)).when(mockJdbcTemplate) + .withTransaction(any()); + + resourceSharingPolicyHandlerService.addResourceSharingPolicyWithAttributes(resourceSharingPolicy, + Collections.singletonList(new SharedResourceAttribute())); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (TransactionException e) { + throw new TestException(e); + } + } + + @Test(priority = 35) + public void testGetResourceSharingPoliciesWithSharedAttributesSuccess() throws Exception { + // Prepare mock data + List policyHoldingOrganizationIds = Arrays.asList( + UM_ID_ORGANIZATION_SUPER, UM_ID_ORGANIZATION_ORG_ALL); + + SharedResourceAttribute attribute1 = new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(1) + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_1) + .build(); + + SharedResourceAttribute attribute2 = new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(2) + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_2) + .build(); + + List sharedAttributes = Arrays.asList(attribute1, attribute2); + boolean attributesAdded = resourceSharingPolicyHandlerService.addSharedResourceAttributes(sharedAttributes); + Assert.assertTrue(attributesAdded, "Shared resource attributes were not added successfully."); + + Map>> result = + resourceSharingPolicyHandlerService.getResourceSharingPoliciesWithSharedAttributes( + policyHoldingOrganizationIds); + + Assert.assertNotNull(result); + Assert.assertEquals(result.size(), policyHoldingOrganizationIds.size(), + "Grouped result size does not match the number of policy holding organizations."); + + for (String policyHoldingOrgId : policyHoldingOrganizationIds) { + Assert.assertTrue(result.containsKey(policyHoldingOrgId), + "Grouped result does not contain expected organization ID: " + policyHoldingOrgId); + + Map> policyMap = result.get(policyHoldingOrgId); + + for (Map.Entry> entry : policyMap.entrySet()) { + ResourceSharingPolicy policy = entry.getKey(); + List attributes = entry.getValue(); + + Assert.assertNotNull(policy, "Resource sharing policy should not be null."); + Assert.assertNotNull(attributes, "Shared resource attributes list should not be null."); + } + } + } + + @Test(priority = 36) + public void testGetResourceSharingPoliciesWithSharedAttributesEmptyResult() throws Exception { + + List policyHoldingOrganizationIds = Collections.singletonList(UM_ID_ORGANIZATION_INVALID); + + Map>> result = + resourceSharingPolicyHandlerService.getResourceSharingPoliciesWithSharedAttributes( + policyHoldingOrganizationIds); + + Assert.assertEquals(result.size(), 0); + } + + @Test(expectedExceptions = ResourceSharingPolicyMgtServerException.class, priority = 37) + public void testGetResourceSharingPoliciesWithSharedAttributesFailure() throws ResourceSharingPolicyMgtException { + + NamedJdbcTemplate mockJdbcTemplate = mock(NamedJdbcTemplate.class); + + try (MockedStatic mockedStatic = mockStatic(Utils.class)) { + mockedStatic.when(Utils::getNewTemplate).thenReturn(mockJdbcTemplate); + doThrow(new DataAccessException(MOCKED_DATA_ACCESS_EXCEPTION)).when(mockJdbcTemplate) + .executeQuery(anyString(), any(), any()); + + resourceSharingPolicyHandlerService.getResourceSharingPoliciesWithSharedAttributes( + Arrays.asList(UM_ID_ORGANIZATION_SUPER, UM_ID_ORGANIZATION_ORG_ALL)); + + mockedStatic.verify(Utils::getNewTemplate, times(1)); + } catch (DataAccessException e) { + throw new TestException(e); + } + } + + // Helpers: Private helper methods for tests. + private List addAndAssertResourceSharingPolicy(List policyHoldingOrgIds) + throws ResourceSharingPolicyMgtException { + + ResourceSharingPolicy policy1 = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_1) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(policyHoldingOrgIds.get(0)) + .withSharingPolicy(PolicyEnum.ALL_EXISTING_AND_FUTURE_ORGS) + .build(); + + ResourceSharingPolicy policy2 = new ResourceSharingPolicy.Builder() + .withResourceId(UM_ID_RESOURCE_2) + .withResourceType(RESOURCE_TYPE_RESOURCE_1) + .withInitiatingOrgId(UM_ID_ORGANIZATION_SUPER) + .withPolicyHoldingOrgId(policyHoldingOrgIds.get(1)) + .withSharingPolicy(PolicyEnum.SELECTED_ORG_WITH_ALL_EXISTING_AND_FUTURE_CHILDREN) + .build(); + + List policyIds = new ArrayList<>(); + List resourceSharingPolicies = Arrays.asList(policy1, policy2); + + for (ResourceSharingPolicy resourceSharingPolicy : resourceSharingPolicies) { + int resourceSharingPolicyRecord = + resourceSharingPolicyHandlerService.addResourceSharingPolicy(resourceSharingPolicy); + Assert.assertTrue(resourceSharingPolicyRecord > 0, + "Expected a positive non-zero integer as the result for a clean record insertion " + + "to the database."); + policyIds.add(resourceSharingPolicyRecord); + } + return policyIds; + } + + private void addAndAssertSharedResourceAttributes() + throws ResourceSharingPolicyMgtException { + + List sharedResourceAttributes = new ArrayList<>(); + List resourceSharingPolicyIds = + addAndAssertResourceSharingPolicy(Arrays.asList(UM_ID_ORGANIZATION_SUPER, UM_ID_ORGANIZATION_ORG_ALL)); + + for (int resourceSharingPolicyId : resourceSharingPolicyIds) { + SharedResourceAttribute sharedResourceAttribute = new SharedResourceAttribute.Builder() + .withResourceSharingPolicyId(resourceSharingPolicyId) + .withSharedAttributeType(SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1) + .withSharedAttributeId(UM_ID_RESOURCE_ATTRIBUTE_1) + .build(); + + sharedResourceAttributes.add(sharedResourceAttribute); + } + + boolean isAdded = resourceSharingPolicyHandlerService.addSharedResourceAttributes(sharedResourceAttributes); + Assert.assertTrue(isAdded, "Added shared resource attributes."); + + } + +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constants/TestResourceSharingConstants.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constants/TestResourceSharingConstants.java new file mode 100644 index 000000000..28130a31a --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/constants/TestResourceSharingConstants.java @@ -0,0 +1,60 @@ +/* + * 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.resource.sharing.policy.management.constants; + +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.ResourceType; +import org.wso2.carbon.identity.organization.resource.sharing.policy.management.constant.SharedAttributeType; + +/** + * Constants related to the test cases of Resource Sharing policy Management component. + */ +public class TestResourceSharingConstants { + + //Organizations. + public static final String UM_ID_ORGANIZATION_SUPER = "10084a8d-113f-4211-a0d5-efe36b082211"; + public static final String UM_ID_ORGANIZATION_ORG_ALL = "c524c30a-cbd4-4169-ac9d-1ee3edf1bf16"; + public static final String UM_ID_ORGANIZATION_ORG_ALL_CHILD1 = "cd5a1dcb-fff2-4c14-a073-c07b3caf1757"; + public static final String UM_ID_ORGANIZATION_ORG_IMMEDIATE = "7cb4ab7e-9a25-44bd-a9e0-cf4e07d804dc"; + public static final String UM_ID_ORGANIZATION_ORG_IMMEDIATE_CHILD1 = "440ad5b6-6a41-4da7-aadd-272995d0e5db"; + + //Invalid Organizations. + public static final String UM_ID_ORGANIZATION_INVALID = "abcdefgh-0123-ijkl-4563-mnopqrstuvwx"; + public static final String UM_ID_ORGANIZATION_INVALID_FORMAT = "12'3"; + + //Resources. + public static final String UM_ID_RESOURCE_1 = "448e57e7-ff6b-4c31-a1eb-2a0e2d635b2a"; + public static final String UM_ID_RESOURCE_2 = "558e57e7-ff6b-4c31-a1eb-2a0e2d635b2a"; + public static final String UM_ID_RESOURCE_3 = "668e57e7-ff6b-4c31-a1eb-2a0e2d635b2b"; + public static final String UM_ID_RESOURCE_4 = "778e57e7-ff6b-4c31-a1eb-2a0e2d635b2c"; + + //Resources Types. + public static final ResourceType RESOURCE_TYPE_RESOURCE_1 = ResourceType.USER; + + //Resource Attributes. + public static final String UM_ID_RESOURCE_ATTRIBUTE_1 = "daea2340-4686-4929-b0c3-aad28237b065"; + public static final String UM_ID_RESOURCE_ATTRIBUTE_2 = "daea2341-4686-4929-b0c3-aad28237b065"; + + //Resource Attributes Types. + public static final SharedAttributeType SHARED_ATTRIBUTE_TYPE_RESOURCE_ATTRIBUTE_1 = SharedAttributeType.ROLE; + + //Mocks + public static final String MOCKED_DATA_ACCESS_EXCEPTION = "Mocked DataAccessException"; + public static final String MOCKED_TRANSACTION_EXCEPTION = "Mocked TransactionException"; + +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/util/TestUtils.java b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/util/TestUtils.java new file mode 100644 index 000000000..3eb83c4ca --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/java/org/wso2/carbon/identity/organization/resource/sharing/policy/management/util/TestUtils.java @@ -0,0 +1,111 @@ +/* + * 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.resource.sharing.policy.management.util; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.lang.StringUtils; +import org.wso2.carbon.base.CarbonBaseConstants; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.internal.CarbonContextDataHolder; +import org.wso2.carbon.identity.organization.management.service.util.Utils; +import org.wso2.carbon.user.api.UserRealm; +import org.wso2.carbon.user.core.util.DatabaseUtil; + +import java.lang.reflect.Field; +import java.nio.file.Paths; +import java.sql.Connection; +import java.util.HashMap; +import java.util.Map; + +import javax.sql.DataSource; + +import static org.mockito.Mockito.mock; + +/** + * Util methods needed for testing of Resource Sharing policy Management component. + */ +public class TestUtils { + + public static final String DB_NAME = "testResourceSharingPolicyMgt_db"; + public static final String H2_SCRIPT_NAME = "h2.sql"; + public static Map dataSourceMap = new HashMap<>(); + + public static String getFilePath(String fileName) { + + if (StringUtils.isNotBlank(fileName)) { + return Paths.get(System.getProperty("user.dir"), "src", "test", "resources", "dbscripts", + fileName).toString(); + } + throw new IllegalArgumentException("DB Script file name cannot be empty."); + } + + public static void initiateH2Base() throws Exception { + + BasicDataSource dataSource = new BasicDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUsername("username"); + dataSource.setPassword("password"); + dataSource.setUrl("jdbc:h2:mem:test" + DB_NAME); + dataSource.setTestOnBorrow(true); + dataSource.setValidationQuery("select 1"); + try (Connection connection = dataSource.getConnection()) { + connection.createStatement().executeUpdate(getExecuteUpdateQuery()); + } + dataSourceMap.put(DB_NAME, dataSource); + } + + public static void closeH2Base() throws Exception { + + BasicDataSource dataSource = dataSourceMap.remove(DB_NAME); + if (dataSource != null) { + dataSource.close(); + } + } + + public static void mockDataSource() throws Exception { + + String carbonHome = Paths.get(System.getProperty("user.dir"), "target", "test-classes").toString(); + System.setProperty(CarbonBaseConstants.CARBON_HOME, carbonHome); + System.setProperty(CarbonBaseConstants.CARBON_CONFIG_DIR_PATH, Paths.get(carbonHome, + "repository/conf").toString()); + + DataSource dataSource = dataSourceMap.get(DB_NAME); + + setStatic(DatabaseUtil.class.getDeclaredField("dataSource"), dataSource); + + Field carbonContextHolderField = + CarbonContext.getThreadLocalCarbonContext().getClass().getDeclaredField("carbonContextHolder"); + carbonContextHolderField.setAccessible(true); + CarbonContextDataHolder carbonContextHolder + = (CarbonContextDataHolder) carbonContextHolderField.get(CarbonContext.getThreadLocalCarbonContext()); + carbonContextHolder.setUserRealm(mock(UserRealm.class)); + setStatic(Utils.class.getDeclaredField("dataSource"), dataSource); + } + + private static void setStatic(Field field, Object newValue) throws Exception { + + field.setAccessible(true); + field.set(null, newValue); + } + + private static String getExecuteUpdateQuery() { + + return "RUNSCRIPT FROM '" + getFilePath(H2_SCRIPT_NAME) + "'"; + } +} diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/dbscripts/h2.sql b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/dbscripts/h2.sql new file mode 100644 index 000000000..733a588a6 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/dbscripts/h2.sql @@ -0,0 +1,74 @@ +-- UM_ORG definition +CREATE TABLE UM_ORG +( + UM_ID CHARACTER VARYING(36) NOT NULL, + UM_ORG_NAME CHARACTER VARYING(255) NOT NULL, + UM_ORG_DESCRIPTION CHARACTER VARYING(1024), + UM_CREATED_TIME TIMESTAMP NOT NULL, + UM_LAST_MODIFIED TIMESTAMP NOT NULL, + UM_STATUS CHARACTER VARYING(255) DEFAULT 'ACTIVE' NOT NULL, + UM_PARENT_ID CHARACTER VARYING(36), + UM_ORG_TYPE CHARACTER VARYING(100) NOT NULL, + PRIMARY KEY (UM_ID), + FOREIGN KEY (UM_PARENT_ID) REFERENCES PUBLIC.UM_ORG (UM_ID) ON DELETE CASCADE ON UPDATE RESTRICT +); +CREATE INDEX IDX_UM_ORG_PARENT_ID ON PUBLIC.UM_ORG (UM_PARENT_ID); +CREATE UNIQUE INDEX IDX_UNIQUE_UM_ORG_ID ON PUBLIC.UM_ORG (UM_ID); + +-- Table to store polices of sharing resources +CREATE TABLE UM_RESOURCE_SHARING_POLICY +( + UM_ID INTEGER NOT NULL AUTO_INCREMENT, + UM_RESOURCE_TYPE VARCHAR(255) NOT NULL, + UM_RESOURCE_ID VARCHAR(36) NOT NULL, + UM_INITIATING_ORG_ID VARCHAR(36) NOT NULL, + UM_POLICY_HOLDING_ORG_ID VARCHAR(36) NOT NULL, + UM_SHARING_POLICY VARCHAR(255) NOT NULL, + PRIMARY KEY (UM_ID), + FOREIGN KEY (UM_INITIATING_ORG_ID) REFERENCES UM_ORG (UM_ID) ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (UM_POLICY_HOLDING_ORG_ID) REFERENCES UM_ORG (UM_ID) ON DELETE CASCADE ON UPDATE CASCADE +); + +-- Table to store attributes related to shared resources +CREATE TABLE UM_SHARED_RESOURCE_ATTRIBUTES +( + UM_ID INTEGER NOT NULL AUTO_INCREMENT, + UM_RESOURCE_SHARING_POLICY_ID INTEGER NOT NULL, + UM_SHARED_ATTRIBUTE_TYPE VARCHAR(255) NOT NULL, + UM_SHARED_ATTRIBUTE_ID VARCHAR(36) NOT NULL, + PRIMARY KEY (UM_ID), + FOREIGN KEY (UM_RESOURCE_SHARING_POLICY_ID) REFERENCES UM_RESOURCE_SHARING_POLICY (UM_ID) ON DELETE CASCADE ON UPDATE CASCADE +); + +INSERT INTO UM_ORG (UM_ID, UM_ORG_NAME, UM_ORG_DESCRIPTION, UM_CREATED_TIME, UM_LAST_MODIFIED, UM_STATUS, UM_PARENT_ID, + UM_ORG_TYPE) +VALUES ('10084a8d-113f-4211-a0d5-efe36b082211', 'Super', 'This is the super organization.', + '2024-10-24 16:40:48.641555', '2024-10-24 16:40:48.641555', 'ACTIVE', NULL, 'TENANT'), + ('c524c30a-cbd4-4169-ac9d-1ee3edf1bf16', 'org-all', NULL, '2024-11-19 07:19:01.16727', + '2024-11-19 07:19:01.16727', 'ACTIVE', '10084a8d-113f-4211-a0d5-efe36b082211', 'TENANT'), + ('cd5a1dcb-fff2-4c14-a073-c07b3caf1757', 'org-all-child1', NULL, '2024-11-19 07:19:17.677139', + '2024-11-19 07:19:17.677139', 'ACTIVE', 'c524c30a-cbd4-4169-ac9d-1ee3edf1bf16', 'TENANT'), + ('46edfee9-b9f7-4480-ab45-353a571eafb4', 'org-all-grandchild1', NULL, '2024-11-19 07:19:49.208315', + '2024-11-19 07:19:49.208315', 'ACTIVE', 'cd5a1dcb-fff2-4c14-a073-c07b3caf1757', 'TENANT'), + ('7cb4ab7e-9a25-44bd-a9e0-cf4e07d804dc', 'org-immediate', NULL, '2024-11-19 07:20:04.418474', + '2024-11-19 07:20:04.418474', 'ACTIVE', '10084a8d-113f-4211-a0d5-efe36b082211', 'TENANT'), + ('440ad5b6-6a41-4da7-aadd-272995d0e5db', 'org-immediate-child1', NULL, '2024-11-19 07:20:19.34002', + '2024-11-19 07:20:19.34002', 'ACTIVE', '7cb4ab7e-9a25-44bd-a9e0-cf4e07d804dc', 'TENANT'), + ('ea1a347c-0b2b-421a-a21a-50fb489bc41f', 'org-immediate-grandchild1', NULL, '2024-11-19 07:20:30.359943', + '2024-11-19 07:20:30.359943', 'ACTIVE', '440ad5b6-6a41-4da7-aadd-272995d0e5db', 'TENANT'); + +INSERT INTO UM_RESOURCE_SHARING_POLICY (UM_RESOURCE_TYPE, UM_RESOURCE_ID, UM_INITIATING_ORG_ID, UM_POLICY_HOLDING_ORG_ID, UM_SHARING_POLICY) +VALUES + ('USER', 'a07a3509-f646-498c-890e-cedb08cd1586', '10084a8d-113f-4211-a0d5-efe36b082211', 'c524c30a-cbd4-4169-ac9d-1ee3edf1bf16', 'SELECTIVE-003'), + ('USER', '678afe66-36ed-4c0a-8789-b6f83c4f40dc', '10084a8d-113f-4211-a0d5-efe36b082211', 'c524c30a-cbd4-4169-ac9d-1ee3edf1bf16', 'SELECTIVE-003'), + ('USER', '150b7b05-21bb-4b20-a7be-9e7a299969bb', '10084a8d-113f-4211-a0d5-efe36b082211', '7cb4ab7e-9a25-44bd-a9e0-cf4e07d804dc', 'SELECTIVE-005'), + ('USER', '94154a9a-e177-404c-8504-d58a71db1f84', '10084a8d-113f-4211-a0d5-efe36b082211', 'c524c30a-cbd4-4169-ac9d-1ee3edf1bf16', 'SELECTIVE-003'), + ('USER', '94154a9a-e177-404c-8504-d58a71db1f84', '10084a8d-113f-4211-a0d5-efe36b082211', 'c524c30a-cbd4-4169-ac9d-1ee3edf1bf16', 'SELECTIVE-005'); + +INSERT INTO UM_SHARED_RESOURCE_ATTRIBUTES (UM_RESOURCE_SHARING_POLICY_ID, UM_SHARED_ATTRIBUTE_TYPE, UM_SHARED_ATTRIBUTE_ID) +VALUES + (1, 'ROLE', 'daea2340-4686-4929-b0c3-aad28237b065'), + (2, 'ROLE', 'fcee2861-3687-4f66-b656-94591faf44ab'), + (3, 'ROLE', 'daea2340-4686-4929-b0c3-aad28237b065'), + (4, 'ROLE', 'fcee2861-3687-4f66-b656-94591faf44ab'), + (5, 'ROLE', 'f0dd8c17-e085-4816-bed1-eee84052e3ab'); diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/repository.conf/carbon.xml b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/repository.conf/carbon.xml new file mode 100644 index 000000000..260bcd7f3 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/repository.conf/carbon.xml @@ -0,0 +1,686 @@ + + + + + + + + WSO2 Identity Server + + + IS + + + 5.3.0 + + + localhost + + + localhost + + + local:/${carbon.context}/services/ + + + + + + + IdentityServer + + + + + + + org.wso2.carbon + + + / + + + + + + + + + 15 + + + + + + + + + 0 + + + + + 9999 + + 11111 + + + + + + 10389 + + 8000 + + + + + + 10500 + + + + + + + + + org.wso2.carbon.tomcat.jndi.CarbonJavaURLContextFactory + + + + + + + + + java + + + + + + + + + + false + + + false + + + 600 + + + + false + + + + + + + + 30 + + + + + + + + + 15 + + + + + + ${carbon.home}/repository/deployment/server/ + + + 15 + + + ${carbon.home}/repository/conf/axis2/axis2.xml + + + 30000 + + + ${carbon.home}/repository/deployment/client/ + + ${carbon.home}/repository/conf/axis2/axis2_client.xml + + true + + + + + + + + + + admin + Default Administrator Role + + + user + Default User Role + + + + + + + + + + + + ${carbon.home}/repository/resources/security/wso2carbon.jks + + JKS + + wso2carbon + + wso2carbon + + wso2carbon + + + + + + ${carbon.home}/repository/resources/security/client-truststore.jks + + JKS + + wso2carbon + + + + + + + + + + + + + + + + + + + UserManager + + + false + + org.wso2.carbon.identity.provider.AttributeCallbackHandler + + + org.wso2.carbon.identity.sts.store.DBTokenStore + + + true + allow + + + + + + + claim_mgt_menu + identity_mgt_emailtemplate_menu + identity_security_questions_menu + + + + ${carbon.home}/tmp/work + + + + + + true + + + 10 + + + 30 + + + + + + 100 + + + + keystore + certificate + * + + org.wso2.carbon.ui.transports.fileupload.AnyFileUploadExecutor + + + + + jarZip + + org.wso2.carbon.ui.transports.fileupload.JarZipUploadExecutor + + + + dbs + + org.wso2.carbon.ui.transports.fileupload.DBSFileUploadExecutor + + + + tools + + org.wso2.carbon.ui.transports.fileupload.ToolsFileUploadExecutor + + + + toolsAny + + org.wso2.carbon.ui.transports.fileupload.ToolsAnyFileUploadExecutor + + + + + + + + + + info + org.wso2.carbon.core.transports.util.InfoProcessor + + + wsdl + org.wso2.carbon.core.transports.util.Wsdl11Processor + + + wsdl2 + org.wso2.carbon.core.transports.util.Wsdl20Processor + + + xsd + org.wso2.carbon.core.transports.util.XsdProcessor + + + + + + false + false + true + svn + http://svnrepo.example.com/repos/ + username + password + true + + + + + + + + + + + + + + + ${require.carbon.servlet} + + + + + true + + + + + + + default repository + http://product-dist.wso2.com/p2/carbon/releases/wilkes/ + + + + + + + + true + + + + + + true + + diff --git a/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/testing.xml b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/testing.xml new file mode 100644 index 000000000..c6ed86ce1 --- /dev/null +++ b/components/org.wso2.carbon.identity.organization.resource.sharing.policy.management/src/test/resources/testing.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 8d339b34e..d794fdee9 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ - 4.9.17 + 4.10.25 [4.7.0, 5.0.0) 4.6.0 @@ -573,7 +586,7 @@ [1.0.1, 2.0.0) [4.7.0, 5.0.0) - 2.1.7 + 2.2.2 [2.0.0,3.0.0) 1.4.47 @@ -593,7 +606,8 @@ 5.2.0 6.9.10 2.22.0 - 1.4.199 + 2.2.224 + 4.11.30 4.1.2