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

abhi pushed a commit to branch ranger-2.7
in repository https://gitbox.apache.org/repos/asf/ranger.git

commit 871ebc43b5c194089efb31ae877f407bba294a03
Author: Vyom Mani Tiwari <[email protected]>
AuthorDate: Wed Jul 16 20:59:18 2025 +0530

    RANGER-5251: dedupTags() doesn’t remove duplicate tag IDs within a single 
resource’s resourceToTagIds list (#608)
    
    (cherry picked from commit fb4f8d9ea395f72b3cfe2c7936aeb67ff4ee7c16)
---
 .../org/apache/ranger/plugin/util/ServiceTags.java |  8 ++++
 .../apache/ranger/plugin/util/TestServiceTags.java | 51 ++++++++++++++++++++++
 2 files changed, 59 insertions(+)

diff --git 
a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java 
b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
index 12f026e32..c77b96711 100644
--- a/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
+++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/ServiceTags.java
@@ -21,12 +21,14 @@
 
 
 import java.util.Date;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.ArrayList;
+import java.util.Set;
 
 import org.apache.commons.lang3.tuple.MutablePair;
 import org.apache.ranger.authorization.utils.StringUtil;
@@ -283,6 +285,7 @@ public int dedupTags() {
                final int finalTagsCount = tags.size();
 
                for (Map.Entry<Long, List<Long>> resourceEntry : 
resourceToTagIds.entrySet()) {
+                       Set<Long> uniqueTagIds = new 
HashSet<>(resourceEntry.getValue().size());
                        for (ListIterator<Long> listIter = 
resourceEntry.getValue().listIterator(); listIter.hasNext(); ) {
                                final Long tagId       = listIter.next();
                                Long       mappedTagId = null;
@@ -295,6 +298,11 @@ public int dedupTags() {
                                        continue;
                                }
 
+                               if (!uniqueTagIds.add(mappedTagId)) {
+                                       listIter.remove();
+                                       continue;
+                               }
+
                                listIter.set(mappedTagId);
 
                                RangerTag tag = tags.get(mappedTagId);
diff --git 
a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
 
b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
index d44309805..3866942bd 100644
--- 
a/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
+++ 
b/agents-common/src/test/java/org/apache/ranger/plugin/util/TestServiceTags.java
@@ -23,9 +23,12 @@
 import org.junit.Test;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -205,6 +208,54 @@ public void testDedupTags_HigherIdTagAfterLowerIdRemoval() 
{
         assertFalse(svcTags1.getTags().containsKey(newTagId));
     }
 
+    @Test
+    public void testDedupTags_DuplicateResourceToTagIds() {
+        RangerTag[] tags = {
+                new RangerTag("PII", Collections.singletonMap("type", 
"email")),
+                new RangerTag("PII", Collections.singletonMap("type", 
"email")),
+                new RangerTag("PCI", Collections.emptyMap()),
+                new RangerTag("PCI", Collections.emptyMap()),
+                new RangerTag("PII", Collections.singletonMap("type", "email"))
+        };
+        ServiceTags svcTags = createServiceTags(tags, RESOURCES);
+        assertEquals(5, svcTags.getTags().size());
+
+        int dedupCount = svcTags.dedupTags();
+        assertEquals(3, dedupCount);
+        assertEquals(2, svcTags.getTags().size());
+
+        ServiceTags svcTags1 = new ServiceTags(svcTags);
+        // Simulate resource1 deletion (like delete table_1)
+        svcTags1.getResourceToTagIds().remove(0L);
+        // Clear tags to simulate new sync
+        svcTags1.getTags().clear();
+
+        RangerTag tag1 = new RangerTag("PII", Collections.singletonMap("type", 
"email"));
+        RangerTag tag2 = new RangerTag("PII", Collections.singletonMap("type", 
"email"));
+        tag1.setId(200L);
+        tag2.setId(201L);
+        svcTags1.getTags().put(200L, tag1);
+        svcTags1.getTags().put(201L, tag2);
+
+        // Set resource mappings with duplicate tag IDs
+        svcTags1.getResourceToTagIds().put(0L, new 
ArrayList<>(Arrays.asList(200L, 200L, 201L)));
+        svcTags1.getResourceToTagIds().put(1L, new 
ArrayList<>(Arrays.asList(200L, 200L, 201L, 201L)));
+
+        dedupCount = svcTags1.dedupTags();
+        assertEquals(1, dedupCount);
+        assertEquals(1, svcTags1.getTags().size());
+
+        // Verify resource1 has no duplicate tag IDs
+        List<Long> resource1Tags = svcTags1.getResourceToTagIds().get(0L);
+        Set<Long> uniqueTags = new HashSet<>(resource1Tags);
+        assertEquals("Duplicate tag IDs should be removed from resource1", 
uniqueTags.size(), resource1Tags.size());
+
+        // Verify resource2 has no duplicate tag IDs
+        List<Long> resource2Tags = svcTags1.getResourceToTagIds().get(1L);
+        uniqueTags = new HashSet<>(resource2Tags);
+        assertEquals("Duplicate tag IDs should be removed from resource2", 
uniqueTags.size(), resource2Tags.size());
+    }
+
     private ServiceTags createServiceTags(RangerTag[] tags, 
RangerServiceResource[] resources) {
         ServiceTags ret = new ServiceTags();
 

Reply via email to