Skip to content
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

Get discoverable applciations from root and sub organizations #5934

Closed
wants to merge 11 commits into from
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@ private ApplicationInboundTableColumns() {
}
}

/**
* Grouping of constants related to database SP_SHARED_APP table.
*/
public static class ApplicationSPSharedTableColumns {

public static final String SHARED_IDP_ID = "SHARED_IDP_ID";
public static final String OWNER_ORG_ID = "OWNER_ORG_ID";

private ApplicationSPSharedTableColumns() {

}
Comment on lines +220 to +227
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since SP_SHARED_APP table related queries are not managed in framework, it is not recommended to redefine column names of SP_SHARED_APP here.
Hope you can't even use import the constants from other repo due to cyclic dependencies.

Can't we take an approach like this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't we define the constants in the organization-mgt-core repo and use that instead of moving the logic to the organization management repo?. Was this comment or any other concern lead to move the logic. @asha15

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I restructured the code in a way we don't need this constant anymore. However having SP_SHARED_APP related queries in framework repo will give maintainability issues. that's why we moved it to organization management repo.

}

/**
* Enums for error messages.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,10 @@
import org.wso2.carbon.identity.core.URLBuilderException;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.organization.management.service.OrganizationManagerImpl;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementServerException;
import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil;
import org.wso2.carbon.user.api.Tenant;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;
Expand Down Expand Up @@ -1225,4 +1228,31 @@ public static boolean isTrustedAppConsentRequired() {

return Boolean.parseBoolean(IdentityUtil.getProperty(TRUSTED_APP_CONSENT_REQUIRED_PROPERTY));
}

/**
* Check the given tenant is a sub org.
*
* @param tenantDomain Tenant Domain.
* @return True if the tenant is a sub organization.
* @throws OrganizationManagementException
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complete the exception description.

*/
public static boolean isSubOrg(String tenantDomain)
throws OrganizationManagementException {

return OrganizationManagementUtil.isOrganization(tenantDomain);
}

/**
* Get the parent organization id of the given organization.
*
* @param tenantDomain
* @return parent organization id
* @throws OrganizationManagementServerException
*/
public static String getParentOrgId(String tenantDomain)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the method name and comments as getPrimaryOrgId / getRootOrgId.
Parent org means the immediate org in up, but primary means the root org the tree.

