Skip to content

Commit

Permalink
Enable API Resources APIs for organization level
Browse files Browse the repository at this point in the history
  • Loading branch information
ShanChathusanda93 committed Oct 21, 2024
1 parent ed81688 commit 3a19343
Show file tree
Hide file tree
Showing 10 changed files with 538 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ public enum ErrorMessages {
"properties.", "Error while adding API resource properties to the database."),
ERROR_CODE_ERROR_WHILE_UPDATING_SCOPE_METADATA("65015", "Error while updating scope metadata.",
"Error while updating scope metadata in the database."),
;
ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION("65016", "Error while resolving tenant",
"Error while resolving tenant domain for organization."),;

private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,18 @@ public class SQLConstants {
"DESCRIPTION, TENANT_ID, TYPE, REQUIRES_AUTHORIZATION FROM API_RESOURCE WHERE ";
public static final String GET_API_RESOURCES_TAIL =
" (TENANT_ID = %d OR TENANT_ID IS NULL) ORDER BY CURSOR_KEY %s LIMIT %d";
public static final String GET_API_RESOURCES_TAIL_FOR_ORGANIZATIONS =
" (TENANT_ID = %d OR TENANT_ID IS NULL) AND TYPE != 'TENANT' AND TYPE != 'SYSTEM' " +
"ORDER BY CURSOR_KEY %s LIMIT %d";
public static final String GET_API_RESOURCES_TAIL_MSSQL =
" (TENANT_ID = %d OR TENANT_ID IS NULL) ORDER BY CURSOR_KEY %s";
public static final String GET_API_RESOURCES_TAIL_FOR_ORGANIZATIONS_MSSQL =
" (TENANT_ID = %d OR TENANT_ID IS NULL) AND TYPE != 'TENANT' AND TYPE != 'SYSTEM' ORDER BY CURSOR_KEY %s";
public static final String GET_API_RESOURCES_TAIL_ORACLE =
" (TENANT_ID = %d OR TENANT_ID IS NULL) ORDER BY CURSOR_KEY %s FETCH FIRST %d ROWS ONLY";
public static final String GET_API_RESOURCES_TAIL_FOR_ORGANIZATIONS_ORACLE =
" (TENANT_ID = %d OR TENANT_ID IS NULL) AND TYPE != 'TENANT' AND TYPE != 'SYSTEM' " +
"ORDER BY CURSOR_KEY %s FETCH FIRST %d ROWS ONLY";
public static final String GET_API_RESOURCES_WITH_PROPERTIES_SELECTION = "SELECT" +
" AR.ID AS API_RESOURCE_ID," +
" AR.CURSOR_KEY AS CURSOR_KEY," +
Expand Down Expand Up @@ -99,6 +107,8 @@ public class SQLConstants {
" LEFT JOIN API_RESOURCE_PROPERTY ARP ON AR.ID = ARP.API_ID ORDER BY CURSOR_KEY %s";
public static final String GET_API_RESOURCES_COUNT = "SELECT COUNT(DISTINCT(ID)) FROM API_RESOURCE WHERE ";
public static final String GET_API_RESOURCES_COUNT_TAIL = " (TENANT_ID = ? OR TENANT_ID IS NULL)";
public static final String GET_API_RESOURCES_COUNT_FOR_ORGANIZATIONS_TAIL =
" (TENANT_ID = ? OR TENANT_ID IS NULL) AND TYPE != 'TENANT' AND TYPE != 'SYSTEM'";
public static final String GET_API_RESOURCE_BY_ID = "SELECT" +
" AR.ID AS API_RESOURCE_ID," +
" AR.NAME AS API_RESOURCE_NAME," +
Expand All @@ -113,6 +123,20 @@ public class SQLConstants {
" S.DESCRIPTION AS SCOPE_DESCRIPTION" +
" FROM API_RESOURCE AR LEFT JOIN SCOPE S ON AR.ID = S.API_ID WHERE AR.ID = ? AND (AR.TENANT_ID = ?" +
" OR AR.TENANT_ID IS NULL)";
public static final String GET_API_RESOURCE_BY_ID_FOR_ORGANIZATIONS = "SELECT" +
" AR.ID AS API_RESOURCE_ID," +
" AR.NAME AS API_RESOURCE_NAME," +
" AR.IDENTIFIER AS API_RESOURCE_IDENTIFIER," +
" AR.DESCRIPTION AS API_RESOURCE_DESCRIPTION," +
" AR.TENANT_ID AS API_RESOURCE_TENANT_ID," +
" AR.TYPE AS API_RESOURCE_TYPE," +
" AR.REQUIRES_AUTHORIZATION AS REQUIRES_AUTHORIZATION," +
" S.ID AS SCOPE_ID," +
" S.NAME AS SCOPE_QUALIFIED_NAME," +
" S.DISPLAY_NAME AS SCOPE_DISPLAY_NAME," +
" S.DESCRIPTION AS SCOPE_DESCRIPTION" +
" FROM API_RESOURCE AR LEFT JOIN SCOPE S ON AR.ID = S.API_ID WHERE AR.ID = ? AND (AR.TENANT_ID = ?" +
" OR AR.TENANT_ID IS NULL) AND AR.TYPE != 'TENANT' AND AR.TYPE != 'SYSTEM'";
public static final String GET_SCOPES_BY_API_ID = "SELECT ID, NAME, DISPLAY_NAME, DESCRIPTION, API_ID, TENANT_ID "
+ "FROM SCOPE WHERE API_ID = ? AND (TENANT_ID = ? OR TENANT_ID IS NULL)";
public static final String GET_API_RESOURCE_BY_IDENTIFIER = "SELECT" +
Expand Down Expand Up @@ -151,6 +175,12 @@ public class SQLConstants {
public static final String GET_SCOPES_BY_TENANT_ID = "SELECT ID, NAME, DISPLAY_NAME, DESCRIPTION, API_ID, " +
"TENANT_ID FROM SCOPE WHERE ";
public static final String GET_SCOPES_BY_TENANT_ID_TAIL = " (TENANT_ID = ? OR TENANT_ID IS NULL)";
public static final String GET_SCOPES_BY_TENANT_ID_FOR_ORGANIZATIONS =
"SELECT SC.ID, SC.NAME, SC.DISPLAY_NAME, SC.DESCRIPTION, SC.API_ID, SC.TENANT_ID FROM SCOPE SC" +
" JOIN API_RESOURCE AR ON AR.ID = SC.API_ID" +
" WHERE ";
public static final String GET_SCOPES_BY_TENANT_ID_FOR_ORGANIZATIONS_TAIL = "(AR.TENANT_ID = ? OR AR.TENANT_ID " +
"IS NULL) AND TYPE != 'TENANT' AND TYPE != 'SYSTEM'";
public static final String DELETE_SCOPE_BY_NAME = "DELETE FROM SCOPE WHERE NAME = ? AND TENANT_ID = ?";
public static final String GET_API_RESOURCE_PROPERTIES_BY_API_ID = "SELECT ID, NAME, VALUE FROM " +
"API_RESOURCE_PROPERTY WHERE API_ID = ?";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.wso2.carbon.identity.api.resource.mgt.constant.APIResourceManagementConstants;
import org.wso2.carbon.identity.api.resource.mgt.constant.SQLConstants;
import org.wso2.carbon.identity.api.resource.mgt.dao.APIResourceManagementDAO;
import org.wso2.carbon.identity.api.resource.mgt.internal.APIResourceManagementServiceComponentHolder;
import org.wso2.carbon.identity.api.resource.mgt.model.FilterQueryBuilder;
import org.wso2.carbon.identity.api.resource.mgt.util.APIResourceManagementUtil;
import org.wso2.carbon.identity.application.common.model.APIResource;
Expand All @@ -35,6 +36,9 @@
import org.wso2.carbon.identity.core.model.ExpressionNode;
import org.wso2.carbon.identity.core.util.IdentityCoreConstants;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;
import org.wso2.carbon.identity.core.util.IdentityTenantUtil;
import org.wso2.carbon.identity.organization.management.service.exception.OrganizationManagementException;
import org.wso2.carbon.identity.organization.management.service.util.OrganizationManagementUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
Expand Down Expand Up @@ -94,6 +98,19 @@ public Integer getAPIResourcesCount(Integer tenantId, List<ExpressionNode> expre
Map<Integer, String> filterAttributeValue = filterQueryBuilder.getFilterAttributeValue();
String getAPIResourcesCountSqlStmtTail = SQLConstants.GET_API_RESOURCES_COUNT_TAIL;

try {
if (OrganizationManagementUtil.isOrganization(tenantId)) {
tenantId = getRootOrganizationTenantId(tenantId);
getAPIResourcesCountSqlStmtTail = SQLConstants.GET_API_RESOURCES_COUNT_FOR_ORGANIZATIONS_TAIL;
}
} catch (OrganizationManagementException e) {
throw new APIResourceMgtException(
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getCode(),
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getMessage(), e);
}

String sqlStmt = SQLConstants.GET_API_RESOURCES_COUNT + filterQueryBuilder.getFilterQuery() +
getAPIResourcesCountSqlStmtTail;

Expand Down Expand Up @@ -228,8 +245,21 @@ public boolean isAPIResourceExistById(String apiId, Integer tenantId) throws API
@Override
public APIResource getAPIResourceById(String apiId, Integer tenantId) throws APIResourceMgtException {

String query = SQLConstants.GET_API_RESOURCE_BY_ID;
try {
if (OrganizationManagementUtil.isOrganization(tenantId)) {
tenantId = getRootOrganizationTenantId(tenantId);
query = SQLConstants.GET_API_RESOURCE_BY_ID_FOR_ORGANIZATIONS;
}
} catch (OrganizationManagementException e) {
throw new APIResourceMgtException(
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getCode(),
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getMessage(), e);
}
try (Connection dbConnection = IdentityDatabaseUtil.getDBConnection(false);
PreparedStatement preparedStatement = dbConnection.prepareStatement(SQLConstants.GET_API_RESOURCE_BY_ID)) {
PreparedStatement preparedStatement = dbConnection.prepareStatement(query)) {
preparedStatement.setString(1, apiId);
preparedStatement.setInt(2, tenantId);
ResultSet resultSet = preparedStatement.executeQuery();
Expand Down Expand Up @@ -445,6 +475,21 @@ public List<Scope> getScopesByTenantId(Integer tenantId, List<ExpressionNode> ex
appendFilterQuery(expressionNodes, filterQueryBuilder, true);
String query = SQLConstants.GET_SCOPES_BY_TENANT_ID + filterQueryBuilder.getFilterQuery() +
SQLConstants.GET_SCOPES_BY_TENANT_ID_TAIL;
try {
if (OrganizationManagementUtil.isOrganization(tenantId)) {
FilterQueryBuilder filterQueryBuilderForOrg = new FilterQueryBuilder();
appendFilterQueryForOrganizations(expressionNodes, filterQueryBuilderForOrg, true);
tenantId = getRootOrganizationTenantId(tenantId);
query = SQLConstants.GET_SCOPES_BY_TENANT_ID_FOR_ORGANIZATIONS + filterQueryBuilderForOrg
.getFilterQuery() + SQLConstants.GET_SCOPES_BY_TENANT_ID_FOR_ORGANIZATIONS_TAIL;
}
} catch (OrganizationManagementException e) {
throw new APIResourceMgtException(
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getCode(),
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getMessage(), e);
}
PreparedStatement preparedStatement = dbConnection.prepareStatement(query);
preparedStatement.setInt(1, tenantId);
int filterAttrSize = 0;
Expand Down Expand Up @@ -778,15 +823,42 @@ private static APIResource getApiResource(ResultSet resultSet, List<APIResourceP
* @return SQL statement to retrieve API resources.
*/
private String buildGetAPIResourcesSqlStatement(String databaseName, Integer tenantId, String filterQuery,
String sortOrder, Integer limit) {
String sortOrder, Integer limit) throws APIResourceMgtException {

String sqlStmtHead = SQLConstants.GET_API_RESOURCES;
String sqlStmtTail = SQLConstants.GET_API_RESOURCES_TAIL;
int initialTenantId = -1234;

try {
if (OrganizationManagementUtil.isOrganization(tenantId)) {
initialTenantId = tenantId;
tenantId = getRootOrganizationTenantId(tenantId);
sqlStmtTail = SQLConstants.GET_API_RESOURCES_TAIL_FOR_ORGANIZATIONS;
}
} catch (OrganizationManagementException e) {
throw new APIResourceMgtException(
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getCode(),
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getMessage(), e);
}

if (databaseName.contains(SQLConstants.MICROSOFT)) {
sqlStmtHead = SQLConstants.GET_API_RESOURCES_MSSQL;
sqlStmtTail = SQLConstants.GET_API_RESOURCES_TAIL_MSSQL;

try {
if (OrganizationManagementUtil.isOrganization(initialTenantId)) {
sqlStmtTail = SQLConstants.GET_API_RESOURCES_TAIL_FOR_ORGANIZATIONS_MSSQL;
}
} catch (OrganizationManagementException e) {
throw new APIResourceMgtException(
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getCode(),
APIResourceManagementConstants.ErrorMessages
.ERROR_CODE_ERROR_WHILE_RESOLVING_TENANT_FOR_ORGANIZATION.getMessage(), e);
}

return String.format(sqlStmtHead, limit) + filterQuery + String.format(sqlStmtTail, tenantId, sortOrder);
} else if (databaseName.contains(SQLConstants.ORACLE)) {
sqlStmtTail = SQLConstants.GET_API_RESOURCES_TAIL_ORACLE;
Expand All @@ -796,7 +868,8 @@ private String buildGetAPIResourcesSqlStatement(String databaseName, Integer ten
}

private String buildGetAPIResourcesWithPropertiesSqlStatement(String databaseName, Integer tenantId,
String filterQuery, String sortOrder, Integer limit) {
String filterQuery, String sortOrder, Integer limit)
throws APIResourceMgtException {

String selectionQuery = databaseName.contains(SQLConstants.H2)
? SQLConstants.GET_API_RESOURCES_WITH_PROPERTIES_SELECTION_H2
Expand Down Expand Up @@ -1117,6 +1190,65 @@ private void appendFilterQuery(List<ExpressionNode> expressionNodes, FilterQuery
}
}

/**
* Append the filter query to the query builder for the organization level.
*
* @param expressionNodes List of expression nodes.
* @param filterQueryBuilder Filter query builder.
* @param isScopeFilter Whether the filter is for scopes.
* @throws APIResourceMgtClientException If an error occurs while appending the filter query.
*/
private void appendFilterQueryForOrganizations(List<ExpressionNode> expressionNodes,
FilterQueryBuilder filterQueryBuilder, boolean isScopeFilter)
throws APIResourceMgtClientException {

int count = 1;
StringBuilder filter = new StringBuilder();
if (CollectionUtils.isEmpty(expressionNodes)) {
filterQueryBuilder.setFilterQuery(StringUtils.EMPTY);
} else {
for (ExpressionNode expressionNode : expressionNodes) {
String operation = expressionNode.getOperation();
String value = expressionNode.getValue();
String attributeValue = expressionNode.getAttributeValue();
String attributeName = "AR." + APIResourceManagementConstants.ATTRIBUTE_COLUMN_MAP.get(attributeValue);

// If the filter is for scopes, get the column name from the scope attribute map.
if (isScopeFilter) {
attributeName = "SC." + APIResourceManagementConstants.SCOPE_ATTRIBUTE_COLUMN_MAP
.get(attributeValue);
}

if (StringUtils.isNotBlank(attributeName) && StringUtils.isNotBlank(value) && StringUtils
.isNotBlank(operation)) {
switch (operation) {
case APIResourceManagementConstants.EQ: {
equalFilterBuilder(count, value, attributeName, filter, filterQueryBuilder);
++count;
break;
}
case APIResourceManagementConstants.SW: {
startWithFilterBuilder(count, value, attributeName, filter, filterQueryBuilder);
++count;
break;
}
default: {
break;
}
}
} else {
throw APIResourceManagementUtil.handleClientException(
APIResourceManagementConstants.ErrorMessages.ERROR_CODE_INVALID_FILTER_VALUE);
}
}
if (StringUtils.isBlank(filter.toString())) {
filterQueryBuilder.setFilterQuery(StringUtils.EMPTY);
} else {
filterQueryBuilder.setFilterQuery(filter.toString());
}
}
}

private void equalFilterBuilder(int count, String value, String attributeName, StringBuilder filter,
FilterQueryBuilder filterQueryBuilder) {

Expand Down Expand Up @@ -1188,4 +1320,16 @@ private void lessThanFilterBuilder(int count, String value, String attributeName
filter.append(attributeName).append(filterString);
filterQueryBuilder.setFilterAttributeValue(count, value);
}

private int getRootOrganizationTenantId(int tenantId) throws OrganizationManagementException {

String tenantDomain = IdentityTenantUtil.getTenantDomain(tenantId);
String orgId = APIResourceManagementServiceComponentHolder.getInstance().getOrganizationManager()
.resolveOrganizationId(tenantDomain);
String rootOrganizationId = APIResourceManagementServiceComponentHolder.getInstance()
.getOrganizationManager().getPrimaryOrganizationId(orgId);
String rootTenantDomain = APIResourceManagementServiceComponentHolder.getInstance()
.getOrganizationManager().resolveTenantDomain(rootOrganizationId);
return IdentityTenantUtil.getTenantId(rootTenantDomain);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@ protected void unsetIdentityCoreInitializedEventService(IdentityCoreInitializedE
unbind = "unsetOrganizationManager"
)
protected void setOrganizationManager(OrganizationManager organizationManager) {
/* reference Organization Management service to guarantee that this component will wait until organization
management service is started */

APIResourceManagementServiceComponentHolder.getInstance().setOrganizationManager(organizationManager);
LOG.debug("OrganizationManager set in API Resource Management bundle.");
}

protected void unsetOrganizationManager(OrganizationManager organizationManager) {
/* reference Organization Management service to guarantee that this component will wait until organization
management service is started */

APIResourceManagementServiceComponentHolder.getInstance().setOrganizationManager(null);
LOG.debug("OrganizationManager unset in API Resource Management bundle.");
}

@Reference(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
package org.wso2.carbon.identity.api.resource.mgt.internal;

import org.wso2.carbon.identity.event.services.IdentityEventService;
import org.wso2.carbon.identity.organization.management.service.OrganizationManager;

/**
* Service component holder for the API resource management.
*/
public class APIResourceManagementServiceComponentHolder {

private IdentityEventService identityEventService;
private OrganizationManager organizationManager;

private static final APIResourceManagementServiceComponentHolder instance =
new APIResourceManagementServiceComponentHolder();
Expand Down Expand Up @@ -63,4 +65,24 @@ public void setIdentityEventService(IdentityEventService identityEventService) {

this.identityEventService = identityEventService;
}

/**
* Get the OrganizationManager.
*
* @return OrganizationManager instance.
*/
public OrganizationManager getOrganizationManager() {

return organizationManager;
}

/**
* Set the OrganizationManager.
*
* @param organizationManager OrganizationManager instance.
*/
public void setOrganizationManager(OrganizationManager organizationManager) {

this.organizationManager = organizationManager;
}
}
Loading

0 comments on commit 3a19343

Please sign in to comment.