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

yongzao pushed a commit to branch audit-log-patch-again
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 6216b2add615305a568f70a62432ff8ecbb7ff87
Author: Yongzao <[email protected]>
AuthorDate: Sat Oct 11 13:52:25 2025 +0800

    Fix table model bugs
---
 .../iotdb/db/it/audit/IoTDBAuditLogBasicIT.java    | 791 +++++++++++++++++----
 .../relational/security/AccessControlImpl.java     |  39 +-
 2 files changed, 673 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 39a51468082..372e1e6176c 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
@@ -115,14 +115,7 @@ public class IoTDBAuditLogBasicIT {
     ResultSet resultSet = statement.executeQuery("SHOW DATABASES 
root.__audit");
     Assert.assertTrue(resultSet.next());
     Assert.assertEquals("root.__audit", resultSet.getString(1));
-    Thread.sleep(1000);
-    ((ClusterTestConnection) connection).writeConnection.close();
-    Thread.sleep(1000);
-    for (NodeConnection conn : ((ClusterTestConnection) 
connection).readConnections) {
-      Thread.sleep(1000);
-      conn.close();
-      Thread.sleep(1000);
-    }
+    closeConnectionCompletely(connection);
     connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
     statement = connection.createStatement();
     resultSet = statement.executeQuery("DESC __audit.audit_log");
@@ -135,6 +128,18 @@ public class IoTDBAuditLogBasicIT {
       cnt++;
     }
     Assert.assertEquals(AUDIT_TABLE_COLUMNS.size(), cnt);
+    closeConnectionCompletely(connection);
+  }
+
+  @After
+  public void tearDown() {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  private static void closeConnectionCompletely(Connection connection) throws 
InterruptedException {
+    // Ensure the session conns in test env are closed completely,
+    // in order to generate logout audit log
+    // TODO: Optimize this func after the close func of connection is optimized
     Thread.sleep(1000);
     ((ClusterTestConnection) connection).writeConnection.close();
     Thread.sleep(1000);
@@ -145,34 +150,53 @@ public class IoTDBAuditLogBasicIT {
     }
   }
 
-  @After
-  public void tearDown() {
-    EnvFactory.getEnv().cleanClusterEnvironment();
-  }
-
-  private static final List<String> TABLE_MODEL_AUDIT_SQLS =
+  private static final List<String> TABLE_MODEL_AUDIT_SQLS_USER_ROOT =
       Arrays.asList(
           "CREATE DATABASE test",
-          //          "SHOW DATABASES",
-          "ALTER DATABASE test SET PROPERTIES TTL='INF'",
           "USE test",
-          "CREATE TABLE table1(t1 STRING TAG, a1 STRING ATTRIBUTE, s1 TEXT 
FIELD)",
+          //  "SHOW CURRENT_DATABASE",
+          //  "SHOW DATABASES",
+          "ALTER DATABASE test SET PROPERTIES TTL='INF'",
+          "CREATE TABLE table1(t1 STRING TAG, a1 STRING ATTRIBUTE, s1 STRING 
FIELD)",
           "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",
+          "CREATE USER user1 'IoTDB@2025abc'",
+          "CREATE USER user2 'IoTDB@2025abc'",
+          "CREATE ROLE role1",
+          "GRANT SELECT,ALTER,INSERT,DELETE ON TEST.TABLE1 TO USER user1",
+          "GRANT SELECT ON ANY TO ROLE role1",
+          "GRANT ROLE role1 TO user2",
+          "list user",
+          "list role");
+  private static final List<String> TABLE_MODEL_AUDIT_SQLS_USER_USER1 =
+      Arrays.asList(
+          "LIST PRIVILEGES OF USER user1",
+          "USE test",
           "INSERT INTO table1(time, t1, a1, s1) values(1, 't1', 'a1', 's1')",
           "SELECT * FROM table1",
-          "DELETE FROM table1",
+          "UPDATE table1 SET a1 = t1",
+          "DELETE FROM table1");
+  private static final List<String> TABLE_MODEL_AUDIT_SQLS_USER_USER2 =
+      Arrays.asList(
+          "LIST PRIVILEGES OF USER user2",
+          "LIST PRIVILEGES OF ROLE role1",
+          "list user",
+          "USE test",
+          "INSERT INTO table1(time, t1, a1, s1) values(1, 't1', 'a1', 's1')",
+          "SELECT * FROM table1",
+          "UPDATE table1 SET a1 = t1",
+          "DELETE FROM table1");
+  private static final List<String> TABLE_MODEL_AUDIT_SQLS_USER_ROOT_FINAL =
+      Arrays.asList(
+          "USE test",
           "DROP TABLE table1",
-          "DROP DATABASE IF EXISTS test");
+          "DROP DATABASE IF EXISTS test",
+          "REVOKE SELECT,ALTER,INSERT,DELETE ON TEST.TABLE1 FROM USER user1",
+          "REVOKE SELECT ON ANY FROM ROLE role1",
+          "DROP USER user1",
+          "DROP USER user2",
+          "DROP ROLE role1");
   private static final List<List<String>> TABLE_MODEL_AUDIT_FIELDS =
       Arrays.asList(
           // Start audit service
@@ -189,7 +213,6 @@ public class IoTDBAuditLogBasicIT {
               "null",
               "null",
               "Successfully start the Audit service with configurations 
(auditableOperationType [DDL, DML, QUERY, CONTROL], auditableOperationLevel 
GLOBAL, auditableOperationResult SUCCESS,FAIL)"),
-
           // Environment init login/logout
           Arrays.asList(
               "node_1",
@@ -324,6 +347,7 @@ public class IoTDBAuditLogBasicIT {
               "__audit",
               "DESC __audit.audit_log",
               "User root (ID=0) requests authority on object audit_log with 
result true"),
+          // Setup logout through table model dialect, twice for both read and 
write connections
           Arrays.asList(
               "node_1",
               "u_0",
@@ -337,6 +361,8 @@ public class IoTDBAuditLogBasicIT {
               "",
               "",
               "is closing"),
+          // =============================Audit user 
root=============================
+          // Root login, twice for both read and write connections
           Arrays.asList(
               "node_1",
               "u_0",
@@ -390,6 +416,33 @@ public class IoTDBAuditLogBasicIT {
               "test",
               "CREATE DATABASE test",
               "User root (ID=0) requests authority on object test with result 
true"),
+          // Use database, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User root (ID=0) requests authority on object test with result 
true"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User root (ID=0) requests authority on object test with result 
true"),
           // Show database TODO: Enable only when the order of show databases 
authentication fixed
           //        Arrays.asList(
           //          "node_1",
@@ -445,33 +498,6 @@ 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, twice for both read and write connections
-          Arrays.asList(
-              "node_1",
-              "u_0",
-              "root",
-              "127.0.0.1",
-              "OBJECT_AUTHENTICATION",
-              "QUERY",
-              "[READ_SCHEMA]",
-              "OBJECT",
-              "true",
-              "test",
-              "USE test",
-              "User root (ID=0) requests authority on object test with result 
true"),
-          Arrays.asList(
-              "node_1",
-              "u_0",
-              "root",
-              "127.0.0.1",
-              "OBJECT_AUTHENTICATION",
-              "QUERY",
-              "[READ_SCHEMA]",
-              "OBJECT",
-              "true",
-              "test",
-              "USE test",
-              "User root (ID=0) requests authority on object test with result 
true"),
           // Create table
           Arrays.asList(
               "node_1",
@@ -484,7 +510,7 @@ public class IoTDBAuditLogBasicIT {
               "OBJECT",
               "true",
               "test",
-              "CREATE TABLE table1(t1 STRING TAG, a1 STRING ATTRIBUTE, s1 TEXT 
FIELD)",
+              "CREATE TABLE table1(t1 STRING TAG, a1 STRING ATTRIBUTE, s1 
STRING FIELD)",
               "User root (ID=0) requests authority on object table1 with 
result true"),
           // Show table
           Arrays.asList(
@@ -528,6 +554,20 @@ public class IoTDBAuditLogBasicIT {
               "null",
               "CREATE USER user1 ...",
               "User root (ID=0) requests authority on object user1 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 user2 ...",
+              "User root (ID=0) requests authority on object user2 with result 
true"),
           // Create role
           Arrays.asList(
               "node_1",
@@ -540,9 +580,9 @@ public class IoTDBAuditLogBasicIT {
               "GLOBAL",
               "true",
               "null",
-              "CREATE role role1",
+              "CREATE ROLE role1",
               "User root (ID=0) requests authority on object role1 with result 
true"),
-          // Grant privileges to role
+          // Grant privileges to user
           Arrays.asList(
               "node_1",
               "u_0",
@@ -554,7 +594,21 @@ public class IoTDBAuditLogBasicIT {
               "GLOBAL",
               "true",
               "test",
-              "GRANT SELECT, ALTER, INSERT, DELETE ON test.table1 TO ROLE 
role1",
+              "GRANT SELECT,ALTER,INSERT,DELETE ON TEST.TABLE1 TO USER user1",
+              "User root (ID=0) requests authority on object user1 with result 
true"),
+          // Grant privileges to role
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "GRANT SELECT ON ANY TO ROLE role1",
               "User root (ID=0) requests authority on object role1 with result 
true"),
           // Grant role to user
           Arrays.asList(
@@ -568,9 +622,9 @@ public class IoTDBAuditLogBasicIT {
               "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?
+              "GRANT ROLE role1 TO user2",
+              "User root (ID=0) requests authority on object user: user2, 
role: role1 with result true"),
+          // List user, the user object is null since the root can list all 
users
           Arrays.asList(
               "node_1",
               "u_0",
@@ -582,9 +636,9 @@ public class IoTDBAuditLogBasicIT {
               "GLOBAL",
               "true",
               "null",
-              "LIST USER",
+              "list user",
               "User root (ID=0) requests authority on object null with result 
true"),
-          // List role TODO: whether to include role object?
+          // List role, the role object is null since the root can list all 
roles
           Arrays.asList(
               "node_1",
               "u_0",
@@ -596,41 +650,109 @@ public class IoTDBAuditLogBasicIT {
               "GLOBAL",
               "true",
               "null",
-              "LIST ROLE",
+              "list role",
               "User root (ID=0) requests authority on object null with result 
true"),
-          // Drop role
+          // Root logout, twice for both read and write connections
           Arrays.asList(
               "node_1",
               "u_0",
               "root",
               "127.0.0.1",
-              "OBJECT_AUTHENTICATION",
-              "DDL",
-              "[SECURITY]",
+              "LOGOUT",
+              "CONTROL",
+              "null",
               "GLOBAL",
               "true",
-              "null",
-              "DROP ROLE role1",
-              "User root (ID=0) requests authority on object role1 with result 
true"),
-          // Drop user
+              "",
+              "",
+              "is closing"),
           Arrays.asList(
               "node_1",
               "u_0",
               "root",
               "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          // =============================Audit user 
user1=============================
+          // User1 login, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_10000",
+              "user1",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User user1 (ID=10000), 
opens Session"),
+          Arrays.asList(
+              "node_1",
+              "u_10000",
+              "user1",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User user1 (ID=10000), 
opens Session"),
+          // List privileges of user1
+          Arrays.asList(
+              "node_1",
+              "u_10000",
+              "user1",
+              "127.0.0.1",
               "OBJECT_AUTHENTICATION",
-              "DDL",
-              "[SECURITY]",
+              "QUERY",
+              "null",
               "GLOBAL",
               "true",
               "null",
-              "DROP USER user1",
-              "User root (ID=0) requests authority on object user1 with result 
true"),
+              "LIST PRIVILEGES OF USER user1",
+              "User user1 (ID=10000) requests authority on object user1 with 
result true"),
+          // Use database, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_10000",
+              "user1",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User user1 (ID=10000) requests authority on object test with 
result true"),
+          Arrays.asList(
+              "node_1",
+              "u_10000",
+              "user1",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User user1 (ID=10000) requests authority on object test with 
result true"),
           // Insert into table
           Arrays.asList(
               "node_1",
-              "u_0",
-              "root",
+              "u_10000",
+              "user1",
               "127.0.0.1",
               "OBJECT_AUTHENTICATION",
               "DML",
@@ -639,12 +761,12 @@ public class IoTDBAuditLogBasicIT {
               "true",
               "test",
               "INSERT INTO table1(time, t1, a1, s1) values(...)",
-              "User root (ID=0) requests authority on object table1 with 
result true"),
+              "User user1 (ID=10000) requests authority on object table1 with 
result true"),
           // Select from table, including fetch device
           Arrays.asList(
               "node_1",
-              "u_0",
-              "root",
+              "u_10000",
+              "user1",
               "127.0.0.1",
               "OBJECT_AUTHENTICATION",
               "QUERY",
@@ -653,11 +775,11 @@ public class IoTDBAuditLogBasicIT {
               "true",
               "test",
               "SELECT * FROM table1",
-              "User root (ID=0) requests authority on object table1 with 
result true"),
+              "User user1 (ID=10000) requests authority on object table1 with 
result true"),
           Arrays.asList(
               "node_1",
-              "u_0",
-              "root",
+              "u_10000",
+              "user1",
               "127.0.0.1",
               "OBJECT_AUTHENTICATION",
               "QUERY",
@@ -666,65 +788,424 @@ public class IoTDBAuditLogBasicIT {
               "true",
               "test",
               "fetch device for query",
-              "User root (ID=0) requests authority on object table1 with 
result true"),
-          // Delete table
+              "User user1 (ID=10000) requests authority on object table1 with 
result true"),
+          // Update table
           Arrays.asList(
               "node_1",
-              "u_0",
-              "root",
+              "u_10000",
+              "user1",
               "127.0.0.1",
               "OBJECT_AUTHENTICATION",
               "DML",
-              "[DELETE]",
+              "[INSERT]",
               "OBJECT",
               "true",
               "test",
-              "DELETE FROM table1",
-              "User root (ID=0) requests authority on object table1 with 
result true"),
-          // Drop table
+              "UPDATE table1 SET a1 = t1",
+              "User user1 (ID=10000) requests authority on object table1 with 
result true"),
+          // Delete from table
           Arrays.asList(
               "node_1",
-              "u_0",
-              "root",
+              "u_10000",
+              "user1",
               "127.0.0.1",
               "OBJECT_AUTHENTICATION",
-              "DDL",
-              "[DROP]",
+              "DML",
+              "[DELETE]",
               "OBJECT",
               "true",
               "test",
-              "DROP TABLE table1",
-              "User root (ID=0) requests authority on object table1 with 
result true"),
-          // Drop database
+              "DELETE FROM table1",
+              "User user1 (ID=10000) requests authority on object table1 with 
result true"),
+          // User1 logout, twice for both read and write connections
           Arrays.asList(
               "node_1",
-              "u_0",
-              "root",
+              "u_10000",
+              "user1",
               "127.0.0.1",
-              "OBJECT_AUTHENTICATION",
-              "DDL",
-              "[DROP]",
-              "OBJECT",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
               "true",
-              "test",
-              "DROP DATABASE IF EXISTS test",
-              "User root (ID=0) requests authority on object test with result 
true"),
-          // Select audit log
+              "",
+              "",
+              "is closing"),
           Arrays.asList(
               "node_1",
-              "u_0",
-              "root",
+              "u_10000",
+              "user1",
               "127.0.0.1",
-              "OBJECT_AUTHENTICATION",
-              "QUERY",
-              "[SELECT]",
-              "OBJECT",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
               "true",
-              "__audit",
-              "SELECT * FROM __audit.audit_log ORDER BY TIME",
-              "User root (ID=0) requests authority on object __audit with 
result true"),
-          Arrays.asList(
-              "node_1",
+              "",
+              "",
+              "is closing"),
+          // =============================Audit user 
user2=============================
+          // User2 login, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User user2 (ID=10001), 
opens Session"),
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User user2 (ID=10001), 
opens Session"),
+          // List privileges of user2
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "null",
+              "GLOBAL",
+              "true",
+              "null",
+              "LIST PRIVILEGES OF USER user2",
+              "User user2 (ID=10001) requests authority on object user2 with 
result true"),
+          // List privileges of role1
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "null",
+              "GLOBAL",
+              "true",
+              "null",
+              "LIST PRIVILEGES OF ROLE role1",
+              "User user2 (ID=10001) requests authority on object role1 with 
result true"),
+          // List user, only him/herself
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "null",
+              "GLOBAL",
+              "true",
+              "null",
+              "list user",
+              "User user2 (ID=10001) requests authority on object user2 with 
result true"),
+          // Use database, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User user2 (ID=10001) requests authority on object test with 
result true"),
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User user2 (ID=10001) requests authority on object test with 
result true"),
+          // Failed to insert since no privilege
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DML",
+              "[INSERT]",
+              "OBJECT",
+              "false",
+              "test",
+              "INSERT INTO table1(time, t1, a1, s1) values(...)",
+              "User user2 (ID=10001) requests authority on object table1 with 
result false"),
+          // Select from table1, including fetch device
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[SELECT]",
+              "OBJECT",
+              "true",
+              "test",
+              "SELECT * FROM table1",
+              "User user2 (ID=10001) requests authority on object table1 with 
result true"),
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[SELECT]",
+              "OBJECT",
+              "true",
+              "test",
+              "fetch device for query",
+              "User user2 (ID=10001) requests authority on object table1 with 
result true"),
+          // Update table
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DML",
+              "[INSERT]",
+              "OBJECT",
+              "false",
+              "test",
+              "UPDATE table1 SET a1 = t1",
+              "User user2 (ID=10001) requests authority on object table1 with 
result false"),
+          // Delete from table
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DML",
+              "[DELETE]",
+              "OBJECT",
+              "false",
+              "test",
+              "DELETE FROM table1",
+              "User user2 (ID=10001) requests authority on object table1 with 
result false"),
+          // User2 logout, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          Arrays.asList(
+              "node_1",
+              "u_10001",
+              "user2",
+              "127.0.0.1",
+              "LOGOUT",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "is closing"),
+          // =============================Audit user 
root=============================
+          // Root login, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "LOGIN",
+              "CONTROL",
+              "null",
+              "GLOBAL",
+              "true",
+              "",
+              "",
+              "IoTDB: Login status: Login successfully. User root (ID=0), 
opens Session"),
+          // Use database, twice for both read and write connections
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User root (ID=0) requests authority on object test with result 
true"),
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[READ_SCHEMA]",
+              "OBJECT",
+              "true",
+              "test",
+              "USE test",
+              "User root (ID=0) requests authority on object test 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(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[DROP]",
+              "OBJECT",
+              "true",
+              "test",
+              "DROP DATABASE IF EXISTS test",
+              "User root (ID=0) requests authority on object test with result 
true"),
+          // Revoke user privilege
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "test",
+              "REVOKE SELECT,ALTER,INSERT,DELETE ON TEST.TABLE1 FROM USER 
user1",
+              "User root (ID=0) requests authority on object user1 with result 
true"),
+          // Revoke role privilege
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "REVOKE SELECT ON ANY FROM 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"),
+          // Drop user
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "DDL",
+              "[SECURITY]",
+              "GLOBAL",
+              "true",
+              "null",
+              "DROP USER user2",
+              "User root (ID=0) requests authority on object user2 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"),
+          // Select audit log
+          Arrays.asList(
+              "node_1",
+              "u_0",
+              "root",
+              "127.0.0.1",
+              "OBJECT_AUTHENTICATION",
+              "QUERY",
+              "[SELECT]",
+              "OBJECT",
+              "true",
+              "__audit",
+              "SELECT * FROM __audit.audit_log ORDER BY TIME",
+              "User root (ID=0) requests authority on object __audit with 
result true"),
+          Arrays.asList(
+              "node_1",
               "u_0",
               "root",
               "127.0.0.1",
@@ -740,34 +1221,56 @@ public class IoTDBAuditLogBasicIT {
       Stream.of(11, 12).collect(Collectors.toSet());
 
   @Test
-  public void basicAuditLogTestForTableModel() throws SQLException {
-    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
-        Statement statement = connection.createStatement()) {
-      for (String sql : TABLE_MODEL_AUDIT_SQLS) {
+  public void basicAuditLogTestForTableModel() throws SQLException, 
InterruptedException {
+    Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+    Statement statement = connection.createStatement();
+    for (String sql : TABLE_MODEL_AUDIT_SQLS_USER_ROOT) {
+      statement.execute(sql);
+    }
+    closeConnectionCompletely(connection);
+    connection =
+        EnvFactory.getEnv().getConnection("user1", "IoTDB@2025abc", 
BaseEnv.TABLE_SQL_DIALECT);
+    statement = connection.createStatement();
+    for (String sql : TABLE_MODEL_AUDIT_SQLS_USER_USER1) {
+      statement.execute(sql);
+    }
+    closeConnectionCompletely(connection);
+    connection =
+        EnvFactory.getEnv().getConnection("user2", "IoTDB@2025abc", 
BaseEnv.TABLE_SQL_DIALECT);
+    statement = connection.createStatement();
+    for (String sql : TABLE_MODEL_AUDIT_SQLS_USER_USER2) {
+      try {
         statement.execute(sql);
+      } catch (SQLException e) {
+        // Ignore, only record audit log
       }
-      int count = 0;
-      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<>();
-        for (int i = 1; i <= 12; i++) {
-          actualFields.add(resultSet.getString(i + 1));
-        }
-        LOGGER.info("Actual audit log: {}", actualFields);
-        List<String> expectedFields = TABLE_MODEL_AUDIT_FIELDS.get(count);
-        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));
+    }
+    closeConnectionCompletely(connection);
+    connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+    statement = connection.createStatement();
+    for (String sql : TABLE_MODEL_AUDIT_SQLS_USER_ROOT_FINAL) {
+      statement.execute(sql);
+    }
+    int count = 0;
+    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<>();
+      for (int i = 1; i <= 12; i++) {
+        actualFields.add(resultSet.getString(i + 1));
+      }
+      LOGGER.info("Actual audit log: {}", actualFields);
+      List<String> expectedFields = TABLE_MODEL_AUDIT_FIELDS.get(count);
+      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;
         }
-
-        count++;
+        Assert.assertEquals(expectedFields.get(i - 1), resultSet.getString(i + 
1));
       }
-      Assert.assertEquals(TABLE_MODEL_AUDIT_FIELDS.size(), count);
+      count++;
     }
+    Assert.assertEquals(TABLE_MODEL_AUDIT_FIELDS.size(), count);
   }
 
   private static final List<String> TREE_MODEL_AUDIT_SQLS =
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 d7a35f39913..8c3fbb2253d 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
@@ -284,23 +284,31 @@ public class AccessControlImpl implements AccessControl {
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_USER, auditEntity);
         return;
       case LIST_USER_PRIV:
-        auditEntity
-            .setAuditLogOperation(AuditLogOperation.QUERY)
-            .setPrivilegeType(PrivilegeType.SECURITY);
-        if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()
-            || statement.getUserName().equals(userName)) {
+        auditEntity.setAuditLogOperation(AuditLogOperation.QUERY);
+        if (statement.getUserName().equals(userName)) {
+          // No need any privilege to list him/herself
           ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getUserName);
           return;
         }
+        // Require SECURITY privilege to list other users' privileges
+        if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
+          ITableAuthCheckerImpl.recordAuditLog(
+              
auditEntity.setPrivilegeType(PrivilegeType.SECURITY).setResult(true),
+              statement::getUserName);
+          return;
+        }
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_USER, auditEntity);
         return;
       case LIST_USER:
-        auditEntity.setAuditLogOperation(AuditLogOperation.QUERY);
+        
auditEntity.setAuditLogOperation(AuditLogOperation.QUERY).setResult(true);
         if (!hasGlobalPrivilege(auditEntity, PrivilegeType.MANAGE_USER)) {
+          // No need to check privilege to list himself/herself
           statement.setUserName(userName);
+          ITableAuthCheckerImpl.recordAuditLog(auditEntity, 
statement::getUserName);
         } else {
-          auditEntity.setPrivilegeType(PrivilegeType.SECURITY);
-          ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getUserName);
+          // Require SECURITY privilege to list other users
+          ITableAuthCheckerImpl.recordAuditLog(
+              auditEntity.setPrivilegeType(PrivilegeType.SECURITY), 
statement::getUserName);
         }
         return;
       case CREATE_ROLE:
@@ -343,14 +351,19 @@ public class AccessControlImpl implements AccessControl {
         }
         return;
       case LIST_ROLE_PRIV:
-        auditEntity
-            .setAuditLogOperation(AuditLogOperation.QUERY)
-            .setPrivilegeType(PrivilegeType.SECURITY);
-        if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()
-            || AuthorityChecker.checkRole(userName, statement.getRoleName())) {
+        auditEntity.setAuditLogOperation(AuditLogOperation.QUERY);
+        if (AuthorityChecker.checkRole(userName, statement.getRoleName())) {
+          // No need any privilege to list his/hers own role
           ITableAuthCheckerImpl.recordAuditLog(auditEntity.setResult(true), 
statement::getRoleName);
           return;
         }
+        // Require SECURITY privilege to list other roles' privileges
+        if (AuthorityChecker.SUPER_USER_ID == auditEntity.getUserId()) {
+          ITableAuthCheckerImpl.recordAuditLog(
+              
auditEntity.setPrivilegeType(PrivilegeType.SECURITY).setResult(true),
+              statement::getRoleName);
+          return;
+        }
         authChecker.checkGlobalPrivilege(userName, 
TableModelPrivilege.MANAGE_ROLE, auditEntity);
         return;
       case GRANT_ROLE_ANY:


Reply via email to