This is an automated email from the ASF dual-hosted git repository.

jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git

commit add62dd9bab4d4c0b3e45b1d23f2e93add06f12b
Author: Eric Chang <[email protected]>
AuthorDate: Mon Jul 14 10:42:50 2025 +0800

    [#7545] feat(authz): Support fileset authorization (#7581)
    
    <!--
    1. Title: [#<issue>] <type>(<scope>): <subject>
       Examples:
         - "[#123] feat(operator): support xxx"
         - "[#233] fix: check null before access result in xxx"
         - "[MINOR] refactor: fix typo in variable name"
         - "[MINOR] docs: fix typo in README"
         - "[#255] test: fix flaky test NameOfTheTest"
       Reference: https://www.conventionalcommits.org/en/v1.0.0/
    2. If the PR is unfinished, please mark this PR as draft.
    -->
    
    ### What changes were proposed in this pull request?
    
    Support fileset auth with annotation.
    
    ### Why are the changes needed?
    
    To support fileset auth.
    
    Fix: #7545
    
    ### Does this PR introduce _any_ user-facing change?
    
    Yes.
    
    ### How was this patch tested?
    
    FilesetAuthorizationIT
    
    ---------
    
    Co-authored-by: yangyang zhong <[email protected]>
    Co-authored-by: [email protected] <[email protected]>
---
 .../test/authorization/FilesetAuthorizationIT.java | 308 +++++++++++++++++++++
 .../server/authorization/MetadataFilterHelper.java |   7 +
 .../AuthorizationExpressionConverter.java          |   6 +
 .../web/filter/GravitinoInterceptionService.java   |  14 +-
 .../server/web/rest/TestFilesetOperations.java     |   3 +-
 .../TestFilesetAuthorizationExpression.java        | 186 +++++++++++++
 .../TestModelAuthorizationExpression.java          |   8 +-
 7 files changed, 523 insertions(+), 9 deletions(-)

diff --git 
a/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/FilesetAuthorizationIT.java
 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/FilesetAuthorizationIT.java
new file mode 100644
index 0000000000..f43e03b540
--- /dev/null
+++ 
b/clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/FilesetAuthorizationIT.java
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.client.integration.test.authorization;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import org.apache.gravitino.Catalog;
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.MetadataObjects;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.authorization.Owner;
+import org.apache.gravitino.authorization.Privileges;
+import org.apache.gravitino.authorization.SecurableObject;
+import org.apache.gravitino.authorization.SecurableObjects;
+import org.apache.gravitino.client.GravitinoMetalake;
+import org.apache.gravitino.file.Fileset;
+import org.apache.gravitino.file.FilesetCatalog;
+import org.apache.gravitino.file.FilesetChange;
+import org.apache.gravitino.integration.test.container.ContainerSuite;
+import org.apache.gravitino.integration.test.container.HiveContainer;
+import org.apache.gravitino.integration.test.util.GravitinoITUtils;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+
+@Tag("gravitino-docker-test")
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class FilesetAuthorizationIT extends BaseRestApiAuthorizationIT {
+
+  private static final String CATALOG = "catalog";
+  private static final String SCHEMA = "schema";
+
+  private static final ContainerSuite containerSuite = 
ContainerSuite.getInstance();
+
+  private String role = "role";
+  private String defaultBaseLocation;
+
+  @BeforeAll
+  public void startIntegrationTest() throws Exception {
+    containerSuite.startHiveContainer();
+    super.startIntegrationTest();
+    client
+        .loadMetalake(METALAKE)
+        .createCatalog(
+            CATALOG, Catalog.Type.FILESET, "hadoop", "comment", 
ImmutableMap.of("k1", "k2"))
+        .asSchemas()
+        .createSchema(SCHEMA, "test", new HashMap<>());
+    // try to load the schema as normal user, expect failure
+    assertThrows(
+        "Can not access metadata {" + CATALOG + "." + SCHEMA + "}.",
+        RuntimeException.class,
+        () -> {
+          normalUserClient
+              .loadMetalake(METALAKE)
+              .loadCatalog(CATALOG)
+              .asSchemas()
+              .loadSchema(SCHEMA);
+        });
+    // grant tester privilege
+    List<SecurableObject> securableObjects = new ArrayList<>();
+    GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE);
+    SecurableObject catalogObject =
+        SecurableObjects.ofCatalog(CATALOG, 
ImmutableList.of(Privileges.UseCatalog.allow()));
+    securableObjects.add(catalogObject);
+    gravitinoMetalake.createRole(role, new HashMap<>(), securableObjects);
+    gravitinoMetalake.grantRolesToUser(ImmutableList.of(role), NORMAL_USER);
+    // normal user can load the catalog but not the schema
+    Catalog catalogLoadByNormalUser = 
normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG);
+    assertEquals(CATALOG, catalogLoadByNormalUser.name());
+    assertThrows(
+        "Can not access metadata {" + CATALOG + "." + SCHEMA + "}.",
+        RuntimeException.class,
+        () -> {
+          catalogLoadByNormalUser.asSchemas().loadSchema(SCHEMA);
+        });
+  }
+
+  @Test
+  @Order(1)
+  public void testCreateFileset() {
+    // admin user can create fileset
+    FilesetCatalog filesetCatalog =
+        client.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+    String filename1 = 
GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset1");
+    filesetCatalog.createFileset(
+        // NameIdentifier.of(SCHEMA, "fileset1"),
+        NameIdentifier.of(SCHEMA, "fileset1"),
+        "comment",
+        Fileset.Type.MANAGED,
+        storageLocation(filename1),
+        new HashMap<>());
+    // normal use cannot create fileset
+    FilesetCatalog filesetCatalogNormalUser =
+        
normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+    assertThrows(
+        "Can not access metadata {" + CATALOG + "." + SCHEMA + "}.",
+        RuntimeException.class,
+        () -> {
+          filesetCatalogNormalUser.createFileset(
+              //              NameIdentifier.of(SCHEMA, "fileset2"),
+              NameIdentifier.of(SCHEMA, "fileset2"),
+              "comment",
+              Fileset.Type.MANAGED,
+              
storageLocation(GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset2")),
+              new HashMap<>());
+        });
+    // grant privileges
+    GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE);
+    gravitinoMetalake.grantPrivilegesToRole(
+        role,
+        MetadataObjects.of(CATALOG, SCHEMA, MetadataObject.Type.SCHEMA),
+        ImmutableList.of(Privileges.UseSchema.allow(), 
Privileges.CreateFileset.allow()));
+    // normal user can now create fileset
+    String filename2 = 
GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset2");
+    filesetCatalogNormalUser.createFileset(
+        NameIdentifier.of(SCHEMA, "fileset2"),
+        "comment",
+        Fileset.Type.MANAGED,
+        storageLocation(filename2),
+        new HashMap<>());
+    String filename3 = 
GravitinoITUtils.genRandomName("FilesetAuthorizationIT_fileset3");
+    filesetCatalogNormalUser.createFileset(
+        NameIdentifier.of(SCHEMA, "fileset3"),
+        "comment",
+        Fileset.Type.MANAGED,
+        storageLocation(filename3),
+        new HashMap<>());
+  }
+
+  @Test
+  @Order(2)
+  public void testListFileset() {
+    FilesetCatalog tableCatalog =
+        client.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+    NameIdentifier[] tablesList = 
tableCatalog.listFilesets(Namespace.of(SCHEMA));
+    assertArrayEquals(
+        new NameIdentifier[] {
+          NameIdentifier.of(SCHEMA, "fileset1"),
+          NameIdentifier.of(SCHEMA, "fileset2"),
+          NameIdentifier.of(SCHEMA, "fileset3"),
+        },
+        tablesList);
+    // normal user can only see filesets which they have privilege for
+    FilesetCatalog tableCatalogNormalUser =
+        
normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+    NameIdentifier[] filesetsListNormalUser =
+        tableCatalogNormalUser.listFilesets(Namespace.of(SCHEMA));
+    assertArrayEquals(
+        new NameIdentifier[] {
+          NameIdentifier.of(SCHEMA, "fileset2"), NameIdentifier.of(SCHEMA, 
"fileset3")
+        },
+        filesetsListNormalUser);
+  }
+
+  @Test
+  @Order(3)
+  public void testLoadFileset() {
+    FilesetCatalog filesetCatalogNormalUser =
+        
normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+    // normal user can load fileset2 and fileset3, but not fileset1
+    assertThrows(
+        String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, 
"fileset1"),
+        RuntimeException.class,
+        () -> {
+          filesetCatalogNormalUser.loadFileset(NameIdentifier.of(CATALOG, 
SCHEMA, "fileset1"));
+        });
+    Fileset fileset2 = 
filesetCatalogNormalUser.loadFileset(NameIdentifier.of(SCHEMA, "fileset2"));
+    assertEquals("fileset2", fileset2.name());
+    Fileset fileset3 = 
filesetCatalogNormalUser.loadFileset(NameIdentifier.of(SCHEMA, "fileset3"));
+    assertEquals("fileset3", fileset3.name());
+
+    // grant normal user privilege to use fileset1
+    GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE);
+    gravitinoMetalake.grantPrivilegesToRole(
+        role,
+        MetadataObjects.of(
+            ImmutableList.of(CATALOG, SCHEMA, "fileset1"), 
MetadataObject.Type.FILESET),
+        ImmutableList.of(Privileges.ReadFileset.allow()));
+    Fileset fileset1 = 
filesetCatalogNormalUser.loadFileset(NameIdentifier.of(SCHEMA, "fileset1"));
+    assertEquals("fileset1", fileset1.name());
+  }
+
+  @Test
+  @Order(4)
+  public void testAlterFileset() {
+    GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE);
+    FilesetCatalog filesetCatalogNormalUser =
+        
normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+
+    // normal user cannot alter fileset1 (no privilege)
+    assertThrows(
+        String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, 
"fileset1"),
+        RuntimeException.class,
+        () -> {
+          filesetCatalogNormalUser.alterFileset(
+              NameIdentifier.of(SCHEMA, "fileset1"), 
FilesetChange.setProperty("key", "value"));
+        });
+    // grant normal user write privilege on fileset1
+    gravitinoMetalake.grantPrivilegesToRole(
+        role,
+        MetadataObjects.of(
+            ImmutableList.of(CATALOG, SCHEMA, "fileset1"), 
MetadataObject.Type.FILESET),
+        ImmutableList.of(Privileges.WriteFileset.allow()));
+    filesetCatalogNormalUser.alterFileset(
+        NameIdentifier.of(SCHEMA, "fileset1"), 
FilesetChange.setProperty("key", "value"));
+  }
+
+  @Test
+  @Order(5)
+  public void testGetFileLocation() {
+    GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE);
+    FilesetCatalog filesetCatalogNormalUser =
+        
normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+
+    // normal user cannot alter fileset1 (no privilege)
+    assertThrows(
+        String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, 
"fileset1"),
+        RuntimeException.class,
+        () -> {
+          filesetCatalogNormalUser.getFileLocation(
+              NameIdentifier.of(METALAKE, CATALOG, SCHEMA, "fileset1"), 
"/test");
+        });
+    // grant normal user owner privilege on fileset4
+    gravitinoMetalake.setOwner(
+        MetadataObjects.of(
+            ImmutableList.of(CATALOG, SCHEMA, "fileset1"), 
MetadataObject.Type.FILESET),
+        NORMAL_USER,
+        Owner.Type.USER);
+    filesetCatalogNormalUser.getFileLocation(NameIdentifier.of(SCHEMA, 
"fileset1"), "/test");
+  }
+
+  @Test
+  @Order(6)
+  public void testDropFileset() {
+    GravitinoMetalake gravitinoMetalake = client.loadMetalake(METALAKE);
+    FilesetCatalog filesetCatalogNormalUser =
+        
normalUserClient.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+    // reset owner
+    gravitinoMetalake.setOwner(
+        MetadataObjects.of(
+            ImmutableList.of(CATALOG, SCHEMA, "fileset1"), 
MetadataObject.Type.FILESET),
+        USER,
+        Owner.Type.USER);
+    // normal user cannot drop fileset1
+    assertThrows(
+        String.format("Can not access metadata {%s.%s.%s}.", CATALOG, SCHEMA, 
"fileset1"),
+        RuntimeException.class,
+        () -> {
+          filesetCatalogNormalUser.dropFileset(NameIdentifier.of(SCHEMA, 
"fileset1"));
+        });
+    // normal user can drop fileset2 and fileset3 (they created them)
+    filesetCatalogNormalUser.dropFileset(NameIdentifier.of(SCHEMA, 
"fileset2"));
+    filesetCatalogNormalUser.dropFileset(NameIdentifier.of(SCHEMA, 
"fileset3"));
+
+    // owner can drop fileset1
+    FilesetCatalog filesetCatalog =
+        client.loadMetalake(METALAKE).loadCatalog(CATALOG).asFilesetCatalog();
+    filesetCatalog.dropFileset(NameIdentifier.of(SCHEMA, "fileset1"));
+    // check filesets are dropped
+    NameIdentifier[] filesetsList = 
filesetCatalog.listFilesets(Namespace.of(SCHEMA));
+    assertArrayEquals(new NameIdentifier[] {}, filesetsList);
+    NameIdentifier[] filesetsListNormalUser =
+        filesetCatalogNormalUser.listFilesets(Namespace.of(SCHEMA));
+    assertArrayEquals(new NameIdentifier[] {}, filesetsListNormalUser);
+  }
+
+  private String defaultBaseLocation() {
+    if (defaultBaseLocation == null) {
+      defaultBaseLocation =
+          String.format(
+              "hdfs://%s:%d/user/hive/%s",
+              containerSuite.getHiveContainer().getContainerIpAddress(),
+              HiveContainer.HDFS_DEFAULTFS_PORT,
+              SCHEMA.toLowerCase());
+    }
+    return defaultBaseLocation;
+  }
+
+  private String storageLocation(String filesetName) {
+    return defaultBaseLocation() + "/" + filesetName;
+  }
+}
diff --git 
a/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java
 
