roryqi commented on code in PR #12964:
URL: https://github.com/apache/gravitino/pull/12964#discussion_r4026637126
##########
server/src/main/java/org/apache/gravitino/server/web/rest/TagOperations.java:
##########
@@ -325,6 +333,127 @@ public Response listMetadataObjectsForTag(
}
}
+ @GET
+ @Path("{tag}/policies")
+ @Produces("application/vnd.gravitino.v1+json")
+ @Timed(name = "list-policies-for-tag." + MetricNames.HTTP_PROCESS_DURATION,
absolute = true)
+ @ResponseMetered(name = "list-policies-for-tag", absolute = true)
+ @AuthorizationExpression(
+ expression =
AuthorizationExpressionConstants.LOAD_TAG_AUTHORIZATION_EXPRESSION)
+ public Response listPoliciesForTag(
+ @PathParam("metalake") @AuthorizationMetadata(type =
Entity.EntityType.METALAKE)
+ String metalake,
+ @PathParam("tag") @AuthorizationMetadata(type = Entity.EntityType.TAG)
String tagName,
+ @QueryParam("details") @DefaultValue("false") boolean verbose) {
+ LOG.info("Received list policy associations for tag: {} under metalake:
{}", tagName, metalake);
+ try {
+ return Utils.doAs(
+ httpRequest,
+ () -> {
+ RelationalEntity<?>[] associations =
+ tagDispatcher.listPolicyAssociationsForTag(metalake, tagName);
+ associations =
+ MetadataAuthzHelper.filterByExpression(
+ metalake,
+
AuthorizationExpressionConstants.LOAD_POLICY_AUTHORIZATION_EXPRESSION,
+ Entity.EntityType.POLICY,
+ associations,
+ association ->
+ NameIdentifierUtil.ofPolicy(metalake,
association.targetEntity().name()));
+ if (!verbose) {
+ String[] names =
+ Arrays.stream(associations)
+ .map(association -> association.targetEntity().name())
+ .toArray(String[]::new);
+ return Utils.ok(new NameListResponse(names));
+ }
+
+ PolicyForTagAssociationDTO[] associationDTOs =
+ Arrays.stream(associations)
+ .map(
+ association ->
+ new PolicyForTagAssociationDTO(
+ PolicyOperations.toDTO(
+ (PolicyEntity) association.targetEntity(),
Optional.empty()),
+ PolicyAssociationSelectorDTO.fromSelector(
+ PolicyAssociationSelectorSerde.deserialize(
+
association.relationValue().orElseThrow()))))
+ .toArray(PolicyForTagAssociationDTO[]::new);
+ return Utils.ok(new
PolicyForTagAssociationListResponse(associationDTOs));
+ });
+ } catch (Exception e) {
+ return ExceptionHandlers.handleTagException(OperationType.LIST, tagName,
metalake, e);
+ }
+ }
+
+ @POST
+ @Path("{tag}/policies/{policy}")
+ @Produces("application/vnd.gravitino.v1+json")
+ @Timed(name = "add-policy-for-tag." + MetricNames.HTTP_PROCESS_DURATION,
absolute = true)
+ @ResponseMetered(name = "add-policy-for-tag", absolute = true)
+ @AuthorizationExpression(
+ expression =
+ "METALAKE::OWNER || ((TAG::OWNER || ANY_APPLY_TAG) && (POLICY::OWNER
|| ANY_APPLY_POLICY))")
+ public Response addPolicyForTag(
+ @PathParam("metalake") @AuthorizationMetadata(type =
Entity.EntityType.METALAKE)
+ String metalake,
+ @PathParam("tag") @AuthorizationMetadata(type = Entity.EntityType.TAG)
String tagName,
+ @PathParam("policy") @AuthorizationMetadata(type =
Entity.EntityType.POLICY)
+ String policyName,
+ PolicyTagAddRequest request) {
+ LOG.info(
+ "Received add policy: {} for tag: {} under metalake: {}", policyName,
tagName, metalake);
+ try {
+ return Utils.doAs(
+ httpRequest,
+ () -> {
+ PolicyTagAddRequest effectiveRequest =
+ request == null ? new PolicyTagAddRequest() : request;
+ effectiveRequest.validate();
+ tagDispatcher.addPolicyForTag(
+ metalake, tagName, policyName, effectiveRequest.selector());
+ return Utils.ok(
+ new PolicyTagAssociationResponse(
+ policyName,
+ tagName,
+
PolicyAssociationSelectorDTO.fromSelector(effectiveRequest.selector())));
+ });
+ } catch (Exception e) {
+ return ExceptionHandlers.handleTagException(OperationType.ASSOCIATE,
tagName, metalake, e);
Review Comment:
Thanks. Fixed on both sides. The server tag exception handler now maps
`PolicyAlreadyAssociatedException` to HTTP 409 while preserving the exact error
type, and the Java client tag error handler reconstructs
`PolicyAlreadyAssociatedException` instead of falling back to
`AlreadyExistsException`. The tests cover duplicate associations with the same
and a different selector, the REST mapping, and the client’s exact exception
type.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]