This is an automated email from the ASF dual-hosted git repository.
jt2594838 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 543e03e9fa2 Fix account unlock propagation for pipe password checks
(#17814)
543e03e9fa2 is described below
commit 543e03e9fa23264d9e899e9a75ac8f665d1c82ad
Author: Caideyipi <[email protected]>
AuthorDate: Thu Jun 4 18:23:07 2026 +0800
Fix account unlock propagation for pipe password checks (#17814)
* Fix account unlock propagation for pipe password checks
* Fix account unlock user validation
---
.../treemodel/manual/IoTDBPipePermissionIT.java | 1 +
.../consensus/request/ConfigPhysicalPlan.java | 2 +
.../consensus/request/ConfigPhysicalPlanType.java | 1 +
.../request/ConfigPhysicalPlanVisitor.java | 12 ++++
.../confignode/persistence/auth/AuthorInfo.java | 6 +-
.../persistence/auth/AuthorPlanExecutor.java | 12 ++++
.../persistence/executor/ConfigPlanExecutor.java | 1 +
.../impl/sync/AuthOperationProcedure.java | 6 ++
.../persistence/auth/AuthorPlanExecutorTest.java | 80 ++++++++++++++++++++++
.../impl/sync/AuthOperationProcedureTest.java | 56 +++++++++++++++
.../iotdb/db/auth/ClusterAuthorityFetcher.java | 35 +++-------
.../impl/DataNodeInternalRPCServiceImpl.java | 14 ++++
12 files changed, 201 insertions(+), 25 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/manual/IoTDBPipePermissionIT.java
b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/manual/IoTDBPipePermissionIT.java
index d43bb6564b1..23d0b48d440 100644
---
a/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/manual/IoTDBPipePermissionIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/pipe/it/dual/treemodel/manual/IoTDBPipePermissionIT.java
@@ -595,6 +595,7 @@ public class IoTDBPipePermissionIT extends
AbstractPipeDualTreeModelManualIT {
try {
statement.execute("alter pipe a2b modify source ('password'='fake')");
+ fail();
} catch (final SQLException e) {
Assert.assertEquals("801: Failed to check password for pipe a2b.",
e.getMessage());
}
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
index 1ad547f7845..72e1fb36735 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlan.java
@@ -311,6 +311,7 @@ public abstract class ConfigPhysicalPlan implements
IConsensusRequest {
case UpdateUserV2:
case CreateUserWithRawPassword:
case RenameUser:
+ case AccountUnlock:
plan = new AuthorTreePlan(configPhysicalPlanType);
break;
case RCreateUser:
@@ -343,6 +344,7 @@ public abstract class ConfigPhysicalPlan implements
IConsensusRequest {
case RRevokeUserSysPri:
case RRevokeRoleSysPri:
case RRenameUser:
+ case RAccountUnlock:
plan = new AuthorRelationalPlan(configPhysicalPlanType);
break;
case ApplyConfigNode:
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
index 83bb96bee16..d81028611b0 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanType.java
@@ -333,6 +333,7 @@ public enum ConfigPhysicalPlanType {
RDropUserV2((short) 2103),
RenameUser((short) 2104),
RRenameUser((short) 2105),
+ AccountUnlock((short) 2106),
EnableSeparationOfAdminPowers((short) 2200),
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java
index 8363f023bc4..53e3c4cd37d 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanVisitor.java
@@ -104,6 +104,8 @@ public abstract class ConfigPhysicalPlanVisitor<R, C> {
return visitGrantRoleToUser((AuthorTreePlan) plan, context);
case RevokeRoleFromUser:
return visitRevokeRoleFromUser((AuthorTreePlan) plan, context);
+ case AccountUnlock:
+ return visitAccountUnlock((AuthorTreePlan) plan, context);
case RCreateUser:
return visitRCreateUser((AuthorRelationalPlan) plan, context);
case RCreateRole:
@@ -160,6 +162,8 @@ public abstract class ConfigPhysicalPlanVisitor<R, C> {
return visitRRevokeUserSysPrivilege((AuthorRelationalPlan) plan,
context);
case RRevokeRoleSysPri:
return visitRRevokeRoleSysPrivilege((AuthorRelationalPlan) plan,
context);
+ case RAccountUnlock:
+ return visitRAccountUnlock((AuthorRelationalPlan) plan, context);
case SetTTL:
return visitTTL((SetTTLPlan) plan, context);
case PipeCreateTableOrView:
@@ -310,6 +314,10 @@ public abstract class ConfigPhysicalPlanVisitor<R, C> {
return visitPlan(revokeRoleFromUserPlan, context);
}
+ public R visitAccountUnlock(final AuthorTreePlan accountUnlockPlan, final C
context) {
+ return visitPlan(accountUnlockPlan, context);
+ }
+
public R visitRCreateUser(final AuthorRelationalPlan rCreateUserPlan, final
C context) {
return visitPlan(rCreateUserPlan, context);
}
@@ -426,6 +434,10 @@ public abstract class ConfigPhysicalPlanVisitor<R, C> {
return visitPlan(rRevokeRoleSysPrivilegePlan, context);
}
+ public R visitRAccountUnlock(final AuthorRelationalPlan rAccountUnlockPlan,
final C context) {
+ return visitPlan(rAccountUnlockPlan, context);
+ }
+
public R visitTTL(final SetTTLPlan setTTLPlan, final C context) {
return visitPlan(setTTLPlan, context);
}
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorInfo.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorInfo.java
index bb0fd51c9fb..de9441acc04 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorInfo.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorInfo.java
@@ -74,7 +74,9 @@ public class AuthorInfo implements SnapshotProcessor {
throw new
IndexOutOfBoundsException(ConfigNodeMessages.INVALID_AUTHOR_TYPE_ORDINAL);
}
ConfigPhysicalPlanType configPhysicalPlanType;
- if (authorType >= AuthorType.RENAME_USER.ordinal()) {
+ if (authorType == AuthorType.ACCOUNT_UNLOCK.ordinal()) {
+ return ConfigPhysicalPlanType.AccountUnlock;
+ } else if (authorType >= AuthorType.RENAME_USER.ordinal()) {
AuthorType type = AuthorType.values()[authorType];
switch (type) {
case RENAME_USER:
@@ -105,6 +107,8 @@ public class AuthorInfo implements SnapshotProcessor {
ConfigPhysicalPlanType configPhysicalPlanType;
if (authorRType == AuthorRType.RENAME_USER.ordinal()) {
configPhysicalPlanType = ConfigPhysicalPlanType.RRenameUser;
+ } else if (authorRType == AuthorRType.ACCOUNT_UNLOCK.ordinal()) {
+ configPhysicalPlanType = ConfigPhysicalPlanType.RAccountUnlock;
} else {
configPhysicalPlanType =
ConfigPhysicalPlanType.values()[
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
index 7de717d9c3e..a65e05c8ad7 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutor.java
@@ -124,6 +124,9 @@ public class AuthorPlanExecutor implements
IAuthorPlanExecutor {
case RenameUser:
authorizer.renameUser(userName, newUsername);
break;
+ case AccountUnlock:
+ checkUserExistsForAccountUnlock(userName);
+ break;
case CreateUser:
authorizer.createUser(userName, password);
break;
@@ -241,6 +244,7 @@ public class AuthorPlanExecutor implements
IAuthorPlanExecutor {
authorizer.renameUser(userName, newUsername);
break;
case RAccountUnlock:
+ checkUserExistsForAccountUnlock(userName);
break;
case RDropRole:
authorizer.deleteRole(roleName);
@@ -448,6 +452,14 @@ public class AuthorPlanExecutor implements
IAuthorPlanExecutor {
return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
}
+ private void checkUserExistsForAccountUnlock(final String userName) throws
AuthException {
+ // Account unlock has no persistent ConfigNode auth state change, but the
write path needs this
+ // validation before broadcasting DataNode unlocks and propagating through
pipe.
+ if (authorizer.getUser(userName) == null) {
+ throw new AuthException(TSStatusCode.USER_NOT_EXIST, NO_USER_MSG +
userName);
+ }
+ }
+
@Override
public PermissionInfoResp executeListUsers(final AuthorPlan plan) throws
AuthException {
final PermissionInfoResp result = new PermissionInfoResp();
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
index 96dcdea4648..b606c8d2205 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
@@ -489,6 +489,7 @@ public class ConfigPlanExecutor {
case RevokeRoleFromUserDep:
case UpdateUserDep:
case RenameUser:
+ case AccountUnlock:
case RCreateRole:
case RCreateUser:
case RDropUser:
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedure.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedure.java
index 90112675253..59e4f50b40b 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedure.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedure.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.commons.utils.ThriftCommonsSerDeUtils;
import org.apache.iotdb.confignode.client.sync.CnToDnSyncRequestType;
import org.apache.iotdb.confignode.client.sync.SyncDataNodeClientPool;
import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
import org.apache.iotdb.confignode.consensus.request.write.auth.AuthorPlan;
import
org.apache.iotdb.confignode.consensus.request.write.pipe.payload.PipeEnrichedPlan;
import org.apache.iotdb.confignode.i18n.ProcedureMessages;
@@ -100,6 +101,11 @@ public class AuthOperationProcedure extends
AbstractNodeProcedure<AuthOperationP
TSStatus status;
req.setUsername(user);
req.setRoleName(role);
+ if (plan.getAuthorType() == ConfigPhysicalPlanType.AccountUnlock
+ || plan.getAuthorType() ==
ConfigPhysicalPlanType.RAccountUnlock) {
+ // For account unlock, role carries the optional login address.
+ req.setNeedDisconnect(true);
+ }
Iterator<Pair<TDataNodeConfiguration, Long>> it =
dataNodesToInvalid.iterator();
while (it.hasNext()) {
Pair<TDataNodeConfiguration, Long> pair = it.next();
diff --git
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutorTest.java
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutorTest.java
new file mode 100644
index 00000000000..4daa94dd53f
--- /dev/null
+++
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/auth/AuthorPlanExecutorTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.confignode.persistence.auth;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.auth.authorizer.IAuthorizer;
+import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+import
org.apache.iotdb.confignode.consensus.request.write.auth.AuthorRelationalPlan;
+import org.apache.iotdb.confignode.consensus.request.write.auth.AuthorTreePlan;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Collections;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class AuthorPlanExecutorTest {
+
+ @Test
+ public void testAccountUnlockRequiresExistingUser() throws Exception {
+ final IAuthorizer authorizer = mock(IAuthorizer.class);
+ when(authorizer.getUser("missing")).thenReturn(null);
+
+ final AuthorPlanExecutor executor = new AuthorPlanExecutor(authorizer);
+ final TSStatus status =
+ executor.executeAuthorNonQuery(
+ new AuthorTreePlan(
+ ConfigPhysicalPlanType.AccountUnlock,
+ "missing",
+ "",
+ "",
+ "",
+ Collections.emptySet(),
+ false,
+ Collections.emptyList()));
+
+ Assert.assertEquals(TSStatusCode.USER_NOT_EXIST.getStatusCode(),
status.getCode());
+ }
+
+ @Test
+ public void testRAccountUnlockRequiresExistingUser() throws Exception {
+ final IAuthorizer authorizer = mock(IAuthorizer.class);
+ when(authorizer.getUser("missing")).thenReturn(null);
+
+ final AuthorPlanExecutor executor = new AuthorPlanExecutor(authorizer);
+ final TSStatus status =
+ executor.executeRelationalAuthorNonQuery(
+ new AuthorRelationalPlan(
+ ConfigPhysicalPlanType.RAccountUnlock,
+ "missing",
+ "",
+ "",
+ "",
+ Collections.emptySet(),
+ false,
+ ""));
+
+ Assert.assertEquals(TSStatusCode.USER_NOT_EXIST.getStatusCode(),
status.getCode());
+ }
+}
diff --git
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedureTest.java
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedureTest.java
index 60fdb3bd981..56479669e5b 100644
---
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedureTest.java
+++
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/sync/AuthOperationProcedureTest.java
@@ -98,6 +98,34 @@ public class AuthOperationProcedureTest {
fail();
}
+ try {
+ final AuthOperationProcedure proc =
+ new AuthOperationProcedure(
+ new AuthorTreePlan(
+ ConfigPhysicalPlanType.AccountUnlock,
+ "user1",
+ "",
+ "",
+ "",
+ Collections.emptySet(),
+ false,
+ Collections.emptyList()),
+ datanodes,
+ false);
+ proc.serialize(outputStream);
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(byteArrayOutputStream.getBuf(), 0,
byteArrayOutputStream.size());
+
+ final AuthOperationProcedure proc2 =
+ (AuthOperationProcedure)
ProcedureFactory.getInstance().create(buffer);
+ Assert.assertEquals(proc, proc2);
+ buffer.clear();
+ byteArrayOutputStream.reset();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ fail();
+ }
+
try {
final int begin = ConfigPhysicalPlanType.RCreateUser.ordinal();
final int end = ConfigPhysicalPlanType.RRevokeRoleSysPri.ordinal();
@@ -129,5 +157,33 @@ public class AuthOperationProcedureTest {
e.printStackTrace();
fail();
}
+
+ try {
+ final AuthOperationProcedure proc =
+ new AuthOperationProcedure(
+ new AuthorRelationalPlan(
+ ConfigPhysicalPlanType.RAccountUnlock,
+ "user1",
+ "127.0.0.1",
+ "",
+ "",
+ Collections.emptySet(),
+ false,
+ ""),
+ datanodes,
+ false);
+ proc.serialize(outputStream);
+ final ByteBuffer buffer =
+ ByteBuffer.wrap(byteArrayOutputStream.getBuf(), 0,
byteArrayOutputStream.size());
+
+ final AuthOperationProcedure proc2 =
+ (AuthOperationProcedure)
ProcedureFactory.getInstance().create(buffer);
+ Assert.assertEquals(proc, proc2);
+ buffer.clear();
+ byteArrayOutputStream.reset();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ fail();
+ }
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
index 9ee232c921b..641ead173d2 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/auth/ClusterAuthorityFetcher.java
@@ -424,44 +424,31 @@ public class ClusterAuthorityFetcher implements
IAuthorityFetcher {
@Override
public SettableFuture<ConfigTaskResult> operatePermission(AuthorStatement
authorStatement) {
- return handleAccountUnlock(
- authorStatement,
- authorStatement.getUserName(),
- false,
- () -> onOperatePermissionSuccess(authorStatement));
+ return handleAccountUnlock(authorStatement, false);
}
@Override
public SettableFuture<ConfigTaskResult> operatePermission(
RelationalAuthorStatement authorStatement) {
- return handleAccountUnlock(
- authorStatement,
- authorStatement.getUserName(),
- true,
- () -> onOperatePermissionSuccess(authorStatement));
+ return handleAccountUnlock(authorStatement, true);
}
private SettableFuture<ConfigTaskResult> handleAccountUnlock(
- Object authorStatement, String username, boolean isRelational, Runnable
successCallback) {
+ Object authorStatement, boolean isRelational) {
if (isUnlockStatement(authorStatement, isRelational)) {
- final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
- final User user;
- try {
- user = getUser(username, false);
- } catch (final IoTDBRuntimeException e) {
- future.setException(e);
- return future;
- }
String loginAddr =
isRelational
? ((RelationalAuthorStatement) authorStatement).getLoginAddr()
: ((AuthorStatement) authorStatement).getLoginAddr();
- LoginLockManager.getInstance().unlock(user.getUserId(), loginAddr);
- successCallback.run();
- future.set(new ConfigTaskResult(TSStatusCode.SUCCESS_STATUS));
- return future;
+ // Reuse roleName to carry the optional login address for the internal
unlock broadcast.
+ if (isRelational) {
+ ((RelationalAuthorStatement) authorStatement).setRoleName(loginAddr);
+ } else {
+ ((AuthorStatement) authorStatement).setRoleName(loginAddr);
+ }
+ return operatePermissionInternal(authorStatement, isRelational);
}
return operatePermissionInternal(authorStatement, isRelational);
}
@@ -748,7 +735,7 @@ public class ClusterAuthorityFetcher implements
IAuthorityFetcher {
private TAuthorizerReq statementToAuthorizerReq(AuthorStatement
authorStatement)
throws AuthException {
- if (authorStatement.getAuthorType() == null) {
+ if (authorStatement.getNodeNameList() == null) {
authorStatement.setNodeNameList(new ArrayList<>());
}
return new TAuthorizerReq(
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
index ebef68b0486..f7f2f13b14c 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/DataNodeInternalRPCServiceImpl.java
@@ -109,6 +109,7 @@ import
org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
import org.apache.iotdb.db.audit.DNAuditLogger;
import org.apache.iotdb.db.auth.AuthorityChecker;
+import org.apache.iotdb.db.auth.LoginLockManager;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.consensus.DataRegionConsensusImpl;
import org.apache.iotdb.db.consensus.SchemaRegionConsensusImpl;
@@ -2453,12 +2454,25 @@ public class DataNodeInternalRPCServiceImpl implements
IDataNodeRPCService.Iface
@Override
public TSStatus invalidatePermissionCache(TInvalidatePermissionCacheReq req)
{
+ if (req.isSetNeedDisconnect() && req.isNeedDisconnect()) {
+ return unlockAccountAndInvalidateCache(req);
+ }
if (AuthorityChecker.invalidateCache(req.getUsername(),
req.getRoleName())) {
return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
}
return RpcUtils.getStatus(TSStatusCode.CLEAR_PERMISSION_CACHE_ERROR);
}
+ private TSStatus
unlockAccountAndInvalidateCache(TInvalidatePermissionCacheReq req) {
+ // For account-unlock broadcasts, roleName carries the optional login
address.
+ AuthorityChecker.getUserId(req.getUsername())
+ .ifPresent(userId -> LoginLockManager.getInstance().unlock(userId,
req.getRoleName()));
+ if (AuthorityChecker.invalidateCache(req.getUsername(), null)) {
+ return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS);
+ }
+ return RpcUtils.getStatus(TSStatusCode.CLEAR_PERMISSION_CACHE_ERROR);
+ }
+
@Override
public TSStatus enableSeparationOfAdminPower() throws TException {
return null;