RANGER-4651: update GDS objects ACL for deletion of Ranger user/group/roles

Signed-off-by: Madhan Neethiraj <madhan@apache.org>
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java
index a696479..69b43f2 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/GdsDBStore.java
@@ -22,6 +22,7 @@
 import org.apache.http.HttpStatus;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.ranger.biz.ServiceDBStore.REMOVE_REF_TYPE;
 import org.apache.ranger.common.*;
 import org.apache.ranger.common.db.RangerTransactionSynchronizationAdapter;
 import org.apache.ranger.db.*;
@@ -1339,6 +1340,48 @@
 		return ret;
 	}
 
+    public void deletePrincipalFromGdsAcl(String principalType, String principalName) {
+        Map<Long, RangerGdsObjectACL> datsetAcls    = daoMgr.getXXGdsDataset().getDatasetIdsAndACLs();
+        Map<Long, RangerGdsObjectACL> dataShareAcls = daoMgr.getXXGdsDataShare().getDataShareIdsAndACLs();
+        Map<Long, RangerGdsObjectACL> projectAcls   = daoMgr.getXXGdsProject().getProjectIdsAndACLs();
+
+        for (Map.Entry<Long, RangerGdsObjectACL> entry : datsetAcls.entrySet()) {
+            Long               id  = entry.getKey();
+            RangerGdsObjectACL acl = entry.getValue();
+
+            if (deletePrincipalFromAcl(acl, principalName, principalType) != null) {
+                RangerDataset dataset = datasetService.read(id);
+
+                dataset.setAcl(acl);
+                datasetService.update(dataset);
+            }
+        }
+
+        for (Map.Entry<Long, RangerGdsObjectACL> entry : dataShareAcls.entrySet()) {
+            Long               id  = entry.getKey();
+            RangerGdsObjectACL acl = entry.getValue();
+
+            if (deletePrincipalFromAcl(acl, principalName, principalType) != null) {
+                RangerDataShare dataShare = dataShareService.read(id);
+
+                dataShare.setAcl(acl);
+                dataShareService.update(dataShare);
+            }
+        }
+
+        for (Map.Entry<Long, RangerGdsObjectACL> entry : projectAcls.entrySet()) {
+            Long               id  = entry.getKey();
+            RangerGdsObjectACL acl = entry.getValue();
+
+            if (deletePrincipalFromAcl(acl, principalName, principalType) != null) {
+                RangerProject project = projectService.read(id);
+
+                project.setAcl(acl);
+                projectService.update(project);
+            }
+        }
+    }
+
 	private List<DataShareInDatasetSummary> getDshInDsSummary(List<RangerDataShare> dataShares, List<RangerDataset> datasets, RangerDataShareInDatasetList dshInDsList) {
 		Set<DataShareInDatasetSummary> ret          = new LinkedHashSet<>();
 		Map<Long, RangerDataset>       datasetMap   = toMap(datasets);
@@ -2136,6 +2179,22 @@
         }
     }
 
+	private GdsPermission deletePrincipalFromAcl(RangerGdsObjectACL acl, String principalName, String principalType) {
+        final Map<String, GdsPermission> principalAcls;
+
+		if (principalType.equalsIgnoreCase(REMOVE_REF_TYPE.USER.toString())) {
+            principalAcls = acl.getUsers();
+		} else if (principalType.equalsIgnoreCase(REMOVE_REF_TYPE.GROUP.toString())) {
+            principalAcls = acl.getGroups();
+		} else if (principalType.equalsIgnoreCase(REMOVE_REF_TYPE.ROLE.toString())) {
+            principalAcls = acl.getRoles();
+		} else {
+            principalAcls = null;
+        }
+
+		return principalAcls != null ? principalAcls.remove(principalName) : null;
+	}
+
     private void copyExistingBaseFields(RangerGdsBaseModelObject objToUpdate, RangerGdsBaseModelObject existingObj) {
         if (objToUpdate != null && existingObj != null) {
             // retain existing values for: guid, createdBy, createTime
diff --git a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
index abf2b0c..0aa03e7 100644
--- a/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/RoleDBStore.java
@@ -86,6 +86,9 @@
 	@Autowired
 	ServiceDBStore svcStore;
 
+	@Autowired
+	GdsDBStore gdsStore;
+
     RangerAdminConfig config;
 
     private Boolean populateExistingBaseFields = false;
@@ -200,19 +203,7 @@
             throw restErrorUtil.createRESTException("Role with name: " + roleName + " does not exist");
         }
 
-        ensureRoleDeleteAllowed(roleName);
-
-        Runnable roleVersionUpdater = new RoleVersionUpdater(daoMgr);
-        transactionSynchronizationAdapter.executeOnTransactionCommit(roleVersionUpdater);
-
-        RangerRole role = roleService.read(xxRole.getId());
-        roleRefUpdater.cleanupRefTables(role);
-		// delete role from audit filter configs
-		svcStore.updateServiceAuditConfig(role.getName(), REMOVE_REF_TYPE.ROLE);
-        roleService.delete(role);
-
-        List<XXTrxLog> trxLogList = roleService.getTransactionLog(role, null, "delete");
-        bizUtil.createTrxLog(trxLogList);
+        deleteRole(xxRole.getId());
     }
 
     @Override
