You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by ma...@apache.org on 2024/02/19 19:19:20 UTC

(ranger) branch master updated: RANGER-4630: added multiple tagId search in /tags/tags/paginated API

This is an automated email from the ASF dual-hosted git repository.

madhan 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 48520f998 RANGER-4630: added multiple tagId search in /tags/tags/paginated API
48520f998 is described below

commit 48520f998818f8d4d5c97d28c9f7b5c2c921f304
Author: Anand Nadar <na...@gmail.com>
AuthorDate: Sun Feb 18 14:54:32 2024 -0800

    RANGER-4630: added multiple tagId search in /tags/tags/paginated API
    
    Signed-off-by: Madhan Neethiraj <ma...@apache.org>
---
 .../apache/ranger/plugin/util/SearchFilter.java    |  38 ++++--
 .../org/apache/ranger/common/RangerSearchUtil.java | 128 ++++++++++++++++++++-
 .../main/java/org/apache/ranger/rest/TagREST.java  |  38 ++++++
 .../org/apache/ranger/rest/TagRESTConstants.java   |   1 +
 .../service/RangerTagResourceMapService.java       |   5 +
 .../apache/ranger/service/RangerTagService.java    |   1 +
 6 files changed, 202 insertions(+), 9 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 4534b7848..d1568bbac 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