b/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java
index 2655b98a05..066c550c40 100644
--- 
a/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java
+++ 
b/server-common/src/main/java/org/apache/gravitino/server/authorization/MetadataFilterHelper.java
@@ -144,6 +144,13 @@ public class MetadataFilterHelper {
         nameIdentifierMap.put(
             Entity.EntityType.CATALOG, 
NameIdentifierUtil.getCatalogIdentifier(nameIdentifier));
         break;
+      case FILESET:
+        nameIdentifierMap.put(Entity.EntityType.FILESET, nameIdentifier);
+        nameIdentifierMap.put(
+            Entity.EntityType.SCHEMA, 
NameIdentifierUtil.getSchemaIdentifier(nameIdentifier));
+        nameIdentifierMap.put(
+            Entity.EntityType.CATALOG, 
NameIdentifierUtil.getCatalogIdentifier(nameIdentifier));
+        break;
       default:
         break;
     }
diff --git 
a/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java
 
b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java
index 0ec8ef18a1..694dafbf6d 100644
--- 
a/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java
+++ 
b/server-common/src/main/java/org/apache/gravitino/server/authorization/expression/AuthorizationExpressionConverter.java
@@ -163,6 +163,12 @@ public class AuthorizationExpressionConverter {
     expression =
         expression.replaceAll(
             "ANY_CONSUME_TOPIC", "(ANY(CONSUME_TOPIC, METALAKE, CATALOG, 
SCHEMA, TOPIC))");
+    expression =
+        expression.replaceAll(
+            "ANY_READ_FILESET", "(ANY(READ_FILESET, METALAKE, CATALOG, SCHEMA, 
FILESET))");
+    expression =
+        expression.replaceAll(
+            "ANY_WRITE_FILESET", "(ANY(WRITE_FILESET, METALAKE, CATALOG, 
SCHEMA, FILESET))");
     return expression;
   }
 }
