Skip to content

Commit

Permalink
Merge pull request #190 from AnuradhaSK/add-shared-roles
Browse files Browse the repository at this point in the history
Trigger events on shared application mgt operations and add new service to return shared app data
  • Loading branch information
AnuradhaSK authored Feb 20, 2023
2 parents a5ab428 + 2f19f5b commit 1965915
Show file tree
Hide file tree
Showing 9 changed files with 542 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
org.wso2.carbon.identity.event.handler; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.event.event; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.event; version="${carbon.identity.package.import.version.range}",
org.wso2.carbon.identity.event.services; version="${carbon.identity.package.import.version.range}",
</Import-Package>
</instructions>
</configuration>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.wso2.carbon.identity.organization.management.application;

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.service.exception.OrganizationManagementException;
import org.wso2.carbon.identity.organization.management.service.model.BasicOrganization;

Expand Down Expand Up @@ -63,6 +64,17 @@ void deleteSharedApplication(String organizationId, String applicationId, String
List<BasicOrganization> getApplicationSharedOrganizations(String ownerOrgId, String mainAppId)
throws OrganizationManagementException;

/**
* Returns the shared applications list of a given primary application, along with their organizations.
*
* @param ownerOrgId ID of the organization owning the primary application.
* @param mainAppId UUID of the primary application.
* @return A list of shared applications details.
* @throws OrganizationManagementException on errors occurred while retrieving the list of shared applications.
*/
List<SharedApplication> getSharedApplications(String ownerOrgId, String mainAppId)
throws OrganizationManagementException;

/**
* Resolve the shared application id based on the organization link and the identifier of the main application.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
import org.wso2.carbon.identity.oauth.dto.ScopeDTO;
import org.wso2.carbon.identity.organization.management.application.dao.OrgApplicationMgtDAO;
import org.wso2.carbon.identity.organization.management.application.internal.OrgApplicationMgtDataHolder;
import org.wso2.carbon.identity.organization.management.application.listener.ApplicationSharingManagerListener;
import org.wso2.carbon.identity.organization.management.application.model.SharedApplication;
import org.wso2.carbon.identity.organization.management.application.model.SharedApplicationDO;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
Expand Down Expand Up @@ -242,15 +244,21 @@ public void deleteSharedApplication(String organizationId, String applicationId,
ServiceProvider serviceProvider = getOrgApplication(applicationId, getTenantDomain());

if (sharedOrganizationId == null) {

getListener().preDeleteAllSharedApplications(organizationId, applicationId);
// Delete share for all shared applications.
List<SharedApplicationDO> sharedApplicationDOList =
getOrgApplicationMgtDAO().getSharedApplications(organizationId, applicationId);
for (SharedApplicationDO sharedApplicationDO : sharedApplicationDOList) {
IdentityUtil.threadLocalProperties.get().put(DELETE_SHARE_FOR_MAIN_APPLICATION, true);
deleteSharedApplication(serviceProvider, organizationId, sharedApplicationDO.getOrganizationId());
Optional<String> sharedApplicationId =
resolveSharedApp(serviceProvider.getApplicationResourceId(), organizationId,
sharedApplicationDO.getOrganizationId());
if (sharedApplicationId.isPresent()) {
deleteSharedApplication(sharedApplicationDO.getOrganizationId(), sharedApplicationId.get());
}
IdentityUtil.threadLocalProperties.get().remove(DELETE_SHARE_FOR_MAIN_APPLICATION);
}
getListener().postDeleteAllSharedApplications(organizationId, applicationId, sharedApplicationDOList);
if (Arrays.stream(serviceProvider.getSpProperties()).anyMatch(p ->
SHARE_WITH_ALL_CHILDREN.equals(p.getName()) && Boolean.parseBoolean(p.getValue()))) {
setShareWithAllChildrenProperty(serviceProvider, false);
Expand All @@ -265,48 +273,51 @@ public void deleteSharedApplication(String organizationId, String applicationId,
}
}
} else {
getListener().preDeleteSharedApplication(organizationId, applicationId, sharedOrganizationId);
if (Arrays.stream(serviceProvider.getSpProperties())
.anyMatch(p -> SHARE_WITH_ALL_CHILDREN.equals(p.getName()) && Boolean.parseBoolean(p.getValue()))) {
throw handleClientException(ERROR_CODE_INVALID_DELETE_SHARE_REQUEST,
serviceProvider.getApplicationResourceId(), sharedOrganizationId);
}
deleteSharedApplication(serviceProvider, organizationId, sharedOrganizationId);
Optional<String> sharedApplicationId =
resolveSharedApp(serviceProvider.getApplicationResourceId(), organizationId, sharedOrganizationId);
if (sharedApplicationId.isPresent()) {
deleteSharedApplication(sharedOrganizationId, sharedApplicationId.get());
getListener().postDeleteSharedApplication(organizationId, applicationId, sharedOrganizationId,
sharedApplicationId.get());
}
}
}

private void deleteSharedApplication(ServiceProvider serviceProvider, String organizationId,
String sharedOrganizationId) throws OrganizationManagementException {

Optional<String> fragmentApplicationId =
resolveSharedApp(serviceProvider.getApplicationResourceId(), organizationId, sharedOrganizationId);
private void deleteSharedApplication(String sharedOrganizationId, String sharedApplicationId)
throws OrganizationManagementException {

if (fragmentApplicationId.isPresent()) {
try {
String sharedTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationId);
ServiceProvider fragmentApplication =
getApplicationManagementService().getApplicationByResourceId(fragmentApplicationId.get(),
sharedTenantDomain);
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();

// Setting the thread local property to allow deleting fragment application. Otherwise
// FragmentApplicationMgtListener will reject application deletion.
IdentityUtil.threadLocalProperties.get().put(DELETE_FRAGMENT_APPLICATION, true);
getApplicationManagementService().deleteApplication(fragmentApplication.getApplicationName(),
sharedTenantDomain, username);
} catch (IdentityApplicationManagementException e) {
throw handleServerException(ERROR_CODE_ERROR_REMOVING_FRAGMENT_APP, e, fragmentApplicationId.get(),
sharedOrganizationId);
} finally {
IdentityUtil.threadLocalProperties.get().remove(DELETE_FRAGMENT_APPLICATION);
IdentityUtil.threadLocalProperties.get().remove(DELETE_SHARE_FOR_MAIN_APPLICATION);
}
try {
String sharedTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrganizationId);
ServiceProvider sharedApplication =
getApplicationManagementService().getApplicationByResourceId(sharedApplicationId,
sharedTenantDomain);
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();

// Setting the thread local property to allow deleting fragment application. Otherwise
// FragmentApplicationMgtListener will reject application deletion.
IdentityUtil.threadLocalProperties.get().put(DELETE_FRAGMENT_APPLICATION, true);
getApplicationManagementService().deleteApplication(sharedApplication.getApplicationName(),
sharedTenantDomain, username);
} catch (IdentityApplicationManagementException e) {
throw handleServerException(ERROR_CODE_ERROR_REMOVING_FRAGMENT_APP, e, sharedApplicationId,
sharedOrganizationId);
} finally {
IdentityUtil.threadLocalProperties.get().remove(DELETE_FRAGMENT_APPLICATION);
IdentityUtil.threadLocalProperties.get().remove(DELETE_SHARE_FOR_MAIN_APPLICATION);
}
}

@Override
public List<BasicOrganization> getApplicationSharedOrganizations(String organizationId, String applicationId)
throws OrganizationManagementException {

getListener().preGetApplicationSharedOrganizations(organizationId, applicationId);
ServiceProvider application = getOrgApplication(applicationId, getTenantDomain());
List<SharedApplicationDO> sharedApps =
getOrgApplicationMgtDAO().getSharedApplications(organizationId, application.getApplicationResourceId());
Expand All @@ -315,9 +326,27 @@ public List<BasicOrganization> getApplicationSharedOrganizations(String organiza
Collectors.toList());

List<BasicOrganization> organizations = getOrganizationManager().getChildOrganizations(organizationId, true);
List<BasicOrganization> applicationSharedOrganizationsList =
organizations.stream().filter(o -> sharedOrganizationIds.contains(o.getId())).collect(
Collectors.toList());
getListener().postGetApplicationSharedOrganizations(organizationId, applicationId,
applicationSharedOrganizationsList);
return applicationSharedOrganizationsList;
}

return organizations.stream().filter(o -> sharedOrganizationIds.contains(o.getId())).collect(
Collectors.toList());
@Override
public List<SharedApplication> getSharedApplications(String organizationId, String applicationId)
throws OrganizationManagementException {

getListener().preGetSharedApplications(organizationId, applicationId);
ServiceProvider application = getOrgApplication(applicationId, getTenantDomain());
List<SharedApplicationDO> sharedApplicationDOList =
getOrgApplicationMgtDAO().getSharedApplications(organizationId, application.getApplicationResourceId());
List<SharedApplication> sharedApplications = sharedApplicationDOList.stream()
.map(sharedAppDO -> new SharedApplication(sharedAppDO.getFragmentApplicationId(),
sharedAppDO.getOrganizationId())).collect(Collectors.toList());
getListener().postGetSharedApplications(organizationId, applicationId, sharedApplications);
return sharedApplications;
}

@Override
Expand Down Expand Up @@ -501,6 +530,8 @@ public void shareApplication(String ownerOrgId, String sharedOrgId, ServiceProvi
boolean shareWithAllChildren) throws OrganizationManagementException {

try {
getListener().preShareApplication(ownerOrgId, mainApplication.getApplicationResourceId(), sharedOrgId,
shareWithAllChildren);
// Use tenant of the organization to whom the application getting shared. When the consumer application is
// loaded, tenant domain will be derived from the user who created the application.
String sharedTenantDomain = getOrganizationManager().resolveTenantDomain(sharedOrgId);
Expand Down Expand Up @@ -543,10 +574,10 @@ public void shareApplication(String ownerOrgId, String sharedOrgId, ServiceProvi
throw handleServerException(ERROR_CODE_ERROR_CREATING_OAUTH_APP, e,
mainApplication.getApplicationResourceId(), sharedOrgId);
}

String sharedApplicationId;
try {
ServiceProvider delegatedApplication = prepareSharedApplication(mainApplication, createdOAuthApp);
String sharedApplicationId = getApplicationManagementService().createApplication(delegatedApplication,
sharedApplicationId = getApplicationManagementService().createApplication(delegatedApplication,
sharedOrgId, getAuthenticatedUsername());
getOrgApplicationMgtDAO().addSharedApplication(mainApplication.getApplicationResourceId(), ownerOrgId,
sharedApplicationId, sharedOrgId, shareWithAllChildren);
Expand All @@ -555,6 +586,8 @@ public void shareApplication(String ownerOrgId, String sharedOrgId, ServiceProvi
throw handleServerException(ERROR_CODE_ERROR_SHARING_APPLICATION, e,
mainApplication.getApplicationResourceId(), sharedOrgId);
}
getListener().postShareApplication(ownerOrgId, mainApplication.getApplicationResourceId(), sharedOrgId,
sharedApplicationId, shareWithAllChildren);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
Expand Down Expand Up @@ -758,4 +791,9 @@ private ServiceProvider getDefaultServiceProvider() throws OrganizationManagemen
throw new OrganizationManagementServerException("Error while retrieving default service provider", null, e);
}
}

private ApplicationSharingManagerListener getListener() {

return OrgApplicationMgtDataHolder.getInstance().getApplicationSharingManagerListener();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,28 @@ public class OrgApplicationMgtConstants {
public static final String UPDATE_SP_METADATA_SHARE_WITH_ALL_CHILDREN = "updateShareWithAllChildren";
public static final String DELETE_SHARE_FOR_MAIN_APPLICATION = "deleteShareForMainApp";

public static final String USER_ORGANIZATION_CLAIM_URI = "http://wso2.org/claims/runtime/user_organization";
public static final String USER_ORGANIZATION_CLAIM_URI = "http://wso2.org/claims/runtime/user_organization";
public static final String USER_ORGANIZATION_CLAIM = "user_organization";
public static final String OIDC_CLAIM_DIALECT_URI = "http://wso2.org/oidc/claim";

// Event constants related to shared application management.
public static final String EVENT_PROP_PARENT_ORGANIZATION_ID = "PARENT_ORGANIZATION_ID";
public static final String EVENT_PROP_SHARED_ORGANIZATION_ID = "SHARED_ORGANIZATION_ID";
public static final String EVENT_PROP_PARENT_APPLICATION_ID = "PARENT_APPLICATION_ID";
public static final String EVENT_PROP_SHARED_APPLICATION_ID = "SHARED_APPLICATION_ID";
public static final String EVENT_PROP_SHARED_APPLICATIONS_DATA = "SHARED_APPLICATIONS_DATA";
public static final String EVENT_PROP_SHARE_WITH_ALL_CHILDREN = "SHARE_WITH_ALL_CHILDREN";
public static final String EVENT_PROP_SHARED_ORGANIZATIONS = "SHARED_ORGANIZATIONS";
public static final String EVENT_PRE_SHARE_APPLICATION = "PRE_SHARE_APPLICATION";
public static final String EVENT_POST_SHARE_APPLICATION = "POST_SHARE_APPLICATION";
public static final String EVENT_PRE_DELETE_SHARED_APPLICATION = "PRE_DELETE_SHARED_APPLICATION";
public static final String EVENT_POST_DELETE_SHARED_APPLICATION = "POST_DELETE_SHARED_APPLICATION";
public static final String EVENT_PRE_DELETE_ALL_SHARED_APPLICATIONS = "PRE_DELETE_ALL_SHARED_APPLICATIONS";
public static final String EVENT_POST_DELETE_ALL_SHARED_APPLICATIONS = "POST_DELETE_ALL_SHARED_APPLICATIONS";
public static final String EVENT_PRE_GET_APPLICATION_SHARED_ORGANIZATIONS =
"PRE_GET_APPLICATION_SHARED_ORGANIZATIONS";
public static final String EVENT_POST_GET_APPLICATION_SHARED_ORGANIZATIONS =
"POST_GET_APPLICATION_SHARED_ORGANIZATIONS";
public static final String EVENT_PRE_GET_SHARED_APPLICATIONS = "PRE_GET_SHARED_APPLICATIONS";
public static final String EVENT_POST_GET_SHARED_APPLICATIONS = "POST_GET_SHARED_APPLICATIONS";
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@

import org.wso2.carbon.identity.application.mgt.ApplicationManagementService;
import org.wso2.carbon.identity.claim.metadata.mgt.ClaimMetadataManagementService;
import org.wso2.carbon.identity.event.services.IdentityEventService;
import org.wso2.carbon.identity.oauth.OAuthAdminServiceImpl;
import org.wso2.carbon.identity.organization.management.application.dao.OrgApplicationMgtDAO;
import org.wso2.carbon.identity.organization.management.application.listener.ApplicationSharingManagerListener;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;
import org.wso2.carbon.identity.organization.management.service.OrganizationUserResidentResolverService;
import org.wso2.carbon.idp.mgt.IdpManager;
Expand All @@ -42,6 +44,8 @@ public class OrgApplicationMgtDataHolder {
private OrganizationManager organizationManager;
private OrganizationUserResidentResolverService organizationUserResidentResolverService;
private IdpManager idpManager;
private ApplicationSharingManagerListener applicationSharingManagerListener;
private IdentityEventService identityEventService;

private ClaimMetadataManagementService claimMetadataManagementService;
private OrgApplicationMgtDataHolder() {
Expand Down Expand Up @@ -203,4 +207,45 @@ public void setClaimMetadataManagementService(ClaimMetadataManagementService cla

this.claimMetadataManagementService = claimMetadataManagementService;
}

/**
* Get {@link ApplicationSharingManagerListener}.
*
* @return Application sharing manager listener.
*/
public ApplicationSharingManagerListener getApplicationSharingManagerListener() {

return applicationSharingManagerListener;
}

/**
* Set {@link ApplicationSharingManagerListener}.
*
* @param applicationSharingManagerListener Instance of {@link ApplicationSharingManagerListener}.
*/
public void setApplicationSharingManagerListener(
ApplicationSharingManagerListener applicationSharingManagerListener) {

this.applicationSharingManagerListener = applicationSharingManagerListener;
}

/**
* Get {@link IdentityEventService}.
*
* @return IdentityEventService.
*/
public IdentityEventService getIdentityEventService() {

return identityEventService;
}

/**
* Set {@link IdentityEventService}.
*
* @param identityEventService Instance of {@link IdentityEventService}.
*/
public void setIdentityEventService(IdentityEventService identityEventService) {

this.identityEventService = identityEventService;
}
}
Loading

0 comments on commit 1965915

Please sign in to comment.