@@ -81,6 +81,7 @@ public class SearchFilter {
 	public static final String TAG_SOURCE                = "tagSource";           // search
 	public static final String TAG_SOURCE_PARTIAL        = "tagSourcePartial";    // search
 	public static final String TAG_ID                    = "tagId";               // search
+	public static final String TAG_IDS                   = "tagIds";               // search
 	public static final String TAG_GUID                  = "tagGuid";             // search
 	public static final String TAG_RESOURCE_ID           = "resourceId";          // search
 	public static final String TAG_RESOURCE_GUID         = "resourceGuid";        // search
@@ -136,13 +137,14 @@ public class SearchFilter {
 	public static final String RETRIEVE_ALL_PAGES       = "retrieveAllPages";     // search
 	public static final String SHARED_WITH_ME           = "sharedWithMe";         // search
 
-	private Map<String, String> params;
-	private int                 startIndex;
-	private int                 maxRows    = Integer.MAX_VALUE;
-	private boolean             getCount   = true;
-	private String              sortBy;
-	private String              sortType;
-	private boolean isDistinct = true;
+	private Map<String, String>   params;
+	private Map<String, Object[]> multiValueParams;
+	private int                   startIndex;
+	private int                   maxRows    = Integer.MAX_VALUE;
+	private boolean               getCount   = true;
+	private String                sortBy;
+	private String                sortType;
+	private boolean               isDistinct = true;
 
 	public SearchFilter() {
 		this((Map<String, String>) null);
@@ -151,6 +153,7 @@ public class SearchFilter {
 	public SearchFilter(SearchFilter other) {
 		if (other != null) {
 			setParams(other.params != null ? new HashMap<>(other.params) : null);
+			setMultiValueParams(other.multiValueParams != null ? new HashMap<>(other.multiValueParams) : null);
 			setStartIndex(other.startIndex);
 			setMaxRows(other.maxRows);
 			setGetCount(other.getCount);
@@ -158,6 +161,7 @@ public class SearchFilter {
 			setSortType(other.sortType);
 		} else {
 			setParams(null);
+			setMultiValueParams(null);
 		}
 	}
 
@@ -228,6 +232,26 @@ public class SearchFilter {
 	public boolean isEmpty() {
 		return MapUtils.isEmpty(params);
 	}
+
+	public Map<String, Object[]> getMultiValueParams() {
+		return multiValueParams;
+	}
+
+	public void setMultiValueParams(Map<String, Object[]> multiValueParams) {
+		this.multiValueParams = multiValueParams;
+	}
+
+	public void setMultiValueParam(String name, Object[] value) {
+		if (multiValueParams == null) {
+			multiValueParams = new HashMap<>();
+		}
+
+		multiValueParams.put(name, value);
+	}
+
+	public Object[] getMultiValueParam(String name) {
+		return multiValueParams != null ? multiValueParams.get(name) : null;
+	}
 	
 	public int getStartIndex() {
 		return startIndex;
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 2936c3a13..529472a31 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
@@ -43,6 +43,12 @@ import org.springframework.stereotype.Component;
 public class RangerSearchUtil extends SearchUtil {
 	final static Logger logger = LoggerFactory.getLogger(RangerSearchUtil.class);
 
+	int minInListLength = 20;
+
+	public RangerSearchUtil() {
+		minInListLength = PropertiesUtil.getIntProperty("ranger.db.min_inlist", minInListLength);
+	}
+
 	public SearchFilter getSearchFilter(@Nonnull HttpServletRequest request, List<SortField> sortFields) {
 		Validate.notNull(request, "request");
 		SearchFilter ret = new SearchFilter();
@@ -308,7 +314,62 @@ public class RangerSearchUtil extends SearchUtil {
 				continue;
 			}
 
-			if (searchField.getDataType() == SearchField.DATA_TYPE.INTEGER) {
+			Object[] multiValue   = searchCriteria.getMultiValueParam(searchField.getClientFieldName());
+			boolean  isMultiValue = multiValue != null && multiValue.length > 0;
+
+			if (searchField.getDataType() == SearchField.DATA_TYPE.INT_LIST || (isMultiValue && searchField.getDataType() == SearchField.DATA_TYPE.INTEGER)) {
+				List<Number> intValueList = new ArrayList<>();
+
+				if (isMultiValue) {
+					for (Object value : multiValue) {
+						if (value instanceof Integer || value instanceof Long) {
+							intValueList.add((Number) value);
+						} else if (value != null) {
+							intValueList.add(restErrorUtil.parseInt(value.toString(), "Invalid value for " + searchField.getClientFieldName(), MessageEnums.INVALID_INPUT_DATA, null, searchField.getClientFieldName()));
+						}
+					}
+				} else {
+					String paramVal = searchCriteria.getParam(searchField.getClientFieldName());
+
+					if (paramVal != null) {
+						intValueList.add(restErrorUtil.parseInt(paramVal, "Invalid value for " + searchField.getClientFieldName(), MessageEnums.INVALID_INPUT_DATA, null, searchField.getClientFieldName()));
+					}
+				}
+
+				if (!intValueList.isEmpty()) {
+					if (searchField.getCustomCondition() == null) {
+						if (intValueList.size() <= minInListLength) {
+							whereClause.append(" and ");
+
+							if (intValueList.size() > 1) {
+								whereClause.append(" ( ");
+							}
+
+							for (int count = 0; count < intValueList.size(); count++) {
+								if (count > 0) {
+									whereClause.append(" or ");
+								}
+
+								whereClause.append(searchField.getFieldName()).append("= :")
+								           .append(searchField.getClientFieldName()).append("_").append(count);
+							}
+
+							if (intValueList.size() > 1) {
+								whereClause.append(" ) ");
+							}
+
+							logger.debug("Where clause ...  :: " + whereClause);
+						} else {
+							whereClause.append(" and ")
+							           .append(searchField.getFieldName())
+							           .append(" in ")
+							           .append(" (:").append(searchField.getClientFieldName()).append(")");
+						}
+					} else {
+						whereClause.append(" and ").append(searchField.getCustomCondition());
+					}
+				}
+			} else if (searchField.getDataType() == SearchField.DATA_TYPE.INTEGER) {
 				Integer paramVal = restErrorUtil.parseInt(searchCriteria.getParam(searchField.getClientFieldName()),
 						"Invalid value for " + searchField.getClientFieldName(),
 						MessageEnums.INVALID_INPUT_DATA, null, searchField.getClientFieldName());
@@ -382,10 +443,42 @@ public class RangerSearchUtil extends SearchUtil {
 	}
 	
 	protected void resolveQueryParams(Query query, SearchFilter searchCriteria, List<SearchField> searchFields) {
+		Map<String, String>   params           = searchCriteria.getParams();
+		Map<String, Object[]> multiValueParams = searchCriteria.getMultiValueParams();
 
 		for (SearchField searchField : searchFields) {
+			Object[] multiValue   = multiValueParams != null ? multiValueParams.get(searchField.getClientFieldName()) : null;
+			boolean  isMultiValue = multiValue != null && multiValue.length > 0;
+
+			if (searchField.getDataType() == SearchField.DATA_TYPE.INT_LIST || (isMultiValue && searchField.getDataType() == SearchField.DATA_TYPE.INTEGER)) {
+				List<Number> intValueList = new ArrayList<>();
+
+				if (isMultiValue) {
+					for (Object value : multiValue) {
+						if (value instanceof Integer || value instanceof Long) {
+							intValueList.add((Number) value);
+						} else if (value != null) {
+							intValueList.add(restErrorUtil.parseInt(value.toString(), "Invalid value for " + searchField.getClientFieldName(), MessageEnums.INVALID_INPUT_DATA, null, searchField.getClientFieldName()));
+						}
+					}
+				} else {
+					String paramVal = params != null ? params.get(searchField.getClientFieldName()) : null;
 
-			if (searchField.getDataType() == SearchField.DATA_TYPE.INTEGER) {
+					if (paramVal != null) {
+						intValueList.add(restErrorUtil.parseInt(paramVal, "Invalid value for " + searchField.getClientFieldName(), MessageEnums.INVALID_INPUT_DATA, null, searchField.getClientFieldName()));
+					}
+				}
+
+				if (!intValueList.isEmpty()) {
+					if (intValueList.size() <= minInListLength) {
+						for (int idx = 0; idx < intValueList.size(); idx++) {
+							query.setParameter(searchField.getClientFieldName() + "_" + idx, intValueList.get(idx));
+						}
+					} else {
+						query.setParameter(searchField.getClientFieldName(), intValueList);
+					}
+				}
+			} else if (searchField.getDataType() == SearchField.DATA_TYPE.INTEGER) {
 				Integer paramVal = restErrorUtil.parseInt(searchCriteria.getParam(searchField.getClientFieldName()),
 						"Invalid value for " + searchField.getClientFieldName(),
 						MessageEnums.INVALID_INPUT_DATA, null, searchField.getClientFieldName());
@@ -490,4 +583,35 @@ public class RangerSearchUtil extends SearchUtil {
 
 		return ret;
 	}
+
+	public void extractIntList(HttpServletRequest request, SearchFilter searchFilter, String paramName, String userFriendlyParamName) {
+		String[] values = getParamMultiValues(request, paramName);
+
+		if (values != null) {
+			List<Integer> intValues = new ArrayList<>(values.length);
+
+			for (String value : values) {
+				Integer intValue = restErrorUtil.parseInt(value, "Invalid value for " + userFriendlyParamName, MessageEnums.INVALID_INPUT_DATA, null, paramName);
+
+				intValues.add(intValue);
+			}
+
+			searchFilter.setMultiValueParam(paramName, intValues.toArray());
+		}
+	}
+
+	/**
+	 * @param request
+	 * @param paramName
+	 * @return
+	 */
+	String[] getParamMultiValues(HttpServletRequest request, String paramName) {
+		String[] values = request.getParameterValues(paramName);
+
+		if (values == null || values.length == 0) {
+			values = request.getParameterValues(paramName + "[]");
+		}
+
+		return values;
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java b/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java
old mode 100644
new mode 100755
index f05253fde..01ff442fb
--- a/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/TagREST.java
@@ -48,6 +48,7 @@ import org.apache.ranger.plugin.util.SearchFilter;
 import org.apache.ranger.plugin.util.ServiceTags;
 import org.apache.ranger.service.RangerServiceResourceService;
 import org.apache.ranger.service.RangerTagDefService;
+import org.apache.ranger.service.RangerTagResourceMapService;
 import org.apache.ranger.service.RangerTagService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -117,6 +118,9 @@ public class TagREST {
     @Autowired
     RangerServiceResourceService rangerServiceResourceService;
 
+    @Autowired
+    RangerTagResourceMapService rangerTagResourceMapService;
+
     public TagREST() {
 	}
 
@@ -669,6 +673,8 @@ public class TagREST {
         try {
             SearchFilter filter = searchUtil.getSearchFilter(request, tagService.sortFields);
 
+            searchUtil.extractIntList(request, filter, SearchFilter.TAG_IDS, "Tag Id List");
+
             ret = tagStore.getPaginatedTags(filter);
         } catch (Exception excp) {
             LOG.error("getTags() failed", excp);
@@ -1266,6 +1272,38 @@ public class TagREST {
         return ret;
     }
 
+    @GET
+    @Path(TagRESTConstants.TAGRESOURCEMAPS_RESOURCE_PAGINATED)
+    @Produces({ "application/json" })
+    @PreAuthorize("hasRole('ROLE_SYS_ADMIN')")
+    public PList<RangerTagResourceMap> getTagResourceMaps(@Context HttpServletRequest request) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("==> TagREST.getTagResourceMaps()");
+        }
+
+        final PList<RangerTagResourceMap> ret;
+
+        try {
+            SearchFilter filter = searchUtil.getSearchFilter(request, rangerTagResourceMapService.sortFields);
+
+            ret = tagStore.getPaginatedTagResourceMaps(filter);
+        } catch (Exception excp) {
+            LOG.error("getTagResourceMaps() failed", excp);
+
+            throw restErrorUtil.createRESTException(HttpServletResponse.SC_BAD_REQUEST, excp.getMessage(), true);
+        }
+
+        if (ret == null) {
+            throw restErrorUtil.createRESTException(HttpServletResponse.SC_NOT_FOUND, "Not found", true);
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("<== TagREST.getTagResourceMaps(): " + ret);
+        }
+
+        return ret;
+    }
+
     // This API is used by tag-sync to upload tag-objects
 
     @PUT
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/TagRESTConstants.java b/security-admin/src/main/java/org/apache/ranger/rest/TagRESTConstants.java
index a6e49e731..fe05d9feb 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/TagRESTConstants.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/TagRESTConstants.java
@@ -32,6 +32,7 @@ public class TagRESTConstants {
 	static final String RESOURCES_RESOURCE_PAGINATED = "/resources/paginated";
 	static final String RESOURCE_RESOURCE        = "/resource/";
 	static final String TAGRESOURCEMAPS_RESOURCE = "/tagresourcemaps/";
+	static final String TAGRESOURCEMAPS_RESOURCE_PAGINATED = "/tagresourcemaps/paginated";
 	static final String IMPORT_SERVICETAGS_RESOURCE = "/importservicetags/";
 	static final String TAGRESOURCEMAP_RESOURCE  = "/tagresourcemap/";
 	static final String TAGTYPES_RESOURCE        = "/types/";
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java
index 76c02ac9e..f22963f3c 100644
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerTagResourceMapService.java
@@ -26,6 +26,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.ranger.common.SearchField;
 import org.apache.ranger.common.SearchField.DATA_TYPE;
 import org.apache.ranger.common.SearchField.SEARCH_TYPE;
+import org.apache.ranger.common.SortField;
 import org.apache.ranger.entity.XXTagResourceMap;
 import org.apache.ranger.plugin.model.RangerTagResourceMap;
 import org.apache.ranger.plugin.util.SearchFilter;
@@ -38,6 +39,10 @@ public class RangerTagResourceMapService extends RangerTagResourceMapServiceBase
 		searchFields.add(new SearchField(SearchFilter.TAG_DEF_ID, "obj.id", DATA_TYPE.INTEGER, SEARCH_TYPE.FULL));
 		searchFields.add(new SearchField(SearchFilter.TAG_RESOURCE_ID, "obj.resourceId", DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL));
 		searchFields.add(new SearchField(SearchFilter.TAG_ID, "obj.tagId", DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL));
+
+		sortFields.add(new SortField(SearchFilter.TAG_DEF_ID, "obj.id", true, SortField.SORT_ORDER.ASC));
+		sortFields.add(new SortField(SearchFilter.TAG_RESOURCE_ID, "obj.resourceId"));
+		sortFields.add(new SortField(SearchFilter.TAG_ID, "obj.tagId"));
 	}
 	
 	@Override
diff --git a/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java b/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java
old mode 100644
new mode 100755
index 055525f85..fe79c3e5f
--- a/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java
+++ b/security-admin/src/main/java/org/apache/ranger/service/RangerTagService.java
@@ -51,6 +51,7 @@ public class RangerTagService extends RangerTagServiceBase<XXTag, RangerTag> {
 		searchFields.add(new SearchField(SearchFilter.TAG_DEF_ID, "obj.type", SearchField.DATA_TYPE.INTEGER, SearchField.SEARCH_TYPE.FULL));
 		searchFields.add(new SearchField(SearchFilter.TAG_TYPE, "tagDef.name", DATA_TYPE.STRING, SEARCH_TYPE.FULL, "XXTagDef tagDef", "obj.type = tagDef.id"));
 		searchFields.add(new SearchField(SearchFilter.TAG_TYPE_PARTIAL, "tagDef.name", DATA_TYPE.STRING, SEARCH_TYPE.PARTIAL, "XXTagDef tagDef", "obj.type = tagDef.id"));
+		searchFields.add(new SearchField(SearchFilter.TAG_IDS, "obj.id", SearchField.DATA_TYPE.INT_LIST, SearchField.SEARCH_TYPE.FULL));
 
 		sortFields.add(new SortField(SearchFilter.TAG_ID, "obj.id", true, SortField.SORT_ORDER.ASC));
 		sortFields.add(new SortField(SearchFilter.TAG_DEF_ID, "obj.type"));