From 11b04997433b043d148f4dc15f33a3d04ea0aedc Mon Sep 17 00:00:00 2001 From: Honah J Date: Mon, 19 May 2025 15:19:09 -0500 Subject: [PATCH 1/2] refactor authorize part --- .../service/admin/PolarisAdminService.java | 210 +++++++++--------- 1 file changed, 108 insertions(+), 102 deletions(-) diff --git a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java index 3e7bf92263..478cdd8b8b 100644 --- a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java +++ b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkArgument; +import com.google.common.base.Preconditions; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import jakarta.validation.constraints.NotNull; @@ -413,122 +414,107 @@ private void authorizeGrantOnCatalogRoleToPrincipalRoleOperationOrThrow( principalRoleWrapper); } - private void authorizeGrantOnCatalogOperationOrThrow( - PolarisAuthorizableOperation op, String catalogName, String catalogRoleName) { - resolutionManifest = - entityManager.prepareResolutionManifest(callContext, securityContext, catalogName); - resolutionManifest.addTopLevelName( - catalogName, PolarisEntityType.CATALOG, false /* isOptional */); - resolutionManifest.addPath( - new ResolverPath(List.of(catalogRoleName), PolarisEntityType.CATALOG_ROLE), - catalogRoleName); - ResolverStatus status = resolutionManifest.resolveAll(); - - if (status.getStatus() == ResolverStatus.StatusEnum.ENTITY_COULD_NOT_BE_RESOLVED) { - throw new NotFoundException("Catalog not found: %s", catalogName); - } else if (status.getStatus() == ResolverStatus.StatusEnum.PATH_COULD_NOT_BE_FULLY_RESOLVED) { - throw new NotFoundException("CatalogRole not found: %s.%s", catalogName, catalogRoleName); - } - - PolarisResolvedPathWrapper catalogWrapper = - resolutionManifest.getResolvedTopLevelEntity(catalogName, PolarisEntityType.CATALOG); - PolarisResolvedPathWrapper catalogRoleWrapper = - resolutionManifest.getResolvedPath(catalogRoleName, true); - authorizer.authorizeOrThrow( - callContext, - authenticatedPrincipal, - resolutionManifest.getAllActivatedCatalogRoleAndPrincipalRoles(), - op, - catalogWrapper, - catalogRoleWrapper); - } - - private void authorizeGrantOnNamespaceOperationOrThrow( + private void authorizeGrantOnEntityOperationOrThrow( PolarisAuthorizableOperation op, String catalogName, - Namespace namespace, - String catalogRoleName) { + String catalogRoleName, + PolarisEntityType entityType, + List subTypes, + @Nullable Namespace namespace, + @Nullable String entityName) { resolutionManifest = entityManager.prepareResolutionManifest(callContext, securityContext, catalogName); - resolutionManifest.addPath( - new ResolverPath(Arrays.asList(namespace.levels()), PolarisEntityType.NAMESPACE), - namespace); resolutionManifest.addPath( new ResolverPath(List.of(catalogRoleName), PolarisEntityType.CATALOG_ROLE), catalogRoleName); - ResolverStatus status = resolutionManifest.resolveAll(); - if (status.getStatus() == ResolverStatus.StatusEnum.ENTITY_COULD_NOT_BE_RESOLVED) { - throw new NotFoundException("Catalog not found: %s", catalogName); - } else if (status.getStatus() == ResolverStatus.StatusEnum.PATH_COULD_NOT_BE_FULLY_RESOLVED) { - if (status.getFailedToResolvePath().getLastEntityType() == PolarisEntityType.NAMESPACE) { - throw new NoSuchNamespaceException( - "Namespace does not exist: %s", status.getFailedToResolvePath().getEntityNames()); - } else { - throw new NotFoundException("CatalogRole not found: %s.%s", catalogName, catalogRoleName); + switch (entityType) { + case CATALOG -> + resolutionManifest.addTopLevelName( + catalogName, PolarisEntityType.CATALOG, false /* isOptional */); + case NAMESPACE -> { + Preconditions.checkArgument(namespace != null, "Namespace cannot be null"); + resolutionManifest.addPath( + new ResolverPath(Arrays.asList(namespace.levels()), PolarisEntityType.NAMESPACE), + namespace); + } + case TABLE_LIKE -> { + Preconditions.checkArgument( + namespace != null && entityName != null, "Namespace and table name cannot be null"); + TableIdentifier identifier = TableIdentifier.of(namespace, entityName); + resolutionManifest.addPath( + new ResolverPath( + PolarisCatalogHelpers.tableIdentifierToList(identifier), + PolarisEntityType.TABLE_LIKE), + identifier); } - } - - PolarisResolvedPathWrapper namespaceWrapper = - resolutionManifest.getResolvedPath(namespace, true); - PolarisResolvedPathWrapper catalogRoleWrapper = - resolutionManifest.getResolvedPath(catalogRoleName, true); - authorizer.authorizeOrThrow( - callContext, - authenticatedPrincipal, - resolutionManifest.getAllActivatedCatalogRoleAndPrincipalRoles(), - op, - namespaceWrapper, - catalogRoleWrapper); - } + default -> + throw new IllegalArgumentException( + "Unsupported entity type for grant operation: " + entityType); + } - private void authorizeGrantOnTableLikeOperationOrThrow( - PolarisAuthorizableOperation op, - String catalogName, - List subTypes, - TableIdentifier identifier, - String catalogRoleName) { - resolutionManifest = - entityManager.prepareResolutionManifest(callContext, securityContext, catalogName); - resolutionManifest.addPath( - new ResolverPath( - PolarisCatalogHelpers.tableIdentifierToList(identifier), PolarisEntityType.TABLE_LIKE), - identifier); - resolutionManifest.addPath( - new ResolverPath(List.of(catalogRoleName), PolarisEntityType.CATALOG_ROLE), - catalogRoleName); ResolverStatus status = resolutionManifest.resolveAll(); - if (status.getStatus() == ResolverStatus.StatusEnum.ENTITY_COULD_NOT_BE_RESOLVED) { throw new NotFoundException("Catalog not found: %s", catalogName); } else if (status.getStatus() == ResolverStatus.StatusEnum.PATH_COULD_NOT_BE_FULLY_RESOLVED) { - if (status.getFailedToResolvePath().getLastEntityType() == PolarisEntityType.TABLE_LIKE) { - CatalogHandler.throwNotFoundExceptionForTableLikeEntity(identifier, subTypes); - } else { - throw new NotFoundException("CatalogRole not found: %s.%s", catalogName, catalogRoleName); - } - } - PolarisResolvedPathWrapper tableLikeWrapper = - resolutionManifest.getResolvedPath( - identifier, PolarisEntityType.TABLE_LIKE, PolarisEntitySubType.ANY_SUBTYPE, true); - if (!subTypes.contains(tableLikeWrapper.getRawLeafEntity().getSubType())) { - CatalogHandler.throwNotFoundExceptionForTableLikeEntity(identifier, subTypes); + switch (status.getFailedToResolvePath().getLastEntityType()) { + case NAMESPACE -> + throw new NoSuchNamespaceException( + "Namespace does not exist: %s", status.getFailedToResolvePath().getEntityNames()); + case TABLE_LIKE -> + CatalogHandler.throwNotFoundExceptionForTableLikeEntity( + TableIdentifier.of(namespace, entityName), subTypes); + default -> + throw new NotFoundException( + "CatalogRole not found: %s.%s", catalogName, catalogRoleName); + } } PolarisResolvedPathWrapper catalogRoleWrapper = resolutionManifest.getResolvedPath(catalogRoleName, true); + PolarisResolvedPathWrapper entityWrapper = + getResolvedPathWrapper(resolutionManifest, catalogName, entityType, namespace, entityName); + if (entityType == PolarisEntityType.TABLE_LIKE + && !subTypes.contains(entityWrapper.getRawLeafEntity().getSubType())) { + CatalogHandler.throwNotFoundExceptionForTableLikeEntity( + TableIdentifier.of(namespace, entityName), subTypes); + } authorizer.authorizeOrThrow( callContext, authenticatedPrincipal, resolutionManifest.getAllActivatedCatalogRoleAndPrincipalRoles(), op, - tableLikeWrapper, + entityWrapper, catalogRoleWrapper); } + private PolarisResolvedPathWrapper getResolvedPathWrapper( + PolarisResolutionManifest resolutionManifest, + String catalogName, + PolarisEntityType entityType, + @Nullable Namespace namespace, + @Nullable String entityName) { + return switch (entityType) { + case CATALOG -> + resolutionManifest.getResolvedTopLevelEntity(catalogName, PolarisEntityType.CATALOG); + + case NAMESPACE -> resolutionManifest.getResolvedPath(namespace, true); + + case TABLE_LIKE -> + resolutionManifest.getResolvedPath( + TableIdentifier.of(namespace, entityName), + PolarisEntityType.TABLE_LIKE, + PolarisEntitySubType.ANY_SUBTYPE, + true); + default -> + throw new IllegalArgumentException( + "Unsupported entity type for grant operation: " + entityType); + }; + } + /** Get all locations where data for a `CatalogEntity` may be stored */ private Set getCatalogLocations(CatalogEntity catalogEntity) { HashSet catalogLocations = new HashSet<>(); @@ -1563,7 +1549,8 @@ public boolean grantPrivilegeOnCatalogToRole( PolarisAuthorizableOperation op = PolarisAuthorizableOperation.ADD_CATALOG_GRANT_TO_CATALOG_ROLE; - authorizeGrantOnCatalogOperationOrThrow(op, catalogName, catalogRoleName); + authorizeGrantOnEntityOperationOrThrow( + op, catalogName, catalogRoleName, PolarisEntityType.CATALOG, List.of(), null, null); PolarisEntity catalogEntity = findCatalogByName(catalogName) @@ -1587,7 +1574,8 @@ public boolean revokePrivilegeOnCatalogFromRole( String catalogName, String catalogRoleName, PolarisPrivilege privilege) { PolarisAuthorizableOperation op = PolarisAuthorizableOperation.REVOKE_CATALOG_GRANT_FROM_CATALOG_ROLE; - authorizeGrantOnCatalogOperationOrThrow(op, catalogName, catalogRoleName); + authorizeGrantOnEntityOperationOrThrow( + op, catalogName, catalogRoleName, PolarisEntityType.CATALOG, List.of(), null, null); PolarisEntity catalogEntity = findCatalogByName(catalogName) @@ -1611,7 +1599,8 @@ public boolean grantPrivilegeOnNamespaceToRole( String catalogName, String catalogRoleName, Namespace namespace, PolarisPrivilege privilege) { PolarisAuthorizableOperation op = PolarisAuthorizableOperation.ADD_NAMESPACE_GRANT_TO_CATALOG_ROLE; - authorizeGrantOnNamespaceOperationOrThrow(op, catalogName, namespace, catalogRoleName); + authorizeGrantOnEntityOperationOrThrow( + op, catalogName, catalogRoleName, PolarisEntityType.NAMESPACE, List.of(), namespace, null); PolarisEntity catalogRoleEntity = findCatalogRoleByName(catalogName, catalogRoleName) @@ -1639,7 +1628,9 @@ public boolean revokePrivilegeOnNamespaceFromRole( String catalogName, String catalogRoleName, Namespace namespace, PolarisPrivilege privilege) { PolarisAuthorizableOperation op = PolarisAuthorizableOperation.REVOKE_NAMESPACE_GRANT_FROM_CATALOG_ROLE; - authorizeGrantOnNamespaceOperationOrThrow(op, catalogName, namespace, catalogRoleName); + + authorizeGrantOnEntityOperationOrThrow( + op, catalogName, catalogRoleName, PolarisEntityType.NAMESPACE, List.of(), namespace, null); PolarisEntity catalogRoleEntity = findCatalogRoleByName(catalogName, catalogRoleName) @@ -1669,12 +1660,14 @@ public boolean grantPrivilegeOnTableToRole( PolarisPrivilege privilege) { PolarisAuthorizableOperation op = PolarisAuthorizableOperation.ADD_TABLE_GRANT_TO_CATALOG_ROLE; - authorizeGrantOnTableLikeOperationOrThrow( + authorizeGrantOnEntityOperationOrThrow( op, catalogName, + catalogRoleName, + PolarisEntityType.TABLE_LIKE, List.of(PolarisEntitySubType.GENERIC_TABLE, PolarisEntitySubType.ICEBERG_TABLE), - identifier, - catalogRoleName); + identifier.namespace(), + identifier.name()); return grantPrivilegeOnTableLikeToRole( catalogName, @@ -1692,13 +1685,14 @@ public boolean revokePrivilegeOnTableFromRole( PolarisAuthorizableOperation op = PolarisAuthorizableOperation.REVOKE_TABLE_GRANT_FROM_CATALOG_ROLE; - authorizeGrantOnTableLikeOperationOrThrow( + authorizeGrantOnEntityOperationOrThrow( op, catalogName, + catalogRoleName, + PolarisEntityType.TABLE_LIKE, List.of(PolarisEntitySubType.GENERIC_TABLE, PolarisEntitySubType.ICEBERG_TABLE), - identifier, - catalogRoleName); - + identifier.namespace(), + identifier.name()); return revokePrivilegeOnTableLikeFromRole( catalogName, catalogRoleName, @@ -1714,8 +1708,14 @@ public boolean grantPrivilegeOnViewToRole( PolarisPrivilege privilege) { PolarisAuthorizableOperation op = PolarisAuthorizableOperation.ADD_VIEW_GRANT_TO_CATALOG_ROLE; - authorizeGrantOnTableLikeOperationOrThrow( - op, catalogName, List.of(PolarisEntitySubType.ICEBERG_VIEW), identifier, catalogRoleName); + authorizeGrantOnEntityOperationOrThrow( + op, + catalogName, + catalogRoleName, + PolarisEntityType.TABLE_LIKE, + List.of(PolarisEntitySubType.ICEBERG_VIEW), + identifier.namespace(), + identifier.name()); return grantPrivilegeOnTableLikeToRole( catalogName, @@ -1733,8 +1733,14 @@ public boolean revokePrivilegeOnViewFromRole( PolarisAuthorizableOperation op = PolarisAuthorizableOperation.REVOKE_VIEW_GRANT_FROM_CATALOG_ROLE; - authorizeGrantOnTableLikeOperationOrThrow( - op, catalogName, List.of(PolarisEntitySubType.ICEBERG_VIEW), identifier, catalogRoleName); + authorizeGrantOnEntityOperationOrThrow( + op, + catalogName, + catalogRoleName, + PolarisEntityType.TABLE_LIKE, + List.of(PolarisEntitySubType.ICEBERG_VIEW), + identifier.namespace(), + identifier.name()); return revokePrivilegeOnTableLikeFromRole( catalogName, From 2e67443c9e397c3744c6264055ec23d8201c6bea Mon Sep 17 00:00:00 2001 From: Honah J Date: Mon, 19 May 2025 16:31:59 -0500 Subject: [PATCH 2/2] Refactor AdminService --- .../service/admin/PolarisAdminService.java | 305 ++++++++---------- 1 file changed, 134 insertions(+), 171 deletions(-) diff --git a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java index 478cdd8b8b..c39ad4bd06 100644 --- a/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java +++ b/service/common/src/main/java/org/apache/polaris/service/admin/PolarisAdminService.java @@ -475,12 +475,7 @@ private void authorizeGrantOnEntityOperationOrThrow( PolarisResolvedPathWrapper catalogRoleWrapper = resolutionManifest.getResolvedPath(catalogRoleName, true); PolarisResolvedPathWrapper entityWrapper = - getResolvedPathWrapper(resolutionManifest, catalogName, entityType, namespace, entityName); - if (entityType == PolarisEntityType.TABLE_LIKE - && !subTypes.contains(entityWrapper.getRawLeafEntity().getSubType())) { - CatalogHandler.throwNotFoundExceptionForTableLikeEntity( - TableIdentifier.of(namespace, entityName), subTypes); - } + getResolvedPathWrapper(catalogName, entityType, subTypes, namespace, entityName, true); authorizer.authorizeOrThrow( callContext, @@ -491,30 +486,6 @@ private void authorizeGrantOnEntityOperationOrThrow( catalogRoleWrapper); } - private PolarisResolvedPathWrapper getResolvedPathWrapper( - PolarisResolutionManifest resolutionManifest, - String catalogName, - PolarisEntityType entityType, - @Nullable Namespace namespace, - @Nullable String entityName) { - return switch (entityType) { - case CATALOG -> - resolutionManifest.getResolvedTopLevelEntity(catalogName, PolarisEntityType.CATALOG); - - case NAMESPACE -> resolutionManifest.getResolvedPath(namespace, true); - - case TABLE_LIKE -> - resolutionManifest.getResolvedPath( - TableIdentifier.of(namespace, entityName), - PolarisEntityType.TABLE_LIKE, - PolarisEntitySubType.ANY_SUBTYPE, - true); - default -> - throw new IllegalArgumentException( - "Unsupported entity type for grant operation: " + entityType); - }; - } - /** Get all locations where data for a `CatalogEntity` may be stored */ private Set getCatalogLocations(CatalogEntity catalogEntity) { HashSet catalogLocations = new HashSet<>(); @@ -1552,21 +1523,15 @@ public boolean grantPrivilegeOnCatalogToRole( authorizeGrantOnEntityOperationOrThrow( op, catalogName, catalogRoleName, PolarisEntityType.CATALOG, List.of(), null, null); - PolarisEntity catalogEntity = - findCatalogByName(catalogName) - .orElseThrow(() -> new NotFoundException("Parent catalog %s not found", catalogName)); - PolarisEntity catalogRoleEntity = - findCatalogRoleByName(catalogName, catalogRoleName) - .orElseThrow(() -> new NotFoundException("CatalogRole %s not found", catalogRoleName)); - - return metaStoreManager - .grantPrivilegeOnSecurableToRole( - getCurrentPolarisContext(), - catalogRoleEntity, - PolarisEntity.toCoreList(List.of(catalogEntity)), - catalogEntity, - privilege) - .isSuccess(); + return managePrivilegeOnEntityForRole( + true, + catalogName, + catalogRoleName, + PolarisEntityType.CATALOG, + List.of(), + null, + null, + privilege); } /** Removes a catalog-level grant on {@code catalogName} from {@code catalogRoleName}. */ @@ -1577,21 +1542,15 @@ public boolean revokePrivilegeOnCatalogFromRole( authorizeGrantOnEntityOperationOrThrow( op, catalogName, catalogRoleName, PolarisEntityType.CATALOG, List.of(), null, null); - PolarisEntity catalogEntity = - findCatalogByName(catalogName) - .orElseThrow(() -> new NotFoundException("Parent catalog %s not found", catalogName)); - PolarisEntity catalogRoleEntity = - findCatalogRoleByName(catalogName, catalogRoleName) - .orElseThrow(() -> new NotFoundException("CatalogRole %s not found", catalogRoleName)); - - return metaStoreManager - .revokePrivilegeOnSecurableFromRole( - getCurrentPolarisContext(), - catalogRoleEntity, - PolarisEntity.toCoreList(List.of(catalogEntity)), - catalogEntity, - privilege) - .isSuccess(); + return managePrivilegeOnEntityForRole( + false, + catalogName, + catalogRoleName, + PolarisEntityType.CATALOG, + List.of(), + null, + null, + privilege); } /** Adds a namespace-level grant on {@code namespace} to {@code catalogRoleName}. */ @@ -1602,25 +1561,15 @@ public boolean grantPrivilegeOnNamespaceToRole( authorizeGrantOnEntityOperationOrThrow( op, catalogName, catalogRoleName, PolarisEntityType.NAMESPACE, List.of(), namespace, null); - PolarisEntity catalogRoleEntity = - findCatalogRoleByName(catalogName, catalogRoleName) - .orElseThrow(() -> new NotFoundException("CatalogRole %s not found", catalogRoleName)); - - PolarisResolvedPathWrapper resolvedPathWrapper = resolutionManifest.getResolvedPath(namespace); - if (resolvedPathWrapper == null) { - throw new NotFoundException("Namespace %s not found", namespace); - } - List catalogPath = resolvedPathWrapper.getRawParentPath(); - PolarisEntity namespaceEntity = resolvedPathWrapper.getRawLeafEntity(); - - return metaStoreManager - .grantPrivilegeOnSecurableToRole( - getCurrentPolarisContext(), - catalogRoleEntity, - PolarisEntity.toCoreList(catalogPath), - namespaceEntity, - privilege) - .isSuccess(); + return managePrivilegeOnEntityForRole( + true, + catalogName, + catalogRoleName, + PolarisEntityType.NAMESPACE, + List.of(), + namespace, + null, + privilege); } /** Removes a namespace-level grant on {@code namespace} from {@code catalogRoleName}. */ @@ -1632,25 +1581,15 @@ public boolean revokePrivilegeOnNamespaceFromRole( authorizeGrantOnEntityOperationOrThrow( op, catalogName, catalogRoleName, PolarisEntityType.NAMESPACE, List.of(), namespace, null); - PolarisEntity catalogRoleEntity = - findCatalogRoleByName(catalogName, catalogRoleName) - .orElseThrow(() -> new NotFoundException("CatalogRole %s not found", catalogRoleName)); - - PolarisResolvedPathWrapper resolvedPathWrapper = resolutionManifest.getResolvedPath(namespace); - if (resolvedPathWrapper == null) { - throw new NotFoundException("Namespace %s not found", namespace); - } - List catalogPath = resolvedPathWrapper.getRawParentPath(); - PolarisEntity namespaceEntity = resolvedPathWrapper.getRawLeafEntity(); - - return metaStoreManager - .revokePrivilegeOnSecurableFromRole( - getCurrentPolarisContext(), - catalogRoleEntity, - PolarisEntity.toCoreList(catalogPath), - namespaceEntity, - privilege) - .isSuccess(); + return managePrivilegeOnEntityForRole( + false, + catalogName, + catalogRoleName, + PolarisEntityType.NAMESPACE, + List.of(), + namespace, + null, + privilege); } public boolean grantPrivilegeOnTableToRole( @@ -1668,12 +1607,14 @@ public boolean grantPrivilegeOnTableToRole( List.of(PolarisEntitySubType.GENERIC_TABLE, PolarisEntitySubType.ICEBERG_TABLE), identifier.namespace(), identifier.name()); - - return grantPrivilegeOnTableLikeToRole( + return managePrivilegeOnEntityForRole( + true, catalogName, catalogRoleName, - identifier, + PolarisEntityType.TABLE_LIKE, List.of(PolarisEntitySubType.GENERIC_TABLE, PolarisEntitySubType.ICEBERG_TABLE), + identifier.namespace(), + identifier.name(), privilege); } @@ -1693,11 +1634,14 @@ public boolean revokePrivilegeOnTableFromRole( List.of(PolarisEntitySubType.GENERIC_TABLE, PolarisEntitySubType.ICEBERG_TABLE), identifier.namespace(), identifier.name()); - return revokePrivilegeOnTableLikeFromRole( + return managePrivilegeOnEntityForRole( + false, catalogName, catalogRoleName, - identifier, + PolarisEntityType.TABLE_LIKE, List.of(PolarisEntitySubType.GENERIC_TABLE, PolarisEntitySubType.ICEBERG_TABLE), + identifier.namespace(), + identifier.name(), privilege); } @@ -1717,11 +1661,14 @@ public boolean grantPrivilegeOnViewToRole( identifier.namespace(), identifier.name()); - return grantPrivilegeOnTableLikeToRole( + return managePrivilegeOnEntityForRole( + true, catalogName, catalogRoleName, - identifier, + PolarisEntityType.TABLE_LIKE, List.of(PolarisEntitySubType.ICEBERG_VIEW), + identifier.namespace(), + identifier.name(), privilege); } @@ -1742,14 +1689,60 @@ public boolean revokePrivilegeOnViewFromRole( identifier.namespace(), identifier.name()); - return revokePrivilegeOnTableLikeFromRole( + return managePrivilegeOnEntityForRole( + false, catalogName, catalogRoleName, - identifier, + PolarisEntityType.TABLE_LIKE, List.of(PolarisEntitySubType.ICEBERG_VIEW), + identifier.namespace(), + identifier.name(), privilege); } + private boolean managePrivilegeOnEntityForRole( + boolean isGrant, + String catalogName, + String catalogRoleName, + PolarisEntityType entityType, + List subTypes, + @Nullable Namespace namespace, + @Nullable String entityName, + PolarisPrivilege privilege) { + PolarisEntity catalogRoleEntity = + findCatalogRoleByName(catalogName, catalogRoleName) + .orElseThrow(() -> new NotFoundException("CatalogRole %s not found", catalogRoleName)); + PolarisEntity catalogEntity = + findCatalogByName(catalogName) + .orElseThrow(() -> new NotFoundException("Parent catalog %s not found", catalogName)); + + PolarisResolvedPathWrapper resolvedPathWrapper = + getResolvedPathWrapper(catalogName, entityType, subTypes, namespace, entityName, false); + + List catalogPath = + entityType == PolarisEntityType.CATALOG + ? List.of(catalogEntity) + : resolvedPathWrapper.getRawParentPath(); + PolarisEntity entity = resolvedPathWrapper.getRawLeafEntity(); + return isGrant + ? metaStoreManager + .grantPrivilegeOnSecurableToRole( + getCurrentPolarisContext(), + catalogRoleEntity, + PolarisEntity.toCoreList(catalogPath), + entity, + privilege) + .isSuccess() + : metaStoreManager + .revokePrivilegeOnSecurableFromRole( + getCurrentPolarisContext(), + catalogRoleEntity, + PolarisEntity.toCoreList(catalogPath), + entity, + privilege) + .isSuccess(); + } + public List listAssigneePrincipalRolesForCatalogRole( String catalogName, String catalogRoleName) { PolarisAuthorizableOperation op = @@ -1898,73 +1891,43 @@ public List listGrantsForCatalogRole(String catalogName, String c return null; } - /** Adds a table-level or view-level grant on {@code identifier} to {@code catalogRoleName}. */ - private boolean grantPrivilegeOnTableLikeToRole( - String catalogName, - String catalogRoleName, - TableIdentifier identifier, - List subTypes, - PolarisPrivilege privilege) { - if (findCatalogByName(catalogName).isEmpty()) { - throw new NotFoundException("Parent catalog %s not found", catalogName); - } - PolarisEntity catalogRoleEntity = - findCatalogRoleByName(catalogName, catalogRoleName) - .orElseThrow(() -> new NotFoundException("CatalogRole %s not found", catalogRoleName)); - - PolarisResolvedPathWrapper resolvedPathWrapper = - resolutionManifest.getResolvedPath( - identifier, PolarisEntityType.TABLE_LIKE, PolarisEntitySubType.ANY_SUBTYPE); - if (resolvedPathWrapper == null - || !subTypes.contains(resolvedPathWrapper.getRawLeafEntity().getSubType())) { - CatalogHandler.throwNotFoundExceptionForTableLikeEntity(identifier, subTypes); - } - List catalogPath = resolvedPathWrapper.getRawParentPath(); - PolarisEntity tableLikeEntity = resolvedPathWrapper.getRawLeafEntity(); - - return metaStoreManager - .grantPrivilegeOnSecurableToRole( - getCurrentPolarisContext(), - catalogRoleEntity, - PolarisEntity.toCoreList(catalogPath), - tableLikeEntity, - privilege) - .isSuccess(); - } - - /** - * Removes a table-level or view-level grant on {@code identifier} from {@code catalogRoleName}. - */ - private boolean revokePrivilegeOnTableLikeFromRole( + private PolarisResolvedPathWrapper getResolvedPathWrapper( String catalogName, - String catalogRoleName, - TableIdentifier identifier, + PolarisEntityType entityType, List subTypes, - PolarisPrivilege privilege) { - if (findCatalogByName(catalogName).isEmpty()) { - throw new NotFoundException("Parent catalog %s not found", catalogName); - } - PolarisEntity catalogRoleEntity = - findCatalogRoleByName(catalogName, catalogRoleName) - .orElseThrow(() -> new NotFoundException("CatalogRole %s not found", catalogRoleName)); + @Nullable Namespace namespace, + @Nullable String entityName, + boolean prependRootContainer) { + return switch (entityType) { + case CATALOG -> + resolutionManifest.getResolvedTopLevelEntity(catalogName, PolarisEntityType.CATALOG); - PolarisResolvedPathWrapper resolvedPathWrapper = - resolutionManifest.getResolvedPath( - identifier, PolarisEntityType.TABLE_LIKE, PolarisEntitySubType.ANY_SUBTYPE); - if (resolvedPathWrapper == null - || !subTypes.contains(resolvedPathWrapper.getRawLeafEntity().getSubType())) { - CatalogHandler.throwNotFoundExceptionForTableLikeEntity(identifier, subTypes); - } - List catalogPath = resolvedPathWrapper.getRawParentPath(); - PolarisEntity tableLikeEntity = resolvedPathWrapper.getRawLeafEntity(); + case NAMESPACE -> { + var resolvedPathWrapper = + resolutionManifest.getResolvedPath(namespace, prependRootContainer); + if (resolvedPathWrapper == null) { + throw new NotFoundException("Namespace %s not found", namespace); + } + yield resolvedPathWrapper; + } - return metaStoreManager - .revokePrivilegeOnSecurableFromRole( - getCurrentPolarisContext(), - catalogRoleEntity, - PolarisEntity.toCoreList(catalogPath), - tableLikeEntity, - privilege) - .isSuccess(); + case TABLE_LIKE -> { + TableIdentifier identifier = TableIdentifier.of(namespace, entityName); + var resolvedPathWrapper = + resolutionManifest.getResolvedPath( + identifier, + PolarisEntityType.TABLE_LIKE, + PolarisEntitySubType.ANY_SUBTYPE, + prependRootContainer); + if (resolvedPathWrapper == null + || !subTypes.contains(resolvedPathWrapper.getRawLeafEntity().getSubType())) { + CatalogHandler.throwNotFoundExceptionForTableLikeEntity(identifier, subTypes); + } + yield resolvedPathWrapper; + } + default -> + throw new IllegalArgumentException( + "Unsupported entity type for grant operation: " + entityType); + }; } }