From de361aeab826d9f034986b434923579cfdbaac9d Mon Sep 17 00:00:00 2001 From: Thilina Shashimal Senarath Date: Thu, 24 Aug 2023 12:08:02 +0530 Subject: [PATCH 1/4] Add application roles for Users and Groups --- .../pom.xml | 7 ++++ .../scim2/common/impl/SCIMUserManager.java | 37 ++++++++++++++++++- .../common/internal/SCIMCommonComponent.java | 32 ++++++++++++++++ .../internal/SCIMCommonComponentHolder.java | 22 +++++++++++ .../common/utils/SCIMCommonConstants.java | 2 + pom.xml | 8 +++- 6 files changed, 105 insertions(+), 3 deletions(-) diff --git a/components/org.wso2.carbon.identity.scim2.common/pom.xml b/components/org.wso2.carbon.identity.scim2.common/pom.xml index 4ffabb8f8..b897503c7 100644 --- a/components/org.wso2.carbon.identity.scim2.common/pom.xml +++ b/components/org.wso2.carbon.identity.scim2.common/pom.xml @@ -168,6 +168,11 @@ org.ops4j.pax.logging pax-logging-api + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.role.mgt + provided + @@ -217,6 +222,8 @@ version="${carbon.identity.framework.imp.pkg.version.range}", org.wso2.carbon.identity.role.mgt.core.*; version="${carbon.identity.framework.imp.pkg.version.range}", + org.wso2.carbon.identity.application.role.mgt.*; + version="${carbon.identity.framework.imp.pkg.version.range}", org.wso2.carbon.user.mgt.*;version="${carbon.identity.framework.imp.pkg.version.range}" diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java index 8148eec97..b9483991e 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java @@ -32,6 +32,8 @@ import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException; import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.application.role.mgt.exceptions.ApplicationRoleManagementException; +import org.wso2.carbon.identity.application.role.mgt.model.ApplicationRole; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; import org.wso2.carbon.identity.claim.metadata.mgt.exception.ClaimMetadataException; import org.wso2.carbon.identity.claim.metadata.mgt.model.ExternalClaim; @@ -48,6 +50,7 @@ import org.wso2.carbon.identity.scim2.common.extenstion.SCIMUserStoreErrorResolver; import org.wso2.carbon.identity.scim2.common.extenstion.SCIMUserStoreException; import org.wso2.carbon.identity.scim2.common.group.SCIMGroupHandler; +import org.wso2.carbon.identity.scim2.common.internal.SCIMCommonComponent; import org.wso2.carbon.identity.scim2.common.internal.SCIMCommonComponentHolder; import org.wso2.carbon.identity.scim2.common.utils.AttributeMapper; import org.wso2.carbon.identity.scim2.common.utils.SCIMCommonConstants; @@ -127,6 +130,8 @@ import static org.apache.commons.collections.CollectionUtils.isNotEmpty; import static org.wso2.carbon.identity.core.util.IdentityCoreConstants.MULTI_ATTRIBUTE_SEPARATOR; +import static org.wso2.carbon.identity.scim2.common.utils.SCIMCommonConstants.APP_ROLE_TYPE; +import static org.wso2.carbon.identity.scim2.common.utils.SCIMCommonConstants.DEFAULT_ROLE_TYPE; import static org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils.buildCustomSchema; import static org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils.getCustomSchemaURI; import static org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils @@ -4232,7 +4237,21 @@ private void setRolesOfUser(List rolesOfUser, Map groupMe role.setId(groupObject.getId()); String location = SCIMCommonUtils.getSCIMRoleURL(groupObject.getId()); role.setLocation(location); - scimUser.setRole(role); + scimUser.setRole(role, DEFAULT_ROLE_TYPE); + } + + // Add application roles of the user + try { + List applicationRoles = SCIMCommonComponentHolder.getApplicationRoleManager() + .getApplicationRolesByUserId(scimUser.getId()); + for(ApplicationRole applicationRole: applicationRoles) { + Role role = new Role(); + role.setDisplayName(applicationRole.getRoleName()); + role.setId(applicationRole.getRoleId()); + scimUser.setRole(role, APP_ROLE_TYPE); + } + } catch (ApplicationRoleManagementException e) { + throw new IdentitySCIMException("Error while getting application roles", e); } } @@ -4458,7 +4477,21 @@ private void setGroupRoles(Group group) throws org.wso2.carbon.user.core.UserSto role.setId(groupObject.getId()); String location = SCIMCommonUtils.getSCIMRoleURL(groupObject.getId()); role.setLocation(location); - group.setRole(role); + group.setRole(role, DEFAULT_ROLE_TYPE); + } + + // Add application roles of the group + try { + List applicationRoles = SCIMCommonComponentHolder.getApplicationRoleManager() + .getApplicationRolesByGroupId(group.getId()); + for(ApplicationRole applicationRole: applicationRoles) { + Role role = new Role(); + role.setDisplayName(applicationRole.getRoleName()); + role.setId(applicationRole.getRoleId()); + group.setRole(role, APP_ROLE_TYPE); + } + } catch (ApplicationRoleManagementException e) { + throw new IdentitySCIMException("Error while getting application roles", e); } } diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponent.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponent.java index 7fdb8a785..715c17cf6 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponent.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponent.java @@ -28,6 +28,7 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; +import org.wso2.carbon.identity.application.role.mgt.ApplicationRoleManager; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; import org.wso2.carbon.identity.core.util.IdentityCoreInitializedEvent; import org.wso2.carbon.identity.core.util.IdentityUtil; @@ -266,6 +267,36 @@ protected void unsetRoleManagementService(RoleManagementService roleManagementSe SCIMCommonComponentHolder.setRoleManagementService(null); } + /** + * Set application role manager implementation. + * + * @param applicationRoleManager ApplicationRoleManager + */ + @Reference( + name = "identity.application.role.mgt.component", + service = org.wso2.carbon.identity.application.role.mgt.ApplicationRoleManager.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetApplicationRoleManager") + protected void setApplicationRoleManager(ApplicationRoleManager applicationRoleManager) { + + if (logger.isDebugEnabled()) { + logger.debug("ApplicationRoleManager set in SCIMCommonComponent bundle."); + } + SCIMCommonComponentHolder.setApplicationRoleManager(applicationRoleManager); + } + + /** + * Unset application role manager implementation. + */ + protected void unsetApplicationRoleManager(ApplicationRoleManager applicationRoleManager) { + + if (logger.isDebugEnabled()) { + logger.debug("ApplicationRoleManager unset in SCIMCommonComponent bundle."); + } + SCIMCommonComponentHolder.setApplicationRoleManager(null); + } + /** * Set SCIMUserStoreErrorResolver implementation * @@ -287,6 +318,7 @@ protected void unsetScimUserStoreErrorResolver(SCIMUserStoreErrorResolver scimUs SCIMCommonComponentHolder.removeScimUserStoreErrorResolver(scimUserStoreErrorResolver); } + @Deactivate protected void deactivate(ComponentContext context) { diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponentHolder.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponentHolder.java index 0452bb5c1..bb24ad960 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponentHolder.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/internal/SCIMCommonComponentHolder.java @@ -18,6 +18,7 @@ package org.wso2.carbon.identity.scim2.common.internal; +import org.wso2.carbon.identity.application.role.mgt.ApplicationRoleManager; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; import org.wso2.carbon.identity.scim2.common.extenstion.SCIMUserStoreErrorResolver; import org.wso2.carbon.user.core.service.RealmService; @@ -38,6 +39,7 @@ public class SCIMCommonComponentHolder { private static ClaimMetadataManagementService claimManagementService; private static RolePermissionManagementService rolePermissionManagementService; private static RoleManagementService roleManagementService; + private static ApplicationRoleManager applicationRoleManager; private static final List scimUserStoreErrorResolvers = new ArrayList<>(); /** @@ -120,6 +122,26 @@ public static RoleManagementService getRoleManagementService() { return roleManagementService; } + /** + * Set application role management service. + * + * @param applicationRoleManager ApplicationRoleManager. + */ + public static void setApplicationRoleManager(ApplicationRoleManager applicationRoleManager) { + + SCIMCommonComponentHolder.applicationRoleManager = applicationRoleManager; + } + + /** + * Get role management service. + * + * @return RoleManagementService. + */ + public static ApplicationRoleManager getApplicationRoleManager() { + + return applicationRoleManager; + } + public static List getScimUserStoreErrorResolverList() { return scimUserStoreErrorResolvers; diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java index 93e80db1e..13daccae8 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java @@ -141,6 +141,8 @@ public class SCIMCommonConstants { public static final String MIN_LENGTH = "minLength"; public static final String MAX_LENGTH = "maxLength"; public static final String REQUIRED = "required"; + public static final String DEFAULT_ROLE_TYPE = "default"; + public static final String APP_ROLE_TYPE = "default"; private static final Map groupAttributeSchemaMap = new HashMap<>(); diff --git a/pom.xml b/pom.xml index 9cb0f1a67..eedb6c151 100644 --- a/pom.xml +++ b/pom.xml @@ -160,6 +160,12 @@ ${identity.framework.version} provided + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.application.role.mgt + ${identity.framework.version} + provided + org.wso2.carbon.identity.framework org.wso2.carbon.identity.testutil @@ -258,7 +264,7 @@ 6.5.3 3.2.0.wso2v1 4.9.4 - 5.25.143 + 5.25.287-SNAPSHOT 4.13.1 20030203.000129 1.8.12 From 1fcae41bf901016b261a22ac28f2f92d58112405 Mon Sep 17 00:00:00 2001 From: Thilina Shashimal Senarath Date: Fri, 25 Aug 2023 10:41:31 +0530 Subject: [PATCH 2/4] add tenent domain --- .../carbon/identity/scim2/common/impl/SCIMUserManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java index b9483991e..7d2d10a5e 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java @@ -4243,7 +4243,7 @@ private void setRolesOfUser(List rolesOfUser, Map groupMe // Add application roles of the user try { List applicationRoles = SCIMCommonComponentHolder.getApplicationRoleManager() - .getApplicationRolesByUserId(scimUser.getId()); + .getApplicationRolesByUserId(scimUser.getId(), tenantDomain); for(ApplicationRole applicationRole: applicationRoles) { Role role = new Role(); role.setDisplayName(applicationRole.getRoleName()); @@ -4483,7 +4483,7 @@ private void setGroupRoles(Group group) throws org.wso2.carbon.user.core.UserSto // Add application roles of the group try { List applicationRoles = SCIMCommonComponentHolder.getApplicationRoleManager() - .getApplicationRolesByGroupId(group.getId()); + .getApplicationRolesByGroupId(group.getId(), tenantDomain); for(ApplicationRole applicationRole: applicationRoles) { Role role = new Role(); role.setDisplayName(applicationRole.getRoleName()); From f264f93901311a63bf16f08be7c48cdfe9520641 Mon Sep 17 00:00:00 2001 From: Thilina Shashimal Senarath Date: Fri, 25 Aug 2023 14:18:29 +0530 Subject: [PATCH 3/4] fix app role type --- .../carbon/identity/scim2/common/utils/SCIMCommonConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java index 13daccae8..893d892c2 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/utils/SCIMCommonConstants.java @@ -142,7 +142,7 @@ public class SCIMCommonConstants { public static final String MAX_LENGTH = "maxLength"; public static final String REQUIRED = "required"; public static final String DEFAULT_ROLE_TYPE = "default"; - public static final String APP_ROLE_TYPE = "default"; + public static final String APP_ROLE_TYPE = "application"; private static final Map groupAttributeSchemaMap = new HashMap<>(); From d56389d88963f4e3f0b6b8a9c098b836db38a003 Mon Sep 17 00:00:00 2001 From: Thilina Shashimal Senarath Date: Mon, 4 Sep 2023 13:15:45 +0530 Subject: [PATCH 4/4] fix unit tests --- .../common/impl/SCIMUserManagerTest.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/components/org.wso2.carbon.identity.scim2.common/src/test/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManagerTest.java b/components/org.wso2.carbon.identity.scim2.common/src/test/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManagerTest.java index 48c5f285f..67024ce77 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/test/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManagerTest.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/test/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManagerTest.java @@ -36,6 +36,7 @@ import org.wso2.carbon.identity.application.common.model.InboundProvisioningConfig; import org.wso2.carbon.identity.application.common.model.ServiceProvider; import org.wso2.carbon.identity.application.mgt.ApplicationManagementService; +import org.wso2.carbon.identity.application.role.mgt.ApplicationRoleManager; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataHandler; import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService; import org.wso2.carbon.identity.claim.metadata.mgt.model.AttributeMapping; @@ -195,6 +196,9 @@ public class SCIMUserManagerTest extends PowerMockTestCase { @Mock private RolePermissionManagementService mockedRolePermissionManagementService; + @Mock + private ApplicationRoleManager mockApplicationRoleManager; + @BeforeMethod public void setUp() throws Exception { @@ -314,6 +318,11 @@ public void testGetGroup(String groupId, String roleName, String userStoreDomain when(IdentityUtil.extractDomainFromName(anyString())).thenReturn(userStoreDomain); when(mockedUserStoreManager.getGroup(groupId, null)). thenReturn(buildUserCoreGroupResponse(roleName, groupId, userStoreDomain)); + mockStatic(SCIMCommonComponentHolder.class); + when(SCIMCommonComponentHolder.getApplicationRoleManager()) + .thenReturn(mockApplicationRoleManager); + when(mockApplicationRoleManager.getApplicationRolesByGroupId(anyString(), anyString())) + .thenReturn(new ArrayList<>()); mockStatic(SCIMCommonUtils.class); when(SCIMCommonUtils.getSCIMGroupURL()).thenReturn("https://localhost:9443/scim2/Groups"); SCIMUserManager scimUserManager = new SCIMUserManager(mockedUserStoreManager, mockedClaimManager); @@ -400,6 +409,12 @@ public void testListGroupsWithFilter(String filter, String roleName, String user when(mockedGroupDAO.getSCIMGroupAttributes(0, "testRole")).thenReturn(attributes); when(IdentityUtil.extractDomainFromName(anyString())).thenReturn(userStoreDomain); + mockStatic(SCIMCommonComponentHolder.class); + when(SCIMCommonComponentHolder.getApplicationRoleManager()) + .thenReturn(mockApplicationRoleManager); + when(mockApplicationRoleManager.getApplicationRolesByGroupId(anyString(), anyString())) + .thenReturn(new ArrayList<>()); + mockedUserStoreManager = PowerMockito.mock(AbstractUserStoreManager.class); MemberModifier.field(AbstractUserStoreManager.class, "userStoreManagerHolder") @@ -956,6 +971,13 @@ public void testListApplicationRolesWithDomainParam(Map require when(abstractUserStoreManager.getGroupByGroupName(role, null)). thenReturn(buildUserCoreGroupResponse(role, "123456789", null)); } + + mockStatic(SCIMCommonComponentHolder.class); + when(SCIMCommonComponentHolder.getApplicationRoleManager()) + .thenReturn(mockApplicationRoleManager); + when(mockApplicationRoleManager.getApplicationRolesByGroupId(anyString(), anyString())) + .thenReturn(new ArrayList<>()); + whenNew(GroupDAO.class).withAnyArguments().thenReturn(mockedGroupDAO); when(mockedGroupDAO.isExistingGroup(anyString(), anyInt())).thenReturn(true); when(mockedGroupDAO.getSCIMGroupAttributes(anyInt(), anyString())).thenReturn(attributes); @@ -1021,6 +1043,12 @@ public void testFilterApplicationRolesWithDomainParam(String filter, String[] ro mockStatic(SCIMCommonUtils.class); when(SCIMCommonUtils.getSCIMGroupURL()).thenReturn("https://localhost:9443/scim2/Groups"); + mockStatic(SCIMCommonComponentHolder.class); + when(SCIMCommonComponentHolder.getApplicationRoleManager()) + .thenReturn(mockApplicationRoleManager); + when(mockApplicationRoleManager.getApplicationRolesByGroupId(anyString(), anyString())) + .thenReturn(new ArrayList<>()); + SCIMUserManager scimUserManager = new SCIMUserManager(abstractUserStoreManager, mockedClaimManager); GroupsGetResponse groupsResponse = scimUserManager .listGroupsWithGET(node, 1, null, null, null, "Application", requiredAttributes); @@ -1370,6 +1398,12 @@ public void testGetUser(Boolean isGroupsVsRolesSeparationImprovementsEnabled, Ma when(IdentityUtil.getProperty(SCIMCommonConstants.ENABLE_LOGIN_IDENTIFIERS)).thenReturn(enableLoginIdentifiers); when(IdentityUtil.extractDomainFromName(anyString())).thenReturn("Internal"); + mockStatic(SCIMCommonComponentHolder.class); + when(SCIMCommonComponentHolder.getApplicationRoleManager()) + .thenReturn(mockApplicationRoleManager); + when(mockApplicationRoleManager.getApplicationRolesByGroupId(anyString(), anyString())) + .thenReturn(new ArrayList<>()); + PowerMockito.whenNew(SCIMGroupHandler.class).withArguments(anyInt()).thenReturn(mockedSCIMGroupHandler); when(mockedSCIMGroupHandler.listSCIMRoles()).thenReturn(scimRoles); when(mockedSCIMGroupHandler.getGroupWithAttributes(any(Group.class), anyString()))