throws OrganizationManagementServerException {

OrganizationManagerImpl organizationManager = new OrganizationManagerImpl();
return organizationManager.getPrimaryOrganizationId(tenantDomain);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,19 @@ default List<ApplicationBasicInfo> getDiscoverableApplicationBasicInfo(int limit
return null;
}

/**
* Get discoverable applications from root and sub org.
*
Copy link
Contributor

@SujanSanjula96 SujanSanjula96 Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

params are missing in the java doc comment

* @throws IdentityApplicationManagementException Error when obtaining discoverable applications.
*/
default List<ApplicationBasicInfo> getDiscoverableAppsInfoFromRootAndSubOrg(int limit, int offset, String filter,
String sortOrder, String sortBy, String
tenantDomain, String primaryOrgID)
Comment on lines +281 to +283
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this correctly formatted?

throws IdentityApplicationManagementException {

return null;
}

/**
* Returns basic application information of the application matching given resource Id if discoverable.
*
Expand Down Expand Up @@ -315,6 +328,21 @@ default int getCountOfDiscoverableApplications(String filter, String tenantDomai
return 0;
}

/**
* Returns the count of discoverable applications from root and sub org.
*
* @param filter Filter to search for applications (optional).
* @param tenantDomain Tenant domain.
* @param primaryOrgId Primary organization ID.
* @return Count of discoverable applications.
* @throws IdentityApplicationManagementException
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

complete the exception description

*/
default int getCountOfDiscoverableAppsFromRootAndSubOrg(String filter, String tenantDomain, String primaryOrgId)
throws IdentityApplicationManagementException {

return 0;
}

/**
* Method that can be run after updating components related to the service provider. Contains post application
* dependency update tasks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5904,6 +5904,109 @@ public List<ApplicationBasicInfo> getDiscoverableApplicationBasicInfo(int limit,
return Collections.unmodifiableList(applicationBasicInfoList);
}

@Override
public List<ApplicationBasicInfo> getDiscoverableAppsInfoFromRootAndSubOrg(int limit, int offset, String filter,
String sortOrder, String sortBy,
String tenantDomain, String primaryOrgID)
throws IdentityApplicationManagementException {

if (log.isDebugEnabled()) {
log.debug("Retrieving application basic information of discoverable applications for limit: " + limit +
" offset: " + offset + " filter: " + filter + " sortOrder: " + sortOrder + " sortBy: " + sortBy +
" in tenantDomain: " + tenantDomain);
}

validateForUnImplementedSortingAttributes(sortOrder, sortBy);
validateAttributesForPagination(offset, limit);

// TODO: 11/5/19 : Enforce a max limit
Copy link
Contributor

@SujanSanjula96 SujanSanjula96 Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

11/5/19 is a date it seems and shall we update that

if (StringUtils.isBlank(filter) || ASTERISK.equals(filter)) {
return getDiscoverableAppsInfoFromRootAndSubOrg(limit, offset, tenantDomain, primaryOrgID);
}

String filterResolvedForSQL = resolveSQLFilter(filter);

List<ApplicationBasicInfo> applicationBasicInfoList = new ArrayList<>();

try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {
String databaseVendorType = connection.getMetaData().getDatabaseProductName();

try (NamedPreparedStatement statement =
new NamedPreparedStatement(connection,
getDBQueryForDiscoverableAppsByName(databaseVendorType))) {
statement.setString(1, tenantDomain);
statement.setString(2, filterResolvedForSQL);
statement.setString(3, primaryOrgID);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
statement.setString(3, primaryOrgID);
statement.setString(3, primaryOrgID);

statement.setInt(4, offset);
statement.setInt(5, limit);

try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
applicationBasicInfoList.add(buildApplicationBasicInfo(resultSet));
}
}
}
} catch (SQLException e) {
throw new IdentityApplicationManagementServerException("Error while getting application basic information" +
" for discoverable applications in tenantDomain: " + tenantDomain, e);
}

return Collections.unmodifiableList(applicationBasicInfoList);
}

private List<ApplicationBasicInfo> getDiscoverableAppsInfoFromRootAndSubOrg(int limit, int offset, String
tenantDomain, String primaryOrgId) throws IdentityApplicationManagementException {

List<ApplicationBasicInfo> applicationBasicInfoList = new ArrayList<>();

try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {
String databaseVendorType = connection.getMetaData().getDatabaseProductName();

try (NamedPreparedStatement statement =
new NamedPreparedStatement(connection,
getVendorSpecificDiscoverableAppsQueryForRootAndSubOrg(databaseVendorType))) {
statement.setString(1, tenantDomain);
statement.setString(2, primaryOrgId);
statement.setInt(3, offset);
statement.setInt(4, limit);

try (ResultSet resultSet = statement.executeQuery()) {
while (resultSet.next()) {
applicationBasicInfoList.add(buildApplicationBasicInfo(resultSet));
}
}
}
} catch (SQLException e) {
throw new IdentityApplicationManagementServerException("Error while getting application basic information" +
" for discoverable applications in tenantDomain: " + tenantDomain, e);
}

return Collections.unmodifiableList(applicationBasicInfoList);
}

private String getVendorSpecificDiscoverableAppsQueryForRootAndSubOrg(String dbVendorType) throws
IdentityApplicationManagementException {

if ("MySQL".equals(dbVendorType)
|| "MariaDB".equals(dbVendorType)
|| "H2".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_MYSQL;
} else if ("Oracle".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_ORACLE;
} else if ("Microsoft SQL Server".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_MSSQL;
} else if ("PostgreSQL".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_POSTGRES;
} else if (dbVendorType != null && dbVendorType.contains("DB2")) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_DB2;
} else if ("INFORMIX".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_INFORMIX;
}

throw new IdentityApplicationManagementException("Error while loading discoverable applications from " +
"DB. Database driver for " + dbVendorType + "could not be identified or not supported.");
}

@Override
public int getCountOfDiscoverableApplications(String filter, String tenantDomain) throws
IdentityApplicationManagementException {
Expand Down Expand Up @@ -5941,6 +6044,69 @@ public int getCountOfDiscoverableApplications(String filter, String tenantDomain
return count;
}

@Override
public int getCountOfDiscoverableAppsFromRootAndSubOrg(String filter, String tenantDomain, String primaryOrgId)
throws IdentityApplicationManagementException {

if (log.isDebugEnabled()) {
log.debug("Getting count of discoverable applications matching filter: " + filter + " in tenantDomain: "
+ tenantDomain);
}

if (StringUtils.isBlank(filter) || ASTERISK.equals(filter)) {
return getCountOfDiscoverableAppsFromRootAndSubOrg(tenantDomain, primaryOrgId);
}

int count = 0;
String filterResolvedForSQL = resolveSQLFilter(filter);
try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {

try (NamedPreparedStatement statement =
new NamedPreparedStatement(connection, ApplicationMgtDBQueries
.LOAD_DISCOVERABLE_APP_COUNT_FROM_ROOT_AND_SUBORG_BY_APP_NAME)) {
statement.setString(1, tenantDomain);
statement.setString(2, filterResolvedForSQL);
statement.setString(3, primaryOrgId);

try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
count = resultSet.getInt(1);
}
}
}
} catch (SQLException e) {
throw new IdentityApplicationManagementServerException("Error while getting count of discoverable " +
"applications matching filter:" + filter + " in tenantDomain: " + tenantDomain, e);
}

return count;
}

private int getCountOfDiscoverableAppsFromRootAndSubOrg(String tenantDomain, String primaryOrgId)
throws IdentityApplicationManagementException {

int count;
try (Connection connection = IdentityDatabaseUtil.getDBConnection(false)) {

try (NamedPreparedStatement statement =
new NamedPreparedStatement(connection,
ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APP_COUNT_BY_ROOT_AND_SUBORG)) {
statement.setString(1, tenantDomain);
statement.setString(2, primaryOrgId);

try (ResultSet resultSet = statement.executeQuery()) {
resultSet.next();
count = resultSet.getInt(1);
}
}
} catch (SQLException e) {
throw new IdentityApplicationManagementServerException("Error while getting count of discoverable " +
"applications in tenantDomain: " + tenantDomain, e);
}

return count;
}

@Override
public ApplicationBasicInfo getDiscoverableApplicationBasicInfoByResourceId(String resourceId, String
tenantDomain) throws IdentityApplicationManagementException {
Expand Down Expand Up @@ -6215,6 +6381,30 @@ private String getDBVendorSpecificDiscoverableAppRetrievalQueryByAppName(String
"DB. Database driver for " + dbVendorType + "could not be identified or not supported.");
}

private String getDBQueryForDiscoverableAppsByName(String dbVendorType) throws
IdentityApplicationManagementException {

if ("MySQL".equals(dbVendorType)
|| "MariaDB".equals(dbVendorType)
|| "H2".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_BY_APP_NAME_MYSQL;
} else if ("Oracle".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_BY_APP_NAME_ORACLE;
} else if ("Microsoft SQL Server".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_BY_APP_NAME_MSSQL;
} else if ("PostgreSQL".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_BY_APP_NAME_POSTGRES;
} else if (dbVendorType != null && dbVendorType.contains("DB2")) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_BY_APP_NAME_DB2;
} else if ("INFORMIX".equals(dbVendorType)) {
return ApplicationMgtDBQueries.LOAD_DISCOVERABLE_APPS_FROM_ROOT_AND_SUBORG_BY_APP_NAME_INFORMIX;
}

throw new IdentityApplicationManagementException("Error while loading discoverable applications from " +
"DB. Database driver for " + dbVendorType + "could not be identified or not supported.");

}

private String getDBVendorSpecificDiscoverableAppRetrievalQuery(String dbVendorType) throws
IdentityApplicationManagementException {

Expand Down
Loading
Loading