This is an automated email from the ASF dual-hosted git repository.
yuqi1129 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new 29093d2ecd [#10269] fix(core): prevent fileset privilege removal on
failed drop (#12582)
29093d2ecd is described below
commit 29093d2ecd3d9562335d7f7aa49b7985afd8111e
Author: Saravanan Kandaswamy <[email protected]>
AuthorDate: Mon Sep 21 08:57:52 2026 +0530
[#10269] fix(core): prevent fileset privilege removal on failed drop
(#12582)
[#10269] fix(core): prevent fileset privilege removal on failed drop
### What changes were proposed in this pull request?
Updated `FilesetHookDispatcher.dropFileset` to remove authorization
privileges only when the delegated fileset drop succeeds.
Added a regression test verifying that privileges are not removed when
the delegate returns `false`.
### Why are the changes needed?
When `dropFileset` returned `false`, authorization privileges were still
removed. This could leave authorization state inconsistent with metadata
state when the fileset was not deleted.
Fix: #10269
### Does this PR introduce _any_ user-facing change?
No. This is an internal authorization consistency fix and does not
change any public APIs or configuration properties.
### How was this patch tested?
The following focused tests passed:
```text
./gradlew :core:test --tests
org.apache.gravitino.hook.TestFilesetHookDispatcher -PskipITs
---------
Co-authored-by: Qi Yu <[email protected]>
---
.../gravitino/hook/TestFilesetHookDispatcher.java | 28 ++++++++++++++++++++++
.../gravitino/hook/TestSchemaHookDispatcher.java | 17 +++++++++++++
.../gravitino/hook/TestTopicHookDispatcher.java | 18 ++++++++++++++
3 files changed, 63 insertions(+)
diff --git
a/core/src/test/java/org/apache/gravitino/hook/TestFilesetHookDispatcher.java
b/core/src/test/java/org/apache/gravitino/hook/TestFilesetHookDispatcher.java
index ae662040b3..1a47a83025 100644
---
a/core/src/test/java/org/apache/gravitino/hook/TestFilesetHookDispatcher.java
+++
b/core/src/test/java/org/apache/gravitino/hook/TestFilesetHookDispatcher.java
@@ -43,9 +43,11 @@ import static org.mockito.ArgumentMatchers.eq;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
+import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.gravitino.Config;
+import org.apache.gravitino.Entity;
import org.apache.gravitino.GravitinoEnv;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.NameIdentifier;
@@ -260,6 +262,32 @@ public class TestFilesetHookDispatcher extends
TestOperationDispatcher {
});
}
+ @Test
+ public void testDropFilesetShouldNotRemovePrivilegesWhenDropReturnsFalse() {
+ NameIdentifier ident = NameIdentifier.of("metalake", "catalog", "schema",
"fileset");
+ FilesetDispatcher delegate = Mockito.mock(FilesetDispatcher.class);
+ FilesetHookDispatcher hookDispatcher = new FilesetHookDispatcher(delegate);
+ List<String> locations = Lists.newArrayList("/tmp/fileset");
+
+ Mockito.when(delegate.dropFileset(ident)).thenReturn(false);
+
+ try (MockedStatic<AuthorizationUtils> mockedAuthz =
+ Mockito.mockStatic(AuthorizationUtils.class)) {
+ mockedAuthz
+ .when(
+ () -> AuthorizationUtils.getMetadataObjectLocation(ident,
Entity.EntityType.FILESET))
+ .thenReturn(locations);
+
+ Assertions.assertFalse(hookDispatcher.dropFileset(ident));
+
+ mockedAuthz.verify(
+ () ->
+ AuthorizationUtils.authorizationPluginRemovePrivileges(
+ ident, Entity.EntityType.FILESET, locations),
+ Mockito.never());
+ }
+ }
+
@Test
public void testRenameAuthorizationPrivilege() {
Namespace filesetNs = Namespace.of(metalake, catalog, "schema1121");
diff --git
a/core/src/test/java/org/apache/gravitino/hook/TestSchemaHookDispatcher.java
b/core/src/test/java/org/apache/gravitino/hook/TestSchemaHookDispatcher.java
index 478ab3efd5..8c5cfa41c1 100644
--- a/core/src/test/java/org/apache/gravitino/hook/TestSchemaHookDispatcher.java
+++ b/core/src/test/java/org/apache/gravitino/hook/TestSchemaHookDispatcher.java
@@ -260,6 +260,23 @@ public class TestSchemaHookDispatcher {
}
}
+ @Test
+ public void testDropSchemaDoesNotRemovePrivilegesWhenSchemaDoesNotExist() {
+ NameIdentifier ident = NameIdentifier.of("test_metalake", "test_catalog",
"A:B:C");
+ when(mockDispatcher.dropSchema(eq(ident), eq(false))).thenReturn(false);
+
+ try (MockedStatic<AuthorizationUtils> authz =
Mockito.mockStatic(AuthorizationUtils.class)) {
+ boolean dropped = hookDispatcher.dropSchema(ident, false);
+
+ Assertions.assertFalse(dropped);
+ authz.verify(
+ () ->
+ AuthorizationUtils.authorizationPluginRemovePrivileges(
+ ident, Entity.EntityType.SCHEMA, null),
+ Mockito.never());
+ }
+ }
+
@SuppressWarnings("unchecked")
private List<MetadataObject> captureOwnedObjects() {
ArgumentCaptor<List<MetadataObject>> captor =
ArgumentCaptor.forClass(List.class);
diff --git
a/core/src/test/java/org/apache/gravitino/hook/TestTopicHookDispatcher.java
b/core/src/test/java/org/apache/gravitino/hook/TestTopicHookDispatcher.java
index 96c851aff7..240e3ec71d 100644
--- a/core/src/test/java/org/apache/gravitino/hook/TestTopicHookDispatcher.java
+++ b/core/src/test/java/org/apache/gravitino/hook/TestTopicHookDispatcher.java
@@ -25,6 +25,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.gravitino.Entity;
import org.apache.gravitino.GravitinoEnv;
import org.apache.gravitino.MetadataObject;
import org.apache.gravitino.NameIdentifier;
@@ -78,6 +79,23 @@ public class TestTopicHookDispatcher extends
TestOperationDispatcher {
Mockito.when(catalog.getAuthorizationPlugin()).thenReturn(authorizationPlugin);
}
+ @Test
+ public void testDropTopicDoesNotRemovePrivilegesWhenTopicDoesNotExist() {
+ TopicDispatcher dispatcher = Mockito.mock(TopicDispatcher.class);
+ TopicHookDispatcher hook = new TopicHookDispatcher(dispatcher);
+ NameIdentifier ident = NameIdentifier.of("test_metalake", "test_catalog",
"topic");
+ Mockito.when(dispatcher.dropTopic(ident)).thenReturn(false);
+
+ try (MockedStatic<AuthorizationUtils> authz =
Mockito.mockStatic(AuthorizationUtils.class)) {
+ Assertions.assertFalse(hook.dropTopic(ident));
+ authz.verify(
+ () ->
+ AuthorizationUtils.authorizationPluginRemovePrivileges(
+ ident, Entity.EntityType.TOPIC, null),
+ Mockito.never());
+ }
+ }
+
@Test
public void testCreateTopicSetsOwnerWithNormalizedIdentifier() throws
Exception {
// Self-contained: use a fresh hook with a directly-mocked TopicDispatcher
and a case-