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


##########
integration-test/src/test/java/org/apache/iotdb/db/it/auth/IoTDBRelationalAuthIT.java:
##########
@@ -0,0 +1,306 @@
+/*
+ * 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.it.auth;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.ClusterIT;
+import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({LocalStandaloneIT.class, ClusterIT.class})
+public class IoTDBRelationalAuthIT {
+  @Before
+  public void setUp() throws Exception {
+    EnvFactory.getEnv().initClusterEnvironment();
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  private void validateResultSet(ResultSet set, String ans) throws 
SQLException {
+    try {
+      StringBuilder builder = new StringBuilder();
+      ResultSetMetaData metaData = set.getMetaData();
+      int colNum = metaData.getColumnCount();
+      while (set.next()) {
+        for (int i = 1; i <= colNum; i++) {
+          builder.append(set.getString(i)).append(",");
+        }
+        builder.append("\n");
+      }
+      String result = builder.toString();
+      assertEquals(ans.length(), result.length());
+      List<String> ansLines = Arrays.asList(ans.split("\n"));
+      List<String> resultLines = Arrays.asList(result.split("\n"));
+      assertEquals(ansLines.size(), resultLines.size());
+      for (String resultLine : resultLines) {
+        assertTrue(ansLines.contains(resultLine));

Review Comment:
   Why use "contains"? BTW, there is a similar function called 
TestUtils.assertResultSetEqual().



##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/role/BasicRoleManager.java:
##########
@@ -35,197 +36,205 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 
 /**
  * This class reads roles from local files through LocalFileRoleAccessor and 
manages them in a hash
  * map. We save all roles in our memory. Before providing service, we should 
load all role
  * information from filesystem. Access filesystem only happens at 
starting、taking snapshot、 loading
  * snapshot.
  */
-public abstract class BasicRoleManager implements IRoleManager {
+public abstract class BasicRoleManager implements IEntryManager, 
SnapshotProcessor {
 
-  protected Map<String, Role> roleMap;
-  protected IRoleAccessor accessor;
-  protected HashLock lock;
-  private boolean preVersion = false;
+  protected Map<String, Role> entryMap;
+  protected IEntryAccessor accessor;
 
+  protected HashLock lock;
   private static final Logger LOGGER = 
LoggerFactory.getLogger(BasicRoleManager.class);
 
-  BasicRoleManager(LocalFileRoleAccessor accessor) {
-    this.roleMap = new HashMap<>();
+  protected TSStatusCode getEntryNotExistErrorCode() {
+    return TSStatusCode.ROLE_NOT_EXIST;
+  }
+
+  protected String getNoSuchEntryError() {
+    return "No such role %s";
+  }
+
+  protected BasicRoleManager() {

Review Comment:
   Is it used?



##########
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java:
##########
@@ -190,114 +116,125 @@ public void permissionCacheTest() throws 
IllegalPathException {
 
   @Test
   public void grantOptTest() throws IllegalPathException {
-    User user = new User();
-    Role role = new Role();
-
-    Set<Integer> sysPri = new HashSet<>();
-    sysPri.add(PrivilegeType.MANAGE_DATABASE.ordinal());
-    sysPri.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPrivilegeSet(sysPri);
-
-    Set<Integer> sysGrantOpt = new HashSet<>();
-    sysGrantOpt.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPriGrantOpt(sysGrantOpt);
+    User user = new User("user1", "123456");
+    Role role = new Role("role1");
 
-    List<PathPrivilege> pathList = new ArrayList<>();
-    PartialPath pathRoot = new PartialPath("root.**");
-    PartialPath path1 = new PartialPath("root.d1.**");
-    PathPrivilege priv1 = new PathPrivilege(path1);
-    priv1.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), false);
-    priv1.grantPrivilege(PrivilegeType.WRITE_SCHEMA.ordinal(), true);
-    pathList.add(priv1);
+    user.grantSysPrivilege(PrivilegeType.MANAGE_DATABASE, false);
+    user.grantSysPrivilege(PrivilegeType.USE_PIPE, true);
 
-    user.setPrivilegeList(pathList);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.READ_DATA, false);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.WRITE_SCHEMA, true);
 
-    user.setName("user1");
-    user.setPassword("123456");
+    user.grantDBPrivilege("database", PrivilegeType.SELECT, false);
+    user.grantDBPrivilege("database", PrivilegeType.ALTER, true);
+    user.grantTBPrivilege("database", "table", PrivilegeType.DELETE, true);
+    role.grantSysPrivilege(PrivilegeType.USE_UDF, false);
+    role.grantSysPrivilege(PrivilegeType.USE_CQ, true);
+    role.grantSysPrivilegeGrantOption(PrivilegeType.USE_CQ);
+    role.grantPathPrivilege(new PartialPath("root.t.**"), 
PrivilegeType.READ_DATA, true);
+    role.grantDBPrivilege("database", PrivilegeType.INSERT, true);
 
     // user's priv:
     // 1. MANAGE_DATABASE
     // 2. USE_PIPE with grant option
     // 3. READ_DATA root.d1.**
     // 4. WRITE_SCHEMA root.d1.** with grant option
+    // 5. SELECT on database, ALTER on database with grant option
+    // 6. UPDATE on database.table, DELETE on database.table with grant option
 
     // role's priv:
     // 1. USE_UDF
     // 2. USE_CQ with grant option
     // 3. READ_DATA root.t9.** with grant option

Review Comment:
   t9? Database privilege?



##########
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java:
##########
@@ -190,114 +116,125 @@ public void permissionCacheTest() throws 
IllegalPathException {
 
   @Test
   public void grantOptTest() throws IllegalPathException {
-    User user = new User();
-    Role role = new Role();
-
-    Set<Integer> sysPri = new HashSet<>();
-    sysPri.add(PrivilegeType.MANAGE_DATABASE.ordinal());
-    sysPri.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPrivilegeSet(sysPri);
-
-    Set<Integer> sysGrantOpt = new HashSet<>();
-    sysGrantOpt.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPriGrantOpt(sysGrantOpt);
+    User user = new User("user1", "123456");
+    Role role = new Role("role1");
 
-    List<PathPrivilege> pathList = new ArrayList<>();
-    PartialPath pathRoot = new PartialPath("root.**");
-    PartialPath path1 = new PartialPath("root.d1.**");
-    PathPrivilege priv1 = new PathPrivilege(path1);
-    priv1.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), false);
-    priv1.grantPrivilege(PrivilegeType.WRITE_SCHEMA.ordinal(), true);
-    pathList.add(priv1);
+    user.grantSysPrivilege(PrivilegeType.MANAGE_DATABASE, false);
+    user.grantSysPrivilege(PrivilegeType.USE_PIPE, true);
 
-    user.setPrivilegeList(pathList);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.READ_DATA, false);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.WRITE_SCHEMA, true);
 
