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

justinchen pushed a commit to branch fix-audit-logger
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 69d1381d5cb6aaf59f2454cf66c35fc7c36d25a3
Author: Yongzao <[email protected]>
AuthorDate: Sat Sep 27 21:25:10 2025 +0800

    Audit log patch for both tree and table models (#16497)
---
 .../iotdb/db/it/audit/IoTDBAuditLogBasicIT.java    | 579 ++++++++++++++++++++-
 .../org/apache/iotdb/db/audit/DNAuditLogger.java   |  20 +-
 .../org/apache/iotdb/db/auth/AuthorityChecker.java |  24 +-
 .../protocol/thrift/IoTDBDataNodeReceiver.java     |   8 +-
 .../sink/protocol/writeback/WriteBackSink.java     |   7 +-
 .../PipePlanTreePrivilegeParseVisitor.java         |   5 +-
 .../db/protocol/client/DataNodeInternalClient.java |   7 +-
 .../iotdb/db/protocol/mqtt/MPPPublishHandler.java  |   7 +-
 .../rest/handler/AuthorizationHandler.java         |  12 +-
 .../protocol/thrift/impl/ClientRPCServiceImpl.java | 219 +++++++-
 .../analyze/schema/AutoCreateSchemaExecutor.java   |   3 +-
 .../relational/analyzer/StatementAnalyzer.java     |  37 +-
 .../plan/relational/security/AccessControl.java    |   3 +-
 .../relational/security/AccessControlImpl.java     |  86 ++-
 .../relational/security/AllowAllAccessControl.java |   4 +-
 .../security/TreeAccessCheckContext.java           |  21 +-
 .../security/TreeAccessCheckVisitor.java           |  39 +-
 .../iotdb/commons/audit/AbstractAuditLogger.java   |   2 +-
 18 files changed, 926 insertions(+), 157 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
index 0f831ad8a74..4d96a41406c 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/db/it/audit/IoTDBAuditLogBasicIT.java
@@ -27,9 +27,9 @@ import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
 import org.apache.iotdb.itbase.env.BaseEnv;
 
-import org.junit.AfterClass;
+import org.junit.After;
 import org.junit.Assert;
-import org.junit.BeforeClass;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
@@ -43,18 +43,20 @@ import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import java.util.StringJoiner;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+/**
+ * This test class ensures the audit log behave exactly the same as we 
expected, including the
+ * number, sequence and content of the audit logs.
+ */
 @RunWith(IoTDBTestRunner.class)
 @Category({LocalStandaloneIT.class})
 public class IoTDBAuditLogBasicIT {
 
   private static final Logger LOGGER = 
LoggerFactory.getLogger(IoTDBAuditLogBasicIT.class);
-
-  /**
-   * Ensure the Audit log behave exactly the same as we expected, including 
number, sequence and
-   * content.
-   */
   private static final List<String> AUDIT_TABLE_COLUMNS =
       Arrays.asList(
           AbstractAuditLogger.AUDIT_LOG_NODE_ID,
@@ -93,8 +95,8 @@ public class IoTDBAuditLogBasicIT {
 
   private static final String AUDITABLE_OPERATION_RESULT = "SUCCESS,FAIL";
 
-  @BeforeClass
-  public static void setUp() throws SQLException {
+  @Before
+  public void setUp() throws SQLException {
     EnvFactory.getEnv()
         .getConfig()
         .getCommonConfig()
@@ -130,8 +132,8 @@ public class IoTDBAuditLogBasicIT {
     }
   }
 
-  @AfterClass
-  public static void tearDown() {
+  @After
+  public void tearDown() {
     EnvFactory.getEnv().cleanClusterEnvironment();
   }
 
@@ -145,13 +147,22 @@ public class IoTDBAuditLogBasicIT {
           "SHOW TABLES",
           "DESC table1",
           "ALTER TABLE table1 set properties TTL='INF'",
+          "CREATE USER user1 'IoTDB@2021abc'",
+          "CREATE role role1",
+          "GRANT SELECT, ALTER, INSERT, DELETE ON test.table1 TO ROLE role1",
+          "GRANT ROLE role1 TO user1",
+          "LIST USER",
+          "LIST ROLE",
+          "DROP ROLE role1",
+          "DROP USER user1",
           "INSERT INTO table1(time, t1, a1, s1) values(1, 't1', 'a1', 's1')",
+          "SELECT * FROM table1",
           "DELETE FROM table1",
           "DROP TABLE table1",
           "DROP DATABASE IF EXISTS test");
   private static final List<List<String>> TABLE_MODEL_AUDIT_FIELDS =
       Arrays.asList(
-          // Start DataNode
+          // Start audit service
           Arrays.asList(
               "node_1",
               "u_none",
@@ -165,7 +176,7 @@ public class IoTDBAuditLogBasicIT {
               "null",
               "null",
               "Successfully start the Audit service with configurations 
(auditableOperationType [DDL, DML, QUERY, CONTROL], auditableOperationLevel 
GLOBAL, auditableOperationResult SUCCESS,FAIL)"),
-          // Show audit database TODO: Fix typo in tree model
+          // Show audit database
           Arrays.asList(
               "node_1",
               "u_0",
@@ -174,10 +185,10 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT_AUTHENTICATION",
               "QUERY",
               "[MANAGE_DATABASE]",
-              "GLOBAL",
+              "OBJECT",
               "true",
               "[root.__audit]",
-              "null",
+              "SHOW DATABASES root.__audit",
               "User root (ID=0) requests authority on object root.__audit with 
result true"),
           // Desc audit table
           Arrays.asList(
@@ -262,7 +273,7 @@ public class IoTDBAuditLogBasicIT {
               "test",
               "ALTER DATABASE test SET PROPERTIES TTL='INF'",
               "User root (ID=0) requests authority on object test with result 
true"),
-          // Use database TODO: Find out why twice
+          // Use database, twice for both read and write connections
           Arrays.asList(
               "node_1",
               "u_0",
@@ -297,8 +308,8 @@ public class IoTDBAuditLogBasicIT {
               "127.0.0.1",
               "OBJECT_AUTHENTICATION",
               "DDL",
-              "[SYSTEM]",
-              "GLOBAL",
+              "[CREATE]",
+              "OBJECT",
               "true",
               "test",
               "CREATE TABLE table1(t1 STRING TAG, a1 STRING ATTRIBUTE, s1 TEXT 
FIELD)",
@@ -331,6 +342,118 @@ public class IoTDBAuditLogBasicIT {
               "test",
               "DESC table1",
               "User root (ID=0) requests authority on object table1 with 
result true"),
+          // Create user
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "CREATE USER user1 ...",
+              "User root (ID=0) requests authority on object user1 with result 
true"),
+          // Create role
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "CREATE role role1",
+              "User root (ID=0) requests authority on object role1 with result 
true"),
+          // Grant privileges to role
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "test",
+              "GRANT SELECT, ALTER, INSERT, DELETE ON test.table1 TO ROLE 
role1",
+              "User root (ID=0) requests authority on object role1 with result 
true"),
+          // Grant role to user
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "GRANT ROLE role1 TO user1",
+              "User root (ID=0) requests authority on object user: user1, 
role: role1 with result true"),
+          // List user TODO: whether to include user object?
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "LIST USER",
+              "User root (ID=0) requests authority on object null with result 
true"),
+          // List role TODO: whether to include role object?
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "LIST ROLE",
+              "User root (ID=0) requests authority on object null with result 
true"),
+          // Drop role
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "DROP ROLE role1",
+              "User root (ID=0) requests authority on object role1 with result 
true"),
+          // Drop user
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "DROP USER user1",
+              "User root (ID=0) requests authority on object user1 with result 
true"),
           // Insert into table
           Arrays.asList(
               "node_1",
@@ -343,9 +466,36 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT",
               "true",
               "test",
-              "INSERT INTO table1(time, t1, a1, s1) values(1, 't1', 'a1', 
's1')",
+              "INSERT INTO table1(time, t1, a1, s1) values(...)",
               "User root (ID=0) requests authority on object table1 with 
result true"),
-          // Delete table TODO: find the delete SQL
+          // Select from table, including fetch device
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[SELECT]",
+              "OBJECT",
+              "true",
+              "test",
+              "SELECT * FROM table1",
+              "User root (ID=0) requests authority on object table1 with 
result true"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[SELECT]",
+              "OBJECT",
+              "true",
+              "test",
+              "fetch device for query",
+              "User root (ID=0) requests authority on object table1 with 
result true"),
+          // Delete table
           Arrays.asList(
               "node_1",
               "u_0",
@@ -357,7 +507,21 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT",
               "true",
               "test",
-              "null",
+              "DELETE FROM table1",
+              "User root (ID=0) requests authority on object table1 with 
result true"),
+          // Drop table
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[DROP]",
+              "OBJECT",
+              "true",
+              "test",
+              "DROP TABLE table1",
               "User root (ID=0) requests authority on object table1 with 
result true"),
           // Drop database
           Arrays.asList(
@@ -373,7 +537,7 @@ public class IoTDBAuditLogBasicIT {
               "test",
               "DROP DATABASE IF EXISTS test",
               "User root (ID=0) requests authority on object test with result 
true"),
-          // Select audit log TODO: find out why twice
+          // Select audit log
           Arrays.asList(
               "node_1",
               "u_0",
@@ -385,7 +549,7 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT",
               "true",
               "__audit",
-              "null",
+              "SELECT * FROM __audit.audit_log ORDER BY TIME",
               "User root (ID=0) requests authority on object __audit with 
result true"),
           Arrays.asList(
               "node_1",
@@ -398,8 +562,10 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT",
               "true",
               "__audit",
-              "null",
+              "fetch device for query",
               "User root (ID=0) requests authority on object __audit with 
result true"));
+  private static final Set<Integer> TABLE_INDEX_FOR_CONTAIN =
+      Stream.of(11, 12).collect(Collectors.toSet());
 
   @Test
   public void basicAuditLogTestForTableModel() throws SQLException {
@@ -409,7 +575,7 @@ public class IoTDBAuditLogBasicIT {
         statement.execute(sql);
       }
       int count = 0;
-      ResultSet resultSet = statement.executeQuery("SELECT * FROM 
__audit.audit_log");
+      ResultSet resultSet = statement.executeQuery("SELECT * FROM 
__audit.audit_log ORDER BY TIME");
       while (resultSet.next()) {
         LOGGER.info("Expected audit log: {}", 
TABLE_MODEL_AUDIT_FIELDS.get(count));
         List<String> actualFields = new ArrayList<>();
@@ -418,13 +584,372 @@ public class IoTDBAuditLogBasicIT {
         }
         LOGGER.info("Actual audit log: {}", actualFields);
         List<String> expectedFields = TABLE_MODEL_AUDIT_FIELDS.get(count);
-        for (int i = 1; i <= 11; i++) {
+        for (int i = 1; i <= 12; i++) {
+          if (TABLE_INDEX_FOR_CONTAIN.contains(i)) {
+            Assert.assertTrue(resultSet.getString(i + 
1).contains(expectedFields.get(i - 1)));
+            continue;
+          }
           Assert.assertEquals(expectedFields.get(i - 1), resultSet.getString(i 
+ 1));
         }
-        
Assert.assertTrue(resultSet.getString(13).contains(expectedFields.get(11)));
+
         count++;
       }
       Assert.assertEquals(TABLE_MODEL_AUDIT_FIELDS.size(), count);
     }
   }
+
+  private static final List<String> TREE_MODEL_AUDIT_SQLS =
+      Arrays.asList(
+          "CREATE DATABASE root.test",
+          "CREATE TIMESERIES root.test.d1.s2 WITH DATATYPE=INT64",
+          "CREATE ALIGNED TIMESERIES root.test.d2(s1 BOOLEAN, s2 INT64)",
+          "ALTER TIMESERIES root.test.d2.s1 ADD TAGS tag3=v3, tag4=v4",
+          "CREATE USER user1 'IoTDB@2021abc'",
+          "CREATE role role1",
+          "GRANT READ_DATA, WRITE_DATA ON root.test TO ROLE role1",
+          "GRANT ROLE role1 TO user1",
+          "LIST USER",
+          "LIST ROLE",
+          "DROP ROLE role1",
+          "DROP USER user1",
+          "INSERT INTO root.test.d1(timestamp,s2) VALUES(1,1)",
+          "INSERT INTO root.test.d2(timestamp,s1,s2) ALIGNED VALUES(1,true,1)",
+          "SELECT ** FROM root.test",
+          "DELETE FROM root.test.d2",
+          "DROP TIMESERIES root.test.d1.s2",
+          "set ttl to root.test.** 360000",
+          "DELETE DATABASE root.test");
+  private static final List<List<String>> TREE_MODEL_AUDIT_FIELDS =
+      Arrays.asList(
+          // Start audit service
+          Arrays.asList(
+              "root.__audit.log.node_1.u_none",
+              "true",
+              "GLOBAL",
+              "[AUDIT]",
+              "null",
+              "CONTROL",
+              "Successfully start the Audit service with configurations 
(auditableOperationType [DDL, DML, QUERY, CONTROL], auditableOperationLevel 
GLOBAL, auditableOperationResult SUCCESS,FAIL)",
+              "null",
+              "CHANGE_AUDIT_OPTION",
+              "null",
+              "null"),
+          // Show audit database
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[MANAGE_DATABASE]",
+              "[root.__audit]",
+              "QUERY",
+              "User root (ID=0) requests authority on object root.__audit with 
result true",
+              "SHOW DATABASES root.__audit",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Desc audit table
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[READ_SCHEMA]",
+              "__audit",
+              "QUERY",
+              "User root (ID=0) requests authority on object audit_log with 
result true",
+              "DESC __audit.audit_log",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Create database
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[MANAGE_DATABASE]",
+              "root.test",
+              "DDL",
+              "User root (ID=0) requests authority on object root.test with 
result true",
+              "CREATE DATABASE root.test",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Create (aligned) timeseries TODO: fill database if necessary, 
same as follows
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[WRITE_SCHEMA]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object [root.test.d1.s2] 
with result true",
+              "CREATE TIMESERIES root.test.d1.s2 WITH DATATYPE=INT64",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[WRITE_SCHEMA]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object [root.test.d2.s1, 
root.test.d2.s2] with result true",
+              "CREATE ALIGNED TIMESERIES root.test.d2(s1 BOOLEAN, s2 INT64)",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Alter timeseries
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[WRITE_SCHEMA]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object [root.test.d2.s1] 
with result true",
+              "ALTER TIMESERIES root.test.d2.s1 ADD TAGS tag3=v3, tag4=v4",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Create user
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[MANAGE_USER]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object user1 with result 
true",
+              "CREATE USER user1 ...",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Create role
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[MANAGE_ROLE]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object role1 with result 
true",
+              "CREATE role role1",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Grant privileges to role
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[SECURITY]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object role1 with result 
true",
+              "GRANT READ_DATA, WRITE_DATA ON root.test TO ROLE role1",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Grant role to user
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[MANAGE_ROLE]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object user: user1, 
role: role1 with result true",
+              "GRANT ROLE role1 TO user1",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // List user TODO: whether to include user object?
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[MANAGE_USER]",
+              "null",
+              "QUERY",
+              "User root (ID=0) requests authority on object null with result 
true",
+              "LIST USER",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // List role TODO: whether to include role object?
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[MANAGE_ROLE]",
+              "null",
+              "QUERY",
+              "User root (ID=0) requests authority on object null with result 
true",
+              "LIST ROLE",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Drop role
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[MANAGE_ROLE]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object role1 with result 
true",
+              "DROP ROLE role1",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Drop user
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[MANAGE_USER]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object user1 with result 
true",
+              "DROP USER user1",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Insert into (aligned) timeseries
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[WRITE_DATA]",
+              "null",
+              "DML",
+              "User root (ID=0) requests authority on object [root.test.d1.s2] 
with result true",
+              "INSERT INTO root.test.d1(timestamp,s2) VALUES(...)",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[WRITE_DATA]",
+              "null",
+              "DML",
+              "User root (ID=0) requests authority on object [root.test.d2.s1, 
root.test.d2.s2] with result true",
+              "INSERT INTO root.test.d2(timestamp,s1,s2) ALIGNED VALUES(...)",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Select all timeseries
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[READ_DATA]",
+              "null",
+              "QUERY",
+              "User root (ID=0) requests authority on object [root.test.**] 
with result true",
+              "SELECT ** FROM root.test",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Delete timeseries data
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[WRITE_DATA]",
+              "null",
+              "DML",
+              "User root (ID=0) requests authority on object [root.test.d2] 
with result true",
+              "DELETE FROM root.test.d2",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Drop timeseries
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[WRITE_SCHEMA]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object [root.test.d1.s2] 
with result true",
+              "DROP TIMESERIES root.test.d1.s2",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Set TTL to devices
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "GLOBAL",
+              "[SYSTEM]",
+              "null",
+              "DDL",
+              "User root (ID=0) requests authority on object [root.test.**] 
with result true",
+              "set ttl to root.test.** 360000",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Delete database
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[MANAGE_DATABASE]",
+              "[root.test]",
+              "DDL",
+              "User root (ID=0) requests authority on object [root.test] with 
result true",
+              "DELETE DATABASE root.test",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"),
+          // Select audit log
+          Arrays.asList(
+              "root.__audit.log.node_1.u_0",
+              "true",
+              "OBJECT",
+              "[READ_DATA]",
+              "null",
+              "QUERY",
+              "User root (ID=0) requests authority on object 
[root.__audit.log.**.*] with result true",
+              "SELECT * FROM root.__audit.log.** ORDER BY TIME ALIGN BY 
DEVICE",
+              "OBJECT_AUTHENTICATION",
+              "127.0.0.1",
+              "root"));
+  private static final Set<Integer> TREE_INDEX_FOR_CONTAIN =
+      Stream.of(7).collect(Collectors.toSet());
+
+  @Test
+  public void basicAuditLogTestForTreeModel() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      for (String sql : TREE_MODEL_AUDIT_SQLS) {
+        statement.execute(sql);
+      }
+      int count = 0;
+      ResultSet resultSet =
+          statement.executeQuery("SELECT * FROM root.__audit.log.** ORDER BY 
TIME ALIGN BY DEVICE");
+      while (resultSet.next()) {
+        LOGGER.info("Expected audit log: {}", 
TREE_MODEL_AUDIT_FIELDS.get(count));
+        List<String> actualFields = new ArrayList<>();
+        for (int i = 1; i <= 11; i++) {
+          actualFields.add(resultSet.getString(i + 1));
+        }
+        LOGGER.info("Actual audit log: {}", actualFields);
+        List<String> expectedFields = TREE_MODEL_AUDIT_FIELDS.get(count);
+        for (int i = 1; i <= 11; i++) {
+          if (TREE_INDEX_FOR_CONTAIN.contains(i)) {
+            Assert.assertTrue(resultSet.getString(i + 
1).contains(expectedFields.get(i - 1)));
+            continue;
+          }
+          Assert.assertEquals(expectedFields.get(i - 1), resultSet.getString(i 
+ 1));
+        }
+
+        count++;
+      }
+      Assert.assertEquals(TREE_MODEL_AUDIT_FIELDS.size(), count);
+    }
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
index c26bbb1a38d..1fdb138592f 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/audit/DNAuditLogger.java
@@ -77,6 +77,8 @@ import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import static 
org.apache.iotdb.db.pipe.receiver.protocol.legacy.loader.ILoader.SCHEMA_FETCHER;
 
@@ -159,6 +161,20 @@ public class DNAuditLogger extends AbstractAuditLogger {
           AUDIT_LOG_LOG
         });
     insertStatement.setAligned(false);
+    String sqlString = auditLogFields.getSqlString();
+    if (sqlString != null) {
+      if (sqlString.toUpperCase().startsWith("CREATE USER")) {
+        sqlString = String.join(" ", Arrays.asList(sqlString.split(" 
")).subList(0, 3)) + " ...";
+      }
+      Pattern pattern = Pattern.compile("(?i)(values)\\([^)]*\\)");
+      Matcher matcher = pattern.matcher(sqlString);
+      StringBuffer sb = new StringBuffer();
+      while (matcher.find()) {
+        matcher.appendReplacement(sb, matcher.group(1) + "(...)");
+      }
+      matcher.appendTail(sb);
+      sqlString = sb.toString();
+    }
     insertStatement.setValues(
         new Object[] {
           new Binary(username == null ? "null" : username, 
TSFileConfig.STRING_CHARSET),
@@ -178,9 +194,7 @@ public class DNAuditLogger extends AbstractAuditLogger {
           new Binary(
               auditLogFields.getDatabase() == null ? "null" : 
auditLogFields.getDatabase(),
               TSFileConfig.STRING_CHARSET),
-          new Binary(
-              auditLogFields.getSqlString() == null ? "null" : 
auditLogFields.getSqlString(),
-              TSFileConfig.STRING_CHARSET),
+          new Binary(sqlString == null ? "null" : sqlString, 
TSFileConfig.STRING_CHARSET),
           new Binary(log == null ? "null" : log, TSFileConfig.STRING_CHARSET)
         });
     insertStatement.setDataTypes(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index 31a7ffe3a11..bbd9ada2b9e 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -45,6 +45,7 @@ import 
org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult;
 import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
 import 
org.apache.iotdb.db.queryengine.plan.relational.security.AccessControlImpl;
 import 
org.apache.iotdb.db.queryengine.plan.relational.security.ITableAuthCheckerImpl;
+import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
 import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckVisitor;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.RelationalAuthorStatement;
 import org.apache.iotdb.db.queryengine.plan.statement.Statement;
@@ -176,22 +177,21 @@ public class AuthorityChecker {
     }
   }
 
-  /** Check whether specific Session has the authorization to given plan. */
-  public static TSStatus checkAuthority(Statement statement, IClientSession 
session) {
+  public static TSStatus checkAuthority(Statement statement, IAuditEntity 
auditEntity) {
     long startTime = System.nanoTime();
     try {
+      if (auditEntity instanceof TreeAccessCheckContext) {
+        return accessControl.checkPermissionBeforeProcess(
+            statement, (TreeAccessCheckContext) auditEntity);
+      }
       return accessControl.checkPermissionBeforeProcess(
           statement,
-          new UserEntity(session.getUserId(), session.getUsername(), 
session.getClientAddress()));
-    } finally {
-      PERFORMANCE_OVERVIEW_METRICS.recordAuthCost(System.nanoTime() - 
startTime);
-    }
-  }
-
-  public static TSStatus checkAuthority(Statement statement, UserEntity 
userEntity) {
-    long startTime = System.nanoTime();
-    try {
-      return accessControl.checkPermissionBeforeProcess(statement, userEntity);
+          (TreeAccessCheckContext)
+              new TreeAccessCheckContext(
+                      auditEntity.getUserId(),
+                      auditEntity.getUsername(),
+                      auditEntity.getCliHostname())
+                  .setSqlString(auditEntity.getSqlString()));
     } finally {
       PERFORMANCE_OVERVIEW_METRICS.recordAuthCost(System.nanoTime() - 
startTime);
     }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
index 3544e6736f6..1511933ad35 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/receiver/protocol/thrift/IoTDBDataNodeReceiver.java
@@ -86,6 +86,7 @@ import 
org.apache.iotdb.db.queryengine.plan.execution.config.executor.ClusterCon
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask;
 import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.write.view.AlterLogicalViewNode;
+import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.PipeEnriched;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
 import org.apache.iotdb.db.queryengine.plan.statement.Statement;
@@ -880,7 +881,12 @@ public class IoTDBDataNodeReceiver extends 
IoTDBFileReceiver {
     // For table model, the authority check is done in inner execution. No 
need to check here
     if (!isTableModelStatement) {
       final TSStatus permissionCheckStatus =
-          AuthorityChecker.checkAuthority(statement, clientSession);
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (permissionCheckStatus.getCode() != 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         PipeLogger.log(
             LOGGER::warn,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/sink/protocol/writeback/WriteBackSink.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/sink/protocol/writeback/WriteBackSink.java
index 53af1bed26a..fddb9f2f1a9 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/sink/protocol/writeback/WriteBackSink.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/sink/protocol/writeback/WriteBackSink.java
@@ -45,6 +45,7 @@ import 
org.apache.iotdb.db.queryengine.plan.execution.config.executor.ClusterCon
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask;
 import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertNode;
+import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
 import org.apache.iotdb.db.queryengine.plan.statement.Statement;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertBaseStatement;
@@ -481,7 +482,11 @@ public class WriteBackSink implements PipeConnector {
     if (useEventUserName && userName != null) {
       session.setUsername(userName);
     }
-    final TSStatus permissionCheckStatus = 
AuthorityChecker.checkAuthority(statement, session);
+    final TSStatus permissionCheckStatus =
+        AuthorityChecker.checkAuthority(
+            statement,
+            new TreeAccessCheckContext(
+                session.getUserId(), session.getUsername(), 
session.getClientAddress()));
     if (permissionCheckStatus.getCode() != 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       PipeLogger.log(
           LOGGER::warn,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/schemaregion/PipePlanTreePrivilegeParseVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/schemaregion/PipePlanTreePrivilegeParseVisitor.java
index 260f6bd1d37..5967097418d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/schemaregion/PipePlanTreePrivilegeParseVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/schemaregion/PipePlanTreePrivilegeParseVisitor.java
@@ -20,7 +20,6 @@
 package org.apache.iotdb.db.pipe.source.schemaregion;
 
 import org.apache.iotdb.commons.audit.IAuditEntity;
-import org.apache.iotdb.commons.audit.UserEntity;
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 import org.apache.iotdb.commons.exception.auth.AccessDeniedException;
 import org.apache.iotdb.commons.path.MeasurementPath;
@@ -328,7 +327,9 @@ public class PipePlanTreePrivilegeParseVisitor
       final DeleteDataNode node, final IAuditEntity auditEntity) {
     final List<MeasurementPath> intersectedPaths =
         TreeAccessCheckVisitor.getIntersectedPaths4Pipe(
-            node.getPathList(), new TreeAccessCheckContext((UserEntity) 
auditEntity));
+            node.getPathList(),
+            new TreeAccessCheckContext(
+                auditEntity.getUserId(), auditEntity.getUsername(), 
auditEntity.getCliHostname()));
     if (!skip && !intersectedPaths.equals(node.getPathList())) {
       throw new AccessDeniedException("Not has privilege to transfer plan: " + 
node);
     }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/DataNodeInternalClient.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/DataNodeInternalClient.java
index d96151b2e93..227f8731cae 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/DataNodeInternalClient.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/client/DataNodeInternalClient.java
@@ -38,6 +38,7 @@ import 
org.apache.iotdb.db.queryengine.plan.analyze.schema.ISchemaFetcher;
 import org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
 import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
 import org.apache.iotdb.db.queryengine.plan.statement.StatementType;
 import 
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertMultiTabletsStatement;
@@ -98,7 +99,11 @@ public class DataNodeInternalClient {
   public TSStatus insertTablets(InsertMultiTabletsStatement statement) {
     try {
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, session);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  session.getUserId(), session.getUsername(), 
session.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/mqtt/MPPPublishHandler.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/mqtt/MPPPublishHandler.java
index a6464a56c49..c993da93b73 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/mqtt/MPPPublishHandler.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/mqtt/MPPPublishHandler.java
@@ -37,6 +37,7 @@ import 
org.apache.iotdb.db.queryengine.plan.analyze.schema.ISchemaFetcher;
 import org.apache.iotdb.db.queryengine.plan.execution.ExecutionResult;
 import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner;
 import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
+import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.parser.SqlParser;
 import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertTabletStatement;
@@ -279,7 +280,11 @@ public class MPPPublishHandler extends 
AbstractInterceptHandler {
       }
       statement.setAligned(false);
 
-      tsStatus = AuthorityChecker.checkAuthority(statement, session);
+      tsStatus =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  session.getUserId(), session.getUsername(), 
session.getClientAddress()));
       if (tsStatus.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         LOG.warn(tsStatus.message);
       } else {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/handler/AuthorizationHandler.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/handler/AuthorizationHandler.java
index 989f5211670..3c30e3e95a9 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/handler/AuthorizationHandler.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/rest/handler/AuthorizationHandler.java
@@ -19,29 +19,19 @@ package org.apache.iotdb.db.protocol.rest.handler;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.audit.UserEntity;
-import org.apache.iotdb.commons.auth.entity.User;
 import org.apache.iotdb.db.auth.AuthorityChecker;
-import org.apache.iotdb.db.auth.BasicAuthorityCache;
-import org.apache.iotdb.db.auth.ClusterAuthorityFetcher;
-import org.apache.iotdb.db.auth.IAuthorityFetcher;
 import org.apache.iotdb.db.protocol.rest.model.ExecutionStatus;
 import org.apache.iotdb.db.queryengine.plan.statement.Statement;
 import org.apache.iotdb.rpc.TSStatusCode;
 
-import org.apache.ratis.util.MemoizedSupplier;
-
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.SecurityContext;
 
 public class AuthorizationHandler {
 
-  private static final MemoizedSupplier<IAuthorityFetcher> authorityFetcher =
-      MemoizedSupplier.valueOf(() -> new ClusterAuthorityFetcher(new 
BasicAuthorityCache()));
-
   public Response checkAuthority(SecurityContext securityContext, Statement 
statement) {
     String userName = securityContext.getUserPrincipal().getName();
-    User user = authorityFetcher.get().getUser(userName);
-    long userId = user == null ? -1 : user.getUserId();
+    long userId = AuthorityChecker.getUserId(userName).orElse(-1L);
     TSStatus status =
         AuthorityChecker.checkAuthority(statement, new UserEntity(userId, 
userName, ""));
     if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
index fb7a0813002..74c2f6eda6b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java
@@ -88,6 +88,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.Ta
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.TableDeviceSchemaCache;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.TableId;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.TreeDeviceSchemaCacheManager;
+import 
org.apache.iotdb.db.queryengine.plan.relational.security.TreeAccessCheckContext;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SetSqlDialect;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Use;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.parser.ParsingException;
@@ -346,7 +347,14 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
                   false);
         } else {
           // permission check
-          TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
+          TSStatus status =
+              AuthorityChecker.checkAuthority(
+                  s,
+                  new TreeAccessCheckContext(
+                          clientSession.getUserId(),
+                          clientSession.getUsername(),
+                          clientSession.getClientAddress())
+                      .setSqlString(statement));
           if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) 
{
             return RpcUtils.getTSExecuteStatementResp(status);
           }
@@ -521,7 +529,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       Statement s = StatementGenerator.createStatement(req);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              s,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return RpcUtils.getTSExecuteStatementResp(status);
       }
@@ -610,7 +624,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
     try {
       Statement s = StatementGenerator.createStatement(req);
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              s,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return RpcUtils.getTSExecuteStatementResp(status);
       }
@@ -701,7 +721,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
     try {
       Statement s = StatementGenerator.createStatement(req);
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              s,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return RpcUtils.getTSExecuteStatementResp(status);
       }
@@ -1145,7 +1171,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       // cache miss
       Statement s = StatementGenerator.createStatement(convert(req));
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(s, clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              s,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return RpcUtils.getTSExecuteStatementResp(status);
       }
@@ -1540,7 +1572,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       // Step 1: Create SetStorageGroupStatement
       DatabaseSchemaStatement statement = 
StatementGenerator.createStatement(storageGroup);
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -1578,7 +1616,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       // Step 1: transfer from TSCreateTimeseriesReq to Statement
       CreateTimeSeriesStatement statement = 
StatementGenerator.createStatement(req);
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -1622,7 +1666,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       // Step 1: transfer from CreateAlignedTimeSeriesReq to Statement
       CreateAlignedTimeSeriesStatement statement = 
StatementGenerator.createStatement(req);
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -1666,7 +1716,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       // Step 1: transfer from CreateMultiTimeSeriesReq to Statement
       CreateMultiTimeSeriesStatement statement = 
StatementGenerator.createStatement(req);
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -1706,7 +1762,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
           StatementGenerator.createDeleteTimeSeriesStatement(path);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -1745,7 +1807,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       DeleteDatabaseStatement statement = 
StatementGenerator.createStatement(storageGroups);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -1825,7 +1893,14 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
                       false);
             } else {
               // permission check
-              TSStatus status = AuthorityChecker.checkAuthority(s, 
clientSession);
+              TSStatus status =
+                  AuthorityChecker.checkAuthority(
+                      s,
+                      new TreeAccessCheckContext(
+                              clientSession.getUserId(),
+                              clientSession.getUsername(),
+                              clientSession.getClientAddress())
+                          .setSqlString(statement));
               if (status.getCode() != 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
                 return status;
               }
@@ -2015,7 +2090,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       }
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2075,7 +2156,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       }
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2137,7 +2224,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       }
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2201,7 +2294,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       }
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2270,7 +2369,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       }
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2333,7 +2438,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
 
       // permission check for tree model, table model does this in the 
analysis stage
       if (!req.isWriteToTable()) {
-        TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+        TSStatus status =
+            AuthorityChecker.checkAuthority(
+                statement,
+                new TreeAccessCheckContext(
+                    clientSession.getUserId(),
+                    clientSession.getUsername(),
+                    clientSession.getClientAddress()));
         if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
           return status;
         }
@@ -2404,7 +2515,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       }
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2494,7 +2611,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       DeleteDataStatement statement = StatementGenerator.createStatement(req);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2554,7 +2677,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       CreateSchemaTemplateStatement statement = 
StatementGenerator.createStatement(req);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2717,7 +2846,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
     try {
       IClientSession clientSession = 
SESSION_MANAGER.getCurrSessionAndUpdateIdleTime();
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         resp.setStatus(status);
         return resp;
@@ -2796,7 +2931,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       SetSchemaTemplateStatement statement = 
StatementGenerator.createStatement(req);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2837,7 +2978,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       UnsetSchemaTemplateStatement statement = 
StatementGenerator.createStatement(req);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2878,7 +3025,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       DropSchemaTemplateStatement statement = 
StatementGenerator.createStatement(req);
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -2917,7 +3070,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
           
StatementGenerator.createBatchActivateTemplateStatement(req.getDevicePathList());
 
       // permission check
-      TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
@@ -3007,7 +3166,13 @@ public class ClientRPCServiceImpl implements 
IClientRPCServiceWithHandler {
       final InsertRowStatement statement = 
StatementGenerator.createStatement(req);
 
       // Permission check
-      final TSStatus status = AuthorityChecker.checkAuthority(statement, 
clientSession);
+      final TSStatus status =
+          AuthorityChecker.checkAuthority(
+              statement,
+              new TreeAccessCheckContext(
+                  clientSession.getUserId(),
+                  clientSession.getUsername(),
+                  clientSession.getClientAddress()));
       if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
         return status;
       }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java
index 37be5691ee5..6806b224778 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/schema/AutoCreateSchemaExecutor.java
@@ -495,8 +495,7 @@ class AutoCreateSchemaExecutor {
   // Auto create timeseries and return the existing timeseries info
   private List<MeasurementPath> executeInternalCreateTimeseriesStatement(
       final Statement statement, final MPPQueryContext context) {
-    final TSStatus status =
-        AuthorityChecker.checkAuthority(statement, 
context.getSession().getUserEntity());
+    final TSStatus status = AuthorityChecker.checkAuthority(statement, 
context);
     if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       throw new IoTDBRuntimeException(status.getMessage(), status.getCode());
     }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
index 58e3e510418..408c52909e7 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
@@ -19,7 +19,6 @@
 
 package org.apache.iotdb.db.queryengine.plan.relational.analyzer;
 
-import org.apache.iotdb.commons.audit.UserEntity;
 import org.apache.iotdb.commons.schema.table.TsTable;
 import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory;
 import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema;
@@ -503,10 +502,7 @@ public class StatementAnalyzer {
       accessControl.checkCanInsertIntoTable(
           sessionContext.getUserName(),
           new QualifiedObjectName(node.getDatabase(), node.getTableName()),
-          new UserEntity(
-              sessionContext.getUserId(),
-              sessionContext.getUserName(),
-              sessionContext.getCliHostname()));
+          queryContext);
       final TranslationMap translationMap = analyzeTraverseDevice(node, 
context, true);
       final TsTable table =
           DataNodeTableCache.getInstance().getTable(node.getDatabase(), 
node.getTableName());
@@ -567,10 +563,7 @@ public class StatementAnalyzer {
       accessControl.checkCanDeleteFromTable(
           sessionContext.getUserName(),
           new QualifiedObjectName(node.getDatabase(), node.getTableName()),
-          new UserEntity(
-              sessionContext.getUserId(),
-              sessionContext.getUserName(),
-              sessionContext.getCliHostname()));
+          queryContext);
       final TsTable table =
           DataNodeTableCache.getInstance().getTable(node.getDatabase(), 
node.getTableName());
       DataNodeTreeViewSchemaUtils.checkTableInWrite(node.getDatabase(), table);
@@ -645,12 +638,7 @@ public class StatementAnalyzer {
       }
       // verify access privileges
       accessControl.checkCanInsertIntoTable(
-          sessionContext.getUserName(),
-          targetTable,
-          new UserEntity(
-              sessionContext.getUserId(),
-              sessionContext.getUserName(),
-              sessionContext.getCliHostname()));
+          sessionContext.getUserName(), targetTable, queryContext);
 
       // verify the insert destination columns match the query
       Optional<TableSchema> tableSchema = 
metadata.getTableSchema(sessionContext, targetTable);
@@ -773,10 +761,7 @@ public class StatementAnalyzer {
           new QualifiedObjectName(
               AnalyzeUtils.getDatabaseName(node, queryContext),
               node.getTable().getName().getSuffix()),
-          new UserEntity(
-              sessionContext.getUserId(),
-              sessionContext.getUserName(),
-              sessionContext.getCliHostname()));
+          queryContext);
       AnalyzeUtils.analyzeDelete(node, queryContext);
 
       analysis.setScope(node, ret);
@@ -3071,17 +3056,10 @@ public class StatementAnalyzer {
           return resultScope;
         }
       }
-
       QualifiedObjectName name = createQualifiedObjectName(sessionContext, 
table.getName());
 
       // access control
-      accessControl.checkCanSelectFromTable(
-          sessionContext.getUserName(),
-          name,
-          new UserEntity(
-              sessionContext.getUserId(),
-              sessionContext.getUserName(),
-              sessionContext.getCliHostname()));
+      accessControl.checkCanSelectFromTable(sessionContext.getUserName(), 
name, queryContext);
 
       analysis.setRelationName(
           table, QualifiedName.of(name.getDatabaseName(), 
name.getObjectName()));
@@ -4505,10 +4483,7 @@ public class StatementAnalyzer {
       accessControl.checkCanSelectFromTable(
           sessionContext.getUserName(),
           new QualifiedObjectName(node.getDatabase(), node.getTableName()),
-          new UserEntity(
-              sessionContext.getUserId(),
-              sessionContext.getUserName(),
-              sessionContext.getCliHostname()));
+          queryContext);
       analyzeTraverseDevice(node, context, node.getWhere().isPresent());
 
       final TsTable table =
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControl.java
index 6a1cf27d98a..35c04bf4c18 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControl.java
@@ -21,7 +21,6 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.security;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.audit.IAuditEntity;
-import org.apache.iotdb.commons.audit.UserEntity;
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 import org.apache.iotdb.commons.exception.auth.AccessDeniedException;
 import org.apache.iotdb.commons.path.PartialPath;
@@ -218,7 +217,7 @@ public interface AccessControl {
 
   // ====================================== TREE 
=============================================
 
-  TSStatus checkPermissionBeforeProcess(Statement statement, UserEntity 
userEntity);
+  TSStatus checkPermissionBeforeProcess(Statement statement, 
TreeAccessCheckContext context);
 
   /** called by load */
   TSStatus checkFullPathWriteDataPermission(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
index bfffb794335..af1dec2f68a 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AccessControlImpl.java
@@ -22,7 +22,6 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.security;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.audit.AuditLogOperation;
 import org.apache.iotdb.commons.audit.IAuditEntity;
-import org.apache.iotdb.commons.audit.UserEntity;
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.exception.auth.AccessDeniedException;
@@ -107,7 +106,9 @@ public class AccessControlImpl implements AccessControl {
   @Override
   public void checkCanCreateTable(
       String userName, QualifiedObjectName tableName, IAuditEntity 
auditEntity) {
-    auditEntity.setAuditLogOperation(AuditLogOperation.DDL);
+    auditEntity
+        .setAuditLogOperation(AuditLogOperation.DDL)
+        .setDatabase(tableName.getDatabaseName());
     InformationSchemaUtils.checkDBNameInWrite(tableName.getDatabaseName());
     if (userName.equals(AuthorityChecker.INTERNAL_AUDIT_USER)
         && tableName.getDatabaseName().equals(TABLE_MODEL_AUDIT_DATABASE)) {
@@ -117,7 +118,7 @@ public class AccessControlImpl implements AccessControl {
     checkAuditDatabase(tableName.getDatabaseName());
     if (hasGlobalPrivilege(auditEntity, PrivilegeType.SYSTEM)) {
       ITableAuthCheckerImpl.recordAuditLog(
-          auditEntity.setPrivilegeType(PrivilegeType.SYSTEM).setResult(true),
+          auditEntity.setPrivilegeType(PrivilegeType.CREATE).setResult(true),
           tableName::getObjectName);
       return;
     }
@@ -127,10 +128,15 @@ public class AccessControlImpl implements AccessControl {
   @Override
   public void checkCanDropTable(
       String userName, QualifiedObjectName tableName, IAuditEntity 
auditEntity) {
+    auditEntity
+        .setAuditLogOperation(AuditLogOperation.DDL)
+        .setDatabase(tableName.getDatabaseName());
     InformationSchemaUtils.checkDBNameInWrite(tableName.getDatabaseName());
     checkAuditDatabase(tableName.getDatabaseName());
     if (hasGlobalPrivilege(auditEntity, PrivilegeType.SYSTEM)) {
-      ITableAuthCheckerImpl.recordAuditLog(auditEntity, 
tableName::getObjectName);
+      ITableAuthCheckerImpl.recordAuditLog(
+          auditEntity.setPrivilegeType(PrivilegeType.DROP).setResult(true),
+          tableName::getObjectName);
       return;
     }
     authChecker.checkTablePrivilege(userName, tableName, 
TableModelPrivilege.DROP, auditEntity);
@@ -246,58 +252,82 @@ public class AccessControlImpl implements AccessControl {
     switch (type) {
       case CREATE_USER:
       case DROP_USER:
+      case UPDATE_USER:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
-          ITableAuthCheckerImpl.recordAuditLog(auditEntity, 
statement::getUserName);
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getUserName);
           return;
         }
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_USER, auditEntity);
         return;
-      case UPDATE_USER:
       case LIST_USER_PRIV:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.QUERY)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()
             || statement.getUserName().equals(userName)) {
-          ITableAuthCheckerImpl.recordAuditLog(auditEntity, 
statement::getUserName);
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getUserName);
           return;
         }
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_USER, auditEntity);
         return;
       case LIST_USER:
+        auditEntity.setAuditLogOperation(AuditLogOperation.QUERY);
         if (!hasGlobalPrivilege(auditEntity, PrivilegeType.MANAGE_USER)) {
           statement.setUserName(userName);
+        } else {
+          auditEntity.setPrivilegeType(PrivilegeType.SECURITY);
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getUserName);
         }
         return;
       case CREATE_ROLE:
       case DROP_ROLE:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
-          ITableAuthCheckerImpl.recordAuditLog(auditEntity, 
statement::getRoleName);
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getRoleName);
           return;
         }
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_ROLE, auditEntity);
         return;
       case GRANT_USER_ROLE:
       case REVOKE_USER_ROLE:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
           ITableAuthCheckerImpl.recordAuditLog(
-              auditEntity,
+              auditEntity.setResult(true),
               () -> "user: " + statement.getUserName() + ", role: " + 
statement.getRoleName());
           return;
         }
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_ROLE, auditEntity);
         return;
       case LIST_ROLE:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.QUERY)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (statement.getUserName() != null && 
!statement.getUserName().equals(userName)) {
           authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_ROLE, auditEntity);
-          ITableAuthCheckerImpl.recordAuditLog(auditEntity, 
statement::getRoleName);
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getRoleName);
           return;
         }
         if (!hasGlobalPrivilege(auditEntity, PrivilegeType.MANAGE_ROLE)) {
           statement.setUserName(userName);
+        } else {
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getRoleName);
         }
         return;
       case LIST_ROLE_PRIV:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.QUERY)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()
             || AuthorityChecker.checkRole(userName, statement.getRoleName())) {
-          ITableAuthCheckerImpl.recordAuditLog(auditEntity, 
statement::getRoleName);
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getRoleName);
           return;
         }
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_ROLE, auditEntity);
@@ -306,9 +336,13 @@ public class AccessControlImpl implements AccessControl {
       case GRANT_USER_ANY:
       case REVOKE_ROLE_ANY:
       case REVOKE_USER_ANY:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY)
+            .setDatabase(statement.getDatabase());
         if (hasGlobalPrivilege(auditEntity, PrivilegeType.SECURITY)) {
           ITableAuthCheckerImpl.recordAuditLog(
-              auditEntity, () -> statement.getUserName() + 
statement.getRoleName());
+              auditEntity.setResult(true), () -> statement.getUserName() + 
statement.getRoleName());
           return;
         }
         for (PrivilegeType privilegeType : statement.getPrivilegeTypes()) {
@@ -320,9 +354,13 @@ public class AccessControlImpl implements AccessControl {
       case REVOKE_ROLE_ALL:
       case GRANT_USER_ALL:
       case REVOKE_USER_ALL:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY)
+            .setDatabase(statement.getDatabase());
         if (hasGlobalPrivilege(auditEntity, PrivilegeType.SECURITY)) {
           ITableAuthCheckerImpl.recordAuditLog(
-              auditEntity, () -> statement.getUserName() + 
statement.getRoleName());
+              auditEntity.setResult(true), () -> statement.getUserName() + 
statement.getRoleName());
           return;
         }
         for (TableModelPrivilege privilege : TableModelPrivilege.values()) {
@@ -339,9 +377,13 @@ public class AccessControlImpl implements AccessControl {
       case GRANT_ROLE_DB:
       case REVOKE_USER_DB:
       case REVOKE_ROLE_DB:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY)
+            .setDatabase(statement.getDatabase());
         if (hasGlobalPrivilege(auditEntity, PrivilegeType.SECURITY)) {
           ITableAuthCheckerImpl.recordAuditLog(
-              auditEntity, () -> statement.getUserName() + 
statement.getRoleName());
+              auditEntity.setResult(true), () -> statement.getUserName() + 
statement.getRoleName());
           return;
         }
         for (PrivilegeType privilegeType : statement.getPrivilegeTypes()) {
@@ -356,9 +398,13 @@ public class AccessControlImpl implements AccessControl {
       case GRANT_ROLE_TB:
       case REVOKE_USER_TB:
       case REVOKE_ROLE_TB:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY)
+            .setDatabase(statement.getDatabase());
         if (hasGlobalPrivilege(auditEntity, PrivilegeType.SECURITY)) {
           ITableAuthCheckerImpl.recordAuditLog(
-              auditEntity, () -> statement.getUserName() + 
statement.getRoleName());
+              auditEntity.setResult(true), () -> statement.getUserName() + 
statement.getRoleName());
           return;
         }
         for (PrivilegeType privilegeType : statement.getPrivilegeTypes()) {
@@ -374,9 +420,12 @@ public class AccessControlImpl implements AccessControl {
       case GRANT_ROLE_SYS:
       case REVOKE_USER_SYS:
       case REVOKE_ROLE_SYS:
+        auditEntity
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (hasGlobalPrivilege(auditEntity, PrivilegeType.SECURITY)) {
           ITableAuthCheckerImpl.recordAuditLog(
-              auditEntity, () -> statement.getUserName() + 
statement.getRoleName());
+              auditEntity.setResult(true), () -> statement.getUserName() + 
statement.getRoleName());
           return;
         }
         for (PrivilegeType privilegeType : statement.getPrivilegeTypes()) {
@@ -420,8 +469,9 @@ public class AccessControlImpl implements AccessControl {
   }
 
   @Override
-  public TSStatus checkPermissionBeforeProcess(Statement statement, UserEntity 
userEntity) {
-    return treeAccessCheckVisitor.process(statement, new 
TreeAccessCheckContext(userEntity));
+  public TSStatus checkPermissionBeforeProcess(
+      Statement statement, TreeAccessCheckContext context) {
+    return treeAccessCheckVisitor.process(statement, context);
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java
index 3ce14c2fd47..11b20883dbb 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/AllowAllAccessControl.java
@@ -21,7 +21,6 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.security;
 
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.audit.IAuditEntity;
-import org.apache.iotdb.commons.audit.UserEntity;
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 import org.apache.iotdb.commons.path.PartialPath;
 import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
@@ -116,7 +115,8 @@ public class AllowAllAccessControl implements AccessControl 
{
       String username, Collection<PrivilegeType> privilegeTypes, IAuditEntity 
auditEntity) {}
 
   @Override
-  public TSStatus checkPermissionBeforeProcess(Statement statement, UserEntity 
userEntity) {
+  public TSStatus checkPermissionBeforeProcess(
+      Statement statement, TreeAccessCheckContext context) {
     return SUCCEED;
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckContext.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckContext.java
index dc92249a0bb..5dbb91cdbe6 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckContext.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckContext.java
@@ -22,7 +22,6 @@ package 
org.apache.iotdb.db.queryengine.plan.relational.security;
 import org.apache.iotdb.commons.audit.AuditEventType;
 import org.apache.iotdb.commons.audit.AuditLogOperation;
 import org.apache.iotdb.commons.audit.IAuditEntity;
-import org.apache.iotdb.commons.audit.UserEntity;
 import org.apache.iotdb.commons.auth.entity.PrivilegeType;
 
 import java.util.Collections;
@@ -30,25 +29,29 @@ import java.util.List;
 
 public class TreeAccessCheckContext implements IAuditEntity {
 
-  private final UserEntity userEntity;
+  private final long userId;
+  private final String username;
+  private final String cliHostname;
 
-  public TreeAccessCheckContext(UserEntity userEntity) {
-    this.userEntity = userEntity;
+  public TreeAccessCheckContext(long userId, String username, String 
cliHostname) {
+    this.userId = userId;
+    this.username = username;
+    this.cliHostname = cliHostname;
   }
 
   @Override
   public long getUserId() {
-    return userEntity.getUserId();
+    return userId;
   }
 
   @Override
   public String getUsername() {
-    return userEntity.getUsername();
+    return username;
   }
 
   @Override
   public String getCliHostname() {
-    return userEntity.getCliHostname();
+    return cliHostname;
   }
 
   private AuditEventType auditEventType;
@@ -134,8 +137,4 @@ public class TreeAccessCheckContext implements IAuditEntity 
{
     this.sqlString = sqlString;
     return this;
   }
-
-  public UserEntity getUserEntity() {
-    return userEntity;
-  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
index 76761aab42f..6d8a63d6a83 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/TreeAccessCheckVisitor.java
@@ -530,9 +530,13 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
   @Override
   public TSStatus visitAuthor(AuthorStatement statement, 
TreeAccessCheckContext context) {
     AuthorType authorType = statement.getAuthorType();
+    Supplier<String> auditObject;
     switch (authorType) {
       case CREATE_USER:
       case DROP_USER:
+        context
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         return checkGlobalAuth(
             context.setAuditLogOperation(AuditLogOperation.DDL),
             PrivilegeType.MANAGE_USER,
@@ -542,22 +546,31 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
         if (statement.getUserName().equals(context.getUsername())) {
           return RpcUtils.SUCCESS_STATUS;
         }
+        context
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         return checkGlobalAuth(
             context.setAuditLogOperation(AuditLogOperation.DDL),
             PrivilegeType.MANAGE_USER,
             statement::getUserName);
 
       case LIST_USER:
+        context
+            .setAuditLogOperation(AuditLogOperation.QUERY)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (checkHasGlobalAuth(
             context.setAuditLogOperation(AuditLogOperation.QUERY),
             PrivilegeType.MANAGE_USER,
-            null)) {
+            statement::getUserName)) {
           return RpcUtils.SUCCESS_STATUS;
         }
         statement.setUserName(context.getUsername());
         return RpcUtils.SUCCESS_STATUS;
 
       case LIST_USER_PRIVILEGE:
+        context
+            .setAuditLogOperation(AuditLogOperation.QUERY)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (context.getUsername().equals(statement.getUserName())) {
           return RpcUtils.SUCCESS_STATUS;
         }
@@ -567,6 +580,9 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
             statement::getUserName);
 
       case LIST_ROLE_PRIVILEGE:
+        context
+            .setAuditLogOperation(AuditLogOperation.QUERY)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (!AuthorityChecker.checkRole(context.getUsername(), 
statement.getRoleName())) {
           return checkGlobalAuth(
               context.setAuditLogOperation(AuditLogOperation.QUERY),
@@ -577,10 +593,13 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
         }
 
       case LIST_ROLE:
+        context
+            .setAuditLogOperation(AuditLogOperation.QUERY)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         if (checkHasGlobalAuth(
             context.setAuditLogOperation(AuditLogOperation.QUERY),
             PrivilegeType.MANAGE_ROLE,
-            null)) {
+            statement::getRoleName)) {
           return SUCCEED;
         }
         // list roles of other user is not allowed
@@ -595,17 +614,27 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
       case DROP_ROLE:
       case GRANT_USER_ROLE:
       case REVOKE_USER_ROLE:
+        context
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
+        auditObject =
+            authorType == AuthorType.CREATE_ROLE || authorType == 
AuthorType.DROP_ROLE
+                ? statement::getRoleName
+                : () -> "user: " + statement.getUserName() + ", role: " + 
statement.getRoleName();
         return checkGlobalAuth(
             context.setAuditLogOperation(AuditLogOperation.DDL),
             PrivilegeType.MANAGE_ROLE,
-            statement::getRoleName);
+            auditObject);
 
       case REVOKE_USER:
       case GRANT_USER:
       case GRANT_ROLE:
       case REVOKE_ROLE:
+        context
+            .setAuditLogOperation(AuditLogOperation.DDL)
+            .setPrivilegeType(PrivilegeType.SECURITY);
         context.setAuditLogOperation(AuditLogOperation.DDL);
-        Supplier<String> auditObject =
+        auditObject =
             () ->
                 authorType == AuthorType.REVOKE_USER || authorType == 
AuthorType.GRANT_USER
                     ? statement.getUserName()
@@ -1383,6 +1412,7 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
   @Override
   public TSStatus visitAlterTimeSeries(
       AlterTimeSeriesStatement statement, TreeAccessCheckContext context) {
+    context.setAuditLogOperation(AuditLogOperation.DDL);
     // audit db is read-only
     if (includeByAuditTreeDB(statement.getPath())
         && 
!context.getUsername().equals(AuthorityChecker.INTERNAL_AUDIT_USER)) {
@@ -1398,6 +1428,7 @@ public class TreeAccessCheckVisitor extends 
StatementVisitor<TSStatus, TreeAcces
   @Override
   public TSStatus visitDeleteTimeSeries(
       DeleteTimeSeriesStatement statement, TreeAccessCheckContext context) {
+    context.setAuditLogOperation(AuditLogOperation.DDL);
     // audit db is read-only
     for (PartialPath path : statement.getPathPatternList()) {
       if (includeByAuditTreeDB(path)
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
index 82eac3606d0..d2d8ce6046c 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/audit/AbstractAuditLogger.java
@@ -94,6 +94,7 @@ public abstract class AbstractAuditLogger {
       case DELETE:
       case INSERT:
       case SELECT:
+      case MANAGE_DATABASE:
       case WRITE_DATA:
       case READ_SCHEMA:
       case WRITE_SCHEMA:
@@ -106,7 +107,6 @@ public abstract class AbstractAuditLogger {
       case MANAGE_ROLE:
       case MANAGE_USER:
       case USE_TRIGGER:
-      case MANAGE_DATABASE:
       case EXTEND_TEMPLATE:
       default:
         return PrivilegeLevel.GLOBAL;


Reply via email to