Copilot commented on code in PR #13833:
URL: https://github.com/apache/gravitino/pull/13833#discussion_r4260218591


##########
server-common/src/test/java/org/apache/gravitino/server/authorization/TestMetadataAuthzHelper.java:
##########
@@ -489,6 +489,377 @@ public void testListShortCircuitModelViaSchemaGrant() {
     }
   }
 
+  /** A SELECT_VIEW grant on the schema makes every view visible without 
per-view checks. */
+  @Test
+  public void testListShortCircuitViewViaSchemaGrant() {
+    EntityStore store = mock(EntityStore.class);
+    when(gravitinoEnv.entityStore()).thenReturn(store);
+    when(gravitinoEnv.cacheEnabled()).thenReturn(true);
+    when(gravitinoEnv.internalAccessControlDispatcher())
+        .thenReturn(mock(AccessControlDispatcher.class));
+    GravitinoAuthorizer authorizer =
+        mockParentGrantAuthorizer(MetadataObject.Type.SCHEMA, 
Privilege.Name.SELECT_VIEW);
+    NameIdentifier[] identifiers = views(2000);
+    try {
+      withAuthorizer(
+          authorizer,
+          () -> {
+            NameIdentifier[] filtered =
+                MetadataAuthzHelper.filterByExpression(
+                    "testMetalake",
+                    
AuthorizationExpressionConstants.FILTER_VIEW_AUTHORIZATION_EXPRESSION,
+                    Entity.EntityType.VIEW,
+                    identifiers);
+            Assertions.assertSame(identifiers, filtered);

Review Comment:
   These tests assert reference identity (`assertSame`) for the filtered array, 
which makes them brittle to harmless implementation changes (e.g., returning an 
equal array copy while still short-circuiting per-object checks). Prefer 
asserting content equality (e.g., `assertArrayEquals`) and keep the behavioral 
assertion via `verify(authorizer, never()).authorize(...)`. Apply similarly to 
the other newly added `assertSame` checks in this file.



##########
server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataAuthzHelper.java:
##########
@@ -108,58 +108,111 @@ public class MetadataAuthzHelper {
    */
   private static final Map<Entity.EntityType, Map<String, 
List<ParentScopeAccessPath>>>
       LIST_SHORT_CIRCUITS =
-          Map.of(
-              Entity.EntityType.USER,
-              principalListPaths(
-                  
AuthorizationExpressionConstants.LOAD_USER_AUTHORIZATION_EXPRESSION,
-                  Privilege.Name.MANAGE_USERS),
-              Entity.EntityType.GROUP,
-              principalListPaths(
-                  
AuthorizationExpressionConstants.LOAD_GROUP_AUTHORIZATION_EXPRESSION,
-                  Privilege.Name.MANAGE_GROUPS),
-              Entity.EntityType.ROLE,
-              principalListPaths(
-                  
AuthorizationExpressionConstants.LOAD_ROLE_AUTHORIZATION_EXPRESSION,
-                  Privilege.Name.MANAGE_GRANTS),
-              Entity.EntityType.TABLE,
-              Map.of(
-                  
AuthorizationExpressionConstants.FILTER_TABLE_AUTHORIZATION_EXPRESSION,
-                  List.of(
-                      parentOwnerPath(TABLE_PARENT_SCOPES),
-                      parentPrivilegePath(Privilege.Name.SELECT_TABLE, 
TABLE_PARENT_SCOPES),
-                      parentPrivilegePath(Privilege.Name.MODIFY_TABLE, 
TABLE_PARENT_SCOPES)),
-                  
AuthorizationExpressionConstants.LIST_TABLE_LIKE_AUTHORIZATION_EXPRESSION,
-                  List.of(
-                      parentOwnerPath(TABLE_PARENT_SCOPES),
-                      
tableLikeParentPrivilegePath(Privilege.Name.PROBE_TABLE_LIKE),
-                      
tableLikeParentPrivilegePath(Privilege.Name.SELECT_TABLE),
-                      
tableLikeParentPrivilegePath(Privilege.Name.MODIFY_TABLE),
-                      
tableLikeParentPrivilegePath(Privilege.Name.CREATE_TABLE),
-                      
tableLikeParentPrivilegePath(Privilege.Name.CREATE_VIEW))),
-              Entity.EntityType.MODEL,
-              Map.of(
-                  
AuthorizationExpressionConstants.FILTER_MODEL_AUTHORIZATION_EXPRESSION,
-                  List.of(
-                      parentOwnerPath(MODEL_PARENT_SCOPES),
-                      parentPrivilegePath(Privilege.Name.USE_MODEL, 
MODEL_PARENT_SCOPES))),
-              Entity.EntityType.JOB_TEMPLATE,
-              Map.of(
-                  
AuthorizationExpressionConstants.LOAD_JOB_TEMPLATE_AUTHORIZATION_EXPRESSION,
-                  List.of(
-                      parentOwnerPath(METALAKE_ONLY_SCOPE),
-                      parentPrivilegePath(Privilege.Name.USE_JOB_TEMPLATE, 
METALAKE_ONLY_SCOPE))),
-              Entity.EntityType.SCHEMA,
-              Map.of(
-                  
AuthorizationExpressionConstants.FILTER_SCHEMA_AUTHORIZATION_EXPRESSION,
-                  List.of(
-                      parentOwnerPath(SCHEMA_PARENT_SCOPES),
-                      parentPrivilegePath(Privilege.Name.USE_SCHEMA, 
SCHEMA_PARENT_SCOPES))),
-              Entity.EntityType.CATALOG,
-              Map.of(
-                  
AuthorizationExpressionConstants.LOAD_CATALOG_AUTHORIZATION_EXPRESSION,
-                  List.of(
-                      parentOwnerPath(CATALOG_PARENT_SCOPES),
-                      parentPrivilegePath(Privilege.Name.USE_CATALOG, 
CATALOG_PARENT_SCOPES))));
+          Map.ofEntries(
+              Map.entry(
+                  Entity.EntityType.USER,
+                  principalListPaths(
+                      
AuthorizationExpressionConstants.LOAD_USER_AUTHORIZATION_EXPRESSION,
+                      Privilege.Name.MANAGE_USERS)),
+              Map.entry(
+                  Entity.EntityType.GROUP,
+                  principalListPaths(
+                      
AuthorizationExpressionConstants.LOAD_GROUP_AUTHORIZATION_EXPRESSION,
+                      Privilege.Name.MANAGE_GROUPS)),
+              Map.entry(
+                  Entity.EntityType.ROLE,
+                  principalListPaths(
+                      
AuthorizationExpressionConstants.LOAD_ROLE_AUTHORIZATION_EXPRESSION,
+                      Privilege.Name.MANAGE_GRANTS)),
+              Map.entry(
+                  Entity.EntityType.TABLE,
+                  Map.of(
+                      
AuthorizationExpressionConstants.FILTER_TABLE_AUTHORIZATION_EXPRESSION,
+                      List.of(
+                          parentOwnerPath(TABLE_PARENT_SCOPES),
+                          parentPrivilegePath(Privilege.Name.SELECT_TABLE, 
TABLE_PARENT_SCOPES),
+                          parentPrivilegePath(Privilege.Name.MODIFY_TABLE, 
TABLE_PARENT_SCOPES)),
+                      
AuthorizationExpressionConstants.LIST_TABLE_LIKE_AUTHORIZATION_EXPRESSION,
+                      List.of(
+                          parentOwnerPath(TABLE_PARENT_SCOPES),
+                          
tableLikeParentPrivilegePath(Privilege.Name.PROBE_TABLE_LIKE),
+                          
tableLikeParentPrivilegePath(Privilege.Name.SELECT_TABLE),
+                          
tableLikeParentPrivilegePath(Privilege.Name.MODIFY_TABLE),
+                          
tableLikeParentPrivilegePath(Privilege.Name.CREATE_TABLE),
+                          
tableLikeParentPrivilegePath(Privilege.Name.CREATE_VIEW)))),
+              Map.entry(
+                  Entity.EntityType.MODEL,
+                  Map.of(
+                      
AuthorizationExpressionConstants.FILTER_MODEL_AUTHORIZATION_EXPRESSION,
+                      List.of(
+                          parentOwnerPath(MODEL_PARENT_SCOPES),
+                          parentPrivilegePath(Privilege.Name.USE_MODEL, 
MODEL_PARENT_SCOPES)))),
+              Map.entry(
+                  Entity.EntityType.VIEW,
+                  Map.of(
+                      
AuthorizationExpressionConstants.FILTER_VIEW_AUTHORIZATION_EXPRESSION,
+                      List.of(
+                          parentOwnerPath(TABLE_PARENT_SCOPES),
+                          parentPrivilegePath(Privilege.Name.SELECT_VIEW, 
TABLE_PARENT_SCOPES)))),
+              Map.entry(
+                  Entity.EntityType.FUNCTION,
+                  Map.of(
+                      
AuthorizationExpressionConstants.FILTER_FUNCTION_AUTHORIZATION_EXPRESSION,
+                      List.of(
+                          parentOwnerPath(TABLE_PARENT_SCOPES),
+                          parentPrivilegePath(Privilege.Name.EXECUTE_FUNCTION, 
TABLE_PARENT_SCOPES),
+                          parentPrivilegePath(
+                              Privilege.Name.MODIFY_FUNCTION, 
TABLE_PARENT_SCOPES)))),

Review Comment:
   `TABLE_PARENT_SCOPES` is now used for several non-table entity types (views, 
functions, etc.). This is confusing and makes the code harder to reason about 
(the constant name no longer matches its usage). Consider renaming the constant 
to something scope-based (e.g., `METALAKE_CATALOG_SCHEMA_PARENT_SCOPES`) or 
introducing a new alias constant with a clearer name and using it in these new 
entries.



##########
server-common/src/test/java/org/apache/gravitino/server/authorization/TestMetadataAuthzHelper.java:
##########
@@ -489,6 +489,377 @@ public void testListShortCircuitModelViaSchemaGrant() {
     }
   }
 
+  /** A SELECT_VIEW grant on the schema makes every view visible without 
per-view checks. */
+  @Test
+  public void testListShortCircuitViewViaSchemaGrant() {
+    EntityStore store = mock(EntityStore.class);
+    when(gravitinoEnv.entityStore()).thenReturn(store);
+    when(gravitinoEnv.cacheEnabled()).thenReturn(true);
+    when(gravitinoEnv.internalAccessControlDispatcher())
+        .thenReturn(mock(AccessControlDispatcher.class));
+    GravitinoAuthorizer authorizer =
+        mockParentGrantAuthorizer(MetadataObject.Type.SCHEMA, 
Privilege.Name.SELECT_VIEW);
+    NameIdentifier[] identifiers = views(2000);
+    try {
+      withAuthorizer(
+          authorizer,
+          () -> {
+            NameIdentifier[] filtered =
+                MetadataAuthzHelper.filterByExpression(
+                    "testMetalake",
+                    
AuthorizationExpressionConstants.FILTER_VIEW_AUTHORIZATION_EXPRESSION,
+                    Entity.EntityType.VIEW,
+                    identifiers);
+            Assertions.assertSame(identifiers, filtered);
+            verify(authorizer, never())
+                .authorize(
+                    any(),
+                    eq("testMetalake"),
+                    argThat(object -> object.type() == 
MetadataObject.Type.VIEW),
+                    any(),
+                    any());
+            verifyNoInteractions(store);
+          });
+    } finally {
+      when(gravitinoEnv.cacheEnabled()).thenReturn(false);
+      when(gravitinoEnv.entityStore()).thenReturn(null);
+      when(gravitinoEnv.internalAccessControlDispatcher()).thenReturn(null);
+    }

Review Comment:
   The new tests repeat substantial setup/teardown boilerplate (mocking 
`EntityStore`, toggling `cacheEnabled`, wiring dispatchers, and resetting them 
in `finally`). Consider extracting a small helper (e.g., a method that takes a 
lambda and sets up/resets `gravitinoEnv` consistently) to reduce duplication 
and make future additions less error-prone.



##########
server-common/src/test/java/org/apache/gravitino/server/authorization/TestMetadataAuthzHelper.java:
##########
@@ -489,6 +489,377 @@ public void testListShortCircuitModelViaSchemaGrant() {
     }
   }
 
+  /** A SELECT_VIEW grant on the schema makes every view visible without 
per-view checks. */
+  @Test
+  public void testListShortCircuitViewViaSchemaGrant() {
+    EntityStore store = mock(EntityStore.class);
+    when(gravitinoEnv.entityStore()).thenReturn(store);
+    when(gravitinoEnv.cacheEnabled()).thenReturn(true);
+    when(gravitinoEnv.internalAccessControlDispatcher())
+        .thenReturn(mock(AccessControlDispatcher.class));

Review Comment:
   The new tests repeat substantial setup/teardown boilerplate (mocking 
`EntityStore`, toggling `cacheEnabled`, wiring dispatchers, and resetting them 
in `finally`). Consider extracting a small helper (e.g., a method that takes a 
lambda and sets up/resets `gravitinoEnv` consistently) to reduce duplication 
and make future additions less error-prone.



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