-    user.setName("user1");
-    user.setPassword("123456");
+    user.grantDBPrivilege("database", PrivilegeType.SELECT, false);
+    user.grantDBPrivilege("database", PrivilegeType.ALTER, true);
+    user.grantTBPrivilege("database", "table", PrivilegeType.DELETE, true);
+    role.grantSysPrivilege(PrivilegeType.USE_UDF, false);
+    role.grantSysPrivilege(PrivilegeType.USE_CQ, true);
+    role.grantSysPrivilegeGrantOption(PrivilegeType.USE_CQ);
+    role.grantPathPrivilege(new PartialPath("root.t.**"), 
PrivilegeType.READ_DATA, true);
+    role.grantDBPrivilege("database", PrivilegeType.INSERT, true);
 
     // user's priv:
     // 1. MANAGE_DATABASE
     // 2. USE_PIPE with grant option
     // 3. READ_DATA root.d1.**
     // 4. WRITE_SCHEMA root.d1.** with grant option
+    // 5. SELECT on database, ALTER on database with grant option
+    // 6. UPDATE on database.table, DELETE on database.table with grant option
 
     // role's priv:
     // 1. USE_UDF
     // 2. USE_CQ with grant option
     // 3. READ_DATA root.t9.** with grant option
-
-    role.setName("role1");
-    Set<Integer> sysPriRole = new HashSet<>();
-    sysPriRole.add(PrivilegeType.USE_UDF.ordinal());
-    sysPriRole.add(PrivilegeType.USE_CQ.ordinal());
-    role.setSysPrivilegeSet(sysPriRole);
-
-    Set<Integer> sysGrantOptRole = new HashSet<>();
-    sysGrantOptRole.add(PrivilegeType.USE_CQ.ordinal());
-    role.setSysPriGrantOpt(sysGrantOptRole);
-
-    PathPrivilege privRole = new PathPrivilege(new PartialPath("root.t9.**"));
-    privRole.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), true);
-    role.setPrivilegeList(Collections.singletonList(privRole));
-    user.setRoleList(Collections.singletonList("role1"));
+    user.addRole("role1");
 
     authorityFetcher.getAuthorCache().putUserCache("user1", user);
     authorityFetcher.getAuthorCache().putRoleCache("role1", role);
 
     // for system priv. we have USE_PIPE grant option.
