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

Support filter capability for Tenant Management API #723

Merged
merged 8 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ private TenantManagementConstants() {
public static final String PAGE_LINK_REL_PREVIOUS = "previous";
public static final String NON_EXISTING_USER_CODE = "30007 - ";

/**
* Supported filter operations.
*/
public static class FilterOperations {

public static final String EQ = "eq";
public static final String SW = "sw";
public static final String EW = "ew";
public static final String CO = "co";
}

/**
* Enum for error messages.
*/
Expand All @@ -52,6 +63,12 @@ public enum ErrorMessage {
ERROR_CODE_PARTIALLY_CREATED_OR_UPDATED("TM-60021",
"Tenant creation / update was completed with errors.",
"Tenant creation / update was completed with error: %s"),
ERROR_CODE_INVALID_FILTER_FORMAT("TM-60022", "Invalid format used for filtering.",
"Filter needs to be in the format <attribute>+<operation>+<value>."),
hwupathum marked this conversation as resolved.
Show resolved Hide resolved
ERROR_CODE_UNSUPPORTED_FILTER_ATTRIBUTE("TM-60023", "Unsupported filter attribute.",
"The filter attribute '%s' is not supported."),
ERROR_CODE_UNSUPPORTED_FILTER_OPERATION_FOR_ATTRIBUTE("TM-60024", "Unsupported filter operation.",
"Unsupported filter operation for filter attribute '%s'."),
ERROR_CODE_ERROR_LISTING_TENANTS("TM-65001",
"Unable to list existing tenants.",
"Server encountered an error while listing the tenants."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,13 @@ public Response isDomainExist(@ApiParam(value = "tenant domain",required=true) @
}, tags={ "Tenants", })
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = TenantsListResponse.class),
@ApiResponse(code = 400, message = "Invalid Input Request", response = Error.class),
@ApiResponse(code = 401, message = "Unauthorized", response = Void.class),
@ApiResponse(code = 403, message = "Resource Forbidden", response = Void.class),
@ApiResponse(code = 404, message = "The specified resource is not found", response = Error.class),
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class),
@ApiResponse(code = 501, message = "Not Implemented", response = Error.class)
@ApiResponse(code = 500, message = "Internal Server Error", response = Error.class)
})
public Response retrieveTenants( @Valid @Min(0)@ApiParam(value = "Maximum number of records to return.") @QueryParam("limit") Integer limit, @Valid @Min(0)@ApiParam(value = "Number of records to skip for pagination.") @QueryParam("offset") Integer offset, @Valid@ApiParam(value = "Define the order in which the retrieved tenants should be sorted.", allowableValues="asc, desc") @QueryParam("sortOrder") String sortOrder, @Valid@ApiParam(value = "Attribute by which the retrieved records should be sorted. Currently sorting through _<b>domainName<b>_ only supported.") @QueryParam("sortBy") String sortBy, @Valid@ApiParam(value = "Condition to filter the retrival of records. Supports 'sw', 'co', 'ew' and 'eq' operations and also complex queries with 'and' operations. E.g. /tenants?filter=domain+sw+\"wso2\". _<b>This option is not yet supported.<b>_ ") @QueryParam("filter") String filter) {
public Response retrieveTenants( @Valid @Min(0)@ApiParam(value = "Maximum number of records to return.") @QueryParam("limit") Integer limit, @Valid @Min(0)@ApiParam(value = "Number of records to skip for pagination.") @QueryParam("offset") Integer offset, @Valid@ApiParam(value = "Define the order in which the retrieved tenants should be sorted.", allowableValues="asc, desc") @QueryParam("sortOrder") String sortOrder, @Valid@ApiParam(value = "Attribute by which the retrieved records should be sorted. Currently sorting through <b>domainName</b> only supported.") @QueryParam("sortBy") String sortBy, @Valid@ApiParam(value = "Condition to filter the retrieval of records. Supports 'sw', 'co', 'ew' and 'eq' operations. Currently filtering through <b>domainName</b> only supported. E.g. /tenants?filter=domainName+sw+wso2. ") @QueryParam("filter") String filter) {
hwupathum marked this conversation as resolved.
Show resolved Hide resolved

return delegate.retrieveTenants(limit, offset, sortOrder, sortBy, filter );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.wso2.carbon.stratos.common.exception.TenantManagementServerException;
import org.wso2.carbon.stratos.common.exception.TenantMgtException;
import org.wso2.carbon.stratos.common.util.ClaimsMgtUtil;
import org.wso2.carbon.tenant.mgt.services.TenantMgtImpl;
hwupathum marked this conversation as resolved.
Show resolved Hide resolved
import org.wso2.carbon.tenant.mgt.services.TenantMgtService;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.core.common.User;
Expand All @@ -67,9 +68,17 @@

import static org.wso2.carbon.identity.api.server.common.Constants.ERROR_CODE_RESOURCE_LIMIT_REACHED;
import static org.wso2.carbon.identity.api.server.common.Constants.V1_API_PATH_COMPONENT;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.ErrorMessage.ERROR_CODE_INVALID_FILTER_FORMAT;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.ErrorMessage.ERROR_CODE_PARTIALLY_CREATED_OR_UPDATED;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.ErrorMessage.ERROR_CODE_TENANT_LIMIT_REACHED;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.ErrorMessage.ERROR_CODE_UNSUPPORTED_FILTER_ATTRIBUTE;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.ErrorMessage.ERROR_CODE_UNSUPPORTED_FILTER_OPERATION_FOR_ATTRIBUTE;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.FilterOperations.CO;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.FilterOperations.EQ;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.FilterOperations.EW;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.FilterOperations.SW;
import static org.wso2.carbon.identity.api.server.tenant.management.common.TenantManagementConstants.TENANT_MANAGEMENT_PATH_COMPONENT;
import static org.wso2.carbon.stratos.common.constants.TenantConstants.ErrorMessage.ERROR_CODE_ILLEGAL_CHARACTERS_IN_DOMAIN;
import static org.wso2.carbon.stratos.common.constants.TenantConstants.ErrorMessage.ERROR_CODE_INVALID_EMAIL;
import static org.wso2.carbon.stratos.common.constants.TenantConstants.ErrorMessage.ERROR_CODE_MISSING_REQUIRED_PARAMETER;

Expand All @@ -85,6 +94,8 @@ public class ServerTenantManagementService {
private static final String INLINE_PASSWORD = "inline-password";
private static final String CODE = "code";
private static final String PURPOSE = "purpose";
private static final String ILLEGAL_CHARACTERS_FOR_TENANT_DOMAIN = ".*[^a-z0-9\\._\\-].*";
private static final String SPACE_SEPARATOR = " ";

/**
* Add a tenant.
Expand Down Expand Up @@ -119,10 +130,10 @@ public String addTenant(TenantModel tenantModel) {
public TenantsListResponse listTenants(Integer limit, Integer offset, String sortOrder, String sortBy,
String filter) {

handleNotImplementedCapabilities(filter);
TenantMgtService tenantMgtService = TenantManagementServiceHolder.getTenantMgtService();

try {
verifyFilter(filter);
TenantSearchResult tenantSearchResult = tenantMgtService.listTenants(limit, offset, sortOrder, sortBy,
filter);
return createTenantListResponse(tenantSearchResult);
Expand Down Expand Up @@ -605,26 +616,6 @@ private static String includeData(TenantManagementConstants.ErrorMessage error,
return message;
}

/**
* Return Not Implemented error response for tenant List filtering which are not yet supported by the server.
*
* @param filter Filter string.
*/
private void handleNotImplementedCapabilities(String filter) {

TenantManagementConstants.ErrorMessage errorEnum = null;

if (filter != null) {
errorEnum = TenantManagementConstants.ErrorMessage.ERROR_CODE_FILTER_NOT_IMPLEMENTED;
}

if (errorEnum != null) {
ErrorResponse errorResponse = getErrorBuilder(errorEnum, null).build(log, errorEnum.getDescription());
Response.Status status = Response.Status.NOT_IMPLEMENTED;
throw new APIError(status, errorResponse);
}
}

public String addTenant(ChannelVerifiedTenantModel channelVerifiedTenantModel) {
String resourceId;
TenantMgtService tenantMgtService = TenantManagementServiceHolder.getTenantMgtService();
Expand Down Expand Up @@ -736,4 +727,37 @@ private String getISOFormatDate(Date date) {
.withZoneSameInstant(ZoneId.of("UTC"));
return ISO_OFFSET_DATE_TIME.format(zonedDateTime);
}


private void verifyFilter(String filter) throws TenantMgtException {

if (StringUtils.isNotBlank(filter)) {
String[] filterArgs = filter.split(SPACE_SEPARATOR);
if (filterArgs.length != 3) {
throw handleException(Response.Status.BAD_REQUEST, ERROR_CODE_INVALID_FILTER_FORMAT, null);
}

String filterAttribute = filterArgs[0];
String operation = filterArgs[1];
String attributeValue = filterArgs[2];

if (StringUtils.equalsIgnoreCase(filterAttribute, TenantMgtImpl.DOMAIN_NAME)) {
// Check tenant domain contains any illegal characters.
if (attributeValue.matches(ILLEGAL_CHARACTERS_FOR_TENANT_DOMAIN)) {
throw new TenantManagementClientException(ERROR_CODE_ILLEGAL_CHARACTERS_IN_DOMAIN.getCode(),
String.format(ERROR_CODE_ILLEGAL_CHARACTERS_IN_DOMAIN.getMessage(), attributeValue));
}
if (!StringUtils.equalsIgnoreCase(operation, SW) && !StringUtils.equalsIgnoreCase(operation, EW)
&& !StringUtils.equalsIgnoreCase(operation, EQ)
&& !StringUtils.equalsIgnoreCase(operation, CO)) {
throw handleException(Response.Status.BAD_REQUEST,
ERROR_CODE_UNSUPPORTED_FILTER_OPERATION_FOR_ATTRIBUTE, attributeValue);
}
} else {
throw handleException(Response.Status.BAD_REQUEST, ERROR_CODE_UNSUPPORTED_FILTER_ATTRIBUTE,
filterAttribute);
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ paths:
'application/json':
schema:
$ref: '#/components/schemas/TenantsListResponse'
'400':
$ref: '#/components/responses/InvalidInput'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
Expand All @@ -51,12 +53,6 @@ paths:
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/ServerError'
'501':
description: Not Implemented
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
tags:
- Tenants
Expand Down Expand Up @@ -488,7 +484,7 @@ components:
name: sortBy
required: false
description: >-
Attribute by which the retrieved records should be sorted. Currently sorting through _<b>domainName<b>_ only
Attribute by which the retrieved records should be sorted. Currently sorting through <b>domainName</b> only
supported.
schema:
type: string
Expand All @@ -497,10 +493,9 @@ components:
name: filter
required: false
description: >
Condition to filter the retrival of records. Supports 'sw', 'co', 'ew'
and 'eq' operations and also complex queries with 'and' operations. E.g.
/tenants?filter=domain+sw+"wso2". _<b>This
option is not yet supported.<b>_
Condition to filter the retrieval of records. Supports 'sw', 'co', 'ew' and 'eq' operations. Currently filtering
through <b>domainName</b> only supported.
hwupathum marked this conversation as resolved.
Show resolved Hide resolved
E.g. /tenants?filter=domainName+sw+wso2.
schema:
type: string
additionalClaimsQueryParam:
Expand Down
Loading