RANGER-2273 : Allow service admin and delegated admin user to view list of users and groups though they have 'USER' role

Signed-off-by: Pradeep <pradeep@apache.org>
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
index 54ae07e..9d48531 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
@@ -23,11 +23,14 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
 import org.apache.ranger.common.ContextUtil;
 import org.apache.ranger.common.GUIDUtil;
 import org.apache.ranger.common.RangerCommonEnums;
@@ -1799,6 +1802,99 @@
 		return vXGroupList;
 	}
 
+
+        public VXGroupList lookupXGroups(SearchCriteria searchCriteria) {
+                VXGroupList ret = null;
+
+                try {
+                        HashMap<String, Object> searchParams  = searchCriteria.getParamList();
+                        String                  nameToLookFor = searchParams != null ? (String) searchParams.get("name") : null;
+                        VXGroup                 exactMatch    = null;
+
+                        if (StringUtils.isEmpty(searchCriteria.getSortBy())) {
+                                searchCriteria.setSortBy(nameToLookFor != null ? "name" : "id");
+                        }
+
+                        if(nameToLookFor != null) {
+                                exactMatch = getGroupByGroupName(nameToLookFor);
+
+                                for (Map.Entry<String, Object> entry : searchParams.entrySet()) {
+                                        if(exactMatch == null) {
+                                                break;
+                                        }
+
+                                        String paramName  = entry.getKey();
+                                        Object paramValue = entry.getValue();
+
+                                        switch (paramName.toLowerCase()) {
+                                                case "isvisible":
+                                                        if (!Objects.equals(exactMatch.getIsVisible(), paramValue)) {
+                                                                exactMatch = null;
+                                                        }
+                                                        break;
+
+                                                case "groupsource":
+                                                        if (!Objects.equals(exactMatch.getGroupSource(), paramValue)) {
+                                                                exactMatch = null;
+                                                        }
+                                                        break;
+
+                                                default:
+                                                        // ignore
+                                                        break;
+                                        }
+                                }
+                        }
+
+                        VXGroupList searchResult = xGroupService.searchXGroups(searchCriteria);
+
+                        if (exactMatch != null && exactMatch.getId() != null) {
+                                List<VXGroup> groups = searchResult.getList();
+
+                                if (!groups.isEmpty()) { // remove exactMatch from groups if it is present
+                                        boolean removed = false;
+
+                                        for (Iterator<VXGroup> iter = groups.iterator(); iter.hasNext(); ) {
+                                                VXGroup group = iter.next();
+
+                                                if (group != null && exactMatch.getId().equals(group.getId())) {
+                                                        iter.remove();
+                                                        removed = true;
+
+                                                        break;
+                                                }
+                                        }
+
+                                        if (!removed) { // remove the last entry, if exactMatch was not removed above - to accomodate for add() below
+                                                groups.remove(groups.size() - 1);
+                                        }
+                                }
+
+                                groups.add(0, exactMatch);
+
+                                ret = new VXGroupList(groups);
+
+                                ret.setStartIndex(searchCriteria.getStartIndex());
+                                ret.setTotalCount(searchResult.getTotalCount());
+                                ret.setPageSize(searchCriteria.getMaxRows());
+                                ret.setSortBy(searchCriteria.getSortBy());
+                                ret.setSortType(searchCriteria.getSortType());
+                        } else {
+                                ret = searchResult;
+                        }
+                } catch (Exception e) {
+                        logger.error("Error getting the exact match of group =>"+e);
+                }
+
+                if (ret != null && ret.getListSize() > 0 && !hasAccessToModule(RangerConstants.MODULE_USER_GROUPS)) {
+                        for(VXGroup vXGroup : ret.getList()) {
+                                getMaskedVXGroup(vXGroup);
+                        }
+                }
+
+                return ret;
+        }
+
 	public Collection<String> getMaskedCollection(Collection<String> listunMasked){
         List<String> listMasked=new ArrayList<String>();
         if(listunMasked!=null) {
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java b/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java
index ec1dc26..d06827d 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java
@@ -19,6 +19,7 @@
 
 package org.apache.ranger.rest;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
@@ -1175,4 +1176,62 @@
                         xUserMgr.deleteXGroup(groupId, forceDelete);
                 }
         }
