This is an automated email from the ASF dual-hosted git repository.
jerryshao pushed a commit to branch branch-1.3
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/branch-1.3 by this push:
new 8a811218fa [Cherry-pick to branch-1.3] [#13504] fix(core): Report
missing securable objects correctly (#13505) (#13536)
8a811218fa is described below
commit 8a811218fa0b3713cbed34c47b6ca82c274a0d68
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Mon Sep 28 19:04:10 2026 +0800
[Cherry-pick to branch-1.3] [#13504] fix(core): Report missing securable
objects correctly (#13505) (#13536)
### What changes were proposed in this pull request?
Cherry-pick #13505 to `branch-1.3`.
Convert `NoSuchEntityException` raised while resolving a role's
securable object into `NoSuchMetadataObjectException`, while preserving
the original cause.
Add a regression test that verifies the correct exception and ensures
the role remains unchanged after the failed update.
The cherry-pick conflicts have been resolved in
f53cb8a8438db2f454c4eb1599f94efcda878377.
### Why are the changes needed?
Role privilege updates currently report every missing entity as a
missing role. When the role exists but its securable object cannot be
resolved, clients incorrectly receive `NoSuchRoleException`, masking the
actual failure.
Fix: #13504
### Does this PR introduce _any_ user-facing change?
Yes. When a securable object is missing during a role privilege update,
clients now receive `NoSuchMetadataObjectException` instead of the
incorrect `NoSuchRoleException`. Missing roles retain their existing
behavior.
### How was this patch tested?
- `./gradlew :core:spotlessApply`
- `./gradlew :core:test --tests
org.apache.gravitino.storage.relational.service.TestRoleMetaService`
- `git diff --check`
---------
Co-authored-by: roryqi <[email protected]>
Co-authored-by: roryqi <[email protected]>
---
.../relational/service/RoleMetaService.java | 8 +++-
.../relational/service/TestRoleMetaService.java | 44 ++++++++++++++++++++++
2 files changed, 51 insertions(+), 1 deletion(-)
diff --git
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
index 803d4949df..38358942e4 100644
---
a/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
+++
b/core/src/main/java/org/apache/gravitino/storage/relational/service/RoleMetaService.java
@@ -41,6 +41,7 @@ import org.apache.gravitino.Namespace;
import org.apache.gravitino.authorization.AuthorizationUtils;
import org.apache.gravitino.authorization.SecurableObject;
import org.apache.gravitino.exceptions.NoSuchEntityException;
+import org.apache.gravitino.exceptions.NoSuchMetadataObjectException;
import org.apache.gravitino.meta.RoleEntity;
import org.apache.gravitino.meta.UserEntity;
import org.apache.gravitino.metrics.Monitored;
@@ -281,7 +282,12 @@ public class RoleMetaService {
NameIdentifier nameIdentifier =
MetadataObjectUtil.toEntityIdent(metalake, object);
Entity.EntityType entityType =
MetadataObjectUtil.toEntityType(object.type());
-
objectBuilder.withMetadataObjectId(EntityIdService.getEntityId(nameIdentifier,
entityType));
+ try {
+
objectBuilder.withMetadataObjectId(EntityIdService.getEntityId(nameIdentifier,
entityType));
+ } catch (NoSuchEntityException nse) {
+ throw new NoSuchMetadataObjectException(
+ nse, "Metadata object %s type %s doesn't exist",
object.fullName(), object.type());
+ }
securableObjectPOs.add(objectBuilder.build());
}
return securableObjectPOs;
diff --git
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
index 287b346413..3d3f57a069 100644
---
a/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
+++
b/core/src/test/java/org/apache/gravitino/storage/relational/service/TestRoleMetaService.java
@@ -46,6 +46,7 @@ import org.apache.gravitino.authorization.Privileges;
import org.apache.gravitino.authorization.SecurableObject;
import org.apache.gravitino.authorization.SecurableObjects;
import org.apache.gravitino.exceptions.NoSuchEntityException;
+import org.apache.gravitino.exceptions.NoSuchMetadataObjectException;
import org.apache.gravitino.meta.AuditInfo;
import org.apache.gravitino.meta.BaseMetalake;
import org.apache.gravitino.meta.CatalogEntity;
@@ -835,6 +836,49 @@ class TestRoleMetaService extends TestJDBCBackend {
Assertions.assertTrue(revokeMultipleRole.securableObjects().isEmpty());
}
+ @TestTemplate
+ void testUpdateRoleReportsMissingSecurableObject() throws IOException {
+ createAndInsertMakeLake(METALAKE_NAME);
+ String catalogName = "catalog";
+ createAndInsertCatalog(METALAKE_NAME, catalogName);
+
+ RoleMetaService roleMetaService = RoleMetaService.getInstance();
+ RoleEntity role =
+ createRoleEntity(
+ RandomIdGenerator.INSTANCE.nextId(),
+ AuthorizationUtils.ofRoleNamespace(METALAKE_NAME),
+ "role",
+ AUDIT_INFO,
+ catalogName);
+ roleMetaService.insertRole(role, false);
+
+ String missingCatalog = "missing_catalog";
+ NoSuchMetadataObjectException exception =
+ Assertions.assertThrows(
+ NoSuchMetadataObjectException.class,
+ () ->
+ roleMetaService.updateRole(
+ role.nameIdentifier(),
+ (RoleEntity current) ->
+ RoleEntity.builder()
+ .withId(current.id())
+ .withName(current.name())
+ .withNamespace(current.namespace())
+ .withProperties(current.properties())
+ .withSecurableObjects(
+ Lists.newArrayList(
+ SecurableObjects.ofCatalog(
+ missingCatalog,
+
Lists.newArrayList(Privileges.UseCatalog.allow()))))
+ .withAuditInfo(current.auditInfo())
+ .build()));
+
+ Assertions.assertEquals(
+ "Metadata object missing_catalog type CATALOG doesn't exist",
exception.getMessage());
+ Assertions.assertInstanceOf(NoSuchEntityException.class,
exception.getCause());
+ Assertions.assertEquals(role,
roleMetaService.getRoleByIdentifier(role.nameIdentifier()));
+ }
+
@TestTemplate
void testDeleteMetalakeCascade() throws IOException {
BaseMetalake metalake = createAndInsertMakeLake(METALAKE_NAME);