This is an automated email from the ASF dual-hosted git repository. rmani pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push: new 44e27a4fe RANGER-5213: Add Support for isEnabled Filter and Full/Partial Text Search on Labels and Keywords in Dataset Search 44e27a4fe is described below commit 44e27a4fe2d5538189c5c2c2069403e0d5f106cd Author: Radhika Kundam <radhika.kun...@gmail.com> AuthorDate: Tue May 20 13:56:53 2025 -0700 RANGER-5213: Add Support for isEnabled Filter and Full/Partial Text Search on Labels and Keywords in Dataset Search Signed-off-by: Ramesh Mani <rm...@apache.org> --- .../apache/ranger/plugin/util/SearchFilter.java | 2 ++ .../org/apache/ranger/common/RangerSearchUtil.java | 2 ++ .../main/java/org/apache/ranger/rest/GdsREST.java | 12 +++++-- .../ranger/service/RangerGdsDatasetService.java | 40 +++++++++++++++++++++- 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java index 717b94c67..3704aa3e7 100755 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/SearchFilter.java @@ -145,6 +145,8 @@ public class SearchFilter { public static final String VALIDITY_EXPIRY_END = "validityExpiryEnd"; // search public static final String VALIDITY_TIME_ZONE = "timeZone"; public static final String DEFAULT_TIME_ZONE = "GMT"; + public static final String DATASET_LABEL_MATCH_TYPE = "datasetLabelMatchType"; + public static final String DATASET_KEYWORD_MATCH_TYPE = "datasetKeywordMatchType"; private Map<String, String> params; private Map<String, Object[]> multiValueParams; diff --git a/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java b/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java index a76c2b5a3..79fd27568 100755 --- a/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java +++ b/security-admin/src/main/java/org/apache/ranger/common/RangerSearchUtil.java @@ -154,6 +154,8 @@ public SearchFilter getSearchFilter(@Nonnull HttpServletRequest request, List<So ret.setParam(SearchFilter.VALIDITY_EXPIRY_START, request.getParameter(SearchFilter.VALIDITY_EXPIRY_START)); ret.setParam(SearchFilter.VALIDITY_EXPIRY_END, request.getParameter(SearchFilter.VALIDITY_EXPIRY_END)); ret.setParam(SearchFilter.VALIDITY_TIME_ZONE, request.getParameter(SearchFilter.VALIDITY_TIME_ZONE)); + ret.setParam(SearchFilter.DATASET_LABEL_MATCH_TYPE, request.getParameter(SearchFilter.DATASET_LABEL_MATCH_TYPE)); + ret.setParam(SearchFilter.DATASET_KEYWORD_MATCH_TYPE, request.getParameter(SearchFilter.DATASET_KEYWORD_MATCH_TYPE)); extractCommonCriteriasForFilter(request, ret, sortFields); diff --git a/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java b/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java index 84009c3fa..8bcbd728b 100755 --- a/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/GdsREST.java @@ -393,8 +393,7 @@ public PList<RangerDataset> searchDatasets(@Context HttpServletRequest request) filter = searchUtil.getSearchFilter(request, datasetService.sortFields); - searchUtil.extractStringList(request, filter, SearchFilter.DATASET_LABEL, "Dataset Label List", "datasetLabels", null, null); - searchUtil.extractStringList(request, filter, SearchFilter.DATASET_KEYWORD, "Dataset Keyword List", "datasetKeywords", null, null); + extractDatasetMultiValueParams(request, filter); ret = gdsStore.searchDatasets(filter); } catch (WebApplicationException excp) { @@ -456,6 +455,8 @@ public PList<DatasetSummary> getDatasetSummary(@Context HttpServletRequest reque try { filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + extractDatasetMultiValueParams(request, filter); + ret = gdsStore.getDatasetSummary(filter); } catch (WebApplicationException we) { throw we; @@ -486,6 +487,8 @@ public DatasetsSummary getEnhancedDatasetSummary(@Context HttpServletRequest req try { filter = searchUtil.getSearchFilter(request, datasetService.sortFields); + extractDatasetMultiValueParams(request, filter); + ret = gdsStore.getEnhancedDatasetSummary(filter); } catch (WebApplicationException we) { throw we; @@ -2267,4 +2270,9 @@ private RangerPolicyItem copyOf(RangerPolicyItem policyItem) { return copy; } + + private void extractDatasetMultiValueParams(HttpServletRequest request, SearchFilter filter) { + searchUtil.extractStringList(request, filter, SearchFilter.DATASET_LABEL, "Dataset Label List", "datasetLabels", null, null); + searchUtil.extractStringList(request, filter, SearchFilter.DATASET_KEYWORD, "Dataset Keyword List", "datasetKeywords", null, null); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java index 8ace32a53..7ded325d2 100755 --- a/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java +++ b/security-admin/src/main/java/org/apache/ranger/service/RangerGdsDatasetService.java @@ -40,7 +40,12 @@ import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; +import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; @Service @Scope("singleton") @@ -71,6 +76,7 @@ public RangerGdsDatasetService() { searchFields.add(new SearchField(SearchFilter.CREATED_BY, "obj.addedByUserId", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL)); searchFields.add(new SearchField(SearchFilter.DATASET_LABEL, "obj.labels", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL)); searchFields.add(new SearchField(SearchFilter.DATASET_KEYWORD, "obj.keywords", SearchField.DATA_TYPE.STRING, SearchField.SEARCH_TYPE.PARTIAL)); + searchFields.add(new SearchField(SearchFilter.IS_ENABLED, "obj.isEnabled", SearchField.DATA_TYPE.BOOLEAN, SearchField.SEARCH_TYPE.FULL)); sortFields.add(new SortField(SearchFilter.CREATE_TIME, "obj.createTime")); sortFields.add(new SortField(SearchFilter.UPDATE_TIME, "obj.updateTime")); @@ -214,8 +220,23 @@ public RangerDatasetList searchDatasets(SearchFilter filter) { List<XXGdsDataset> datasets = super.searchResources(filter, searchFields, sortFields, ret); if (datasets != null) { + Set<String> searchLabels = extractFilterValues(SearchFilter.DATASET_LABEL, filter); + Set<String> searchKeywords = extractFilterValues(SearchFilter.DATASET_KEYWORD, filter); + String labelMatchType = filter.getParam(SearchFilter.DATASET_LABEL_MATCH_TYPE); + String keywordMatchType = filter.getParam(SearchFilter.DATASET_KEYWORD_MATCH_TYPE); for (XXGdsDataset dataset : datasets) { - ret.getList().add(getPopulatedViewObject(dataset)); + boolean isLabelOrKeywordMatch = CollectionUtils.isEmpty(searchLabels) && CollectionUtils.isEmpty(searchKeywords); + if (!isLabelOrKeywordMatch) { + isLabelOrKeywordMatch = isAnyMatch(labelMatchType, JsonUtils.jsonToSetString(dataset.getLabels()), searchLabels); + } + + if (!isLabelOrKeywordMatch) { + isLabelOrKeywordMatch = isAnyMatch(keywordMatchType, JsonUtils.jsonToSetString(dataset.getKeywords()), searchKeywords); + } + + if (isLabelOrKeywordMatch) { + ret.getList().add(getPopulatedViewObject(dataset)); + } } } @@ -223,4 +244,21 @@ public RangerDatasetList searchDatasets(SearchFilter filter) { return ret; } + + private Set<String> extractFilterValues(String key, SearchFilter filter) { + Object[] multiVal = filter.getMultiValueParam(key); + + return multiVal != null ? Arrays.stream(multiVal).filter(Objects::nonNull).map(Object::toString).collect(Collectors.toSet()) : Collections.emptySet(); + } + + private boolean isAnyMatch(String matchType, Set<String> values, Set<String> searchValues) { + if (CollectionUtils.isNotEmpty(searchValues) && CollectionUtils.isNotEmpty(values)) { + if (SearchField.SEARCH_TYPE.FULL.name().equalsIgnoreCase(matchType)) { + return searchValues.stream().anyMatch(searchValue -> values.stream().anyMatch(value -> value.equalsIgnoreCase(searchValue))); + } else { + return searchValues.stream().anyMatch(searchValue -> values.stream().anyMatch(value -> StringUtils.containsIgnoreCase(value, searchValue))); + } + } + return false; + } }