+        
+	@GET
+	@Path("/lookup/users")
+	@Produces({ "application/xml", "application/json" })
+	@PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_USERS_LOOKUP + "\")")
+	public VXStringList getUsersLookup(@Context HttpServletRequest request) {
+		SearchCriteria searchCriteria = searchUtil.extractCommonCriterias(request, xUserService.sortFields);
+		VXStringList ret = new VXStringList();
+		List<VXString> vXList = new ArrayList<>();
+		searchUtil.extractString(request, searchCriteria, "name", "User name", null);
+		searchUtil.extractInt(request, searchCriteria, "isVisible", "User Visibility");
+		try {
+			VXUserList vXUserList = xUserMgr.searchXUsers(searchCriteria);
+			VXString VXString = null;
+			for (VXUser vxUser : vXUserList.getList()) {
+				VXString = new VXString();
+				VXString.setValue(vxUser.getName());
+				vXList.add(VXString);
+			}
+			ret.setVXStrings(vXList);
+			ret.setPageSize(vXUserList.getPageSize());
+			ret.setTotalCount(vXUserList.getTotalCount());
+			ret.setSortType(vXUserList.getSortType());
+			ret.setSortBy(vXUserList.getSortBy());
+		} catch (Throwable excp) {
+			throw restErrorUtil.createRESTException(excp.getMessage());
+		}
+		return ret;
+	}
+
+	@GET
+	@Path("/lookup/groups")
+	@Produces({ "application/xml", "application/json" })
+	@PreAuthorize("@rangerPreAuthSecurityHandler.isAPIAccessible(\"" + RangerAPIList.GET_GROUPS_LOOKUP + "\")")
+	public VXStringList getGroupsLookup(@Context HttpServletRequest request) {
+		VXStringList ret = new VXStringList();
+		SearchCriteria searchCriteria = searchUtil.extractCommonCriterias(request, xGroupService.sortFields);
+		List<VXString> vXList = new ArrayList<>();
+		searchUtil.extractString(request, searchCriteria, "name", "group name", null);
+		searchUtil.extractInt(request, searchCriteria, "isVisible", "Group Visibility");
+		try {
+			VXGroupList vXGroupList = xUserMgr.lookupXGroups(searchCriteria);
+			for (VXGroup vxGroup : vXGroupList.getList()) {
+				VXString VXString = new VXString();
+				VXString.setValue(vxGroup.getName());
+				vXList.add(VXString);
+			}
+			ret.setVXStrings(vXList);
+			ret.setPageSize(vXGroupList.getPageSize());
+			ret.setTotalCount(vXGroupList.getTotalCount());
+			ret.setSortType(vXGroupList.getSortType());
+			ret.setSortBy(vXGroupList.getSortBy());
+		} catch (Throwable excp) {
+			throw restErrorUtil.createRESTException(excp.getMessage());
+		}
+		return ret;
+	}
+        
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java b/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java
index 460c7fd..da45338 100644
--- a/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java
+++ b/security-admin/src/main/java/org/apache/ranger/security/context/RangerAPIList.java
@@ -137,6 +137,8 @@
 	public static final String MODIFY_GROUPS_VISIBILITY = "XUserREST.modifyGroupsVisibility";
 	public static final String DELETE_X_GROUP = "XUserREST.deleteXGroup";
 	public static final String SEARCH_X_GROUPS = "XUserREST.searchXGroups";
+        public static final String GET_USERS_LOOKUP = "XUserREST.getUsersLookup";
+        public static final String GET_GROUPS_LOOKUP = "XUserREST.getGroupsLookup";
 	public static final String COUNT_X_GROUPS = "XUserREST.countXGroups";
 	public static final String GET_X_USER = "XUserREST.getXUser";
 	public static final String SECURE_GET_X_USER = "XUserREST.secureGetXUser";