-    Assert.assertTrue(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.USE_PIPE.ordinal()));
-    Assert.assertFalse(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.MANAGE_USER.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher.checkUserSysPrivilegesGrantOpt("user1", 
PrivilegeType.USE_PIPE).getCode(),
+        TSStatusCode.SUCCESS_STATUS.getStatusCode());

Review Comment:
   Put the expected value at the front



##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java:
##########
@@ -193,135 +180,62 @@ public User loadUser(String username) throws IOException 
{
             }
           }
         }
-        user.setRoleList(roleList);
+        user.setRoleSet(roleList);
         return user;
       }
-    } catch (Exception e) {
-      throw new IOException(e);
-    } finally {
-      strBufferLocal.remove();
-    }
-  }
-
-  /**
-   * Serialize the user object to a temp file, then replace the old user file 
with the new file.
-   *
-   * @param user The user object that is to be saved.
-   */
-  @Override
-  public void saveUser(User user) throws IOException {
-    File userProfile =
-        SystemFileFactory.INSTANCE.getFile(
-            userDirPath
-                + File.separator
-                + user.getName()
-                + IoTDBConstant.PROFILE_SUFFIX
-                + TEMP_SUFFIX);
-
-    try (FileOutputStream fileOutputStream = new FileOutputStream(userProfile);
-        BufferedOutputStream outputStream = new 
BufferedOutputStream(fileOutputStream)) {
-      // for IOTDB 1.2, the username's length will be stored as a negative 
number.
-      byte[] strBuffer = user.getName().getBytes(STRING_ENCODING);
-      IOUtils.writeInt(outputStream, -1 * strBuffer.length, 
encodingBufferLocal);
-      outputStream.write(strBuffer);
-      IOUtils.writeString(outputStream, user.getPassword(), STRING_ENCODING, 
encodingBufferLocal);
-      IOUtils.writeInt(outputStream, user.getAllSysPrivileges(), 
encodingBufferLocal);
-
-      int privilegeNum = user.getPathPrivilegeList().size();
-      for (int i = 0; i < privilegeNum; i++) {
-        PathPrivilege pathPrivilege = user.getPathPrivilegeList().get(i);
-        IOUtils.writePathPrivilege(
-            outputStream, pathPrivilege, STRING_ENCODING, encodingBufferLocal);
+      assert (tag == VERSION);
+      user.setName(IOUtils.readString(dataInputStream, STRING_ENCODING, 
strBufferLocal));
+      user.setPassword(IOUtils.readString(dataInputStream, STRING_ENCODING, 
strBufferLocal));
+      user.setSysPrivilegesWithMask(dataInputStream.readInt());

Review Comment:
   Why not put this in "loadPrivileges"?



##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java:
##########
@@ -333,54 +247,24 @@ public boolean deleteURole(String username) throws 
IOException {
   }
 
   @Override
-  public List<String> listAllUsers() {
-    File userDir = SystemFileFactory.INSTANCE.getFile(userDirPath);
+  public List<String> listAllEntries() {
+    File userDir = SystemFileFactory.INSTANCE.getFile(entryDirPath);
     String[] names =
         userDir.list(
             (dir, name) ->
                 (name.endsWith(IoTDBConstant.PROFILE_SUFFIX)
                         && !name.endsWith(ROLE_SUFFIX + 
IoTDBConstant.PROFILE_SUFFIX))
                     || (name.endsWith(TEMP_SUFFIX) && 
!name.endsWith(ROLE_SUFFIX + TEMP_SUFFIX)));

Review Comment:
   ROLE_SUFFIX + PROFILE_SUFFIX + TEMP_SUFFIX?



##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java:
##########
@@ -193,135 +180,62 @@ public User loadUser(String username) throws IOException 
{
             }
           }
         }
-        user.setRoleList(roleList);
+        user.setRoleSet(roleList);
         return user;
       }
-    } catch (Exception e) {
-      throw new IOException(e);
-    } finally {
-      strBufferLocal.remove();
-    }
-  }
-
-  /**
-   * Serialize the user object to a temp file, then replace the old user file 
with the new file.
-   *
-   * @param user The user object that is to be saved.
-   */
-  @Override
-  public void saveUser(User user) throws IOException {
-    File userProfile =
-        SystemFileFactory.INSTANCE.getFile(
-            userDirPath
-                + File.separator
-                + user.getName()
-                + IoTDBConstant.PROFILE_SUFFIX
-                + TEMP_SUFFIX);
-
-    try (FileOutputStream fileOutputStream = new FileOutputStream(userProfile);
-        BufferedOutputStream outputStream = new 
BufferedOutputStream(fileOutputStream)) {
-      // for IOTDB 1.2, the username's length will be stored as a negative 
number.
-      byte[] strBuffer = user.getName().getBytes(STRING_ENCODING);
-      IOUtils.writeInt(outputStream, -1 * strBuffer.length, 
encodingBufferLocal);
-      outputStream.write(strBuffer);
-      IOUtils.writeString(outputStream, user.getPassword(), STRING_ENCODING, 
encodingBufferLocal);
-      IOUtils.writeInt(outputStream, user.getAllSysPrivileges(), 
encodingBufferLocal);
-
-      int privilegeNum = user.getPathPrivilegeList().size();
-      for (int i = 0; i < privilegeNum; i++) {
-        PathPrivilege pathPrivilege = user.getPathPrivilegeList().get(i);
-        IOUtils.writePathPrivilege(
-            outputStream, pathPrivilege, STRING_ENCODING, encodingBufferLocal);
+      assert (tag == VERSION);
+      user.setName(IOUtils.readString(dataInputStream, STRING_ENCODING, 
strBufferLocal));
+      user.setPassword(IOUtils.readString(dataInputStream, STRING_ENCODING, 
strBufferLocal));
+      user.setSysPrivilegesWithMask(dataInputStream.readInt());
+      loadPrivileges(dataInputStream, user);
+
+      File roleOfUser = checkFileAvailable(entryName, "_role");
+      Set<String> roleSet = new HashSet<>();
+      if (roleOfUser.exists()) {
+        inputStream = new FileInputStream(roleOfUser);
+        try (DataInputStream roleInpuStream =

Review Comment:
   roleInputStream



##########
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java:
##########
@@ -190,114 +116,125 @@ public void permissionCacheTest() throws 
IllegalPathException {
 
   @Test
   public void grantOptTest() throws IllegalPathException {
-    User user = new User();
-    Role role = new Role();
-
-    Set<Integer> sysPri = new HashSet<>();
-    sysPri.add(PrivilegeType.MANAGE_DATABASE.ordinal());
-    sysPri.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPrivilegeSet(sysPri);
-
-    Set<Integer> sysGrantOpt = new HashSet<>();
-    sysGrantOpt.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPriGrantOpt(sysGrantOpt);
+    User user = new User("user1", "123456");
+    Role role = new Role("role1");
 
-    List<PathPrivilege> pathList = new ArrayList<>();
-    PartialPath pathRoot = new PartialPath("root.**");
-    PartialPath path1 = new PartialPath("root.d1.**");
-    PathPrivilege priv1 = new PathPrivilege(path1);
-    priv1.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), false);
-    priv1.grantPrivilege(PrivilegeType.WRITE_SCHEMA.ordinal(), true);
-    pathList.add(priv1);
+    user.grantSysPrivilege(PrivilegeType.MANAGE_DATABASE, false);
+    user.grantSysPrivilege(PrivilegeType.USE_PIPE, true);
 
-    user.setPrivilegeList(pathList);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.READ_DATA, false);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.WRITE_SCHEMA, true);
 
-    user.setName("user1");
-    user.setPassword("123456");
+    user.grantDBPrivilege("database", PrivilegeType.SELECT, false);
+    user.grantDBPrivilege("database", PrivilegeType.ALTER, true);
+    user.grantTBPrivilege("database", "table", PrivilegeType.DELETE, true);
+    role.grantSysPrivilege(PrivilegeType.USE_UDF, false);
+    role.grantSysPrivilege(PrivilegeType.USE_CQ, true);
+    role.grantSysPrivilegeGrantOption(PrivilegeType.USE_CQ);
+    role.grantPathPrivilege(new PartialPath("root.t.**"), 
PrivilegeType.READ_DATA, true);
+    role.grantDBPrivilege("database", PrivilegeType.INSERT, true);
 
     // user's priv:
     // 1. MANAGE_DATABASE
     // 2. USE_PIPE with grant option
     // 3. READ_DATA root.d1.**
     // 4. WRITE_SCHEMA root.d1.** with grant option
+    // 5. SELECT on database, ALTER on database with grant option
+    // 6. UPDATE on database.table, DELETE on database.table with grant option
 
     // role's priv:
     // 1. USE_UDF
     // 2. USE_CQ with grant option
     // 3. READ_DATA root.t9.** with grant option
-
-    role.setName("role1");
-    Set<Integer> sysPriRole = new HashSet<>();
-    sysPriRole.add(PrivilegeType.USE_UDF.ordinal());
-    sysPriRole.add(PrivilegeType.USE_CQ.ordinal());
-    role.setSysPrivilegeSet(sysPriRole);
-
-    Set<Integer> sysGrantOptRole = new HashSet<>();
-    sysGrantOptRole.add(PrivilegeType.USE_CQ.ordinal());
-    role.setSysPriGrantOpt(sysGrantOptRole);
-
-    PathPrivilege privRole = new PathPrivilege(new PartialPath("root.t9.**"));
-    privRole.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), true);
-    role.setPrivilegeList(Collections.singletonList(privRole));
-    user.setRoleList(Collections.singletonList("role1"));
+    user.addRole("role1");
 
     authorityFetcher.getAuthorCache().putUserCache("user1", user);
     authorityFetcher.getAuthorCache().putRoleCache("role1", role);
 
     // for system priv. we have USE_PIPE grant option.
-    Assert.assertTrue(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.USE_PIPE.ordinal()));
-    Assert.assertFalse(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.MANAGE_USER.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher.checkUserSysPrivilegesGrantOpt("user1", 
PrivilegeType.USE_PIPE).getCode(),
+        TSStatusCode.SUCCESS_STATUS.getStatusCode());
+    Assert.assertEquals(
+        authorityFetcher
+            .checkUserSysPrivilegesGrantOpt("user1", PrivilegeType.MANAGE_USER)
+            .getCode(),
+        TSStatusCode.NO_PERMISSION.getStatusCode());
 
     // for path priv. we have write_schema on root.d1.** with grant option.
     // require root.d1.** with write_schema, return true
