Caideyipi commented on code in PR #13158:
URL: https://github.com/apache/iotdb/pull/13158#discussion_r1904837167


##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/DatabasePrivilege.java:
##########
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.commons.auth.entity;
+
+import org.apache.iotdb.commons.utils.AuthUtils;
+import org.apache.iotdb.commons.utils.SerializeUtils;
+
+import org.apache.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+public class DatabasePrivilege {
+  private String databaseName;
+
+  private Map<String, TablePrivilege> tablePrivilegeMap;
+  private Set<PrivilegeType> privilegeSet;
+  private Set<PrivilegeType> grantOptionSet;
+
+  public DatabasePrivilege(String databaseName) {
+    this.databaseName = databaseName;
+    this.tablePrivilegeMap = new HashMap<>();
+    this.privilegeSet = new HashSet<>();
+    this.grantOptionSet = new HashSet<>();
+  }
+
+  public DatabasePrivilege() {
+    //
+  }
+
+  public String getDatabaseName() {
+    return this.databaseName;
+  }
+
+  public Map<String, TablePrivilege> getTablePrivilegeMap() {
+    return this.tablePrivilegeMap;
+  }
+
+  public void setPrivileges(int mask) {
+    final int PRI_SIZE = 
PrivilegeType.getPrivilegeCount(PrivilegeModelType.RELATIONAL);
+    for (int i = 0; i < PRI_SIZE; i++) {
+      if (((1 << i) & mask) != 0) {
+        this.privilegeSet.add(AuthUtils.posToObjPri(i));
+        if (((1 << (i + 16)) & mask) != 0) {
+          this.grantOptionSet.add(AuthUtils.posToObjPri(i));
+        }
+      }
+    }
+  }
+
+  public int getAllPrivileges() {
+    int privilege = 0;
+    for (PrivilegeType pri : privilegeSet) {
+      privilege |= 1 << AuthUtils.objPriToPos(pri);
+    }
+    for (PrivilegeType pri : grantOptionSet) {
+      privilege |= 1 << (AuthUtils.objPriToPos(pri) + 16);
+    }
+    return privilege;
+  }
+
+  public Set<Integer> getPrivilegeSet() {
+    Set<Integer> res = new HashSet<>();
+    for (PrivilegeType priv : this.privilegeSet) {
+      res.add(priv.ordinal());
+    }
+    return res;
+  }
+
+  public Set<Integer> getPrivilegeGrantOptSet() {
+    Set<Integer> res = new HashSet<>();
+    for (PrivilegeType priv : this.grantOptionSet) {
+      res.add(priv.ordinal());
+    }
+    return res;
+  }
+
+  public void grantDBPrivilege(PrivilegeType privilegeType) {
+    this.privilegeSet.add(privilegeType);
+  }
+
+  public void revokeDBPrivilege(PrivilegeType privilegeType) {
+    this.privilegeSet.remove(privilegeType);
+    revokeDBGrantOption(privilegeType);
+  }
+
+  public void grantDBGrantOption(PrivilegeType privilegeType) {
+    this.grantOptionSet.add(privilegeType);
+  }
+
+  public void revokeDBGrantOption(PrivilegeType privilegeType) {
+    this.grantOptionSet.remove(privilegeType);
+  }
+
+  public void grantTablePrivilege(String tableName, PrivilegeType 
privilegeType) {
+    if (!this.tablePrivilegeMap.containsKey(tableName)) {
+      TablePrivilege tablePrivilege = new TablePrivilege(tableName);
+      tablePrivilege.grantPrivilege(privilegeType);
+      this.tablePrivilegeMap.put(tableName, tablePrivilege);
+    } else {
+      tablePrivilegeMap.get(tableName).grantPrivilege(privilegeType);
+    }
+  }
+
+  public void revokeTablePrivilege(String tableName, PrivilegeType 
privilegeType) {
+    if (this.tablePrivilegeMap.containsKey(tableName)) {
+      TablePrivilege tablePrivilege = this.tablePrivilegeMap.get(tableName);
+      tablePrivilege.revokePrivilege(privilegeType);
+      tablePrivilege.revokeGrantOption(privilegeType);
+      if (tablePrivilege.getPrivileges().isEmpty()) {
+        this.tablePrivilegeMap.remove(tableName);
+      }
+    }
+  }
+
+  public void grantTableGrantOption(String tableName, PrivilegeType 
privilegeType) {
+    if (this.tablePrivilegeMap.containsKey(tableName)) {
+      TablePrivilege tablePrivilege = this.tablePrivilegeMap.get(tableName);
+      tablePrivilege.grantOption(privilegeType);
+    }
+  }
+
+  public void revokeTableGrantOption(String tableName, PrivilegeType 
privilegeType) {
+    if (this.tablePrivilegeMap.containsKey(tableName)) {
+      TablePrivilege tablePrivilege = this.tablePrivilegeMap.get(tableName);
+      tablePrivilege.revokeGrantOption(privilegeType);
+    }
+  }
+
+  public boolean checkDBPrivilege(PrivilegeType privilegeType) {
+    return this.privilegeSet.contains(privilegeType);
+  }
+
+  public boolean checkTablePrivilege(String tableName, PrivilegeType 
privilegeType) {
+    TablePrivilege privileges = tablePrivilegeMap.get(tableName);
+    if (privileges == null) {
+      return false;
+    }
+    return privileges.getPrivileges().contains(privilegeType);
+  }
+
+  public boolean checkDBGrantOption(PrivilegeType type) {
+    return this.privilegeSet.contains(type) && 
this.grantOptionSet.contains(type);
+  }
+
+  public boolean checkTableGrantOption(String tableName, PrivilegeType type) {
+    TablePrivilege tablePrivilege = this.tablePrivilegeMap.get(tableName);
+    if (tablePrivilege == null) {
+      return false;
+    }
+    return tablePrivilege.getPrivileges().contains(type)
+        && tablePrivilege.getGrantOption().contains(type);
+  }
+
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    DatabasePrivilege that = (DatabasePrivilege) o;
+    return databaseName.equals(that.databaseName)

Review Comment:
   Using "Objects.equals()" may be safer because the "databaseName" is 
nullable(though now nullable privilege won't call "equals()")



##########
iotdb-protocol/thrift-confignode/src/main/thrift/confignode.thrift:
##########
@@ -374,11 +398,22 @@ struct TLoginReq {
   2: required string password
 }
 
+// reqtype : tree, relational, system
+// to check tree privilege, paths is required
+// to check relational privilege, database or table is required
+// to check system privilege, just spec permission
+
+// if grant opt is ture, check grant option of spec permission.

Review Comment:
   true



##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.queryengine.plan.relational.security;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.db.auth.AuthorityChecker;
+import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+public class ITableAuthCheckerImpl implements ITableAuthChecker {
+
+  @Override
+  public void checkDatabaseVisibility(String userName, String databaseName) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    if (!AuthorityChecker.checkDBVisible(userName, databaseName)) {
+      throw new RuntimeException(
+          new IoTDBException("NO PERMISSION", 
TSStatusCode.NO_PERMISSION.getStatusCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilege(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkDBPermission(
+                userName, databaseName, privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            databaseName);
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilegeGrantOption(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    TSStatus result =
+        AuthorityChecker.getGrantOptTSStatus(
+            AuthorityChecker.checkDBPermissionGrantOption(
+                userName, databaseName, privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            databaseName);
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkTablePrivilege(
+      String userName, QualifiedObjectName tableName, TableModelPrivilege 
privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkTablePermission(
+                userName,
+                tableName.getDatabaseName(),
+                tableName.getObjectName(),
+                privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            tableName.getDatabaseName(),
+            tableName.getObjectName());
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkTablePrivilegeGrantOption(
+      String userName, QualifiedObjectName tableName, TableModelPrivilege 
privilege) {
+    TSStatus result =

Review Comment:
   Why there are no "AuthorityChecker.SUPER_USER.equals(userName)" here...



##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/entity/DatabasePrivilege.java:
##########
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.commons.auth.entity;
+
+import org.apache.iotdb.commons.utils.AuthUtils;
+import org.apache.iotdb.commons.utils.SerializeUtils;
+
+import org.apache.tsfile.utils.ReadWriteIOUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+public class DatabasePrivilege {
+  private String databaseName;
+
+  private Map<String, TablePrivilege> tablePrivilegeMap;
+  private Set<PrivilegeType> privilegeSet;
+  private Set<PrivilegeType> grantOptionSet;
+
+  public DatabasePrivilege(String databaseName) {
+    this.databaseName = databaseName;
+    this.tablePrivilegeMap = new HashMap<>();
+    this.privilegeSet = new HashSet<>();
+    this.grantOptionSet = new HashSet<>();
+  }
+
+  public DatabasePrivilege() {
+    //

Review Comment:
   May not leave "//"?



##########
iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java:
##########
@@ -423,6 +465,7 @@ public TAuthizedPatternTreeResp 
generateAuthizedPTree(String username, int permi
       throws AuthException {
     TAuthizedPatternTreeResp resp = new TAuthizedPatternTreeResp();

Review Comment:
   Better rename this to "Authorized"



##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.queryengine.plan.relational.security;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.db.auth.AuthorityChecker;
+import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+public class ITableAuthCheckerImpl implements ITableAuthChecker {
+
+  @Override
+  public void checkDatabaseVisibility(String userName, String databaseName) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    if (!AuthorityChecker.checkDBVisible(userName, databaseName)) {
+      throw new RuntimeException(
+          new IoTDBException("NO PERMISSION", 
TSStatusCode.NO_PERMISSION.getStatusCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilege(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkDBPermission(
+                userName, databaseName, privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            databaseName);
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilegeGrantOption(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    TSStatus result =
+        AuthorityChecker.getGrantOptTSStatus(
+            AuthorityChecker.checkDBPermissionGrantOption(
+                userName, databaseName, privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            databaseName);
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkTablePrivilege(
+      String userName, QualifiedObjectName tableName, TableModelPrivilege 
privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkTablePermission(
+                userName,
+                tableName.getDatabaseName(),
+                tableName.getObjectName(),
+                privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            tableName.getDatabaseName(),
+            tableName.getObjectName());
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkTablePrivilegeGrantOption(
+      String userName, QualifiedObjectName tableName, TableModelPrivilege 
privilege) {
+    TSStatus result =
+        AuthorityChecker.getGrantOptTSStatus(
+            AuthorityChecker.checkTablePermissionGrantOption(
+                userName,
+                tableName.getDatabaseName(),
+                tableName.getObjectName(),
+                privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            tableName.getDatabaseName(),
+            tableName.getObjectName());
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkTableVisibility(String userName, QualifiedObjectName 
tableName) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    if (!AuthorityChecker.checkTableVisible(
+        userName, tableName.getDatabaseName(), tableName.getObjectName())) {
+      throw new RuntimeException(
+          new IoTDBException("NO PERMISSION", 
TSStatusCode.NO_PERMISSION.getStatusCode()));
+    }
+  }
+
+  @Override
+  public void checkGlobalPrivilege(String userName, TableModelPrivilege 
privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkSystemPermission(userName, 
privilege.getPrivilegeType()),
+            privilege.getPrivilegeType());
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkGlobalPrivilegeGrantOption(String userName, 
TableModelPrivilege privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(

Review Comment:
   getGrantOptTSStatus?



##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.queryengine.plan.relational.security;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.db.auth.AuthorityChecker;
+import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+public class ITableAuthCheckerImpl implements ITableAuthChecker {
+
+  @Override
+  public void checkDatabaseVisibility(String userName, String databaseName) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    if (!AuthorityChecker.checkDBVisible(userName, databaseName)) {
+      throw new RuntimeException(
+          new IoTDBException("NO PERMISSION", 
TSStatusCode.NO_PERMISSION.getStatusCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilege(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkDBPermission(
+                userName, databaseName, privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            databaseName);
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilegeGrantOption(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    TSStatus result =

Review Comment:
   Why there are no "AuthorityChecker.SUPER_USER.equals(userName)" here...



##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/security/ITableAuthCheckerImpl.java:
##########
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.iotdb.db.queryengine.plan.relational.security;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.exception.IoTDBException;
+import org.apache.iotdb.db.auth.AuthorityChecker;
+import 
org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+public class ITableAuthCheckerImpl implements ITableAuthChecker {
+
+  @Override
+  public void checkDatabaseVisibility(String userName, String databaseName) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    if (!AuthorityChecker.checkDBVisible(userName, databaseName)) {
+      throw new RuntimeException(
+          new IoTDBException("NO PERMISSION", 
TSStatusCode.NO_PERMISSION.getStatusCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilege(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkDBPermission(
+                userName, databaseName, privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            databaseName);
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkDatabasePrivilegeGrantOption(
+      String userName, String databaseName, TableModelPrivilege privilege) {
+    TSStatus result =
+        AuthorityChecker.getGrantOptTSStatus(
+            AuthorityChecker.checkDBPermissionGrantOption(
+                userName, databaseName, privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            databaseName);
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));
+    }
+  }
+
+  @Override
+  public void checkTablePrivilege(
+      String userName, QualifiedObjectName tableName, TableModelPrivilege 
privilege) {
+    if (AuthorityChecker.SUPER_USER.equals(userName)) {
+      return;
+    }
+    TSStatus result =
+        AuthorityChecker.getTSStatus(
+            AuthorityChecker.checkTablePermission(
+                userName,
+                tableName.getDatabaseName(),
+                tableName.getObjectName(),
+                privilege.getPrivilegeType()),
+            privilege.getPrivilegeType(),
+            tableName.getDatabaseName(),
+            tableName.getObjectName());
+    if (result.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+      throw new RuntimeException(new IoTDBException(result.getMessage(), 
result.getCode()));

Review Comment:
   Use "AccessControlException" instead?



##########
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/SqlFormatter.java:
##########
@@ -1169,6 +1170,67 @@ protected Void visitShowTopics(ShowTopics node, Integer 
context) {
       return null;
     }
 
+    @Override
+    protected Void visitRelationalAuthorPlan(RelationalAuthorStatement node, 
Integer context) {

Review Comment:
   Well, personally I think all other sqls just write the full SQL...



##########
iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/AuthorInfoTest.java:
##########
@@ -668,383 +641,294 @@ public void testMultPathsPermission() throws 
TException, AuthException, IllegalP
             new HashSet<>(),
             false,
             new ArrayList<>());
-    permissionInfoResp = authorInfo.executeListRolePrivileges(authorReadPlan);
+    permissionInfoResp = authorInfo.executeListRolePrivileges(authorPlan);
     status = permissionInfoResp.getStatus();
-    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
   }
 
   @Test
-  public void testDepAuthorPlan() throws TException, AuthException, 
IllegalPathException {
-
-    AuthorPlan authorPlan;
+  public void createUserWithRawPassword() {
     TSStatus status;
+    AuthorPlan authorPlan;
+    authorPlan =
+        new AuthorTreePlan(
+            ConfigPhysicalPlanType.CreateUserWithRawPassword,
+            "testuser",
+            "",
+            AuthUtils.encryptPassword("password"),
+            "",
+            new HashSet<>(),
+            false,
+            new ArrayList<>());
+    status = authorInfo.authorNonQuery(authorPlan);
+    assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    TPermissionInfoResp result = authorInfo.login("testuser", "password");
+    assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
result.getStatus().getCode());
+  }
+
+  private void checkAuthorNonQueryReturn(AuthorPlan plan) {
+    TSStatus status = authorInfo.authorNonQuery(plan);
+    Assert.assertNull(status.getMessage());
+    assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+  }
+
+  @Test
+  public void relationalPermissionTest() throws AuthException {
     cleanUserAndRole();
+    TSStatus status;
 
-    /*--TEST FOR USER CREATE 、UPDATE AND DROP -*/
-    // this operation will success for pre version.
-    {
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.CreateUserDep,
-              "user1",
-              "",
-              "password1",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    // create user
+    AuthorPlan plan =
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RCreateUser, "user", "", "", "", -1, false, 
"password");
 
-      // this operation will success for pre version. --length~(32,64)
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.CreateUserDep,
-              "user1234567user1234567user1234567user1234567",
-              "",
-              "password1",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    checkAuthorNonQueryReturn(plan);
 
-      // this operation will fail for pre version. --length > 64
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.CreateUserDep,
-              
"user1234567user1234567user1234567user1234567user1234567user1234567user1234567user1234567",
-              "",
-              "password1",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.ILLEGAL_PARAMETER.getStatusCode(), 
status.getCode());
+    // check user permission
+    status =
+        authorInfo
+            .checkUserPrivileges("user", new 
PrivilegeUnion(PrivilegeType.MANAGE_USER))
+            .getStatus();
+    assertEquals(TSStatusCode.NO_PERMISSION.getStatusCode(), status.getCode());
 
-      // this operation will fail for pre version. -- contain &%*@
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.CreateUserDep,
-              "user1*&%",
-              "",
-              "password1",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.ILLEGAL_PARAMETER.getStatusCode(), 
status.getCode());
-
-      // root, user1, user1234567user1234567user1234567user1234567
-      Assert.assertEquals(
-          3,
-          authorInfo
-              .executeListUsers(
-                  new AuthorReadPlan(
-                      ConfigPhysicalPlanType.ListUser,
-                      "",
-                      "",
-                      "",
-                      "",
-                      new HashSet<>(),
-                      false,
-                      new ArrayList<>()))
-              .getMemberList()
-              .size());
+    plan =
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RDropUser, "user", "", "", "", -1, false, 
"");
+    checkAuthorNonQueryReturn(plan);
 
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.DropUserDep,
-              "user1234567user1234567user1234567user1234567",
-              "",
-              "",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-
-      Assert.assertEquals(
-          2,
-          authorInfo
-              .executeListUsers(
-                  new AuthorReadPlan(
-                      ConfigPhysicalPlanType.ListUserDep,
-                      "",
-                      "",
-                      "",
-                      "",
-                      new HashSet<>(),
-                      false,
-                      new ArrayList<>()))
-              .getMemberList()
-              .size());
-
-      // for pre version, password with &% will meet error.
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.UpdateUserDep,
-              "user1",
-              "",
-              "password*&S",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.ILLEGAL_PARAMETER.getStatusCode(), 
status.getCode());
+    // list user
+    plan =
+        new AuthorTreePlan(
+            ConfigPhysicalPlanType.ListUser,
+            "",
+            "",
+            "",
+            "",
+            new HashSet<>(),
+            false,
+            new ArrayList<>());
+    PermissionInfoResp permissionInfoResp = authorInfo.executeListUsers(plan);
+    status = permissionInfoResp.getStatus();
+    assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    assertEquals(1, permissionInfoResp.getMemberList().size()); // Only root
 
-      /*--TEST FOR ROLE CREATE AND DROP -*/
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.CreateRoleDep,
-              "",
-              "role1",
-              "",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    // create role
+    plan =
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RCreateRole, "", "role", "", "", -1, false, 
"");
 
-      // name longer than 32, It's ok.
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.CreateRoleDep,
-              "",
-              "role1234567role1234567role1234567role1234567",
-              "",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    checkAuthorNonQueryReturn(plan);
 
-      // contain wrong character, error.
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.CreateRoleDep,
-              "",
-              "role1234567role1%%234567role1234567role1234567",
-              "",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.ILLEGAL_PARAMETER.getStatusCode(), 
status.getCode());
+    // create user
+    plan =
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RCreateUser, "user", "", "", "", -1, false, 
"password");
 
-      authorPlan =
-          new AuthorPlan(
-              ConfigPhysicalPlanType.DropRoleDep,
-              "",
-              "role1234567role1234567role1234567role1234567",
-              "",
-              "",
-              new HashSet<>(),
-              false,
-              new ArrayList<>());
-      status = authorInfo.authorNonQuery(authorPlan);
-      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-
-      Assert.assertEquals(
-          1,
-          authorInfo
-              .executeListRoles(
-                  new AuthorReadPlan(
-                      ConfigPhysicalPlanType.ListRoleDep,
-                      "",
-                      "",
-                      "",
-                      "",
-                      new HashSet<>(),
-                      false,
-                      new ArrayList<>()))
-              .getMemberList()
-              .size());
-    }
-    // NOW WE HAVE USER:user1, root; ROLE: role1
+    checkAuthorNonQueryReturn(plan);
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserRole, "user", "role", "", "", -1, 
false, ""));
 
-    for (PriPrivilegeType item : PriPrivilegeType.values()) {
-      /*-- TEST IGNORE PRIVILEGES --*/
-      if (!item.isAccept()) {
-        // for user to grant
-        authorPlan =
-            new AuthorPlan(
-                ConfigPhysicalPlanType.GrantUserDep,
-                "user1",
-                "",
-                "",
-                "",
-                Collections.singleton(item.ordinal()),
-                false,
-                Collections.singletonList(new PartialPath("root.**")));
-        status = authorInfo.authorNonQuery(authorPlan);
-        Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getUser("user1").getPathPrivilegeList().size());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getUser("user1").getSysPrivilege().size());
+    // grant privileges
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserSysPri,
+            "user",
+            "",
+            "",
+            "",
+            PrivilegeType.MAINTAIN.ordinal(),
+            false,
+            ""));
 
-        // for role to grant
-        authorPlan =
-            new AuthorPlan(
-                ConfigPhysicalPlanType.GrantRoleDep,
-                "",
-                "role1",
-                "",
-                "",
-                Collections.singleton(item.ordinal()),
-                false,
-                Collections.singletonList(new PartialPath("root.**")));
-        status = authorInfo.authorNonQuery(authorPlan);
-        Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getRole("role1").getPathPrivilegeList().size());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getRole("role1").getSysPrivilege().size());
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserSysPri,
+            "user",
+            "",
+            "",
+            "",
+            PrivilegeType.MANAGE_USER.ordinal(),
+            true,
+            ""));
 
-        // for user to revoke
-        authorPlan =
-            new AuthorPlan(
-                ConfigPhysicalPlanType.RevokeUserDep,
-                "user1",
-                "",
-                "",
-                "",
-                Collections.singleton(item.ordinal()),
-                false,
-                Collections.singletonList(new PartialPath("root.**")));
-        status = authorInfo.authorNonQuery(authorPlan);
-        Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getUser("user1").getPathPrivilegeList().size());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getUser("user1").getSysPrivilege().size());
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserAny,
+            "user",
+            "",
+            "",
+            "",
+            PrivilegeType.DELETE.ordinal(),
+            false,
+            ""));
 
-        // for role to revoke
-        authorPlan =
-            new AuthorPlan(
-                ConfigPhysicalPlanType.RevokeRoleDep,
-                "",
-                "role1",
-                "",
-                "",
-                Collections.singleton(item.ordinal()),
-                false,
-                Collections.singletonList(new PartialPath("root.**")));
-        status = authorInfo.authorNonQuery(authorPlan);
-        Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getRole("role1").getPathPrivilegeList().size());
-        Assert.assertEquals(
-            0, 
BasicAuthorizer.getInstance().getRole("role1").getSysPrivilege().size());
-
-      } else {
-        if (item == PriPrivilegeType.ALL) {
-          continue;
-        }
-        if (item.isPrePathRelevant()) {
-          authorPlan =
-              new AuthorPlan(
-                  ConfigPhysicalPlanType.GrantUserDep,
-                  "user1",
-                  "",
-                  "",
-                  "",
-                  Collections.singleton(item.ordinal()),
-                  false,
-                  Collections.singletonList(new PartialPath("root.t1.*.t2")));
-          status = authorInfo.authorNonQuery(authorPlan);
-          Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-          Assert.assertEquals(
-              1,
-              BasicAuthorizer.getInstance()
-                  .getUser("user1")
-                  .getPathPrivileges(new PartialPath("root.t1.*.t2"))
-                  .size());
-          authorInfo.checkUserPathPrivilege();
-          PartialPath path1 = AuthUtils.convertPatternPath(new 
PartialPath("root.t1.*.t2"));
-          for (PrivilegeType pri : item.getSubPri()) {
-            if (pri.isPathRelevant()) {
-              Assert.assertTrue(
-                  BasicAuthorizer.getInstance()
-                      .getUser("user1")
-                      .checkPathPrivilege(path1, pri.ordinal()));
-              BasicAuthorizer.getInstance()
-                  .getUser("user1")
-                  .removePathPrivilege(path1, pri.ordinal());
-            } else {
-              Assert.assertTrue(
-                  
BasicAuthorizer.getInstance().getUser("user1").checkSysPrivilege(pri.ordinal()));
-              
BasicAuthorizer.getInstance().getUser("user1").removeSysPrivilege(pri.ordinal());
-            }
-          }
-        } else {
-          authorPlan =
-              new AuthorPlan(
-                  ConfigPhysicalPlanType.GrantUserDep,
-                  "user1",
-                  "",
-                  "",
-                  "",
-                  Collections.singleton(item.ordinal()),
-                  false,
-                  Collections.singletonList(new PartialPath("root.**")));
-
-          status = authorInfo.authorNonQuery(authorPlan);
-          Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-          authorInfo.checkUserPathPrivilege();
-          Assert.assertTrue(
-              BasicAuthorizer.getInstance()
-                  .getUser("user1")
-                  .getSysPrivilege()
-                  .containsAll(item.getSubSysPriOrd()));
-
-          for (PrivilegeType pri : item.getSubPri()) {
-            authorPlan =
-                new AuthorPlan(
-                    ConfigPhysicalPlanType.RevokeUser,
-                    "user1",
-                    "",
-                    "",
-                    "",
-                    Collections.singleton(pri.ordinal()),
-                    false,
-                    Collections.emptyList());
-            status = authorInfo.authorNonQuery(authorPlan);
-            Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-            Assert.assertEquals(
-                0, 
BasicAuthorizer.getInstance().getUser("user1").getSysPrivilege().size());
-          }
-        }
-      }
-    }
-  }
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserDBPriv,
+            "user",
+            "",
+            "testdb",
+            "",
+            PrivilegeType.SELECT.ordinal(),
+            false,
+            ""));
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserDBPriv,
+            "user",
+            "",
+            "testdb2",
+            "",
+            PrivilegeType.INSERT.ordinal(),
+            false,
+            ""));
 
-  @Test
-  public void createUserWithRawPassword() throws AuthException {
-    TSStatus status;
-    AuthorPlan authorPlan;
-    authorPlan =
-        new AuthorPlan(
-            ConfigPhysicalPlanType.CreateUserWithRawPassword,
-            "testuser",
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserTBPriv,
+            "user",
             "",
-            AuthUtils.encryptPassword("password"),
+            "testdb",
+            "table",
+            PrivilegeType.CREATE.ordinal(),
+            false,
+            ""));
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantUserTBPriv,
+            "user",
             "",
-            new HashSet<>(),
+            "testdb",
+            "table2",
+            PrivilegeType.DELETE.ordinal(),
+            true,
+            ""));
+
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantRoleSysPri,
+            "",
+            "role",
+            "",
+            "",
+            PrivilegeType.MANAGE_ROLE.ordinal(),
             false,
-            new ArrayList<>());
-    status = authorInfo.authorNonQuery(authorPlan);
-    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
-    TPermissionInfoResp result = authorInfo.login("testuser", "password");
-    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
result.getStatus().getCode());
+            ""));
+    checkAuthorNonQueryReturn(
+        new AuthorRelationalPlan(
+            ConfigPhysicalPlanType.RGrantRoleTBPriv,
+            "",
+            "role",
+            "database",
+            "table",
+            PrivilegeType.ALTER.ordinal(),
+            false,
+            ""));
+
+    // privileges status:
+    // user <-- role
+    // user
+    // SYS: MAINTAIN, MANAGE_USER(with grant option)
+    // ANY: DELETE
+    // DB: testdb.*       SELECT
+    //     testdb2.*      INSERT
+    // TB: testdb.table   CREATE
+    //     testdb.table2  DELETE(with grant option)
+
+    // role
+    // SYS: MANAGE_ROLE
+    // TB:  database.table ALTER
+
+    assertEquals(
+        authorInfo.checkRoleOfUser("user", "role").getStatus().getCode(),
+        TSStatusCode.SUCCESS_STATUS.getStatusCode());

Review Comment:
   Better place the expected value at first.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to