diff --git a/components/org.wso2.carbon.identity.organization.user.invitation.management/pom.xml b/components/org.wso2.carbon.identity.organization.user.invitation.management/pom.xml index 8a15d7ba6..f3b1ac81a 100644 --- a/components/org.wso2.carbon.identity.organization.user.invitation.management/pom.xml +++ b/components/org.wso2.carbon.identity.organization.user.invitation.management/pom.xml @@ -64,6 +64,14 @@ org.wso2.carbon.identity.framework org.wso2.carbon.identity.event + + org.wso2.carbon.identity.organization.management + org.wso2.carbon.identity.organization.management.role.management.service + + + org.wso2.carbon.identity.framework + org.wso2.carbon.identity.role.v2.mgt.core + org.testng @@ -131,12 +139,15 @@ org.wso2.carbon.identity.organization.management.service.constant; version="${org.wso2.identity.organization.mgt.core.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.identity.organization.management.service.exception;version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", + org.wso2.carbon.identity.organization.management.role.management.service;version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", org.wso2.carbon.user.api;version="${carbon.user.api.imp.pkg.version.range}", org.wso2.carbon.user.core;version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.user.core.common;version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.user.core.listener;version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.user.core.service;version="${carbon.kernel.package.import.version.range}", org.wso2.carbon.user.core.util;version="${carbon.kernel.package.import.version.range}", + org.wso2.carbon.identity.role.v2.mgt.core;version="${carbon.identity.package.import.version.range}", + org.wso2.carbon.identity.role.v2.mgt.core.exception;version="${carbon.identity.package.import.version.range}", org.wso2.carbon.identity.organization.management.organization.user.sharing;version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", org.wso2.carbon.identity.organization.management.organization.user.sharing.constant;version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", org.wso2.carbon.identity.organization.management.organization.user.sharing.models;version="${org.wso2.identity.organization.mgt.imp.pkg.version.range}", diff --git a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/InvitationCoreServiceImpl.java b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/InvitationCoreServiceImpl.java index a3816e5e9..4d1d508de 100644 --- a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/InvitationCoreServiceImpl.java +++ b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/InvitationCoreServiceImpl.java @@ -29,6 +29,8 @@ import org.wso2.carbon.identity.event.IdentityEventException; import org.wso2.carbon.identity.event.event.Event; import org.wso2.carbon.identity.organization.management.organization.user.sharing.OrganizationUserSharingService; +import org.wso2.carbon.identity.organization.management.organization.user.sharing.OrganizationUserSharingServiceImpl; +import org.wso2.carbon.identity.organization.management.organization.user.sharing.internal.OrganizationUserSharingDataHolder; import org.wso2.carbon.identity.organization.management.organization.user.sharing.util.OrganizationSharedUserUtil; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException; @@ -41,6 +43,8 @@ import org.wso2.carbon.identity.organization.user.invitation.management.internal.UserInvitationMgtDataHolder; import org.wso2.carbon.identity.organization.user.invitation.management.models.Invitation; import org.wso2.carbon.identity.organization.user.invitation.management.models.RoleAssignments; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; +import org.wso2.carbon.identity.role.v2.mgt.core.exception.IdentityRoleManagementException; import org.wso2.carbon.user.api.UserRealm; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.common.AbstractUserStoreManager; @@ -50,7 +54,9 @@ import java.security.SecureRandom; import java.sql.Timestamp; import java.time.Instant; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -78,6 +84,7 @@ import static org.wso2.carbon.identity.organization.user.invitation.management.constant.UserInvitationMgtConstants.ErrorMessage.ERROR_CODE_INVALID_CONFIRMATION_CODE; import static org.wso2.carbon.identity.organization.user.invitation.management.constant.UserInvitationMgtConstants.ErrorMessage.ERROR_CODE_INVALID_FILTER; import static org.wso2.carbon.identity.organization.user.invitation.management.constant.UserInvitationMgtConstants.ErrorMessage.ERROR_CODE_INVALID_INVITATION_ID; +import static org.wso2.carbon.identity.organization.user.invitation.management.constant.UserInvitationMgtConstants.ErrorMessage.ERROR_CODE_INVALID_ROLE; import static org.wso2.carbon.identity.organization.user.invitation.management.constant.UserInvitationMgtConstants.ErrorMessage.ERROR_CODE_INVITATION_EXPIRED; import static org.wso2.carbon.identity.organization.user.invitation.management.constant.UserInvitationMgtConstants.ErrorMessage.ERROR_CODE_NO_INVITATION_FOR_USER; import static org.wso2.carbon.identity.organization.user.invitation.management.constant.UserInvitationMgtConstants.ErrorMessage.ERROR_CODE_UNABLE_TO_RESEND_INVITATION; @@ -107,6 +114,8 @@ public Invitation createInvitation(Invitation invitation) throws UserInvitationM String organizationId = Utils.getOrganizationId(); OrganizationManager organizationManager = UserInvitationMgtDataHolder.getInstance() .getOrganizationManagerService(); + RoleManagementService roleManagementService = UserInvitationMgtDataHolder.getInstance() + .getRoleManagementService(); Invitation createdInvitation; try { // Checking the parent organization id @@ -125,6 +134,7 @@ public Invitation createInvitation(Invitation invitation) throws UserInvitationM String.format(ERROR_CODE_ACTIVE_INVITATION_EXISTS.getDescription(), invitation.getUsername())); } int parentTenantId = IdentityTenantUtil.getTenantId(parentTenantDomain); + String invitedTenantDomain = organizationManager.resolveTenantDomain(organizationId); AbstractUserStoreManager userStoreManager = getAbstractUserStoreManager(parentTenantId); String userDomainQualifiedUserName = UserCoreUtil .addDomainToName(invitation.getUsername(), invitation.getUserDomain()); @@ -141,8 +151,19 @@ public Invitation createInvitation(Invitation invitation) throws UserInvitationM invitation.setInvitedOrganizationId(organizationId); invitation.setStatus(STATUS_PENDING); if (ArrayUtils.isNotEmpty(invitation.getRoleAssignments())) { - // ToDO : Check the role existence by introducing a role validation service. - + for (RoleAssignments roleAssignments : invitation.getRoleAssignments()) { + String[] roles = roleAssignments.getRoles(); + for (String roleId : roles) { + if (!roleManagementService.isExistingRole(roleId, invitedTenantDomain)) { + LOG.error("Role: " + roleId + " is not exists in the organization: " + + organizationId); + throw new UserInvitationMgtClientException(ERROR_CODE_INVALID_ROLE.getCode(), + ERROR_CODE_INVALID_ROLE.getMessage(), + String.format(ERROR_CODE_INVALID_ROLE.getDescription(), roleId)); + } + } + } + invitation.setRoleAssignments(invitation.getRoleAssignments()); } invitation.setInvitationId(UUID.randomUUID().toString()); invitation.setConfirmationCode(UUID.randomUUID().toString()); @@ -150,7 +171,7 @@ public Invitation createInvitation(Invitation invitation) throws UserInvitationM createdInvitation = userInvitationDAO.getInvitationByInvitationId(invitation.getInvitationId()); // Trigger the event for invitation creation triggerInvitationAddNotification(createdInvitation); - } catch (UserStoreException | OrganizationManagementException e) { + } catch (UserStoreException | OrganizationManagementException | IdentityRoleManagementException e) { throw new UserInvitationMgtServerException(ERROR_CODE_CREATE_INVITATION.getCode(), ERROR_CODE_CREATE_INVITATION.getMessage(), String.format(ERROR_CODE_CREATE_INVITATION.getDescription(), invitation.getUsername()), e); @@ -165,8 +186,11 @@ public boolean acceptInvitation(String confirmationCode) throws UserInvitationMg if (invitation != null) { if (invitation.getExpiredAt().getTime() > Instant.now().toEpochMilli()) { try { + OrganizationUserSharingService userSharingService = new OrganizationUserSharingServiceImpl(); OrganizationManager organizationManager = UserInvitationMgtDataHolder.getInstance() .getOrganizationManagerService(); + RoleManagementService roleManagementService = OrganizationUserSharingDataHolder.getInstance() + .getRoleManagementService(); String invitedOrganizationId = invitation.getInvitedOrganizationId(); String invitedTenantDomain = organizationManager.resolveTenantDomain(invitedOrganizationId); int invitedTenantId = IdentityTenantUtil.getTenantId(invitedTenantDomain); @@ -187,13 +211,34 @@ public boolean acceptInvitation(String confirmationCode) throws UserInvitationMg String userId = getInvitedUserId(invitation); getOrganizationUserSharingService().shareOrganizationUser(invitedOrganizationId, userId, invitation.getUserOrganizationId()); + String associatedUserId = userSharingService + .getUserAssociationOfAssociatedUserByOrgId(userId, invitedOrganizationId).getUserId(); // Trigger event to add the role assignments if any available in the invitation. if (ArrayUtils.isNotEmpty(invitation.getRoleAssignments())) { - // Get the available group name for the group in the invited organization. - String availableGroupName = getAvailableGroupName(); - userStoreManager.addRole(availableGroupName, new String[]{invitation.getUserDomain()}, null); - triggerRoleAssignmentEvent(invitedOrganizationId, availableGroupName, - Arrays.asList(invitation.getRoleAssignments())); + ArrayList availableRoleNames = new ArrayList(); + for (RoleAssignments roleAssignments : invitation.getRoleAssignments()) { + String[] roles = roleAssignments.getRoles(); + for (String roleId : roles) { + if (roleManagementService.isExistingRole(roleId, invitedTenantDomain)) { + availableRoleNames.add(roleId); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Role: " + roleId + " is not exist in the invitedTenantDomain : " + + invitedTenantDomain); + } + } + } + } + availableRoleNames.forEach((role) -> { + try { + roleManagementService.updateUserListOfRole(role, + Collections.singletonList(associatedUserId), Collections.emptyList(), + invitedTenantDomain); + } catch (IdentityRoleManagementException e) { + LOG.error("An error occurred while assigning the role: " + + role + " to the user: " + associatedUserId); + } + }); } // Removing the invitation since the user is added to the organization. if (LOG.isDebugEnabled()) { @@ -203,7 +248,7 @@ public boolean acceptInvitation(String confirmationCode) throws UserInvitationMg } userInvitationDAO.deleteInvitation(invitation.getInvitationId()); return true; - } catch (UserStoreException | OrganizationManagementException e) { + } catch (UserStoreException | OrganizationManagementException | IdentityRoleManagementException e) { UserCoreUtil.removeSkipPasswordPatternValidationThreadLocal(); throw new UserInvitationMgtServerException(ERROR_CODE_ACCEPT_INVITATION.getCode(), ERROR_CODE_ACCEPT_INVITATION.getMessage(), diff --git a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/constant/UserInvitationMgtConstants.java b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/constant/UserInvitationMgtConstants.java index ff0473aeb..da1c87026 100644 --- a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/constant/UserInvitationMgtConstants.java +++ b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/constant/UserInvitationMgtConstants.java @@ -120,6 +120,9 @@ public enum ErrorMessage { ERROR_CODE_INVALID_USER("10028", "Invalid user identification provided.", "Authenticated user %s is not entitled for the invitation."), + ERROR_CODE_INVALID_ROLE("10029", + "Invalid role identification provided.", + "Could not find a role with given roleId %s."), // DAO layer errors ERROR_CODE_STORE_INVITATION("10501", diff --git a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtDataHolder.java b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtDataHolder.java index e985a848b..6bb2e7f80 100644 --- a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtDataHolder.java +++ b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtDataHolder.java @@ -21,6 +21,7 @@ import org.wso2.carbon.identity.event.services.IdentityEventService; import org.wso2.carbon.identity.organization.management.organization.user.sharing.OrganizationUserSharingService; import org.wso2.carbon.identity.organization.management.service.OrganizationManager; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; import org.wso2.carbon.user.core.service.RealmService; /** @@ -34,6 +35,7 @@ public class UserInvitationMgtDataHolder { private IdentityEventService identityEventService; private OrganizationManager organizationManager; private OrganizationUserSharingService organizationUserSharingService; + private RoleManagementService roleManagementService; public static UserInvitationMgtDataHolder getInstance() { @@ -80,4 +82,24 @@ public void setOrganizationUserSharingService( this.organizationUserSharingService = organizationUserSharingService; } + + /** + * Get the organization role manager service. + * + * @return Organization role manager service. + */ + public RoleManagementService getRoleManagementService() { + + return roleManagementService; + } + + /** + * Set the organization role manager service. + * + * @param roleManagementService Organization role manager service. + */ + public void setRoleManagementService(RoleManagementService roleManagementService) { + + this.roleManagementService = roleManagementService; + } } diff --git a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtServiceComponent.java b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtServiceComponent.java index bd05edbce..4ccb561eb 100644 --- a/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtServiceComponent.java +++ b/components/org.wso2.carbon.identity.organization.user.invitation.management/src/main/java/org/wso2/carbon/identity/organization/user/invitation/management/internal/UserInvitationMgtServiceComponent.java @@ -34,6 +34,7 @@ import org.wso2.carbon.identity.organization.user.invitation.management.InvitationCoreService; import org.wso2.carbon.identity.organization.user.invitation.management.InvitationCoreServiceImpl; import org.wso2.carbon.identity.organization.user.invitation.management.handler.UserInvitationEventHandler; +import org.wso2.carbon.identity.role.v2.mgt.core.RoleManagementService; import org.wso2.carbon.user.core.service.RealmService; /** @@ -137,4 +138,20 @@ protected void unsetOrganizationUserAssociationService( UserInvitationMgtDataHolder.getInstance().setOrganizationUserSharingService(null); LOG.debug("Unset organization user association Service."); } + + @Reference( + name = "RoleManagementService", + service = RoleManagementService.class, + cardinality = ReferenceCardinality.MANDATORY, + policy = ReferencePolicy.DYNAMIC, + unbind = "unsetRoleManagementService") + protected void setRoleManagementService(RoleManagementService roleManagementService) { + + UserInvitationMgtDataHolder.getInstance().setRoleManagementService(roleManagementService); + } + + protected void unsetRoleManagementService(RoleManagementService roleManagementService) { + + UserInvitationMgtDataHolder.getInstance().setRoleManagementService(null); + } }