-    Assert.assertTrue(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(path1), 
PrivilegeType.WRITE_SCHEMA.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher
+            .checkUserPathPrivilegesGrantOpt(
+                "user1",
+                Collections.singletonList(new PartialPath("root.d1.**")),
+                PrivilegeType.WRITE_SCHEMA)
+            .getCode(),
+        TSStatusCode.SUCCESS_STATUS.getStatusCode());
     // require root.** with write_schema, return false
-    Assert.assertFalse(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.WRITE_SCHEMA.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher
+            .checkUserPathPrivilegesGrantOpt(
+                "user1",
+                Collections.singletonList(new PartialPath("root.**")),
+                PrivilegeType.WRITE_SCHEMA)
+            .getCode(),
+        TSStatusCode.NO_PERMISSION.getStatusCode());
     // reuqire root.d1.d2 with write_schema, return true

Review Comment:
   "require"



##########
iotdb-core/datanode/src/test/java/org/apache/iotdb/db/auth/AuthorizerManagerTest.java:
##########
@@ -190,114 +116,125 @@ public void permissionCacheTest() throws 
IllegalPathException {
 
   @Test
   public void grantOptTest() throws IllegalPathException {
-    User user = new User();
-    Role role = new Role();
-
-    Set<Integer> sysPri = new HashSet<>();
-    sysPri.add(PrivilegeType.MANAGE_DATABASE.ordinal());
-    sysPri.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPrivilegeSet(sysPri);
-
-    Set<Integer> sysGrantOpt = new HashSet<>();
-    sysGrantOpt.add(PrivilegeType.USE_PIPE.ordinal());
-    user.setSysPriGrantOpt(sysGrantOpt);
+    User user = new User("user1", "123456");
+    Role role = new Role("role1");
 
-    List<PathPrivilege> pathList = new ArrayList<>();
-    PartialPath pathRoot = new PartialPath("root.**");
-    PartialPath path1 = new PartialPath("root.d1.**");
-    PathPrivilege priv1 = new PathPrivilege(path1);
-    priv1.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), false);
-    priv1.grantPrivilege(PrivilegeType.WRITE_SCHEMA.ordinal(), true);
-    pathList.add(priv1);
+    user.grantSysPrivilege(PrivilegeType.MANAGE_DATABASE, false);
+    user.grantSysPrivilege(PrivilegeType.USE_PIPE, true);
 
