roryqi commented on code in PR #12964:
URL: https://github.com/apache/gravitino/pull/12964#discussion_r4044729600


##########
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(

Review Comment:
   We intentionally keep `TAG_VALUE` validation independent of the tag's 
current allowed values. Selector validation is syntactic; a selector that 
cannot match a current effective assignment is still a valid relation and 
simply does not select the policy. Commit 41c900e291 updates the design rule 
accordingly and changes the manager test to associate `engineering` with a tag 
whose allowed values are `finance` and `risk`, documenting this behavior.



##########
docs/open-api/policies.yaml:
##########
@@ -441,7 +441,8 @@ components:
           $ref: "./openapi.yaml#/components/schemas/Audit"
         inherited:
           type: boolean
-          description: Whether the policy is inherited from the parent 
metadata object
+          description: Whether the policy is selected only through tags 
inherited from ancestor

Review Comment:
   Fixed in 41c900e291. The `inherited` contract now covers both inherited 
effective tags and legacy direct relations from ancestor objects, including the 
entity Javadoc and design document. The three new path groups and their 
selector/association request and response schemas are now registered in 
`openapi.yaml`, `tags.yaml`, and `policies.yaml`; `./gradlew :docs:build` 
passes.



-- 
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]

Reply via email to