@@ -227,6 +218,10 @@
         roleRefUpdater.cleanupRefTables(role);
 		// delete role from audit filter configs
 		svcStore.updateServiceAuditConfig(role.getName(), REMOVE_REF_TYPE.ROLE);
+
+		// delete gdsObject mapping of role
+		gdsStore.deletePrincipalFromGdsAcl(REMOVE_REF_TYPE.ROLE.toString(), role.getName());
+
         roleService.delete(role);
         List<XXTrxLog> trxLogList = roleService.getTransactionLog(role, null, "delete");
         bizUtil.createTrxLog(trxLogList);
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 d961bc5..2874002 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
@@ -166,6 +166,9 @@
 	RangerTransactionSynchronizationAdapter transactionSynchronizationAdapter;
 
 	@Autowired
+	GdsDBStore gdsStore;
+
+	@Autowired
 	@Qualifier(value = "transactionManager")
 	PlatformTransactionManager txManager;
 
@@ -2169,6 +2172,8 @@
 			}
 			//delete group from audit filter configs
 			svcStore.updateServiceAuditConfig(vXGroup.getName(), REMOVE_REF_TYPE.GROUP);
+			// delete group from dataset,datashare,project
+			gdsStore.deletePrincipalFromGdsAcl(REMOVE_REF_TYPE.GROUP.toString(), vXGroup.getName());
 			//delete XXGroup
 			xXGroupDao.remove(id);
 			//Create XXTrxLog
@@ -2396,6 +2401,8 @@
 			}
 			//delete user from audit filter configs
 			svcStore.updateServiceAuditConfig(vXUser.getName(), REMOVE_REF_TYPE.USER);
+			//delete gdsObject mapping of user
+			gdsStore.deletePrincipalFromGdsAcl(REMOVE_REF_TYPE.USER.toString(),vXUser.getName());
 			//delete XXUser entry of user
 			xXUserDao.remove(id);
 			//delete XXPortal entry of user
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java
index 8acca8f..20084bc 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDataShareDao.java
@@ -20,15 +20,19 @@
 package org.apache.ranger.db;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.authorization.utils.JsonUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXGdsDataShare;
+import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import javax.persistence.NoResultException;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 
 @Service
@@ -144,4 +148,27 @@
 
 		return ret != null ? ret : Collections.emptyList();
 	}