diff --git a/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js b/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js
index 9184675..742f0a7 100644
--- a/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js
+++ b/security-admin/src/main/webapp/scripts/views/policies/PermissionList.js
@@ -185,7 +185,7 @@
                 createDropDown :function($select, typeGroup){
                         var that = this, tags = [],
 			placeholder = (typeGroup) ? 'Select Group' : 'Select User',
-                        searchUrl   = (typeGroup) ? "service/xusers/groups" : "service/xusers/users";
+                                        searchUrl   = (typeGroup) ? "service/xusers/lookup/groups" : "service/xusers/lookup/users";
 			if(this.model.has('editMode') && !_.isEmpty($select.val())){
                                 var temp = this.model.attributes[ (typeGroup) ? 'groupName': 'userName'];
 				_.each(temp , function(name){
@@ -211,11 +211,11 @@
 						var results = [] , selectedVals = [];
 						//Get selected values of groups/users dropdown
 						selectedVals = that.getSelectedValues($select, typeGroup);
-						if(data.resultSize != "0"){
+                                                if(data.totalCount != "0"){
 							if(typeGroup){
-                                                                results = data.vXGroups.map(function(m, i){	return {id : _.escape(m.name), text: _.escape(m.name) };	});
+                                                                results = data.vXStrings.map(function(m){	return {id : _.escape(m.value), text: _.escape(m.value) };	});
 							} else {
-                                                                results = data.vXUsers.map(function(m, i){	return {id : _.escape(m.name), text: _.escape(m.name) };	});
+                                                                results = data.vXStrings.map(function(m){	return {id : _.escape(m.value), text: _.escape(m.value) };	});
 							}
 							if(!_.isEmpty(selectedVals)){
 								results = XAUtil.filterResultByText(results, selectedVals);
diff --git a/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js b/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js
index 90f44c1..74bbd5f 100644
--- a/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js
+++ b/security-admin/src/main/webapp/scripts/views/reports/UserAccessLayout.js
@@ -629,7 +629,7 @@
 					callback(data);
 				},
 				ajax: { 
-					url: "service/xusers/groups",
+                                        url: "service/xusers/lookup/groups",
 					dataType: 'json',
 					data: function (term, page) {
 						return {name : term};
@@ -638,8 +638,8 @@
 						var results = [],selectedVals = [];
 						if(!_.isEmpty(that.ui.userGroup.val()))
 							selectedVals = that.ui.userGroup.val().split(',');
-						if(data.resultSize != "0"){
-							results = data.vXGroups.map(function(m, i){	return {id : m.name, text: _.escape(m.name) };	});
+                                                if(data.totalCount != "0"){
+                                                        results = data.vXStrings.map(function(m){	return {id : m.value, text: _.escape(m.value) };	});
 							if(!_.isEmpty(selectedVals))
 								results = XAUtil.filterResultByIds(results, selectedVals);
 							return {results : results};
@@ -683,7 +683,7 @@
 					callback(data);
 				},
 				ajax: { 
-					url: "service/xusers/users",
+                                        url: "service/xusers/lookup/users",
 					dataType: 'json',
 					data: function (term, page) {
 						return {name : term};
@@ -692,8 +692,8 @@
 						var results = [],selectedVals=[];
 						if(!_.isEmpty(that.ui.userName.select2('val')))
 							selectedVals = that.ui.userName.select2('val');
-						if(data.resultSize != "0"){
-							results = data.vXUsers.map(function(m, i){	return {id : m.name, text: _.escape(m.name) };	});
+                                                if(data.totalCount != "0"){
+                                                        results = data.vXStrings.map(function(m){	return {id : m.value, text: _.escape(m.value) };	});
 							if(!_.isEmpty(selectedVals))
 								results = XAUtil.filterResultByIds(results, selectedVals);
 							return {results : results};