-    user.setPrivilegeList(pathList);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.READ_DATA, false);
+    user.grantPathPrivilege(new PartialPath("root.d1.**"), 
PrivilegeType.WRITE_SCHEMA, true);
 
-    user.setName("user1");
-    user.setPassword("123456");
+    user.grantDBPrivilege("database", PrivilegeType.SELECT, false);
+    user.grantDBPrivilege("database", PrivilegeType.ALTER, true);
+    user.grantTBPrivilege("database", "table", PrivilegeType.DELETE, true);
+    role.grantSysPrivilege(PrivilegeType.USE_UDF, false);
+    role.grantSysPrivilege(PrivilegeType.USE_CQ, true);
+    role.grantSysPrivilegeGrantOption(PrivilegeType.USE_CQ);
+    role.grantPathPrivilege(new PartialPath("root.t.**"), 
PrivilegeType.READ_DATA, true);
+    role.grantDBPrivilege("database", PrivilegeType.INSERT, true);
 
     // user's priv:
     // 1. MANAGE_DATABASE
     // 2. USE_PIPE with grant option
     // 3. READ_DATA root.d1.**
     // 4. WRITE_SCHEMA root.d1.** with grant option
+    // 5. SELECT on database, ALTER on database with grant option
+    // 6. UPDATE on database.table, DELETE on database.table with grant option
 
     // role's priv:
     // 1. USE_UDF
     // 2. USE_CQ with grant option
     // 3. READ_DATA root.t9.** with grant option