+
+	public Map<Long, RangerGdsObjectACL> getDataShareIdsAndACLs() {
+		Map<Long, RangerGdsObjectACL> ret = new HashMap<>();
+
+		try {
+			List<Object[]> rows = getEntityManager().createNamedQuery("XXGdsDataShare.getDataShareIdsAndACLs", Object[].class).getResultList();
+
+			if (rows != null) {
+				for (Object[] row : rows) {
+					Long               id  = (Long) row[0];
+					RangerGdsObjectACL acl = JsonUtils.jsonToObject((String) row[1], RangerGdsObjectACL.class);
+
+					if (acl != null) {
+						ret.put(id, acl);
+					}
+				}
+			}
+		} catch (NoResultException e) {
+			LOG.debug("getDataShareIdsAndACLs()", e);
+		}
+
+		return ret;
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java
index 5743ad7..4661b41 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsDatasetDao.java
@@ -20,6 +20,7 @@
 package org.apache.ranger.db;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.authorization.utils.JsonUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXGdsDataset;
 import org.slf4j.Logger;
@@ -28,8 +29,11 @@
 
 import javax.persistence.NoResultException;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL;
 
 @Service
 public class XXGdsDatasetDao extends BaseDao<XXGdsDataset> {
@@ -113,4 +117,27 @@
 
 		return ret != null ? ret : Collections.emptyList();
 	}
+
+	public Map<Long, RangerGdsObjectACL> getDatasetIdsAndACLs() {
+		Map<Long, RangerGdsObjectACL> ret = new HashMap<>();
+
+		try {
+			List<Object[]> rows = getEntityManager().createNamedQuery("XXGdsDataset.getDatasetIdsAndACLs", Object[].class).getResultList();
+
+			if (rows != null) {
+				for (Object[] row : rows) {
+					Long               id  = (Long) row[0];
+					RangerGdsObjectACL acl = JsonUtils.jsonToObject((String) row[1], RangerGdsObjectACL.class);
+
+					if (acl != null) {
+						ret.put(id, acl);
+					}
+				}
+			}
+		} catch (NoResultException e) {
+			LOG.debug("getDatasetIdsAndACLs()", e);
+		}
+
+		return ret;
+	}
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java
index 76bab86..ba8f6c6 100644
--- a/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java
+++ b/security-admin/src/main/java/org/apache/ranger/db/XXGdsProjectDao.java
@@ -20,15 +20,19 @@
 package org.apache.ranger.db;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.ranger.authorization.utils.JsonUtils;
 import org.apache.ranger.common.db.BaseDao;
 import org.apache.ranger.entity.XXGdsProject;
+import org.apache.ranger.plugin.model.RangerGds.RangerGdsObjectACL;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import javax.persistence.NoResultException;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 
 @Service
@@ -98,4 +102,27 @@
 
 		return ret != null ? ret : Collections.emptyList();
 	}
+
+	public Map<Long, RangerGdsObjectACL> getProjectIdsAndACLs() {
+		Map<Long, RangerGdsObjectACL> ret = new HashMap<>();
+
+		try {
+			List<Object[]> rows = getEntityManager().createNamedQuery("XXGdsProject.getProjectIdsAndACLs", Object[].class).getResultList();
+
+			if (rows != null) {
+				for (Object[] row : rows) {
+					Long               id  = (Long) row[0];
+					RangerGdsObjectACL acl = JsonUtils.jsonToObject((String) row[1], RangerGdsObjectACL.class);
+
+					if (acl != null) {
+						ret.put(id, acl);
+					}
+				}
+			}
+		} catch (NoResultException e) {
+			LOG.debug("getProjectIdsAndACLs()", e);
+		}
+
+		return ret;
+	}
 }
diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
index 52ecf8a..b3557d5 100755
--- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
+++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml
@@ -2178,6 +2178,11 @@
 		</query>
 	</named-query>
 
+   <named-query name="XXGdsDataset.getAlldatasetIdsAndACLs">
+		<query>select obj.id, obj.acl from XXGdsDataset obj where obj.id is NOT null
+		</query>
+	</named-query>
+
 	<named-query name="XXGdsProject.findByGuid">
 		<query>select obj from XXGdsProject obj where obj.guid = :guid</query>
 	</named-query>
@@ -2200,6 +2205,11 @@
 		</query>
 	</named-query>
 
+   <named-query name="XXGdsProject.getAllProjectIdsAndACLs">
+		<query>select obj.id, obj.acl from XXGdsProject obj where obj.id  is NOT null
+		</query>
+	</named-query>
+
 	<named-query name="XXGdsDataShare.findByGuid">
 		<query>select obj from XXGdsDataShare obj where obj.guid = :guid</query>
 	</named-query>
@@ -2227,6 +2237,11 @@
 		</query>
 	</named-query>
 
+<named-query name="XXGdsDataShare.getAlldataShareIdsAndACLs">
+		<query>select obj.id, obj.acl from XXGdsDataShare obj where obj.id is NOT null
+		</query>
+	</named-query>
+
 	<named-query name="XXGdsSharedResource.findByGuid">
 		<query>select obj from XXGdsSharedResource obj where obj.guid = :guid</query>
 	</named-query>
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java b/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java
index 6d340f2..6df1f73 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestRoleDBStore.java
@@ -78,6 +78,9 @@
     RoleDBStore roleDBStore = new RoleDBStore();
 
     @Mock
+    GdsDBStore gdsStore;
+
+    @Mock
     RangerBizUtil bizUtil;
 
     @Mock
