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 ba35f50e9e86c9a4edd870bbea22d19cc57a9d23
Author: yangyang zhong <[email protected]>
AuthorDate: Wed May 21 15:25:27 2025 +0800

    [#6827] feat(authz): Jcasbin model file for Gravitino (#7086)
    
    ### What changes were proposed in this pull request?
    
    Define the jcasbin permission model
    
    ### Why are the changes needed?
    
    Fix: #6827
    
    ### Does this PR introduce _any_ user-facing change?
    
    None
    
    ### How was this patch tested?
    
    org.apache.gravitino.server.authorization.TestJcasbinModel
---
 .../src/main/resources/jcasbin_model.conf          |  55 ++
 .../server/authorization/TestJcasbinModel.java     | 569 +++++++++++++++++++++
 .../src/test/resources/jcasbin_policy.txt          |  28 +
 3 files changed, 652 insertions(+)

diff --git a/server-common/src/main/resources/jcasbin_model.conf 
b/server-common/src/main/resources/jcasbin_model.conf
new file mode 100644
index 0000000000..3247012b3b
--- /dev/null
+++ b/server-common/src/main/resources/jcasbin_model.conf
@@ -0,0 +1,55 @@
+; 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.
+
+; The model file of jcasbin defines a permission model used to describe the 
permissions
+; of users, groups, and roles for a single metadata type.
+
+; "r" represents the parameters passed when making a request to jCasbin.
+; "sub" represents a roleId, userId, or groupCodeId.
+; The combination of `sub` and `metalakeId` uniquely identifies a user, role, 
or group.
+; "metadataType" represents the type of metadata.
+; "metadataId" represents the id of metadata
+; "act" represents the privilege that needs to be authorized or whether it is 
an OWNER.
+[request_definition]
+r = sub, metadataType, metadataId, act
+
+; "p" represents a permission policy.
+; "eft" stands for "effect" which can be either "allow" or "deny".
+[policy_definition]
+p = sub, metadataType, metadataId, act, eft
+
+; "g" represents the membership or ownership relationship of users, groups, or 
roles.
+[role_definition]
+g = _, _
+
+; "e" represents the effect of the "eft",eft performs a logical combination 
judgment on the matching results
+; of Matchers.
+; e = some(where(p.eft == allow)): This statement means that if the matching 
strategy result p.eft has the result
+; of (some) allow
+; e = some(where (p.eft == allow)) && !some(where (p.eft == deny)): The 
logical meaning of this example combination
+; is: if there is a strategy that matches the result of allow and no strategy 
that matches the result of deny,
+; the result is true. In other words, it is true when the matching strategies 
are all allow. If there is any deny,
+; both are false (more simply, when allow and deny exist at the same time, 
deny takes precedence).
+;
+; see more in https://casbin.org/zh/docs/how-it-works/#effect
+[policy_effect]
+e = some(where (p.eft == allow)) && !some(where (p.eft == deny))
+
+; "m" represents the matching rules of the model
+[matchers]
+m = g(r.sub, p.sub) && r.metadataId == p.metadataId && r.metadataType == 
p.metadataType && ( p.act == "OWNER" || r.act == p.act )
+
diff --git 
a/server-common/src/test/java/org/apache/gravitino/server/authorization/TestJcasbinModel.java
 
b/server-common/src/test/java/org/apache/gravitino/server/authorization/TestJcasbinModel.java
new file mode 100644
index 0000000000..43410b8f28
--- /dev/null
+++ 
b/server-common/src/test/java/org/apache/gravitino/server/authorization/TestJcasbinModel.java
@@ -0,0 +1,569 @@
+/*
+ * 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.authorization;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.gravitino.MetadataObject;
+import org.apache.gravitino.authorization.Privilege;
+import org.casbin.jcasbin.main.Enforcer;
+import org.casbin.jcasbin.model.Model;
+import org.casbin.jcasbin.persist.file_adapter.FileAdapter;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+/** Test for jcasbin model. */
+public class TestJcasbinModel {
+
+  /** Jcasbin enforcer */
+  private static Enforcer enforcer;
+
+  @BeforeAll
+  public static void init() throws IOException {
+    // Load jcasbin policy from jcasbin_policy.txt
+    URL resource = TestJcasbinModel.class.getResource("/jcasbin_policy.txt");
+    Assertions.assertNotNull(resource);
+    List<String> policyWithLicense =
+        FileUtils.readLines(new File(resource.getFile()), 
StandardCharsets.UTF_8);
+    // remove license
+    String policy =
+        policyWithLicense.stream()
+            .filter(line -> !line.startsWith("#"))
+            .collect(Collectors.joining("\n"));
+    try (InputStream modelStream =
+            TestJcasbinModel.class.getResourceAsStream("/jcasbin_model.conf");
+        InputStream policyInputStream =
+            new ByteArrayInputStream(policy.getBytes(StandardCharsets.UTF_8))) 
{
+      Assertions.assertNotNull(modelStream);
+      String modelString = IOUtils.toString(modelStream, 
StandardCharsets.UTF_8);
+      Model model = new Model();
+      model.loadModelFromText(modelString);
+      FileAdapter fileAdapter = new FileAdapter(policyInputStream);
+      enforcer = new Enforcer(model, fileAdapter);
+    }
+  }
+
+  /**
+   * "role1" is the OWNER of metalake1. Determine whether role1 has the OWNER 
permission for
+   * metalake1.
+   */
+  @Test
+  public void testMetalakeOwner() {
+    Assertions.assertTrue(
+        enforcer.enforce("role1", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce("role1", MetadataObject.Type.METALAKE.name(), 
"metalake2", "OWNER"));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+  }
+
+  /**
+   * "role2" is the OWNER of catalog1. Determine whether role2 has the OWNER 
permission for
+   * catalog2.
+   */
+  @Test
+  public void testCatalogOwner() {
+    Assertions.assertTrue(
+        enforcer.enforce("role2", MetadataObject.Type.CATALOG.name(), 
"catalog1", "OWNER"));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role2",
+            MetadataObject.Type.CATALOG.name(),
+            "catalog1",
+            Privilege.Name.USE_SCHEMA.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role2",
+            MetadataObject.Type.CATALOG.name(),
+            "catalog1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce("role2", MetadataObject.Type.CATALOG.name(), 
"catalog2", "OWNER"));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role2",
+            MetadataObject.Type.CATALOG.name(),
+            "catalog2",
+            Privilege.Name.USE_CATALOG.name()));
+  }
+
+  /**
+   * role3 is the owner of schema1. Determine whether role3 has the owner 
permission for schema1.
+   */
+  @Test
+  public void testSchemaOwner() {
+    Assertions.assertTrue(
+        enforcer.enforce("role3", MetadataObject.Type.SCHEMA.name(), 
"schema1", "OWNER"));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role3",
+            MetadataObject.Type.SCHEMA.name(),
+            "schema1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce("role3", MetadataObject.Type.SCHEMA.name(), 
"schema2", "OWNER"));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role3",
+            MetadataObject.Type.SCHEMA.name(),
+            "schema2",
+            Privilege.Name.SELECT_TABLE.name()));
+  }
+
+  /** "role4" is the owner of table1. Determine whether role4 has the 
permissions for table1. */
+  @Test
+  public void testTableOwner() {
+    Assertions.assertTrue(
+        enforcer.enforce("role4", MetadataObject.Type.TABLE.name(), "table1", 
"OWNER"));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role4",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role4",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce("role3", MetadataObject.Type.SCHEMA.name(), "table1", 
"OWNER"));
+    Assertions.assertFalse(
+        enforcer.enforce("role3", MetadataObject.Type.SCHEMA.name(), "table2", 
"OWNER"));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role4",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+  }
+
+  /** Check whether a role can have privileges. */
+  @Test
+  public void testRolePrivilege() {
+    // "role5" has partial privilege.
+    Assertions.assertFalse(
+        enforcer.enforce("role5", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role5",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role5",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "role5",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role5",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role5",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role5",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role5",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+
+    // role1000 has no privilege.
+    Assertions.assertFalse(
+        enforcer.enforce("role1000", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1000",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1000",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "role1000",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+  }
+
+  /**
+   * Determine whether a group, after being assigned a role, can inherit the 
permissions of that
+   * role.
+   */
+  @Test
+  public void testGroupPrivilege() {
+    // "group1" possesses role5, and therefore, group5 has the permissions of 
role5.
+    Assertions.assertFalse(
+        enforcer.enforce("group1", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "group1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "group1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "group1",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+
+    // group1000 has no roles and therefore has no permissions.
+    Assertions.assertFalse(
+        enforcer.enforce("group1000", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1000",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1000",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "group1000",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+  }
+
+  /**
+   * Determine whether a user can have the corresponding permissions after 
being granted a role or
+   * belonging to a user group.
+   */
+  @Test
+  public void testUserPrivilege() {
+    // ”user1" has the privilege of role5.
+    Assertions.assertFalse(
+        enforcer.enforce("user1", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "user1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "user1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "user1",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+
+    // ”user2" has the privilege of group1.
+    Assertions.assertFalse(
+        enforcer.enforce("user2", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "user2",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "user2",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user2",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user2",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user2",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user2",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user2",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+
+    // "user3" has the privilege of both role1 and group1.
+    Assertions.assertTrue(
+        enforcer.enforce("user3", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "user3",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertTrue(
+        enforcer.enforce(
+            "user3",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user3",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user3",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user3",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user3",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user3",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+
+    Assertions.assertFalse(
+        enforcer.enforce("user1000", MetadataObject.Type.METALAKE.name(), 
"metalake1", "OWNER"));
+
+    // "user1000" has no roles and therefore has no permissions.
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake1",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1000",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.MODIFY_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.SELECT_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1000",
+            MetadataObject.Type.METALAKE.name(),
+            "metalake2",
+            Privilege.Name.USE_CATALOG.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1000",
+            MetadataObject.Type.TABLE.name(),
+            "table2",
+            Privilege.Name.MODIFY_TABLE.name()));
+    Assertions.assertFalse(
+        enforcer.enforce(
+            "user1000",
+            MetadataObject.Type.TABLE.name(),
+            "table1",
+            Privilege.Name.SELECT_TABLE.name()));
+  }
+}
diff --git a/server-common/src/test/resources/jcasbin_policy.txt 
b/server-common/src/test/resources/jcasbin_policy.txt
new file mode 100644
index 0000000000..e71a5b6c54
--- /dev/null
+++ b/server-common/src/test/resources/jcasbin_policy.txt
@@ -0,0 +1,28 @@
+# 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.
+
+p, role1, METALAKE, metalake1, OWNER, allow
+p, role2, CATALOG, catalog1, OWNER, allow
+p, role3, SCHEMA, schema1, OWNER, allow
+p, role4, TABLE, table1, OWNER, allow
+p, role5, METALAKE, metalake1, SELECT_TABLE, allow
+p, role5, METALAKE, metalake1, USE_CATALOG, allow
+p, role5, TABLE, table1, SELECT_TABLE, allow
+
+g, user1, role5
+g, group1, role5
+g, user2, group1
+g, user3, role1
+g, user3, group1

Reply via email to