This is an automated email from the ASF dual-hosted git repository.
wangchao316 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 21c530abf7 [IOTDB-4007]Support multiple paths in privilege control
(#6854)
21c530abf7 is described below
commit 21c530abf75cb3825c3724fc1c4e00cb5f8013a4
Author: Yifu Zhou <[email protected]>
AuthorDate: Tue Aug 2 15:11:58 2022 +0800
[IOTDB-4007]Support multiple paths in privilege control (#6854)
[IOTDB-4007]Support multiple paths in privilege control (#6854)
---
.../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 | 12 +-
.../consensus/request/auth/AuthorPlan.java | 25 +-
.../iotdb/confignode/persistence/AuthorInfo.java | 68 +++--
.../thrift/ConfigNodeRPCServiceProcessor.java | 4 +-
.../request/ConfigPhysicalPlanSerDeTest.java | 121 ++++++--
.../confignode/persistence/AuthorInfoTest.java | 305 +++++++++++++++++++--
.../thrift/ConfigNodeRPCServiceProcessorTest.java | 74 +++--
.../Administration-Management/Administration.md | 38 +--
.../Administration-Management/Administration.md | 38 +--
.../commons/utils/BasicStructureSerDeUtil.java | 31 +++
.../iotdb/db/auth/ClusterAuthorityFetcher.java | 9 +-
.../iotdb/db/localconfignode/LocalConfigNode.java | 73 +++--
.../iotdb/db/mpp/plan/parser/ASTVisitor.java | 48 +++-
.../db/mpp/plan/statement/sys/AuthorStatement.java | 12 +-
.../apache/iotdb/db/qp/executor/PlanExecutor.java | 74 +++--
.../iotdb/db/qp/logical/sys/AuthorOperator.java | 14 +-
.../iotdb/db/qp/physical/sys/AuthorPlan.java | 54 ++--
.../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java | 44 ++-
.../iotdb/db/qp/physical/PhysicalPlanTest.java | 2 +-
.../src/main/thrift/confignode.thrift | 2 +-
20 files changed, 814 insertions(+), 234 deletions(-)
diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 73e762f051..410f32d388 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -530,12 +530,12 @@ alterUser
// Grant User Privileges
grantUser
- : GRANT USER userName=identifier PRIVILEGES privileges (ON prefixPath)?
+ : GRANT USER userName=identifier PRIVILEGES privileges (ON prefixPath
(COMMA prefixPath)*)?
;
// Grant Role Privileges
grantRole
- : GRANT ROLE roleName=identifier PRIVILEGES privileges ON prefixPath
+ : GRANT ROLE roleName=identifier PRIVILEGES privileges ON prefixPath
(COMMA prefixPath)*
;
// Grant User Role
@@ -545,12 +545,12 @@ grantRoleToUser
// Revoke User Privileges
revokeUser
- : REVOKE USER userName=identifier PRIVILEGES privileges (ON prefixPath)?
+ : REVOKE USER userName=identifier PRIVILEGES privileges (ON prefixPath
(COMMA prefixPath)*)?
;
// Revoke Role Privileges
revokeRole
- : REVOKE ROLE roleName=identifier PRIVILEGES privileges ON prefixPath
+ : REVOKE ROLE roleName=identifier PRIVILEGES privileges ON prefixPath
(COMMA prefixPath)*
;
// Revoke Role From User
@@ -580,12 +580,12 @@ listRole
// List Privileges
listPrivilegesUser
- : LIST PRIVILEGES USER userName=usernameWithRoot ON prefixPath
+ : LIST PRIVILEGES USER userName=usernameWithRoot ON prefixPath (COMMA
prefixPath)*
;
// List Privileges of Roles On Specific Path
listPrivilegesRole
- : LIST PRIVILEGES ROLE roleName=identifier ON prefixPath
+ : LIST PRIVILEGES ROLE roleName=identifier ON prefixPath (COMMA
prefixPath)*
;
// List Privileges of Users
diff --git
a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
index 754f1e00ce..9684b864d6 100644
---
a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
+++
b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/auth/AuthorPlan.java
@@ -27,6 +27,7 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -37,7 +38,7 @@ public class AuthorPlan extends ConfigPhysicalPlan {
private String password;
private String newPassword;
private Set<Integer> permissions;
- private String nodeName;
+ private List<String> nodeNameList;
private String userName;
public AuthorPlan(ConfigPhysicalPlanType type) {
@@ -54,7 +55,7 @@ public class AuthorPlan extends ConfigPhysicalPlan {
* @param password password
* @param newPassword new password
* @param permissions permissions
- * @param nodeName node name in Path structure
+ * @param nodeNameList node name in Path structure
* @throws AuthException Authentication Exception
*/
public AuthorPlan(
@@ -64,7 +65,7 @@ public class AuthorPlan extends ConfigPhysicalPlan {
String password,
String newPassword,
Set<Integer> permissions,
- String nodeName)
+ List<String> nodeNameList)
throws AuthException {
this(authorType);
this.authorType = authorType;
@@ -73,7 +74,7 @@ public class AuthorPlan extends ConfigPhysicalPlan {
this.password = password;
this.newPassword = newPassword;
this.permissions = permissions;
- this.nodeName = nodeName;
+ this.nodeNameList = nodeNameList;
}
public ConfigPhysicalPlanType getAuthorType() {
@@ -116,12 +117,12 @@ public class AuthorPlan extends ConfigPhysicalPlan {
this.permissions = permissions;
}
- public String getNodeName() {
- return nodeName;
+ public List<String> getNodeNameList() {
+ return nodeNameList;
}
- public void setNodeName(String nodeName) {
- this.nodeName = nodeName;
+ public void setNodeNameList(List<String> nodeNameList) {
+ this.nodeNameList = nodeNameList;
}
public String getUserName() {
@@ -148,7 +149,7 @@ public class AuthorPlan extends ConfigPhysicalPlan {
stream.writeInt(permission);
}
}
- BasicStructureSerDeUtil.write(nodeName, stream);
+ BasicStructureSerDeUtil.write(nodeNameList, stream);
}
@Override
@@ -167,7 +168,7 @@ public class AuthorPlan extends ConfigPhysicalPlan {
permissions.add(buffer.getInt());
}
}
- nodeName = BasicStructureSerDeUtil.readString(buffer);
+ nodeNameList = BasicStructureSerDeUtil.readStringList(buffer);
}
private int getPlanTypeOrdinal(ConfigPhysicalPlanType
configPhysicalPlanType) {
@@ -245,12 +246,12 @@ public class AuthorPlan extends ConfigPhysicalPlan {
&& Objects.equals(password, that.password)
&& Objects.equals(newPassword, that.newPassword)
&& Objects.equals(permissions, that.permissions)
- && Objects.equals(nodeName, that.nodeName);
+ && Objects.equals(nodeNameList, that.nodeNameList);
}
@Override
public int hashCode() {
return Objects.hash(
- authorType, userName, roleName, password, newPassword, permissions,
nodeName);
+ authorType, userName, roleName, password, newPassword, permissions,
nodeNameList);
}
}
diff --git
a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
index e034bb2f2e..0edaf346a2 100644
---
a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
+++
b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/AuthorInfo.java
@@ -50,6 +50,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -145,7 +146,7 @@ public class AuthorInfo implements SnapshotProcessor {
String password = authorPlan.getPassword();
String newPassword = authorPlan.getNewPassword();
Set<Integer> permissions = authorPlan.getPermissions();
- String nodeName = authorPlan.getNodeName();
+ List<String> nodeNameList = authorPlan.getNodeNameList();
try {
switch (authorType) {
case UpdateUser:
@@ -165,12 +166,16 @@ public class AuthorInfo implements SnapshotProcessor {
break;
case GrantRole:
for (int i : permissions) {
- authorizer.grantPrivilegeToRole(roleName, nodeName, i);
+ for (String path : nodeNameList) {
+ authorizer.grantPrivilegeToRole(roleName, path, i);
+ }
}
break;
case GrantUser:
for (int i : permissions) {
- authorizer.grantPrivilegeToUser(userName, nodeName, i);
+ for (String path : nodeNameList) {
+ authorizer.grantPrivilegeToUser(userName, path, i);
+ }
}
break;
case GrantRoleToUser:
@@ -178,12 +183,16 @@ public class AuthorInfo implements SnapshotProcessor {
break;
case RevokeUser:
for (int i : permissions) {
- authorizer.revokePrivilegeFromUser(userName, nodeName, i);
+ for (String path : nodeNameList) {
+ authorizer.revokePrivilegeFromUser(userName, path, i);
+ }
}
break;
case RevokeRole:
for (int i : permissions) {
- authorizer.revokePrivilegeFromRole(roleName, nodeName, i);
+ for (String path : nodeNameList) {
+ authorizer.revokePrivilegeFromRole(roleName, path, i);
+ }
}
break;
case RevokeRoleFromUser:
@@ -291,15 +300,20 @@ public class AuthorInfo implements SnapshotProcessor {
} catch (AuthException e) {
throw new AuthException(e);
}
- List<String> rolePrivilegesList = new ArrayList<>();
+ Set<String> rolePrivilegesSet = new HashSet<>();
for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (plan.getNodeName().equals("")
- || AuthUtils.pathOrBelongsTo(plan.getNodeName(),
pathPrivilege.getPath())) {
- rolePrivilegesList.add(pathPrivilege.toString());
+ if (plan.getNodeNameList().isEmpty()) {
+ rolePrivilegesSet.add(pathPrivilege.toString());
+ continue;
+ }
+ for (String path : plan.getNodeNameList()) {
+ if (AuthUtils.pathOrBelongsTo(path, pathPrivilege.getPath())) {
+ rolePrivilegesSet.add(pathPrivilege.toString());
+ }
}
}
- permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, rolePrivilegesList);
+ permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, new
ArrayList<>(rolePrivilegesSet));
result.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
result.setPermissionInfo(permissionInfo);
return result;
@@ -329,25 +343,45 @@ public class AuthorInfo implements SnapshotProcessor {
}
} else {
List<String> rolePrivileges = new ArrayList<>();
+ Set<String> userPrivilegeSet = new HashSet<>();
for (PathPrivilege pathPrivilege : user.getPrivilegeList()) {
- if (plan.getNodeName().equals("")
- || AuthUtils.pathOrBelongsTo(plan.getNodeName(),
pathPrivilege.getPath())) {
+ if (plan.getNodeNameList().isEmpty()
+ && !userPrivilegeSet.contains(pathPrivilege.toString())) {
rolePrivileges.add("");
- userPrivilegesList.add(pathPrivilege.toString());
+ userPrivilegeSet.add(pathPrivilege.toString());
+ continue;
+ }
+ for (String path : plan.getNodeNameList()) {
+ if (AuthUtils.pathOrBelongsTo(path, pathPrivilege.getPath())
+ && !userPrivilegeSet.contains(pathPrivilege.toString())) {
+ rolePrivileges.add("");
+ userPrivilegeSet.add(pathPrivilege.toString());
+ }
}
}
+ userPrivilegesList.addAll(userPrivilegeSet);
for (String roleN : user.getRoleList()) {
Role role = authorizer.getRole(roleN);
if (roleN == null) {
continue;
}
+ Set<String> rolePrivilegeSet = new HashSet<>();
for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (plan.getNodeName().equals("")
- || AuthUtils.pathOrBelongsTo(plan.getNodeName(),
pathPrivilege.getPath())) {
- rolePrivileges.add(roleN);
- userPrivilegesList.add(pathPrivilege.toString());
+ if (plan.getNodeNameList().isEmpty()
+ && !rolePrivilegeSet.contains(pathPrivilege.toString())) {
+ rolePrivileges.add("");
+ rolePrivilegeSet.add(pathPrivilege.toString());
+ continue;
+ }
+ for (String path : plan.getNodeNameList()) {
+ if (AuthUtils.pathOrBelongsTo(path, pathPrivilege.getPath())
+ && !rolePrivilegeSet.contains(pathPrivilege.toString())) {
+ rolePrivileges.add(roleN);
+ rolePrivilegeSet.add(pathPrivilege.toString());
+ }
}
}
+ userPrivilegesList.addAll(rolePrivilegeSet);
}
permissionInfo.put(IoTDBConstant.COLUMN_ROLE, rolePrivileges);
}
diff --git
a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index 6c954faf66..e0cfbfbd79 100644
---
a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++
b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -372,7 +372,7 @@ public class ConfigNodeRPCServiceProcessor implements
IConfigNodeRPCService.Ifac
req.getPassword(),
req.getNewPassword(),
req.getPermissions(),
- req.getNodeName());
+ req.getNodeNameList());
} catch (AuthException e) {
LOGGER.error(e.getMessage());
}
@@ -396,7 +396,7 @@ public class ConfigNodeRPCServiceProcessor implements
IConfigNodeRPCService.Ifac
req.getPassword(),
req.getNewPassword(),
req.getPermissions(),
- req.getNodeName());
+ req.getNodeNameList());
} catch (AuthException e) {
LOGGER.error(e.getMessage());
}
diff --git
a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
index 0bfb25764e..71cf569c19 100644
---
a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
+++
b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
@@ -382,27 +382,49 @@ public class ConfigPhysicalPlanSerDeTest {
// create user
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.CreateUser, "thulab", "", "passwd", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.CreateUser,
+ "thulab",
+ "",
+ "passwd",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// create role
req0 =
- new AuthorPlan(ConfigPhysicalPlanType.CreateRole, "", "admin", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.CreateRole,
+ "",
+ "admin",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// alter user
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.UpdateUser, "tempuser", "", "", "newpwd",
new HashSet<>(), "");
+ ConfigPhysicalPlanType.UpdateUser,
+ "tempuser",
+ "",
+ "",
+ "newpwd",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// grant user
+ List<String> nodeNameList = new ArrayList<>();
+ nodeNameList.add("root.ln.**");
+ nodeNameList.add("root.abc.**");
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.GrantUser, "tempuser", "", "", "",
permissions, "root.ln");
+ ConfigPhysicalPlanType.GrantUser, "tempuser", "", "", "",
permissions, nodeNameList);
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
@@ -415,28 +437,34 @@ public class ConfigPhysicalPlanSerDeTest {
"",
"",
permissions,
- "root.ln");
+ nodeNameList);
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// grant role to user
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.GrantRole, "", "temprole", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.GrantRole,
+ "",
+ "temprole",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// revoke user
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.RevokeUser, "tempuser", "", "", "",
permissions, "root.ln");
+ ConfigPhysicalPlanType.RevokeUser, "tempuser", "", "", "",
permissions, nodeNameList);
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// revoke role
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.RevokeRole, "", "temprole", "", "",
permissions, "root.ln");
+ ConfigPhysicalPlanType.RevokeRole, "", "temprole", "", "",
permissions, nodeNameList);
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
@@ -449,70 +477,125 @@ public class ConfigPhysicalPlanSerDeTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// drop user
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.DropUser, "xiaoming", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.DropUser,
+ "xiaoming",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// drop role
req0 =
- new AuthorPlan(ConfigPhysicalPlanType.DropRole, "", "admin", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.DropRole,
+ "",
+ "admin",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list user
- req0 = new AuthorPlan(ConfigPhysicalPlanType.ListUser, "", "", "", "", new
HashSet<>(), "");
+ req0 =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListUser, "", "", "", "", new HashSet<>(),
new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list role
- req0 = new AuthorPlan(ConfigPhysicalPlanType.ListRole, "", "", "", "", new
HashSet<>(), "");
+ req0 =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListRole, "", "", "", "", new HashSet<>(),
new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list privileges user
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.ListUserPrivilege, "", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListUserPrivilege,
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list privileges role
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.ListRolePrivilege, "", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListRolePrivilege,
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list user privileges
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.ListUserPrivilege, "", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListUserPrivilege,
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list role privileges
req0 =
new AuthorPlan(
- ConfigPhysicalPlanType.ListRolePrivilege, "", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListRolePrivilege,
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list all role of user
req0 =
- new AuthorPlan(ConfigPhysicalPlanType.ListUserRoles, "", "", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListUserRoles,
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
// list all user of role
req0 =
- new AuthorPlan(ConfigPhysicalPlanType.ListRoleUsers, "", "", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListRoleUsers,
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
req1 = (AuthorPlan)
ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
Assert.assertEquals(req0, req1);
}
diff --git
a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/AuthorInfoTest.java
b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/AuthorInfoTest.java
index c17b4301ab..f17cbb3565 100644
---
a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/AuthorInfoTest.java
+++
b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/AuthorInfoTest.java
@@ -39,10 +39,12 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
import static org.apache.iotdb.db.constant.TestConstant.BASE_OUTPUT_PATH;
@@ -104,7 +106,13 @@ public class AuthorInfoTest {
// create user
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.CreateUser, "user0", "", "passwd", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.CreateUser,
+ "user0",
+ "",
+ "passwd",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertNull(status.getMessage());
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -121,7 +129,14 @@ public class AuthorInfoTest {
// drop user
authorPlan =
- new AuthorPlan(ConfigPhysicalPlanType.DropUser, "user1", "", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.DropUser,
+ "user1",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -135,7 +150,14 @@ public class AuthorInfoTest {
// create role
authorPlan =
- new AuthorPlan(ConfigPhysicalPlanType.CreateRole, "", "role0", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.CreateRole,
+ "",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
authorPlan.setRoleName("role1");
@@ -144,7 +166,14 @@ public class AuthorInfoTest {
// drop role
authorPlan =
- new AuthorPlan(ConfigPhysicalPlanType.DropRole, "", "role1", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.DropRole,
+ "",
+ "role1",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -159,14 +188,22 @@ public class AuthorInfoTest {
// alter user
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.UpdateUser, "user0", "", "", "newpwd", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.UpdateUser,
+ "user0",
+ "",
+ "",
+ "newpwd",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// grant user
+ List<String> nodeNameList = new ArrayList<>();
+ nodeNameList.add("root.ln.**");
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.GrantUser, "user0", "", "", "",
privilegeList, "root.ln");
+ ConfigPhysicalPlanType.GrantUser, "user0", "", "", "",
privilegeList, nodeNameList);
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -180,28 +217,34 @@ public class AuthorInfoTest {
// grant role
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.GrantRole, "", "role0", "", "",
privilegeList, "root.ln");
+ ConfigPhysicalPlanType.GrantRole, "", "role0", "", "",
privilegeList, nodeNameList);
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// grant role to user
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.GrantRoleToUser, "user0", "role0", "", "",
new HashSet<>(), "");
+ ConfigPhysicalPlanType.GrantRoleToUser,
+ "user0",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// revoke user
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.RevokeUser, "user0", "", "", "",
revokePrivilege, "root.ln");
+ ConfigPhysicalPlanType.RevokeUser, "user0", "", "", "",
revokePrivilege, nodeNameList);
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// revoke role
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.RevokeRole, "", "role0", "", "",
revokePrivilege, "root.ln");
+ ConfigPhysicalPlanType.RevokeRole, "", "role0", "", "",
revokePrivilege, nodeNameList);
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -214,7 +257,7 @@ public class AuthorInfoTest {
"",
"",
new HashSet<>(),
- "root.ln");
+ nodeNameList);
permissionInfoResp = authorInfo.executeListUserPrivileges(authorPlan);
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -224,7 +267,13 @@ public class AuthorInfoTest {
// list user privileges
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.ListUserPrivilege, "user0", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListUserPrivilege,
+ "user0",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
permissionInfoResp = authorInfo.executeListUserPrivileges(authorPlan);
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -240,7 +289,7 @@ public class AuthorInfoTest {
"",
"",
new HashSet<>(),
- "root.ln");
+ nodeNameList);
permissionInfoResp = authorInfo.executeListRolePrivileges(authorPlan);
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -251,7 +300,13 @@ public class AuthorInfoTest {
// list role privileges
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.ListRolePrivilege, "", "role0", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListRolePrivilege,
+ "",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
permissionInfoResp = authorInfo.executeListRolePrivileges(authorPlan);
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -261,7 +316,13 @@ public class AuthorInfoTest {
// list all role of user
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.ListUserRoles, "user0", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListUserRoles,
+ "user0",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
permissionInfoResp = authorInfo.executeListUserRoles(authorPlan);
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -272,7 +333,13 @@ public class AuthorInfoTest {
// list all user of role
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.ListRoleUsers, "", "role0", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListRoleUsers,
+ "",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
permissionInfoResp = authorInfo.executeListRoleUsers(authorPlan);
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -290,14 +357,20 @@ public class AuthorInfoTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// list root privileges
authorPlan =
new AuthorPlan(
- ConfigPhysicalPlanType.ListUserPrivilege, "root", "", "", "", new
HashSet<>(), "");
+ ConfigPhysicalPlanType.ListUserPrivilege,
+ "root",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
permissionInfoResp = authorInfo.executeListUserPrivileges(authorPlan);
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -313,7 +386,8 @@ public class AuthorInfoTest {
// clean user
AuthorPlan authorPlan =
- new AuthorPlan(ConfigPhysicalPlanType.ListUser, "", "", "", "", new
HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListUser, "", "", "", "", new HashSet<>(),
new ArrayList<>());
PermissionInfoResp permissionInfoResp = authorInfo.executeListUser();
status = permissionInfoResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -322,7 +396,14 @@ public class AuthorInfoTest {
for (String user : allUsers) {
if (!user.equals("root")) {
authorPlan =
- new AuthorPlan(ConfigPhysicalPlanType.DropUser, user, "", "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.DropUser,
+ user,
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
}
@@ -336,7 +417,14 @@ public class AuthorInfoTest {
List<String> roleList =
permissionInfoResp.getPermissionInfo().get(IoTDBConstant.COLUMN_ROLE);
for (String roleN : roleList) {
authorPlan =
- new AuthorPlan(ConfigPhysicalPlanType.DropRole, "", roleN, "", "",
new HashSet<>(), "");
+ new AuthorPlan(
+ ConfigPhysicalPlanType.DropRole,
+ "",
+ roleN,
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
status = authorInfo.authorNonQuery(authorPlan);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
}
@@ -364,4 +452,179 @@ public class AuthorInfoTest {
Assert.assertEquals(1,
authorInfo.executeListRole().getPermissionInfo().get("role").size());
Assert.assertEquals(2,
authorInfo.executeListUser().getPermissionInfo().get("user").size());
}
+
+ @Test
+ public void testMultPathsPermission() throws TException, AuthException {
+ TSStatus status;
+
+ AuthorPlan authorPlan;
+
+ Set<Integer> privilegeList = new HashSet<>();
+ privilegeList.add(PrivilegeType.INSERT_TIMESERIES.ordinal());
+ privilegeList.add(PrivilegeType.READ_TIMESERIES.ordinal());
+
+ Map<String, List<String>> permissionInfo;
+ List<String> userPrivilege = new ArrayList<>();
+ userPrivilege.add("root.sg.** : INSERT_TIMESERIES READ_TIMESERIES");
+ userPrivilege.add("root.ln.** : INSERT_TIMESERIES READ_TIMESERIES");
+ Collections.sort(userPrivilege);
+
+ List<String> rolePrivilege = new ArrayList<>();
+ rolePrivilege.add("root.abc.** : INSERT_TIMESERIES READ_TIMESERIES");
+ rolePrivilege.add("root.role_1.** : INSERT_TIMESERIES READ_TIMESERIES");
+ Collections.sort(rolePrivilege);
+
+ List<String> allPrivilege = new ArrayList<>();
+ allPrivilege.addAll(userPrivilege);
+ allPrivilege.addAll(rolePrivilege);
+ Collections.sort(allPrivilege);
+
+ List<String> userPaths = new ArrayList<>();
+ userPaths.add("root.ln.**");
+ userPaths.add("root.sg.**");
+
+ List<String> rolePaths = new ArrayList<>();
+ rolePaths.add("root.role_1.**");
+ rolePaths.add("root.abc.**");
+
+ cleanUserAndRole();
+
+ // create user
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.CreateUser,
+ "user0",
+ "",
+ "passwd",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
+ status = authorInfo.authorNonQuery(authorPlan);
+ Assert.assertNull(status.getMessage());
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+
+ // create role
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.CreateRole,
+ "",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
+ status = authorInfo.authorNonQuery(authorPlan);
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+
+ // grant user
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.GrantUser, "user0", "", "", "",
privilegeList, userPaths);
+ status = authorInfo.authorNonQuery(authorPlan);
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+
+ // check user privileges
+ status =
+ authorInfo
+ .checkUserPrivileges("user0", userPaths,
PrivilegeType.INSERT_TIMESERIES.ordinal())
+ .getStatus();
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+
+ // grant role
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.GrantRole, "", "role0", "", "",
privilegeList, rolePaths);
+ status = authorInfo.authorNonQuery(authorPlan);
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+
+ // grant role to user
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.GrantRoleToUser,
+ "user0",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
+ status = authorInfo.authorNonQuery(authorPlan);
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+
+ // list privileges user
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListUserPrivilege,
+ "user0",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ userPaths);
+ PermissionInfoResp permissionInfoResp;
+ permissionInfoResp = authorInfo.executeListUserPrivileges(authorPlan);
+ status = permissionInfoResp.getStatus();
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+ Assert.assertEquals(
+ userPrivilege,
+
permissionInfoResp.getPermissionInfo().get(IoTDBConstant.COLUMN_PRIVILEGE).stream()
+ .sorted()
+ .collect(Collectors.toList()));
+
+ // list all user privileges
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListUserPrivilege,
+ "user0",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
+ permissionInfoResp = authorInfo.executeListUserPrivileges(authorPlan);
+ status = permissionInfoResp.getStatus();
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+ Assert.assertEquals(
+ allPrivilege,
+
permissionInfoResp.getPermissionInfo().get(IoTDBConstant.COLUMN_PRIVILEGE).stream()
+ .sorted()
+ .collect(Collectors.toList()));
+
+ // list privileges role
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListRolePrivilege,
+ "",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ rolePaths);
+ permissionInfoResp = authorInfo.executeListRolePrivileges(authorPlan);
+ status = permissionInfoResp.getStatus();
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+ Assert.assertEquals(
+ rolePrivilege,
+
permissionInfoResp.getPermissionInfo().get(IoTDBConstant.COLUMN_PRIVILEGE).stream()
+ .sorted()
+ .collect(Collectors.toList()));
+
+ // list all role privileges
+ authorPlan =
+ new AuthorPlan(
+ ConfigPhysicalPlanType.ListRolePrivilege,
+ "",
+ "role0",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
+ permissionInfoResp = authorInfo.executeListRolePrivileges(authorPlan);
+ status = permissionInfoResp.getStatus();
+ Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
+ Assert.assertEquals(
+ rolePrivilege,
+
permissionInfoResp.getPermissionInfo().get(IoTDBConstant.COLUMN_PRIVILEGE).stream()
+ .sorted()
+ .collect(Collectors.toList()));
+ }
}
diff --git
a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
index ee81f23bdd..88b537c218 100644
---
a/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
+++
b/confignode/src/test/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessorTest.java
@@ -667,7 +667,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"passwd",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
authorizerReq.setUserName("tempuser1");
@@ -689,14 +689,20 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// list user
authorizerReq =
new TAuthorizerReq(
- AuthorOperator.AuthorType.LIST_USER.ordinal(), "", "", "", "", new
HashSet<>(), "");
+ AuthorOperator.AuthorType.LIST_USER.ordinal(),
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -713,7 +719,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
authorizerReq.setRoleName("temprole1");
@@ -729,14 +735,20 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// list role
authorizerReq =
new TAuthorizerReq(
- AuthorOperator.AuthorType.LIST_ROLE.ordinal(), "", "", "", "", new
HashSet<>(), "");
+ AuthorOperator.AuthorType.LIST_ROLE.ordinal(),
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -753,11 +765,13 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"newpwd",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
// grant user
+ List<String> nodeNameList = new ArrayList<>();
+ nodeNameList.add("root.ln.**");
authorizerReq =
new TAuthorizerReq(
AuthorOperator.AuthorType.GRANT_USER.ordinal(),
@@ -766,7 +780,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
privilegeList,
- "root.ln.**");
+ nodeNameList);
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -785,7 +799,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
privilegeList,
- "root.ln.**");
+ nodeNameList);
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -798,7 +812,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ nodeNameList);
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -811,7 +825,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
revokePrivilege,
- "root.ln.**");
+ nodeNameList);
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -824,7 +838,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
revokePrivilege,
- "root.ln.**");
+ nodeNameList);
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -837,7 +851,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "root.ln.**");
+ nodeNameList);
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -853,7 +867,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -869,7 +883,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "root.ln.**");
+ nodeNameList);
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -886,7 +900,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -902,7 +916,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -919,7 +933,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -937,7 +951,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -950,7 +964,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -1021,7 +1035,13 @@ public class ConfigNodeRPCServiceProcessorTest {
// clean user
TAuthorizerReq authorizerReq =
new TAuthorizerReq(
- AuthorOperator.AuthorType.LIST_USER.ordinal(), "", "", "", "", new
HashSet<>(), "");
+ AuthorOperator.AuthorType.LIST_USER.ordinal(),
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
TAuthorizerResp authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -1037,7 +1057,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
}
@@ -1046,7 +1066,13 @@ public class ConfigNodeRPCServiceProcessorTest {
// clean role
authorizerReq =
new TAuthorizerReq(
- AuthorOperator.AuthorType.LIST_ROLE.ordinal(), "", "", "", "", new
HashSet<>(), "");
+ AuthorOperator.AuthorType.LIST_ROLE.ordinal(),
+ "",
+ "",
+ "",
+ "",
+ new HashSet<>(),
+ new ArrayList<>());
authorizerResp = processor.queryPermission(authorizerReq);
status = authorizerResp.getStatus();
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
@@ -1061,7 +1087,7 @@ public class ConfigNodeRPCServiceProcessorTest {
"",
"",
new HashSet<>(),
- "");
+ new ArrayList<>());
status = processor.operatePermission(authorizerReq);
Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(),
status.getCode());
}
diff --git a/docs/UserGuide/Administration-Management/Administration.md
b/docs/UserGuide/Administration-Management/Administration.md
index 5bd3e36749..7eae10a4fe 100644
--- a/docs/UserGuide/Administration-Management/Administration.md
+++ b/docs/UserGuide/Administration-Management/Administration.md
@@ -100,7 +100,7 @@ We use `GRANT USER <userName> PRIVILEGES <privileges> ON
<nodeName>` to grant us
```
GRANT USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
-GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc.**
+GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc1.**,
root.sgcc2.**
GRANT USER `ln_write_user` PRIVILEGES CREATE_USER
```
The execution result is as follows:
@@ -108,7 +108,7 @@ The execution result is as follows:
```
IoTDB> GRANT USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
Msg: The statement is executed successfully.
-IoTDB> GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on
root.sgcc.**
+IoTDB> GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on
root.sgcc1.**, root.sgcc2.**
Msg: The statement is executed successfully.
IoTDB> GRANT USER `ln_write_user` PRIVILEGES CREATE_USER
Msg: The statement is executed successfully.
@@ -126,7 +126,7 @@ After granting user privileges, we could use `REVOKE USER
<userName> PRIVILEGES
```
REVOKE USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
-REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc.**
+REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc1.**,
root.sgcc2.**
REVOKE USER `ln_write_user` PRIVILEGES CREATE_USER
```
@@ -135,7 +135,7 @@ The execution result is as follows:
```
REVOKE USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
Msg: The statement is executed successfully.
-REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc.**
+REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc1.**,
root.sgcc2.**
Msg: The statement is executed successfully.
REVOKE USER `ln_write_user` PRIVILEGES CREATE_USER
Msg: The statement is executed successfully.
@@ -182,28 +182,28 @@ Eg: IoTDB > DROP ROLE `admin`;
* Grant User Privileges
```
-GRANT USER <userName> PRIVILEGES <privileges> ON <nodeName>;
-Eg: IoTDB > GRANT USER `tempuser` PRIVILEGES DELETE_TIMESERIES on root.ln.**;
+GRANT USER <userName> PRIVILEGES <privileges> ON <nodeNames>;
+Eg: IoTDB > GRANT USER `tempuser` PRIVILEGES INSERT_TIMESERIES,
DELETE_TIMESERIES on root.ln.**, root.sgcc.**;
```
- Grant User All Privileges
```
-GRANT USER <userName> PRIVILEGES ALL ON <nodeName>;
-Eg: IoTDB > grant user renyuhua privileges all on root.**
+GRANT USER <userName> PRIVILEGES ALL ON <nodeNames>;
+Eg: IoTDB > grant user renyuhua privileges all on root.sgcc.**, root.**;
```
* Grant Role Privileges
```
-GRANT ROLE <roleName> PRIVILEGES <privileges> ON <nodeName>;
-Eg: IoTDB > GRANT ROLE `temprole` PRIVILEGES DELETE_TIMESERIES ON root.ln.**;
+GRANT ROLE <roleName> PRIVILEGES <privileges> ON <nodeNames>;
+Eg: IoTDB > GRANT ROLE `temprole` PRIVILEGES INSERT_TIMESERIES,
DELETE_TIMESERIES ON root.sgcc.**, root.ln.**;
```
- Grant Role All Privileges
```
-GRANT ROLE <roleName> PRIVILEGES ALL ON <nodeName>;
+GRANT ROLE <roleName> PRIVILEGES ALL ON <nodeNames>;
Eg: IoTDB > GRANT ROLE `temprole` PRIVILEGES ALL ON root.ln.**;
```
@@ -217,28 +217,28 @@ Eg: IoTDB > GRANT `temprole` TO tempuser;
* Revoke User Privileges
```
-REVOKE USER <userName> PRIVILEGES <privileges> ON <nodeName>;
+REVOKE USER <userName> PRIVILEGES <privileges> ON <nodeNames>;
Eg: IoTDB > REVOKE USER `tempuser` PRIVILEGES DELETE_TIMESERIES on root.ln.**;
```
* Revoke User All Privileges
```
-REVOKE USER <userName> PRIVILEGES ALL ON <nodeName>;
+REVOKE USER <userName> PRIVILEGES ALL ON <nodeNames>;
Eg: IoTDB > REVOKE USER `tempuser` PRIVILEGES ALL on root.ln.**;
```
* Revoke Role Privileges
```
-REVOKE ROLE <roleName> PRIVILEGES <privileges> ON <nodeName>;
+REVOKE ROLE <roleName> PRIVILEGES <privileges> ON <nodeNames>;
Eg: IoTDB > REVOKE ROLE `temprole` PRIVILEGES DELETE_TIMESERIES ON root.ln.**;
```
* Revoke All Role Privileges
```
-REVOKE ROLE <roleName> PRIVILEGES ALL ON <nodeName>;
+REVOKE ROLE <roleName> PRIVILEGES ALL ON <nodeNames>;
Eg: IoTDB > REVOKE ROLE `temprole` PRIVILEGES ALL ON root.ln.**;
```
@@ -266,8 +266,8 @@ Eg: IoTDB > LIST ROLE
* List Related Privileges of Users(On Specific Path)
```
-LIST PRIVILEGES USER <username> ON <path>;
-Eg: IoTDB> LIST PRIVILEGES USER `tempuser` ON root.ln.**;
+LIST PRIVILEGES USER <username> ON <paths>;
+Eg: IoTDB> LIST PRIVILEGES USER `tempuser` ON root.ln.**, root.ln.wf01.**;
+--------+-----------------------------------+
| role| privilege|
+--------+-----------------------------------+
@@ -297,8 +297,8 @@ Eg: IoTDB > LIST ROLE PRIVILEGES `actor`;
* List Related Privileges of Roles(On Specific Path)
```
-LIST PRIVILEGES ROLE <roleName> ON <path>;
-Eg: IoTDB> LIST PRIVILEGES ROLE `temprole` ON root.ln.**;
+LIST PRIVILEGES ROLE <roleName> ON <paths>;
+Eg: IoTDB> LIST PRIVILEGES ROLE `temprole` ON root.ln.**, root.ln.wf01.wt01.**;
+-----------------------------------+
| privilege|
+-----------------------------------+
diff --git a/docs/zh/UserGuide/Administration-Management/Administration.md
b/docs/zh/UserGuide/Administration-Management/Administration.md
index 692971e393..92f9cc5be6 100644
--- a/docs/zh/UserGuide/Administration-Management/Administration.md
+++ b/docs/zh/UserGuide/Administration-Management/Administration.md
@@ -99,7 +99,7 @@ Msg: 602: No permissions for this operation INSERT
```
GRANT USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
-GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc.**
+GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc1.**,
root.sgcc2.**
GRANT USER `ln_write_user` PRIVILEGES CREATE_USER
```
执行状态如下所示:
@@ -107,7 +107,7 @@ GRANT USER `ln_write_user` PRIVILEGES CREATE_USER
```
IoTDB> GRANT USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
Msg: The statement is executed successfully.
-IoTDB> GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on
root.sgcc.**
+IoTDB> GRANT USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on
root.sgcc1.**, root.sgcc2.**
Msg: The statement is executed successfully.
IoTDB> GRANT USER `ln_write_user` PRIVILEGES CREATE_USER
Msg: The statement is executed successfully.
@@ -125,7 +125,7 @@ Msg: The statement is executed successfully.
```
REVOKE USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
-REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc.**
+REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc1.**,
root.sgcc2.**
REVOKE USER `ln_write_user` PRIVILEGES CREATE_USER
```
@@ -134,7 +134,7 @@ REVOKE USER `ln_write_user` PRIVILEGES CREATE_USER
```
REVOKE USER `ln_write_user` PRIVILEGES INSERT_TIMESERIES on root.ln.**
Msg: The statement is executed successfully.
-REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc.**
+REVOKE USER `sgcc_write_user` PRIVILEGES INSERT_TIMESERIES on root.sgcc1.**,
root.sgcc2.**
Msg: The statement is executed successfully.
REVOKE USER `ln_write_user` PRIVILEGES CREATE_USER
Msg: The statement is executed successfully.
@@ -181,28 +181,28 @@ Eg: IoTDB > DROP ROLE `admin`;
* 赋予用户权限
```
-GRANT USER <userName> PRIVILEGES <privileges> ON <nodeName>;
-Eg: IoTDB > GRANT USER `tempuser` PRIVILEGES DELETE_TIMESERIES on root.ln.**;
+GRANT USER <userName> PRIVILEGES <privileges> ON <nodeNames>;
+Eg: IoTDB > GRANT USER `tempuser` PRIVILEGES INSERT_TIMESERIES,
DELETE_TIMESERIES on root.ln.**, root.sgcc.**;
```
- 赋予用户全部的权限
```
-GRANT USER <userName> PRIVILEGES ALL ON <nodeName>;
-Eg: IoTDB > grant user renyuhua privileges all on root.**
+GRANT USER <userName> PRIVILEGES ALL ON <nodeNames>;
+Eg: IoTDB > grant user renyuhua privileges all on root.sgcc.**, root.**;
```
* 赋予角色权限
```
-GRANT ROLE <roleName> PRIVILEGES <privileges> ON <nodeName>;
-Eg: IoTDB > GRANT ROLE `temprole` PRIVILEGES DELETE_TIMESERIES ON root.ln.**;
+GRANT ROLE <roleName> PRIVILEGES <privileges> ON <nodeNames>;
+Eg: IoTDB > GRANT ROLE `temprole` PRIVILEGES INSERT_TIMESERIES,
DELETE_TIMESERIES ON root.sgcc.**, root.ln.**;
```
- 赋予角色全部的权限
```
-GRANT ROLE <roleName> PRIVILEGES ALL ON <nodeName>;
+GRANT ROLE <roleName> PRIVILEGES ALL ON <nodeNames>;
Eg: IoTDB > GRANT ROLE `temprole` PRIVILEGES ALL ON root.ln.**;
```
@@ -216,28 +216,28 @@ Eg: IoTDB > GRANT `temprole` TO tempuser;
* 撤销用户权限
```
-REVOKE USER <userName> PRIVILEGES <privileges> ON <nodeName>;
+REVOKE USER <userName> PRIVILEGES <privileges> ON <nodeNames>;
Eg: IoTDB > REVOKE USER `tempuser` PRIVILEGES DELETE_TIMESERIES on root.ln.**;
```
- 移除用户所有权限
```
-REVOKE USER <userName> PRIVILEGES ALL ON <nodeName>;
+REVOKE USER <userName> PRIVILEGES ALL ON <nodeNames>;
Eg: IoTDB > REVOKE USER `tempuser` PRIVILEGES ALL on root.ln.**;
```
* 撤销角色权限
```
-REVOKE ROLE <roleName> PRIVILEGES <privileges> ON <nodeName>;
+REVOKE ROLE <roleName> PRIVILEGES <privileges> ON <nodeNames>;
Eg: IoTDB > REVOKE ROLE `temprole` PRIVILEGES DELETE_TIMESERIES ON root.ln.**;
```
- 撤销角色全部的权限
```
-REVOKE ROLE <roleName> PRIVILEGES ALL ON <nodeName>;
+REVOKE ROLE <roleName> PRIVILEGES ALL ON <nodeNames>;
Eg: IoTDB > REVOKE ROLE `temprole` PRIVILEGES ALL ON root.ln.**;
```
@@ -265,8 +265,8 @@ Eg: IoTDB > LIST ROLE
* 列出用户在具体路径上相关联的权限
```
-LIST PRIVILEGES USER <username> ON <path>;
-Eg: IoTDB> LIST PRIVILEGES USER `tempuser` ON root.ln.**;
+LIST PRIVILEGES USER <username> ON <paths>;
+Eg: IoTDB> LIST PRIVILEGES USER `tempuser` ON root.ln.**, root.ln.wf01.**;
+--------+-----------------------------------+
| role| privilege|
+--------+-----------------------------------+
@@ -296,8 +296,8 @@ Eg: IoTDB > LIST ROLE PRIVILEGES `actor`;
* 列出角色在具体路径上相关联的权限
```
-LIST PRIVILEGES ROLE <roleName> ON <path>;
-Eg: IoTDB> LIST PRIVILEGES ROLE `temprole` ON root.ln.**;
+LIST PRIVILEGES ROLE <roleName> ON <paths>;
+Eg: IoTDB> LIST PRIVILEGES ROLE `temprole` ON root.ln.**, root.ln.wf01.wt01.**;
+-----------------------------------+
| privilege|
+-----------------------------------+
diff --git
a/node-commons/src/main/java/org/apache/iotdb/commons/utils/BasicStructureSerDeUtil.java
b/node-commons/src/main/java/org/apache/iotdb/commons/utils/BasicStructureSerDeUtil.java
index 6979e2eeea..49669553ab 100644
---
a/node-commons/src/main/java/org/apache/iotdb/commons/utils/BasicStructureSerDeUtil.java
+++
b/node-commons/src/main/java/org/apache/iotdb/commons/utils/BasicStructureSerDeUtil.java
@@ -45,6 +45,19 @@ public class BasicStructureSerDeUtil {
return new String(bytes, 0, strLength);
}
+ /** read string list from byteBuffer. */
+ public static List<String> readStringList(ByteBuffer buffer) {
+ int size = readInt(buffer);
+ if (size < 0) {
+ return null;
+ }
+ List<String> stringList = new ArrayList<>();
+ for (int i = 0; i < size; i++) {
+ stringList.add(readString(buffer));
+ }
+ return stringList;
+ }
+
/** read a int var from byteBuffer. */
public static int readInt(ByteBuffer buffer) {
return buffer.getInt();
@@ -84,6 +97,24 @@ public class BasicStructureSerDeUtil {
return len;
}
+ /**
+ * write string list to dataOutputStream.
+ *
+ * @return the length of string represented by byte[].
+ */
+ public static int write(List<String> stringList, DataOutputStream stream)
throws IOException {
+ if (stringList == null) {
+ throw new IllegalArgumentException("stringList must not be null!");
+ }
+ int res = 0;
+ int size = stringList.size();
+ res += write(size, stream);
+ for (String s : stringList) {
+ res += write(s, stream);
+ }
+ return res;
+ }
+
/**
* write a int n to byteBuffer.
*
diff --git
a/server/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
b/server/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
index 750b5f9236..9a1bc33de0 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
@@ -26,6 +26,7 @@ import org.apache.iotdb.commons.auth.entity.Role;
import org.apache.iotdb.commons.auth.entity.User;
import org.apache.iotdb.commons.client.IClientManager;
import org.apache.iotdb.commons.consensus.PartitionRegionId;
+import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.commons.utils.AuthUtils;
import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerReq;
import org.apache.iotdb.confignode.rpc.thrift.TAuthorizerResp;
@@ -49,10 +50,12 @@ import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
+import java.util.stream.Collectors;
public class ClusterAuthorityFetcher implements IAuthorityFetcher {
private static final Logger logger =
LoggerFactory.getLogger(ClusterAuthorityFetcher.class);
@@ -300,6 +303,10 @@ public class ClusterAuthorityFetcher implements
IAuthorityFetcher {
authorStatement.getPassWord() == null ? "" :
authorStatement.getPassWord(),
authorStatement.getNewPassword() == null ? "" :
authorStatement.getNewPassword(),
AuthUtils.strToPermissions(authorStatement.getPrivilegeList()),
- authorStatement.getNodeName() == null ? "" :
authorStatement.getNodeName().getFullPath());
+ authorStatement.getNodeNameList() == null
+ ? Collections.emptyList()
+ : authorStatement.getNodeNameList().stream()
+ .map(PartialPath::getFullPath)
+ .collect(Collectors.toList()));
}
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java
index a13035438e..7fca93226b 100644
---
a/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java
+++
b/server/src/main/java/org/apache/iotdb/db/localconfignode/LocalConfigNode.java
@@ -104,6 +104,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import static
org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
@@ -1059,8 +1060,10 @@ public class LocalConfigNode {
String password = authorStatement.getPassWord();
String newPassword = authorStatement.getNewPassword();
Set<Integer> permissions =
AuthUtils.strToPermissions(authorStatement.getPrivilegeList());
- PartialPath partialPath = authorStatement.getNodeName();
- String nodeName = partialPath == null ? null : partialPath.getFullPath();
+ List<String> nodeNameList =
+ authorStatement.getNodeNameList().stream()
+ .map(PartialPath::getFullPath)
+ .collect(Collectors.toList());
switch (authorType) {
case UPDATE_USER:
iAuthorizer.updateUserPassword(userName, newPassword);
@@ -1079,12 +1082,16 @@ public class LocalConfigNode {
break;
case GRANT_ROLE:
for (int i : permissions) {
- iAuthorizer.grantPrivilegeToRole(roleName, nodeName, i);
+ for (String path : nodeNameList) {
+ iAuthorizer.grantPrivilegeToRole(roleName, path, i);
+ }
}
break;
case GRANT_USER:
for (int i : permissions) {
- iAuthorizer.grantPrivilegeToUser(userName, nodeName, i);
+ for (String path : nodeNameList) {
+ iAuthorizer.grantPrivilegeToUser(userName, path, i);
+ }
}
break;
case GRANT_ROLE_TO_USER:
@@ -1092,12 +1099,16 @@ public class LocalConfigNode {
break;
case REVOKE_USER:
for (int i : permissions) {
- iAuthorizer.revokePrivilegeFromUser(userName, nodeName, i);
+ for (String path : nodeNameList) {
+ iAuthorizer.revokePrivilegeFromUser(userName, path, i);
+ }
}
break;
case REVOKE_ROLE:
for (int i : permissions) {
- iAuthorizer.revokePrivilegeFromRole(roleName, nodeName, i);
+ for (String path : nodeNameList) {
+ iAuthorizer.revokePrivilegeFromRole(roleName, path, i);
+ }
}
break;
case REVOKE_ROLE_FROM_USER:
@@ -1201,16 +1212,20 @@ public class LocalConfigNode {
} catch (AuthException e) {
throw new AuthException(e);
}
- List<String> rolePrivilegesList = new ArrayList<>();
+ Set<String> rolePrivilegeSet = new HashSet<>();
for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (authorStatement.getNodeName().getFullPath().equals("")
- || AuthUtils.pathOrBelongsTo(
- authorStatement.getNodeName().getFullPath(),
pathPrivilege.getPath())) {
- rolePrivilegesList.add(pathPrivilege.toString());
+ if (authorStatement.getNodeNameList().isEmpty()) {
+ rolePrivilegeSet.add(pathPrivilege.toString());
+ continue;
+ }
+ for (PartialPath path : authorStatement.getNodeNameList()) {
+ if (AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())) {
+ rolePrivilegeSet.add(pathPrivilege.toString());
+ }
}
}
- permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, rolePrivilegesList);
+ permissionInfo.put(IoTDBConstant.COLUMN_PRIVILEGE, new
ArrayList<>(rolePrivilegeSet));
return permissionInfo;
}
@@ -1234,27 +1249,45 @@ public class LocalConfigNode {
}
} else {
List<String> rolePrivileges = new ArrayList<>();
+ Set<String> userPrivilegeSet = new HashSet<>();
for (PathPrivilege pathPrivilege : user.getPrivilegeList()) {
- if (authorStatement.getNodeName().getFullPath().equals("")
- || AuthUtils.pathOrBelongsTo(
- authorStatement.getNodeName().getFullPath(),
pathPrivilege.getPath())) {
+ if (authorStatement.getNodeNameList().isEmpty()
+ && !userPrivilegeSet.contains(pathPrivilege.toString())) {
rolePrivileges.add("");
- userPrivilegesList.add(pathPrivilege.toString());
+ userPrivilegeSet.add(pathPrivilege.toString());
+ continue;
+ }
+ for (PartialPath path : authorStatement.getNodeNameList()) {
+ if (AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())
+ && !userPrivilegeSet.contains(pathPrivilege.toString())) {
+ rolePrivileges.add("");
+ userPrivilegeSet.add(pathPrivilege.toString());
+ }
}
}
+ userPrivilegesList.addAll(userPrivilegeSet);
for (String roleN : user.getRoleList()) {
Role role = iAuthorizer.getRole(roleN);
if (roleN == null) {
continue;
}
+ Set<String> rolePrivilegeSet = new HashSet<>();
for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (authorStatement.getNodeName().getFullPath().equals("")
- || AuthUtils.pathOrBelongsTo(
- authorStatement.getNodeName().getFullPath(),
pathPrivilege.getPath())) {
+ if (authorStatement.getNodeNameList().isEmpty()
+ && !rolePrivilegeSet.contains(pathPrivilege.toString())) {
rolePrivileges.add(roleN);
- userPrivilegesList.add(pathPrivilege.toString());
+ rolePrivilegeSet.add(pathPrivilege.toString());
+ continue;
+ }
+ for (PartialPath path : authorStatement.getNodeNameList()) {
+ if (AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())
+ && !rolePrivilegeSet.contains(pathPrivilege.toString())) {
+ rolePrivileges.add(roleN);
+ rolePrivilegeSet.add(pathPrivilege.toString());
+ }
}
}
+ userPrivilegesList.addAll(rolePrivilegeSet);
}
permissionInfo.put(IoTDBConstant.COLUMN_ROLE, rolePrivileges);
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
index e8a550df78..2f01be859a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
@@ -149,6 +149,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.time.ZoneId;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
@@ -156,6 +157,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/** Parse AST to Statement. */
public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
@@ -1600,17 +1602,20 @@ public class ASTVisitor extends
IoTDBSqlParserBaseVisitor<Statement> {
authorStatement.setPrivilegeList(parsePrivilege(ctx.privileges()));
String privilege = parsePrivilege(ctx.privileges())[0];
- PartialPath prefixPath;
+ List<PartialPath> nodeNameList;
if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
String[] path = {"root"};
- prefixPath = new PartialPath(path);
+ nodeNameList = Collections.singletonList(new PartialPath(path));
} else {
if (ctx.prefixPath() == null) {
throw new SQLParserException("Invalid prefix path");
}
- prefixPath = parsePrefixPath(ctx.prefixPath());
+ nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
}
- authorStatement.setNodeNameList(prefixPath);
+ authorStatement.setNodeNameList(nodeNameList);
return authorStatement;
}
@@ -1621,7 +1626,11 @@ public class ASTVisitor extends
IoTDBSqlParserBaseVisitor<Statement> {
AuthorStatement authorStatement = new
AuthorStatement(AuthorOperator.AuthorType.GRANT_ROLE);
authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
authorStatement.setPrivilegeList(parsePrivilege(ctx.privileges()));
- authorStatement.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ authorStatement.setNodeNameList(nodeNameList);
return authorStatement;
}
@@ -1645,17 +1654,20 @@ public class ASTVisitor extends
IoTDBSqlParserBaseVisitor<Statement> {
authorStatement.setPrivilegeList(parsePrivilege(ctx.privileges()));
String privilege = parsePrivilege(ctx.privileges())[0];
- PartialPath prefixPath;
+ List<PartialPath> nodeNameList;
if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
String[] path = {"root"};
- prefixPath = new PartialPath(path);
+ nodeNameList = Collections.singletonList(new PartialPath(path));
} else {
if (ctx.prefixPath() == null) {
throw new SQLParserException("Invalid prefix path");
}
- prefixPath = parsePrefixPath(ctx.prefixPath());
+ nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
}
- authorStatement.setNodeNameList(prefixPath);
+ authorStatement.setNodeNameList(nodeNameList);
return authorStatement;
}
@@ -1666,7 +1678,11 @@ public class ASTVisitor extends
IoTDBSqlParserBaseVisitor<Statement> {
AuthorStatement authorStatement = new
AuthorStatement(AuthorOperator.AuthorType.REVOKE_ROLE);
authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
authorStatement.setPrivilegeList(parsePrivilege(ctx.privileges()));
- authorStatement.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ authorStatement.setNodeNameList(nodeNameList);
return authorStatement;
}
@@ -1720,7 +1736,11 @@ public class ASTVisitor extends
IoTDBSqlParserBaseVisitor<Statement> {
AuthorStatement authorStatement =
new AuthorStatement(AuthorOperator.AuthorType.LIST_USER_PRIVILEGE);
authorStatement.setUserName(parseIdentifier(ctx.userName.getText()));
- authorStatement.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ authorStatement.setNodeNameList(nodeNameList);
return authorStatement;
}
@@ -1731,7 +1751,11 @@ public class ASTVisitor extends
IoTDBSqlParserBaseVisitor<Statement> {
AuthorStatement authorStatement =
new AuthorStatement(AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE);
authorStatement.setRoleName(parseIdentifier(ctx.roleName.getText()));
- authorStatement.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ authorStatement.setNodeNameList(nodeNameList);
return authorStatement;
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/sys/AuthorStatement.java
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/sys/AuthorStatement.java
index 6b136def0b..8ea486b1ec 100644
---
a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/sys/AuthorStatement.java
+++
b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/sys/AuthorStatement.java
@@ -37,7 +37,7 @@ public class AuthorStatement extends Statement implements
IConfigStatement {
private String password;
private String newPassword;
private String[] privilegeList;
- private PartialPath nodeName;
+ private List<PartialPath> nodeNameList;
/**
* AuthorOperator Constructor with AuthorType.
@@ -158,12 +158,12 @@ public class AuthorStatement extends Statement implements
IConfigStatement {
this.privilegeList = privilegeList;
}
- public PartialPath getNodeName() {
- return nodeName;
+ public List<PartialPath> getNodeNameList() {
+ return nodeNameList != null ? nodeNameList : Collections.emptyList();
}
- public void setNodeNameList(PartialPath nodePath) {
- this.nodeName = nodePath;
+ public void setNodeNameList(List<PartialPath> nodeNameList) {
+ this.nodeNameList = nodeNameList;
}
@Override
@@ -204,6 +204,6 @@ public class AuthorStatement extends Statement implements
IConfigStatement {
@Override
public List<PartialPath> getPaths() {
- return nodeName != null ? Collections.singletonList(nodeName) :
Collections.emptyList();
+ return nodeNameList != null ? nodeNameList : Collections.emptyList();
}
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
index 95f6381c6c..2d3711b20f 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
@@ -1986,7 +1986,7 @@ public class PlanExecutor implements IPlanExecutor {
String password = author.getPassword();
String newPassword = author.getNewPassword();
Set<Integer> permissions = author.getPermissions();
- PartialPath nodeName = author.getNodeName();
+ List<PartialPath> nodeNameList = author.getNodeNameList();
try {
switch (authorType) {
case UPDATE_USER:
@@ -2006,12 +2006,16 @@ public class PlanExecutor implements IPlanExecutor {
break;
case GRANT_ROLE:
for (int i : permissions) {
- authorizerManager.grantPrivilegeToRole(roleName,
nodeName.getFullPath(), i);
+ for (PartialPath path : nodeNameList) {
+ authorizerManager.grantPrivilegeToRole(roleName,
path.getFullPath(), i);
+ }
}
break;
case GRANT_USER:
for (int i : permissions) {
- authorizerManager.grantPrivilegeToUser(userName,
nodeName.getFullPath(), i);
+ for (PartialPath path : nodeNameList) {
+ authorizerManager.grantPrivilegeToUser(userName,
path.getFullPath(), i);
+ }
}
break;
case GRANT_ROLE_TO_USER:
@@ -2019,12 +2023,16 @@ public class PlanExecutor implements IPlanExecutor {
break;
case REVOKE_USER:
for (int i : permissions) {
- authorizerManager.revokePrivilegeFromUser(userName,
nodeName.getFullPath(), i);
+ for (PartialPath path : nodeNameList) {
+ authorizerManager.revokePrivilegeFromUser(userName,
path.getFullPath(), i);
+ }
}
break;
case REVOKE_ROLE:
for (int i : permissions) {
- authorizerManager.revokePrivilegeFromRole(roleName,
nodeName.getFullPath(), i);
+ for (PartialPath path : nodeNameList) {
+ authorizerManager.revokePrivilegeFromRole(roleName,
path.getFullPath(), i);
+ }
}
break;
case REVOKE_ROLE_FROM_USER:
@@ -2224,7 +2232,7 @@ public class PlanExecutor implements IPlanExecutor {
AuthorType authorType = plan.getAuthorType();
String userName = plan.getUserName();
String roleName = plan.getRoleName();
- PartialPath path = plan.getNodeName();
+ List<PartialPath> nodeNameList = plan.getNodeNameList();
ListDataSet dataSet;
@@ -2243,10 +2251,10 @@ public class PlanExecutor implements IPlanExecutor {
dataSet = executeListUserRoles(userName);
break;
case LIST_ROLE_PRIVILEGE:
- dataSet = executeListRolePrivileges(roleName, path);
+ dataSet = executeListRolePrivileges(roleName, nodeNameList);
break;
case LIST_USER_PRIVILEGE:
- dataSet = executeListUserPrivileges(userName, path);
+ dataSet = executeListUserPrivileges(userName, nodeNameList);
break;
default:
throw new QueryProcessException("Unsupported operation " +
authorType);
@@ -2300,7 +2308,7 @@ public class PlanExecutor implements IPlanExecutor {
boolean hasListUserPrivilege =
AuthorityChecker.check(
plan.getLoginUserName(),
- Collections.singletonList((plan.getNodeName())),
+ plan.getNodeNameList(),
plan.getOperatorType(),
plan.getLoginUserName());
if (!hasListUserPrivilege) {
@@ -2357,7 +2365,7 @@ public class PlanExecutor implements IPlanExecutor {
}
}
- private ListDataSet executeListRolePrivileges(String roleName, PartialPath
path)
+ private ListDataSet executeListRolePrivileges(String roleName,
List<PartialPath> nodeNameList)
throws AuthException {
Role role = authorizerManager.getRole(roleName);
if (role != null) {
@@ -2368,13 +2376,22 @@ public class PlanExecutor implements IPlanExecutor {
ListDataSet dataSet = new ListDataSet(headerList, typeList);
int index = 0;
for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (path == null
- || AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())) {
+ if (nodeNameList.isEmpty()) {
RowRecord record = new RowRecord(index++);
Field field = new Field(TSDataType.TEXT);
field.setBinaryV(new Binary(pathPrivilege.toString()));
record.addField(field);
dataSet.putRecord(record);
+ continue;
+ }
+ for (PartialPath path : nodeNameList) {
+ if (AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())) {
+ RowRecord record = new RowRecord(index++);
+ Field field = new Field(TSDataType.TEXT);
+ field.setBinaryV(new Binary(pathPrivilege.toString()));
+ record.addField(field);
+ dataSet.putRecord(record);
+ }
}
}
return dataSet;
@@ -2383,7 +2400,7 @@ public class PlanExecutor implements IPlanExecutor {
}
}
- private ListDataSet executeListUserPrivileges(String userName, PartialPath
path)
+ private ListDataSet executeListUserPrivileges(String userName,
List<PartialPath> nodeNameList)
throws AuthException {
User user = authorizerManager.getUser(userName);
if (user == null) {
@@ -2411,8 +2428,7 @@ public class PlanExecutor implements IPlanExecutor {
typeList.add(TSDataType.TEXT);
ListDataSet dataSet = new ListDataSet(headerList, typeList);
for (PathPrivilege pathPrivilege : user.getPrivilegeList()) {
- if (path == null
- || AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())) {
+ if (nodeNameList.isEmpty()) {
RowRecord record = new RowRecord(index++);
Field roleF = new Field(TSDataType.TEXT);
roleF.setBinaryV(new Binary(""));
@@ -2421,6 +2437,19 @@ public class PlanExecutor implements IPlanExecutor {
privilegeF.setBinaryV(new Binary(pathPrivilege.toString()));
record.addField(privilegeF);
dataSet.putRecord(record);
+ continue;
+ }
+ for (PartialPath path : nodeNameList) {
+ if (AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())) {
+ RowRecord record = new RowRecord(index++);
+ Field roleF = new Field(TSDataType.TEXT);
+ roleF.setBinaryV(new Binary(""));
+ record.addField(roleF);
+ Field privilegeF = new Field(TSDataType.TEXT);
+ privilegeF.setBinaryV(new Binary(pathPrivilege.toString()));
+ record.addField(privilegeF);
+ dataSet.putRecord(record);
+ }
}
}
for (String roleN : user.getRoleList()) {
@@ -2429,8 +2458,7 @@ public class PlanExecutor implements IPlanExecutor {
continue;
}
for (PathPrivilege pathPrivilege : role.getPrivilegeList()) {
- if (path == null
- || AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())) {
+ if (nodeNameList.isEmpty()) {
RowRecord record = new RowRecord(index++);
Field roleF = new Field(TSDataType.TEXT);
roleF.setBinaryV(new Binary(roleN));
@@ -2440,6 +2468,18 @@ public class PlanExecutor implements IPlanExecutor {
record.addField(privilegeF);
dataSet.putRecord(record);
}
+ for (PartialPath path : nodeNameList) {
+ if (AuthUtils.pathOrBelongsTo(path.getFullPath(),
pathPrivilege.getPath())) {
+ RowRecord record = new RowRecord(index++);
+ Field roleF = new Field(TSDataType.TEXT);
+ roleF.setBinaryV(new Binary(roleN));
+ record.addField(roleF);
+ Field privilegeF = new Field(TSDataType.TEXT);
+ privilegeF.setBinaryV(new Binary(pathPrivilege.toString()));
+ record.addField(privilegeF);
+ dataSet.putRecord(record);
+ }
+ }
}
}
return dataSet;
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/AuthorOperator.java
b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/AuthorOperator.java
index 263c1e942e..4378872f5f 100644
---
a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/AuthorOperator.java
+++
b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/AuthorOperator.java
@@ -26,6 +26,8 @@ import org.apache.iotdb.db.qp.physical.PhysicalPlan;
import org.apache.iotdb.db.qp.physical.sys.AuthorPlan;
import org.apache.iotdb.db.qp.strategy.PhysicalGenerator;
+import java.util.List;
+
/**
* this class maintains information in Author statement, including CREATE,
DROP, GRANT and REVOKE.
*/
@@ -37,7 +39,7 @@ public class AuthorOperator extends Operator {
private String password;
private String newPassword;
private String[] privilegeList;
- private PartialPath nodeName;
+ private List<PartialPath> nodeNameList;
/**
* AuthorOperator Constructor with AuthorType.
@@ -107,12 +109,12 @@ public class AuthorOperator extends Operator {
this.privilegeList = authorizationList;
}
- public PartialPath getNodeName() {
- return nodeName;
+ public List<PartialPath> getNodeNameList() {
+ return nodeNameList;
}
- public void setNodeNameList(PartialPath nodePath) {
- this.nodeName = nodePath;
+ public void setNodeNameList(List<PartialPath> nodePath) {
+ this.nodeNameList = nodePath;
}
@Override
@@ -120,7 +122,7 @@ public class AuthorOperator extends Operator {
throws QueryProcessException {
try {
return new AuthorPlan(
- authorType, userName, roleName, password, newPassword,
privilegeList, nodeName);
+ authorType, userName, roleName, password, newPassword,
privilegeList, nodeNameList);
} catch (AuthException e) {
throw new QueryProcessException(e.getMessage());
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
index cb39680963..06c1a6d9ec 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/AuthorPlan.java
@@ -27,6 +27,7 @@ import org.apache.iotdb.db.qp.logical.Operator.OperatorType;
import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
import org.apache.iotdb.db.qp.logical.sys.AuthorOperator.AuthorType;
import org.apache.iotdb.db.qp.physical.PhysicalPlan;
+import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -36,6 +37,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.stream.Collectors;
public class AuthorPlan extends PhysicalPlan {
@@ -44,7 +46,7 @@ public class AuthorPlan extends PhysicalPlan {
private String password;
private String newPassword;
private Set<Integer> permissions;
- private PartialPath nodeName;
+ private List<PartialPath> nodeNameList;
private String userName;
/**
@@ -56,7 +58,7 @@ public class AuthorPlan extends PhysicalPlan {
* @param password password
* @param newPassword new password
* @param authorizationList authorization list in String[] structure
- * @param nodeName node name in Path structure
+ * @param nodeNameList node name in Path structure
* @throws AuthException Authentication Exception
*/
public AuthorPlan(
@@ -66,7 +68,7 @@ public class AuthorPlan extends PhysicalPlan {
String password,
String newPassword,
String[] authorizationList,
- PartialPath nodeName)
+ List<PartialPath> nodeNameList)
throws AuthException {
super(Operator.OperatorType.AUTHOR);
this.authorType = authorType;
@@ -75,7 +77,7 @@ public class AuthorPlan extends PhysicalPlan {
this.password = password;
this.newPassword = newPassword;
this.permissions = AuthUtils.strToPermissions(authorizationList);
- this.nodeName = nodeName;
+ this.nodeNameList = nodeNameList;
switch (authorType) {
case DROP_ROLE:
this.setOperatorType(Operator.OperatorType.DELETE_ROLE);
@@ -214,8 +216,8 @@ public class AuthorPlan extends PhysicalPlan {
this.permissions = permissions;
}
- public PartialPath getNodeName() {
- return nodeName;
+ public List<PartialPath> getNodeNameList() {
+ return nodeNameList != null ? nodeNameList : Collections.emptyList();
}
public String getUserName() {
@@ -235,14 +237,14 @@ public class AuthorPlan extends PhysicalPlan {
+ "\npermissions: "
+ permissions
+ "\nnodeName: "
- + nodeName
+ + nodeNameList
+ "\nauthorType: "
+ authorType;
}
@Override
public List<PartialPath> getPaths() {
- return nodeName != null ? Collections.singletonList(nodeName) :
Collections.emptyList();
+ return nodeNameList != null ? nodeNameList : Collections.emptyList();
}
@Override
@@ -260,7 +262,7 @@ public class AuthorPlan extends PhysicalPlan {
&& Objects.equals(getPassword(), that.getPassword())
&& Objects.equals(getNewPassword(), that.getNewPassword())
&& Objects.equals(getPermissions(), that.getPermissions())
- && Objects.equals(getNodeName(), that.getNodeName());
+ && Objects.equals(getNodeNameList(), that.getNodeNameList());
}
@Override
@@ -272,7 +274,7 @@ public class AuthorPlan extends PhysicalPlan {
getPassword(),
getNewPassword(),
getPermissions(),
- getNodeName());
+ getNodeNameList());
}
@Override
@@ -293,10 +295,11 @@ public class AuthorPlan extends PhysicalPlan {
stream.writeInt(permission);
}
}
- if (nodeName == null) {
- putString(stream, null);
+ if (nodeNameList == null) {
+ ReadWriteIOUtils.writeStringList(Collections.emptyList(), stream);
} else {
- putString(stream, nodeName.getFullPath());
+ ReadWriteIOUtils.writeStringList(
+
nodeNameList.stream().map(PartialPath::getFullPath).collect(Collectors.toList()),
stream);
}
stream.writeLong(index);
@@ -320,10 +323,11 @@ public class AuthorPlan extends PhysicalPlan {
buffer.putInt(permission);
}
}
- if (nodeName == null) {
- putString(buffer, null);
+ if (nodeNameList == null) {
+ ReadWriteIOUtils.writeStringList(Collections.emptyList(), buffer);
} else {
- putString(buffer, nodeName.getFullPath());
+ ReadWriteIOUtils.writeStringList(
+
nodeNameList.stream().map(PartialPath::getFullPath).collect(Collectors.toList()),
buffer);
}
buffer.putLong(index);
@@ -346,11 +350,21 @@ public class AuthorPlan extends PhysicalPlan {
permissions.add(buffer.getInt());
}
}
- String nodeNameStr = readString(buffer);
- if (nodeNameStr == null) {
- this.nodeName = null;
+ List<String> nodeNameList = ReadWriteIOUtils.readStringList(buffer);
+ if (nodeNameList.size() == 0) {
+ this.nodeNameList = null;
} else {
- this.nodeName = new PartialPath(nodeNameStr);
+ this.nodeNameList =
+ nodeNameList.stream()
+ .map(
+ path -> {
+ try {
+ return new PartialPath(path);
+ } catch (IllegalPathException e) {
+ throw new IllegalArgumentException("Deserialize node
paths failed.");
+ }
+ })
+ .collect(Collectors.toList());
}
this.index = buffer.getLong();
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
index 0164e3decf..b0a7aad469 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java
@@ -175,6 +175,7 @@ import java.io.File;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
@@ -184,6 +185,7 @@ import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import static org.apache.iotdb.db.qp.constant.SQLConstant.TIME_PATH;
import static org.apache.iotdb.db.qp.constant.SQLConstant.TOK_KILL_QUERY;
@@ -1974,15 +1976,16 @@ public class IoTDBSqlVisitor extends
IoTDBSqlParserBaseVisitor<Operator> {
authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
String privilege = parsePrivilege(ctx.privileges())[0];
- PartialPath prefixPath;
+ List<PartialPath> prefixPath;
if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
String[] path = {"root"};
- prefixPath = new PartialPath(path);
+ prefixPath = Collections.singletonList(new PartialPath(path));
} else {
if (ctx.prefixPath() == null) {
throw new SQLParserException("Invalid prefix path");
}
- prefixPath = parsePrefixPath(ctx.prefixPath());
+ prefixPath =
+ ctx.prefixPath().stream().map(path ->
parsePrefixPath(path)).collect(Collectors.toList());
}
authorOperator.setNodeNameList(prefixPath);
return authorOperator;
@@ -1996,7 +1999,11 @@ public class IoTDBSqlVisitor extends
IoTDBSqlParserBaseVisitor<Operator> {
new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
AuthorType.GRANT_ROLE);
authorOperator.setRoleName(parseIdentifier(ctx.roleName.getText()));
authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
- authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ authorOperator.setNodeNameList(nodeNameList);
return authorOperator;
}
@@ -2022,17 +2029,20 @@ public class IoTDBSqlVisitor extends
IoTDBSqlParserBaseVisitor<Operator> {
authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
String privilege = parsePrivilege(ctx.privileges())[0];
- PartialPath prefixPath;
+ List<PartialPath> nodeNameList;
if (!PrivilegeType.valueOf(privilege.toUpperCase()).isPathRelevant()) {
String[] path = {"root"};
- prefixPath = new PartialPath(path);
+ nodeNameList = Collections.singletonList(new PartialPath(path));
} else {
if (ctx.prefixPath() == null) {
throw new SQLParserException("Invalid prefix path");
}
- prefixPath = parsePrefixPath(ctx.prefixPath());
+ nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
}
- authorOperator.setNodeNameList(prefixPath);
+ authorOperator.setNodeNameList(nodeNameList);
return authorOperator;
}
@@ -2044,7 +2054,11 @@ public class IoTDBSqlVisitor extends
IoTDBSqlParserBaseVisitor<Operator> {
new AuthorOperator(SQLConstant.TOK_AUTHOR_GRANT,
AuthorType.REVOKE_ROLE);
authorOperator.setRoleName(parseIdentifier(ctx.roleName.getText()));
authorOperator.setPrivilegeList(parsePrivilege(ctx.privileges()));
- authorOperator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ authorOperator.setNodeNameList(nodeNameList);
return authorOperator;
}
@@ -2100,7 +2114,11 @@ public class IoTDBSqlVisitor extends
IoTDBSqlParserBaseVisitor<Operator> {
AuthorOperator operator =
new AuthorOperator(SQLConstant.TOK_LIST,
AuthorOperator.AuthorType.LIST_USER_PRIVILEGE);
operator.setUserName(parseIdentifier(ctx.userName.getText()));
- operator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ operator.setNodeNameList(nodeNameList);
return operator;
}
@@ -2111,7 +2129,11 @@ public class IoTDBSqlVisitor extends
IoTDBSqlParserBaseVisitor<Operator> {
AuthorOperator operator =
new AuthorOperator(SQLConstant.TOK_LIST,
AuthorOperator.AuthorType.LIST_ROLE_PRIVILEGE);
operator.setRoleName(parseIdentifier(ctx.roleName.getText()));
- operator.setNodeNameList(parsePrefixPath(ctx.prefixPath()));
+ List<PartialPath> nodeNameList =
+ ctx.prefixPath().stream()
+ .map(prefixPath -> parsePrefixPath(prefixPath))
+ .collect(Collectors.toList());
+ operator.setNodeNameList(nodeNameList);
return operator;
}
diff --git
a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
index bc25d7b75b..9fce97b490 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/physical/PhysicalPlanTest.java
@@ -199,7 +199,7 @@ public class PhysicalPlanTest {
+ "password: null\n"
+ "newPassword: null\n"
+ "permissions: [0, 5]\n"
- + "nodeName: root.vehicle.d1.s1\n"
+ + "nodeName: [root.vehicle.d1.s1]\n"
+ "authorType: GRANT_ROLE",
plan.toString());
}
diff --git a/thrift-confignode/src/main/thrift/confignode.thrift
b/thrift-confignode/src/main/thrift/confignode.thrift
index bb842ac90e..c8fb44fd2e 100644
--- a/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/thrift-confignode/src/main/thrift/confignode.thrift
@@ -174,7 +174,7 @@ struct TAuthorizerReq {
4: required string password
5: required string newPassword
6: required set<i32> permissions
- 7: required string nodeName
+ 7: required list<string> nodeNameList
}
struct TAuthorizerResp {