@@ -482,14 +485,11 @@
 
     @Test
     public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMorePolices() throws Exception {
-        XXRole             xxRole             = getTestRole();
-        XXRoleDao          xxRoleDao          = Mockito.mock(XXRoleDao.class);
-        XXPolicyRefRoleDao xxPolicyRefRoleDao = Mockito.mock(XXPolicyRefRoleDao.class);
+        XXRole    xxRole    = getTestRole();
+        XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class);
 
         Mockito.when(xxRoleDao.findByRoleName(roleName)).thenReturn(xxRole);
-        Mockito.when(daoMgr.getXXPolicyRefRole()).thenReturn(xxPolicyRefRoleDao);
         Mockito.when(daoMgr.getXXRole()).thenReturn(xxRoleDao);
-        Mockito.when(xxPolicyRefRoleDao.findRoleRefPolicyCount(roleName)).thenReturn(1L);
         thrown.expect(Exception.class);
 
         roleDBStore.deleteRole(roleName);
@@ -497,17 +497,11 @@
 
     @Test
     public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMoreRoles() throws Exception {
-        XXRole             xxRole             = getTestRole();
-        XXRoleDao          xxRoleDao          = Mockito.mock(XXRoleDao.class);
-        XXPolicyRefRoleDao xxPolicyRefRoleDao = Mockito.mock(XXPolicyRefRoleDao.class);
-        XXRoleRefRoleDao   xxRoleRefRoleDao   = Mockito.mock(XXRoleRefRoleDao.class);
+        XXRole    xxRole    = getTestRole();
+        XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class);
 
         Mockito.when(daoMgr.getXXRole()).thenReturn(xxRoleDao);
         Mockito.when(xxRoleDao.findByRoleName(roleName)).thenReturn(xxRole);
-        Mockito.when(daoMgr.getXXPolicyRefRole()).thenReturn(xxPolicyRefRoleDao);
-        Mockito.when(xxPolicyRefRoleDao.findRoleRefPolicyCount(roleName)).thenReturn(0L);
-        Mockito.when(daoMgr.getXXRoleRefRole()).thenReturn(xxRoleRefRoleDao);
-        Mockito.when(xxRoleRefRoleDao.findRoleRefRoleCount(roleName)).thenReturn(1L);
         thrown.expect(Exception.class);
 
         roleDBStore.deleteRole(roleName);
@@ -515,20 +509,11 @@
 
     @Test
     public void testDeleteRoleByValidRoleNameWhenRoleIsAssociatedWithOneOrMoreSecurityZones() throws Exception {
-        XXRole                   xxRole             = getTestRole();
-        XXRoleDao                xxRoleDao          = Mockito.mock(XXRoleDao.class);
-        XXPolicyRefRoleDao       xxPolicyRefRoleDao = Mockito.mock(XXPolicyRefRoleDao.class);
-        XXRoleRefRoleDao         xxRoleRefRoleDao   = Mockito.mock(XXRoleRefRoleDao.class);
-        XXSecurityZoneRefRoleDao xxSzRefRoleDao     = Mockito.mock(XXSecurityZoneRefRoleDao.class);
+        XXRole    xxRole    = getTestRole();
+        XXRoleDao xxRoleDao = Mockito.mock(XXRoleDao.class);
 
         Mockito.when(daoMgr.getXXRole()).thenReturn(xxRoleDao);
         Mockito.when(xxRoleDao.findByRoleName(roleName)).thenReturn(xxRole);
-        Mockito.when(daoMgr.getXXPolicyRefRole()).thenReturn(xxPolicyRefRoleDao);
-        Mockito.when(xxPolicyRefRoleDao.findRoleRefPolicyCount(roleName)).thenReturn(0L);
-        Mockito.when(daoMgr.getXXRoleRefRole()).thenReturn(xxRoleRefRoleDao);
-        Mockito.when(xxRoleRefRoleDao.findRoleRefRoleCount(roleName)).thenReturn(0L);
-        Mockito.when(daoMgr.getXXSecurityZoneRefRole()).thenReturn(xxSzRefRoleDao);
-        Mockito.when(xxSzRefRoleDao.findRoleRefZoneCount(roleName)).thenReturn(1L);
         thrown.expect(Exception.class);
 
         roleDBStore.deleteRole(roleName);
diff --git a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
index 601dbe9..ce48c82 100644
--- a/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
+++ b/security-admin/src/test/java/org/apache/ranger/biz/TestXUserMgr.java
@@ -220,6 +220,9 @@
 	ServiceDBStore svcStore;
 
 	@Mock
+	GdsDBStore gdsStore;
+
+	@Mock
 	XGroupGroupService xGroupGroupService;
 
 	@Mock