-
-    role.setName("role1");
-    Set<Integer> sysPriRole = new HashSet<>();
-    sysPriRole.add(PrivilegeType.USE_UDF.ordinal());
-    sysPriRole.add(PrivilegeType.USE_CQ.ordinal());
-    role.setSysPrivilegeSet(sysPriRole);
-
-    Set<Integer> sysGrantOptRole = new HashSet<>();
-    sysGrantOptRole.add(PrivilegeType.USE_CQ.ordinal());
-    role.setSysPriGrantOpt(sysGrantOptRole);
-
-    PathPrivilege privRole = new PathPrivilege(new PartialPath("root.t9.**"));
-    privRole.grantPrivilege(PrivilegeType.READ_DATA.ordinal(), true);
-    role.setPrivilegeList(Collections.singletonList(privRole));
-    user.setRoleList(Collections.singletonList("role1"));
+    user.addRole("role1");
 
     authorityFetcher.getAuthorCache().putUserCache("user1", user);
     authorityFetcher.getAuthorCache().putRoleCache("role1", role);
 
     // for system priv. we have USE_PIPE grant option.
-    Assert.assertTrue(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.USE_PIPE.ordinal()));
-    Assert.assertFalse(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.MANAGE_USER.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher.checkUserSysPrivilegesGrantOpt("user1", 
PrivilegeType.USE_PIPE).getCode(),
+        TSStatusCode.SUCCESS_STATUS.getStatusCode());
+    Assert.assertEquals(
+        authorityFetcher
+            .checkUserSysPrivilegesGrantOpt("user1", PrivilegeType.MANAGE_USER)
+            .getCode(),
+        TSStatusCode.NO_PERMISSION.getStatusCode());
 
     // for path priv. we have write_schema on root.d1.** with grant option.
     // require root.d1.** with write_schema, return true
-    Assert.assertTrue(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(path1), 
PrivilegeType.WRITE_SCHEMA.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher
+            .checkUserPathPrivilegesGrantOpt(
+                "user1",
+                Collections.singletonList(new PartialPath("root.d1.**")),
+                PrivilegeType.WRITE_SCHEMA)
+            .getCode(),
+        TSStatusCode.SUCCESS_STATUS.getStatusCode());
     // require root.** with write_schema, return false
-    Assert.assertFalse(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1", Collections.singletonList(pathRoot), 
PrivilegeType.WRITE_SCHEMA.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher
+            .checkUserPathPrivilegesGrantOpt(
+                "user1",
+                Collections.singletonList(new PartialPath("root.**")),
+                PrivilegeType.WRITE_SCHEMA)
+            .getCode(),
+        TSStatusCode.NO_PERMISSION.getStatusCode());
     // reuqire root.d1.d2 with write_schema, return true
-    Assert.assertTrue(
-        authorityFetcher.checkUserPrivilegeGrantOpt(
-            "user1",
-            Collections.singletonList(new PartialPath(new 
String("root.d1.d2"))),
-            PrivilegeType.WRITE_SCHEMA.ordinal()));
+    Assert.assertEquals(
+        authorityFetcher
+            .checkUserPathPrivilegesGrantOpt(
+                "user1",
+                Collections.singletonList(new PartialPath("root.d1.d1.**")),

Review Comment:
   Above just said "root.d1.d2"



##########
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/auth/user/LocalFileUserAccessor.java:
##########
@@ -77,112 +74,102 @@
  * All user/role file store in config node's user/role folder. when our system 
start, we load all
  * user/role from folder. If we did some alter query, we just store raft log.
  */
-public class LocalFileUserAccessor implements IUserAccessor {
+public class LocalFileUserAccessor extends LocalFileRoleAccessor {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(LocalFileUserAccessor.class);
-  private static final String TEMP_SUFFIX = ".temp";
-  private static final String STRING_ENCODING = "utf-8";
-  private static final String USER_SNAPSHOT_FILE_NAME = "system" + 
File.separator + "users";
-
   public static final String ROLE_SUFFIX = "_role";
 
-  private final String userDirPath;
+  public LocalFileUserAccessor(String userDirPath) {
+    super(userDirPath);
+  }
 
-  /**
-   * Reused buffer for primitive types encoding/decoding, which aim to reduce 
memory fragments. Use
-   * ThreadLocal for thread safety.
-   */
-  private final ThreadLocal<ByteBuffer> encodingBufferLocal = new 
ThreadLocal<>();
+  @Override
+  protected String getEntrySnapshotFileName() {
+    return "system" + File.separator + "users";
+  }
 
-  private final ThreadLocal<byte[]> strBufferLocal = new ThreadLocal<>();
+  @Override
+  protected void saveEntryName(BufferedOutputStream outputStream, Role role) 
throws IOException {
+    super.saveEntryName(outputStream, role);
+    IOUtils.writeString(
+        outputStream, ((User) role).getPassword(), STRING_ENCODING, 
encodingBufferLocal);
+  }
 
-  public LocalFileUserAccessor(String userDirPath) {
-    this.userDirPath = userDirPath;
+  @Override
+  protected void saveRoles(Role role) throws IOException {
+    User user = (User) role;
+    File roleProfile =
+        SystemFileFactory.INSTANCE.getFile(
+            entryDirPath
+                + File.separator
+                + user.getName()
+                + ROLE_SUFFIX
+                + IoTDBConstant.PROFILE_SUFFIX
+                + TEMP_SUFFIX);
+    try (FileOutputStream fileOutputStream = new FileOutputStream(roleProfile);
+        BufferedOutputStream outputStream = new 
BufferedOutputStream(fileOutputStream)) {
+      int roleNum = user.getRoleSet().size();
+      IOUtils.writeInt(outputStream, roleNum, encodingBufferLocal);
+      for (String roleName : user.getRoleSet()) {
+        IOUtils.writeString(outputStream, roleName, STRING_ENCODING, 
encodingBufferLocal);
+      }
+      outputStream.flush();
+      fileOutputStream.getFD().sync();
+    } catch (Exception e) {
+      LOGGER.warn("Get Exception when save user {}'s roles", user.getName(), 
e);
+      throw new IOException(e);
+    } finally {
+      encodingBufferLocal.remove();
+    }
+
+    File oldURoleFile =
+        SystemFileFactory.INSTANCE.getFile(
+            entryDirPath
+                + File.separator
+                + user.getName()
+                + ROLE_SUFFIX
+                + IoTDBConstant.PROFILE_SUFFIX);
+    IOUtils.replaceFile(roleProfile, oldURoleFile);
   }
 
   /**
    * Deserialize a user from its user file.
    *
-   * @param username The name of the user to be deserialized.
+   * @param entryName The name of the user to be deserialized.
    * @return The user object or null if no such user.
    */
   @Override
-  public User loadUser(String username) throws IOException {
-    File userProfile =
-        SystemFileFactory.INSTANCE.getFile(
-            userDirPath + File.separator + username + 
IoTDBConstant.PROFILE_SUFFIX);
-    if (!userProfile.exists() || !userProfile.isFile()) {
-      // System may crush before a newer file is renamed.
-      File newProfile =
-          SystemFileFactory.INSTANCE.getFile(
-              userDirPath + File.separator + username + 
IoTDBConstant.PROFILE_SUFFIX + TEMP_SUFFIX);
-      if (newProfile.exists() && newProfile.isFile()) {
-        if (!newProfile.renameTo(userProfile)) {
-          LOGGER.error("New profile renaming not succeed.");
-        }
-        userProfile = newProfile;
-      } else {
-        return null;
-      }
+  public User loadEntry(String entryName) throws IOException {
+    File entryFile = checkFileAvailable(entryName, "");
+    if (entryFile == null) {
+      return null;
     }
-
-    FileInputStream inputStream = new FileInputStream(userProfile);
+    FileInputStream inputStream = new FileInputStream(entryFile);
     try (DataInputStream dataInputStream =
         new DataInputStream(new BufferedInputStream(inputStream))) {
+      boolean fromOldVersion = false;
+      int tag = dataInputStream.readInt();
+      if (tag < 0) {
+        fromOldVersion = true;
+      }
       User user = new User();
-      Pair<String, Boolean> result =
-          IOUtils.readAuthString(dataInputStream, STRING_ENCODING, 
strBufferLocal);
-      boolean oldVersion = result.getRight();
-      user.setName(result.getLeft());
-      user.setPassword(IOUtils.readString(dataInputStream, STRING_ENCODING, 
strBufferLocal));
-      if (oldVersion) {
-        IOUtils.loadRolePrivilege(user, dataInputStream, STRING_ENCODING, 
strBufferLocal);
-        int roleNum = dataInputStream.readInt();
-        List<String> roleList = new ArrayList<>();
-        for (int i = 0; i < roleNum; i++) {
-          String roleName = IOUtils.readString(dataInputStream, 
STRING_ENCODING, strBufferLocal);
-          roleList.add(roleName);
-        }
-        user.setRoleList(roleList);
-        try {
-          user.setUseWaterMark(dataInputStream.readInt() != 0);
-        } catch (EOFException e1) {
-          user.setUseWaterMark(false);
-        }
-        return user;
-      } else {
-        user.setSysPrivilegeSet(dataInputStream.readInt());
+
+      if (fromOldVersion) {
+        String name =
+            IOUtils.readString(dataInputStream, STRING_ENCODING, 
strBufferLocal, -1 * tag);
+        user.setName(name);
+        user.setPassword(IOUtils.readString(dataInputStream, STRING_ENCODING, 
strBufferLocal));
+        user.setSysPrivilegesWithMask(dataInputStream.readInt());
         List<PathPrivilege> pathPrivilegeList = new ArrayList<>();
         for (int i = 0; dataInputStream.available() != 0; i++) {
           pathPrivilegeList.add(
-              IOUtils.readPathPrivilege(dataInputStream, STRING_ENCODING, 
strBufferLocal, false));
+              IOUtils.readPathPrivilege(dataInputStream, STRING_ENCODING, 
strBufferLocal));
         }
         user.setPrivilegeList(pathPrivilegeList);
 
-        File roleOfUser =
-            SystemFileFactory.INSTANCE.getFile(
-                userDirPath,
-                File.separator + username + ROLE_SUFFIX + 
IoTDBConstant.PROFILE_SUFFIX);
+        File roleOfUser = checkFileAvailable(entryName, "_role");
 
-        if (!roleOfUser.isFile() || !roleOfUser.exists()) {
-          // System may crush before a newer file is renamed.
-          File newRoleProfile =
-              SystemFileFactory.INSTANCE.getFile(
-                  userDirPath
-                      + File.separator
-                      + username
-                      + "_role"
-                      + IoTDBConstant.PROFILE_SUFFIX
-                      + TEMP_SUFFIX);
-          if (newRoleProfile.exists() && newRoleProfile.isFile()) {
-            if (!newRoleProfile.renameTo(roleOfUser)) {
-              LOGGER.warn(" New role profile renaming not succeed.");
-            }
-            roleOfUser = newRoleProfile;
-          }
-        }
-
-        List<String> roleList = new ArrayList<>();
-        if (roleOfUser.exists()) {
+        Set<String> roleList = new HashSet<>();

Review Comment:
   roleSet



-- 
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