diff --git 
a/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java
 
b/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java
index d39faf0ad8..7d26113aaf 100644
--- 
a/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java
+++ 
b/server/src/main/java/org/apache/gravitino/server/web/filter/GravitinoInterceptionService.java
@@ -40,6 +40,7 @@ import 
org.apache.gravitino.server.authorization.annotations.AuthorizationMetada
 import 
org.apache.gravitino.server.authorization.expression.AuthorizationExpressionEvaluator;
 import org.apache.gravitino.server.web.Utils;
 import org.apache.gravitino.server.web.rest.CatalogOperations;
+import org.apache.gravitino.server.web.rest.FilesetOperations;
 import org.apache.gravitino.server.web.rest.ModelOperations;
 import org.apache.gravitino.server.web.rest.SchemaOperations;
 import org.apache.gravitino.server.web.rest.TableOperations;
@@ -64,7 +65,8 @@ public class GravitinoInterceptionService implements 
InterceptionService {
             SchemaOperations.class.getName(),
             TableOperations.class.getName(),
             ModelOperations.class.getName(),
-            TopicOperations.class.getName()));
+            TopicOperations.class.getName(),
+            FilesetOperations.class.getName()));
   }
 
   @Override
@@ -140,6 +142,7 @@ public class GravitinoInterceptionService implements 
InterceptionService {
       String schema = metadatas.get(Entity.EntityType.SCHEMA);
       String table = metadatas.get(Entity.EntityType.TABLE);
       String topic = metadatas.get(Entity.EntityType.TOPIC);
+      String fileset = metadatas.get(Entity.EntityType.FILESET);
       metadatas.forEach(
           (type, metadata) -> {
             switch (type) {
@@ -162,9 +165,10 @@ public class GravitinoInterceptionService implements 
InterceptionService {
                     Entity.EntityType.TOPIC,
                     NameIdentifierUtil.ofTopic(metalake, catalog, schema, 
topic));
                 break;
-              case METALAKE:
+              case FILESET:
                 nameIdentifierMap.put(
-                    Entity.EntityType.METALAKE, 
NameIdentifierUtil.ofMetalake(metalake));
+                    Entity.EntityType.FILESET,
+                    NameIdentifierUtil.ofFileset(metalake, catalog, schema, 
fileset));
                 break;
               case MODEL:
                 String model = metadatas.get(Entity.EntityType.MODEL);
@@ -172,6 +176,10 @@ public class GravitinoInterceptionService implements 
InterceptionService {
                     Entity.EntityType.MODEL,
                     NameIdentifierUtil.ofModel(metadata, catalog, schema, 
model));
                 break;
+              case METALAKE:
+                nameIdentifierMap.put(
+                    Entity.EntityType.METALAKE, 
NameIdentifierUtil.ofMetalake(metalake));
+                break;
               default:
                 break;
             }
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
index f8248bc1d8..56665ae914 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/TestFilesetOperations.java
@@ -69,7 +69,6 @@ import org.apache.gravitino.lock.LockManager;
 import org.apache.gravitino.rest.RESTUtils;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
 import org.glassfish.jersey.server.ResourceConfig;
-import org.glassfish.jersey.test.JerseyTest;
 import org.glassfish.jersey.test.TestProperties;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -77,7 +76,7 @@ import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 import org.mockito.stubbing.Answer;
 
-public class TestFilesetOperations extends JerseyTest {
+public class TestFilesetOperations extends BaseOperationsTest {
   private static class MockServletRequestFactory extends 
ServletRequestFactoryBase {
     @Override
     public HttpServletRequest get() {
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestFilesetAuthorizationExpression.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestFilesetAuthorizationExpression.java
new file mode 100644
index 0000000000..74f8fd45e5
--- /dev/null
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestFilesetAuthorizationExpression.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.gravitino.server.web.rest.authorization;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.google.common.collect.ImmutableSet;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import ognl.OgnlException;
+import org.apache.gravitino.dto.requests.FilesetCreateRequest;
+import org.apache.gravitino.dto.requests.FilesetUpdatesRequest;
+import 
org.apache.gravitino.server.authorization.annotations.AuthorizationExpression;
+import org.apache.gravitino.server.web.rest.FilesetOperations;
+import org.junit.jupiter.api.Test;
+
+public class TestFilesetAuthorizationExpression {
+
+  @Test
+  public void testCreateFileset() throws NoSuchMethodException, OgnlException {
+    Method method =
+        FilesetOperations.class.getMethod(
+            "createFileset", String.class, String.class, String.class, 
FilesetCreateRequest.class);
+    AuthorizationExpression authorizationExpressionAnnotation =
+        method.getAnnotation(AuthorizationExpression.class);
+    String expression = authorizationExpressionAnnotation.expression();
+    MockAuthorizationExpressionEvaluator mockEvaluator =
+        new MockAuthorizationExpressionEvaluator(expression);
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of()));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("CATALOG::OWNER")));
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", 
"CATALOG::USE_CATALOG")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET", 
"CATALOG::USE_CATALOG")));
+    assertTrue(
+        mockEvaluator.getResult(
+            ImmutableSet.of(
+                "SCHEMA::CREATE_FILESET", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+  }
+
+  @Test
+  public void testLoadFileset() throws OgnlException, NoSuchFieldException, 
IllegalAccessException {
+    Field loadFilesetAuthorizationExpressionField =
+        
FilesetOperations.class.getDeclaredField("loadFilesetAuthorizationExpression");
+    loadFilesetAuthorizationExpressionField.setAccessible(true);
+    String loadFilesetAuthorizationExpression =
+        (String) loadFilesetAuthorizationExpressionField.get(null);
+    MockAuthorizationExpressionEvaluator mockEvaluator =
+        new 
MockAuthorizationExpressionEvaluator(loadFilesetAuthorizationExpression);
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of()));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(
+            ImmutableSet.of("SCHEMA::CREATE_FILESET", 
"CATALOG::CREATE_CATALOG")));
+
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::WRITE_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::WRITE_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET", 
"CATALOG::USE_CATALOG")));
+    assertTrue(
+        mockEvaluator.getResult(
+            ImmutableSet.of(
+                "SCHEMA::WRITE_FILESET", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::READ_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::READ_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::READ_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(ImmutableSet.of("SCHEMA::READ_FILESET", 
"CATALOG::USE_CATALOG")));
+    assertTrue(
+        mockEvaluator.getResult(
+            ImmutableSet.of("SCHEMA::READ_FILESET", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", 
"CATALOG::USE_CATALOG")));
+    assertTrue(
+        mockEvaluator.getResult(
+            ImmutableSet.of("SCHEMA::OWNER", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+  }
+
+  @Test
+  public void testAlterFileset() throws NoSuchMethodException, OgnlException {
+    Method method =
+        FilesetOperations.class.getMethod(
+            "alterFileset",
+            String.class,
+            String.class,
+            String.class,
+            String.class,
+            FilesetUpdatesRequest.class);
+    AuthorizationExpression authorizationExpressionAnnotation =
+        method.getAnnotation(AuthorizationExpression.class);
+    String expression = authorizationExpressionAnnotation.expression();
+    MockAuthorizationExpressionEvaluator mockEvaluator =
+        new MockAuthorizationExpressionEvaluator(expression);
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of()));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(
+            ImmutableSet.of("SCHEMA::CREATE_FILESET", 
"CATALOG::CREATE_CATALOG")));
+
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::WRITE_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::WRITE_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET", 
"CATALOG::USE_CATALOG")));
+    assertTrue(
+        mockEvaluator.getResult(
+            ImmutableSet.of(
+                "SCHEMA::WRITE_FILESET", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", 
"CATALOG::USE_CATALOG")));
+    assertTrue(
+        mockEvaluator.getResult(
+            ImmutableSet.of("SCHEMA::OWNER", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+  }
+
+  @Test
+  public void testDropFileset() throws NoSuchMethodException, OgnlException {
+    Method method =
+        FilesetOperations.class.getMethod(
+            "dropFileset", String.class, String.class, String.class, 
String.class);
+    AuthorizationExpression authorizationExpressionAnnotation =
+        method.getAnnotation(AuthorizationExpression.class);
+    String expression = authorizationExpressionAnnotation.expression();
+    MockAuthorizationExpressionEvaluator mockEvaluator =
+        new MockAuthorizationExpressionEvaluator(expression);
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of()));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_CATALOG")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER")));
+
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::USE_METALAKE")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::CREATE_CATALOG")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::CREATE_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(
+            ImmutableSet.of("SCHEMA::CREATE_FILESET", 
"CATALOG::CREATE_CATALOG")));
+
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("METALAKE::WRITE_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("CATALOG::WRITE_FILESET")));
+    
assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET")));
+    assertFalse(
+        mockEvaluator.getResult(ImmutableSet.of("SCHEMA::WRITE_FILESET", 
"CATALOG::USE_CATALOG")));
+    assertFalse(
+        mockEvaluator.getResult(
+            ImmutableSet.of(
+                "SCHEMA::WRITE_FILESET", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+
+    assertFalse(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER")));
+    assertTrue(mockEvaluator.getResult(ImmutableSet.of("SCHEMA::OWNER", 
"CATALOG::USE_CATALOG")));
+    assertTrue(
+        mockEvaluator.getResult(
+            ImmutableSet.of("SCHEMA::OWNER", "SCHEMA::USE_SCHEMA", 
"CATALOG::USE_CATALOG")));
+  }
+}
diff --git 
a/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java
 
b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java
index b2a97ffe7e..53b1e91536 100644
--- 
a/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java
+++ 
b/server/src/test/java/org/apache/gravitino/server/web/rest/authorization/TestModelAuthorizationExpression.java
@@ -68,12 +68,12 @@ public class TestModelAuthorizationExpression {
 
   @Test
   public void testLoadModel() throws OgnlException, NoSuchFieldException, 
IllegalAccessException {
-    Field loadTableAuthorizationExpressionField =
+    Field loadModelAuthorizationExpressionField =
         
ModelOperations.class.getDeclaredField("loadModelAuthorizationExpression");
-    loadTableAuthorizationExpressionField.setAccessible(true);
-    String loadTableAuthExpression = (String) 
loadTableAuthorizationExpressionField.get(null);
+    loadModelAuthorizationExpressionField.setAccessible(true);
+    String loadModelAuthExpression = (String) 
loadModelAuthorizationExpressionField.get(null);
     MockAuthorizationExpressionEvaluator mockEvaluator =
-        new MockAuthorizationExpressionEvaluator(loadTableAuthExpression);
+        new MockAuthorizationExpressionEvaluator(loadModelAuthExpression);
     assertFalse(mockEvaluator.getResult(ImmutableSet.of()));
     assertTrue(mockEvaluator.getResult(ImmutableSet.of("METALAKE::OWNER")));
     assertTrue(mockEvaluator.getResult(ImmutableSet.of("CATALOG::OWNER")));

Reply via email to