-
Notifications
You must be signed in to change notification settings - Fork 85
Provide support for selective role sharing with application sharing #512
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide support for selective role sharing with application sharing #512
Conversation
...java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManager.java
Show resolved
Hide resolved
...java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManager.java
Outdated
Show resolved
Hide resolved
...so2/carbon/identity/organization/management/application/util/OrganizationShareProcessor.java
Show resolved
Hide resolved
7d1ddeb to
08e73a2
Compare
.../org/wso2/carbon/identity/organization/management/application/OrgApplicationManagerImpl.java
Outdated
Show resolved
Hide resolved
.../org/wso2/carbon/identity/organization/management/application/OrgApplicationManagerImpl.java
Outdated
Show resolved
Hide resolved
.../org/wso2/carbon/identity/organization/management/application/OrgApplicationManagerImpl.java
Outdated
Show resolved
Hide resolved
...2/carbon/identity/organization/management/application/util/OrgApplicationShareProcessor.java
Outdated
Show resolved
Hide resolved
- Provide the support to get application with filtering option. - Add new error message for application sharing - Moved application share operations models to a new package
08e73a2 to
732dfc9
Compare
# Conflicts: # components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManagerImpl.java # components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/constant/OrgApplicationMgtConstants.java # components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/internal/OrgApplicationMgtDataHolder.java # components/org.wso2.carbon.identity.organization.management.application/src/main/java/org/wso2/carbon/identity/organization/management/application/internal/OrgApplicationMgtServiceComponent.java
| org.wso2.carbon.identity.role.v2.mgt.core.*; | ||
| version="${carbon.identity.package.import.version.range}", | ||
| org.wso2.carbon; version="${carbon.kernel.package.import.version.range}", | ||
| *;resolution:=optional, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove before merging, by adding all required imports
...java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManager.java
Show resolved
Hide resolved
...java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManager.java
Outdated
Show resolved
Hide resolved
...java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManager.java
Outdated
Show resolved
Hide resolved
...java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManager.java
Show resolved
Hide resolved
...java/org/wso2/carbon/identity/organization/management/application/OrgApplicationManager.java
Outdated
Show resolved
Hide resolved
| org.wso2.carbon.identity.role.v2.mgt.core.*; | ||
| version="${carbon.identity.package.import.version.range}", | ||
| org.wso2.carbon; version="${carbon.kernel.package.import.version.range}", | ||
| *;resolution:=optional, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Properly fix the imports
| // This is done to ensure that the sharing is done in a way that respects the organization hierarchy. | ||
| List<SelectiveShareApplicationOperation> orgsThatNeedToBeShared = processAndSortOrganizationShares( | ||
| filteredChildOrgConfigs, mainOrganizationId); | ||
| if (CollectionUtils.isEmpty(orgsThatNeedToBeShared)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update the APIs with this change
...main/java/org/wso2/carbon/identity/organization/management/handler/SharedRoleMgtHandler.java
Outdated
Show resolved
Hide resolved
.../org/wso2/carbon/identity/organization/management/application/OrgApplicationManagerImpl.java
Show resolved
Hide resolved
- Convert logs to debug - Convert the ShareRoleMgt behaviour to previous behavior
045e793 to
dfdd654
Compare
- Improve logging - Add unit tests - Reduce using start tenant flows - Optimize to execute less DB queries
Codecov ReportAttention: Patch coverage is
❌ Your patch status has failed because the patch coverage (26.86%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #512 +/- ##
============================================
- Coverage 55.49% 52.16% -3.34%
- Complexity 1980 2080 +100
============================================
Files 184 196 +12
Lines 11213 12840 +1627
Branches 1639 1936 +297
============================================
+ Hits 6223 6698 +475
- Misses 4460 5519 +1059
- Partials 530 623 +93
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| } else { | ||
| // The string does not match the strict pattern. | ||
| throw new OrganizationManagementClientException("Invalid filter string format", | ||
| ERROR_CODE_INVALID_ORGANIZATION_PATH_FILTER.getDescription(), | ||
| ERROR_CODE_INVALID_ORGANIZATION_PATH_FILTER.getCode()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } else { | |
| // The string does not match the strict pattern. | |
| throw new OrganizationManagementClientException("Invalid filter string format", | |
| ERROR_CODE_INVALID_ORGANIZATION_PATH_FILTER.getDescription(), | |
| ERROR_CODE_INVALID_ORGANIZATION_PATH_FILTER.getCode()); | |
| } | |
| } | |
| // The string does not match the strict pattern. | |
| throw new OrganizationManagementClientException("Invalid filter string format", | |
| ERROR_CODE_INVALID_ORGANIZATION_PATH_FILTER.getDescription(), | |
| ERROR_CODE_INVALID_ORGANIZATION_PATH_FILTER.getCode()); |
| * The class enforces a strict format and provides a method to extract the organization ID | ||
| * and an optional path attribute (e.g., ".roles"). | ||
| */ | ||
| public class OrgApplicationScimFilterParser { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change the class name excluding SCIM, it's fine to have in the comment
| error) { | ||
| return new OrganizationManagementClientException(error.getMessage(), error.getDescription(), error.getCode()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing new line after method signature
| * | ||
| * @param error The error enum. | ||
| * @param e The error. | ||
| * @return OrganizationManagementServerException |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
complete the comment
| import org.wso2.carbon.identity.application.common.model.ApplicationBasicInfo; | ||
| import org.wso2.carbon.identity.application.common.model.ServiceProvider; | ||
| import org.wso2.carbon.identity.organization.management.application.model.SharedApplication; | ||
| import org.wso2.carbon.identity.organization.management.application.model.SharedApplicationOrganizationNodePage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change the year range in copy right header.
Check other classes as well
| throws OrganizationManagementException { | ||
|
|
||
| throw new NotImplementedException( | ||
| "selectiveShareOrganizationApplication method is not implemented in " + this.getClass().getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "selectiveShareOrganizationApplication method is not implemented in " + this.getClass().getName()); | |
| "shareApplicationWithSelectedOrganizations method is not implemented in " + this.getClass().getName()); |
| throws OrganizationManagementException { | ||
|
|
||
| throw new NotImplementedException( | ||
| "generalOrganizationApplicationShare method is not implemented in " + this.getClass().getName()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "generalOrganizationApplicationShare method is not implemented in " + this.getClass().getName()); | |
| "shareApplicationWithAllOrganizations method is not implemented in " + this.getClass().getName()); |
| if (!parentOrgId.equals(ownerOrgId)) { | ||
| Optional<String> parentOrgSharedAppId = resolveSharedApp( | ||
| mainApplication.getApplicationResourceId(), ownerOrgId, parentOrgId); | ||
| if (!parentOrgSharedAppId.isPresent()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible for an application to be shared with the immediate parent organization, but not with higher-level parent organizations in the hierarchy?
f99fb05 to
73f2fca
Compare
| parentOrgId); | ||
| if (!sharedAppIdOptional.isPresent()) { | ||
| // No shared application found for the main application. | ||
| // TODO: Should we throw an error here and fail org creation? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix this todo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are few more todos in the code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request adds support for selective role sharing in application sharing, along with new operations and modifications to the DAO, listener, and manager interfaces to integrate resource sharing policies. Key changes include the introduction of SelectiveShareApplicationOperation, updates to role-sharing configuration classes and events, and enhancements in SQL query building for shared applications.
Reviewed Changes
Copilot reviewed 20 out of 33 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| ApplicationShareRolePolicy.java | Added builder and enum changes for role sharing policies. |
| OrganizationCreationHandler.java | Updated event handling to support new resource sharing exceptions and role sharing logic. |
| OrgApplicationMgtDAOImpl.java | Modified DAO methods to support filtering and new shared application retrieval queries. |
| OrgApplicationManager.java & ApplicationSharingManagerListener*.java | Introduced new methods for selective and policy-based application sharing. |
| Other files (various listener, model, constants, pom.xml) | Updated imports and integrated resource sharing policy support across components. |
| if (ApplicationShareRolePolicy.Mode.SELECTED.ordinal() == roleSharingMode.ordinal()) { | ||
|
|
||
| // That mean the original application is available in the parent org. Not a fragment application. | ||
| for (SharedResourceAttribute sharedResourceAttribute : sharedResourceAttributes) { | ||
| if (SharedAttributeType.ROLE.ordinal() != sharedResourceAttribute.getSharedAttributeType() | ||
| .ordinal()) { |
Copilot
AI
Jun 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid using ordinal() for enum comparisons as it can be error-prone if the enum order changes. It is recommended to use equals() for comparing enum values.
| if (ApplicationShareRolePolicy.Mode.SELECTED.ordinal() == roleSharingMode.ordinal()) { | |
| // That mean the original application is available in the parent org. Not a fragment application. | |
| for (SharedResourceAttribute sharedResourceAttribute : sharedResourceAttributes) { | |
| if (SharedAttributeType.ROLE.ordinal() != sharedResourceAttribute.getSharedAttributeType() | |
| .ordinal()) { | |
| if (ApplicationShareRolePolicy.Mode.SELECTED == roleSharingMode) { | |
| // That mean the original application is available in the parent org. Not a fragment application. | |
| for (SharedResourceAttribute sharedResourceAttribute : sharedResourceAttributes) { | |
| if (SharedAttributeType.ROLE != sharedResourceAttribute.getSharedAttributeType()) { |
| String filterQuery = filterQueryBuilder.getFilterQuery(); | ||
| Map<String, String> filterAttributeValue = filterQueryBuilder.getFilterAttributeValue(); | ||
| String placeholders = IntStream.range(0, sharedOrgIds.size()) | ||
| .mapToObj(i -> ":" + SHARED_ORG_ID_PLACEHOLDER_PREFIX + i + ";") |
Copilot
AI
Jun 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder construction appends a semicolon to the parameter name, which may not match with the parameter keys when setting them. Remove the trailing semicolon to ensure the parameter names remain consistent.
| .mapToObj(i -> ":" + SHARED_ORG_ID_PLACEHOLDER_PREFIX + i + ";") | |
| .mapToObj(i -> ":" + SHARED_ORG_ID_PLACEHOLDER_PREFIX + i) |
|
|
||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove unwanted newlines
| // Filter only valid child org configs that exist in the owner's child orgs using the map (O(1) lookups). | ||
| List<SelectiveShareApplicationOperation> filteredChildOrgConfigs = selectiveShareApplicationList.stream() | ||
| .filter(config -> subOrganizationIdsSet.contains(config.getOrganizationId())) | ||
| .collect(Collectors.toList()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better if we can add a debug log for invalid child org IDs sent.
| // 3. Collect valid organization IDs and validate complete hierarchy paths. | ||
| Set<String> availableOrgIds = new HashSet<>(selectiveShareApplicationList.size()); | ||
| Map<String, SelectiveShareApplicationOperation> orgIdToConfigMap = new HashMap<>( | ||
| selectiveShareApplicationList.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of using a set for availableOrgIds we can use, orgIdToConfigMap.keySet() which returns the list of available organization IDs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Map.keySet() returns a live view of the map’s keys. It's backed directly by the map — no copying or new allocation.
| parentConfig.getPolicy(), | ||
| parentConfig.getRoleSharing() | ||
| ); | ||
| effectiveConfigs.put(descendantId, inheritedConfig); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can there be descendantId in the effectiveConfigs if we are iterating the Ids in the bfsOrder?
| // Find organizations that are no longer in the share config and need to be unshared. | ||
| List<SharedApplicationDO> orgsThatOmitted = sharedApplications.stream() | ||
| .filter(sharedApp -> !configOrgIds.contains(sharedApp.getOrganizationId())) | ||
| .collect(Collectors.toList()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will omit all orgs not sent in the request and gets unshared along with it's child orgs. And if it is present in the orgsThatNeedToBeShared list, get reshared again. Can't we remove it from both lists if the config is unchanged? It could reduce the overhead, as a whole subtree would not get unshared/reshared.
| // mainApplication.getApplicationResourceId(), sharedOrgId); | ||
| // } | ||
| // return sharedApplicationId; | ||
| // } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was there a particular reason this part is commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods can be removed
Purpose
$subject
TODOs: