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

dockerzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new ac5aa1c502 [INLONG-12075][Manager] Allow admin or in-charge delete 
InlongGroup (#12076)
ac5aa1c502 is described below

commit ac5aa1c5026a392accf1c088186573122df91f96
Author: healchow <[email protected]>
AuthorDate: Wed Feb 25 19:39:25 2026 +0800

    [INLONG-12075][Manager] Allow admin or in-charge delete InlongGroup (#12076)
---
 .../inlong/manager/common/util/Preconditions.java  |   8 +-
 .../service/cluster/InlongClusterServiceImpl.java  |  31 +++---
 .../service/group/InlongGroupProcessService.java   |  12 +--
 .../service/group/InlongGroupServiceImpl.java      |  33 +++---
 .../service/sink/StreamSinkServiceImpl.java        |  14 +--
 .../service/source/StreamSourceServiceImpl.java    |   2 +-
 .../inlong/manager/service/user/UserService.java   |  11 ++
 .../manager/service/user/UserServiceImpl.java      |  71 ++++++++-----
 .../manager/service/user/UserServiceImplTest.java  | 111 +++++++++++++++++++++
 .../workflow/core/impl/ProcessServiceImpl.java     |  14 ++-
 10 files changed, 214 insertions(+), 93 deletions(-)

diff --git 
a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/util/Preconditions.java
 
b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/util/Preconditions.java
index 47cd431039..122e793426 100644
--- 
a/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/util/Preconditions.java
+++ 
b/inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/util/Preconditions.java
@@ -25,11 +25,9 @@ import org.apache.commons.lang3.StringUtils;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.Set;
 import java.util.function.Supplier;
 
 /**
@@ -197,7 +195,9 @@ public class Preconditions {
         if (StringUtils.isBlank(target) || StringUtils.isBlank(separatedStr)) {
             return false;
         }
-        Set<String> set = new 
HashSet<>(Arrays.asList(separatedStr.split(separator)));
-        return set.contains(target);
+        // For a single lookup, using a List avoids the extra cost of building 
a Set;
+        // prefer Set only for repeated lookups.
+        List<String> list = Arrays.asList(separatedStr.split(separator));
+        return list.contains(target);
     }
 }
diff --git 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/cluster/InlongClusterServiceImpl.java
 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/cluster/InlongClusterServiceImpl.java
index a4b65e6c2e..8002ae77e6 100644
--- 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/cluster/InlongClusterServiceImpl.java
+++ 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/cluster/InlongClusterServiceImpl.java
@@ -34,7 +34,6 @@ import org.apache.inlong.manager.common.enums.ClusterType;
 import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
 import org.apache.inlong.manager.common.enums.GroupStatus;
 import org.apache.inlong.manager.common.enums.NodeStatus;
-import org.apache.inlong.manager.common.enums.TenantUserTypeEnum;
 import org.apache.inlong.manager.common.exceptions.BusinessException;
 import org.apache.inlong.manager.common.util.CommonBeanUtils;
 import org.apache.inlong.manager.common.util.Preconditions;
@@ -85,6 +84,7 @@ import 
org.apache.inlong.manager.service.repository.DataProxyConfigRepository;
 import org.apache.inlong.manager.service.tenant.InlongTenantService;
 import org.apache.inlong.manager.service.user.InlongRoleService;
 import org.apache.inlong.manager.service.user.TenantRoleService;
+import org.apache.inlong.manager.service.user.UserService;
 
 import com.github.pagehelper.Page;
 import com.github.pagehelper.PageHelper;
@@ -168,6 +168,8 @@ public class InlongClusterServiceImpl implements 
InlongClusterService {
     @Autowired
     private TenantClusterTagEntityMapper tenantClusterTagMapper;
     @Autowired
+    private UserService userService;
+    @Autowired
     private InlongTenantService tenantService;
     @Autowired
     private InlongRoleService inlongRoleService;
@@ -283,12 +285,9 @@ public class InlongClusterServiceImpl implements 
InlongClusterService {
         List<InlongClusterTagEntity> clusterTagEntities = 
clusterTagMapper.selectByCondition(request);
         if (CollectionUtils.isNotEmpty(clusterTagEntities)) {
             for (InlongClusterTagEntity tagEntity : clusterTagEntities) {
-                // only the person in charges can query
-                if 
(!opInfo.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode())) {
-                    List<String> inCharges = 
Arrays.asList(tagEntity.getInCharges().split(InlongConstants.COMMA));
-                    if (!inCharges.contains(opInfo.getName())) {
-                        continue;
-                    }
+                // only the person is admin or in charges can query
+                if (!userService.isAdminOrInCharge(opInfo, null, 
tagEntity.getInCharges())) {
+                    continue;
                 }
                 filterResult.add(tagEntity);
             }
@@ -503,12 +502,9 @@ public class InlongClusterServiceImpl implements 
InlongClusterService {
         List<InlongClusterEntity> clusterEntities = 
clusterMapper.selectByCondition(request);
         List<InlongClusterEntity> filterResult = new ArrayList<>();
         for (InlongClusterEntity entity : clusterEntities) {
-            // only the person in charges can query
-            if 
(!opInfo.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode())) {
-                List<String> inCharges = 
Arrays.asList(entity.getInCharges().split(InlongConstants.COMMA));
-                if (!inCharges.contains(opInfo.getName())) {
-                    continue;
-                }
+            // only the person is admin or in charges can query
+            if (!userService.isAdminOrInCharge(opInfo, null, 
entity.getInCharges())) {
+                continue;
             }
             filterResult.add(entity);
         }
@@ -797,12 +793,9 @@ public class InlongClusterServiceImpl implements 
InlongClusterService {
             List<InlongClusterEntity> clusterList =
                     clusterMapper.selectByKey(request.getClusterTag(), 
request.getName(), request.getType());
             for (InlongClusterEntity cluster : clusterList) {
-                // only the person in charges can query
-                if 
(!opInfo.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode())) {
-                    List<String> inCharges = 
Arrays.asList(cluster.getInCharges().split(InlongConstants.COMMA));
-                    if (!inCharges.contains(opInfo.getName())) {
-                        continue;
-                    }
+                // only the person is admin or in charges can query
+                if (!userService.isAdminOrInCharge(opInfo, null, 
cluster.getInCharges())) {
+                    continue;
                 }
                 
allNodeList.addAll(clusterNodeMapper.selectByParentId(cluster.getId(), null));
             }
diff --git 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupProcessService.java
 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupProcessService.java
index 8052315d1a..9e01df43ec 100644
--- 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupProcessService.java
+++ 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupProcessService.java
@@ -17,13 +17,11 @@
 
 package org.apache.inlong.manager.service.group;
 
-import org.apache.inlong.manager.common.consts.InlongConstants;
 import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
 import org.apache.inlong.manager.common.enums.GroupOperateType;
 import org.apache.inlong.manager.common.enums.GroupStatus;
 import org.apache.inlong.manager.common.enums.ProcessName;
 import org.apache.inlong.manager.common.enums.TaskStatus;
-import org.apache.inlong.manager.common.enums.TenantUserTypeEnum;
 import org.apache.inlong.manager.common.exceptions.BusinessException;
 import org.apache.inlong.manager.common.exceptions.WorkflowListenerException;
 import 
org.apache.inlong.manager.common.threadPool.VisiableThreadPoolTaskExecutor;
@@ -54,7 +52,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
@@ -274,15 +271,10 @@ public class InlongGroupProcessService {
     public Boolean deleteProcess(String groupId, UserInfo opInfo) {
         InlongGroupEntity entity = groupMapper.selectByGroupId(groupId);
         Preconditions.expectNotNull(entity, ErrorCodeEnum.GROUP_NOT_FOUND, 
ErrorCodeEnum.GROUP_NOT_FOUND.getMessage());
-        // only the person in charges can delete
-        if 
(!opInfo.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode())) {
-            List<String> inCharges = 
Arrays.asList(entity.getInCharges().split(InlongConstants.COMMA));
-            if (!inCharges.contains(opInfo.getName())) {
-                throw new 
BusinessException(ErrorCodeEnum.GROUP_PERMISSION_DENIED);
-            }
-        }
+
         // check can be deleted
         InlongGroupInfo groupInfo = groupService.doDeleteCheck(groupId, 
opInfo.getName());
+
         // start to delete group process
         GroupResourceProcessForm form = genGroupResourceProcessForm(groupInfo, 
GroupOperateType.DELETE);
         WorkflowResult result = 
workflowService.start(ProcessName.DELETE_GROUP_PROCESS, opInfo.getName(), form);
diff --git 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupServiceImpl.java
 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupServiceImpl.java
index e9cf001f62..7428c342bd 100644
--- 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupServiceImpl.java
+++ 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/group/InlongGroupServiceImpl.java
@@ -27,7 +27,6 @@ import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
 import org.apache.inlong.manager.common.enums.GroupStatus;
 import org.apache.inlong.manager.common.enums.OperationTarget;
 import org.apache.inlong.manager.common.enums.ProcessName;
-import org.apache.inlong.manager.common.enums.TenantUserTypeEnum;
 import org.apache.inlong.manager.common.exceptions.BusinessException;
 import org.apache.inlong.manager.common.util.CommonBeanUtils;
 import org.apache.inlong.manager.common.util.JsonUtils;
@@ -108,7 +107,6 @@ import org.springframework.validation.annotation.Validated;
 import java.sql.Timestamp;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -463,12 +461,9 @@ public class InlongGroupServiceImpl implements 
InlongGroupService {
         OrderFieldEnum.checkOrderField(request);
         OrderTypeEnum.checkOrderType(request);
         for (InlongGroupEntity groupEntity : 
groupMapper.selectByCondition(request)) {
-            // only the person in charges can query
-            if 
(!opInfo.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode())) {
-                List<String> inCharges = 
Arrays.asList(groupEntity.getInCharges().split(InlongConstants.COMMA));
-                if (!inCharges.contains(opInfo.getName())) {
-                    continue;
-                }
+            // only the person is admin or in charges can query
+            if (!userService.isAdminOrInCharge(opInfo, null, 
groupEntity.getInCharges())) {
+                continue;
             }
             filterGroupEntities.add(groupEntity);
         }
@@ -635,12 +630,10 @@ public class InlongGroupServiceImpl implements 
InlongGroupService {
     @Override
     public InlongGroupInfo doDeleteCheck(String groupId, String operator) {
         InlongGroupInfo groupInfo = this.get(groupId);
-        // only the person in charges can update
-        List<String> inCharges = 
Arrays.asList(groupInfo.getInCharges().split(InlongConstants.COMMA));
-        if (!inCharges.contains(operator)) {
-            throw new BusinessException(ErrorCodeEnum.GROUP_PERMISSION_DENIED,
-                    String.format("user [%s] has no privilege for the inlong 
group", operator));
-        }
+        // only the person is admin or in charges can delete
+        userService.checkUser(groupInfo.getInCharges(), operator,
+                "Current user does not have permission to delete group info");
+
         // determine whether the current status can be deleted
         GroupStatus curState = GroupStatus.forCode(groupInfo.getStatus());
         if (GroupStatus.notAllowedTransition(curState, 
GroupStatus.CONFIG_DELETING)) {
@@ -762,14 +755,12 @@ public class InlongGroupServiceImpl implements 
InlongGroupService {
     }
 
     private void chkUnmodifiableParams(InlongGroupEntity entity, 
InlongGroupRequest request) {
-        // check mqType
-        Preconditions.expectTrue(
-                Objects.equals(entity.getMqType(), request.getMqType())
-                        || Objects.equals(entity.getStatus(), 
GroupStatus.TO_BE_SUBMIT.getCode()),
+        // check mqType, the mqType must not null in entity
+        Preconditions.expectTrue(entity.getMqType().equals(request.getMqType())
+                || 
GroupStatus.TO_BE_SUBMIT.getCode().equals(entity.getStatus()),
                 "mqType not allowed modify");
         // check record version
-        Preconditions.expectEquals(entity.getVersion(), request.getVersion(),
-                ErrorCodeEnum.CONFIG_EXPIRED,
+        Preconditions.expectEquals(entity.getVersion(), request.getVersion(), 
ErrorCodeEnum.CONFIG_EXPIRED,
                 String.format("record has expired with record version=%d, 
request version=%d",
                         entity.getVersion(), request.getVersion()));
     }
@@ -783,7 +774,7 @@ public class InlongGroupServiceImpl implements 
InlongGroupService {
 
         // check if the group mode is data sync mode
         if 
(InlongConstants.DATASYNC_REALTIME_MODE.equals(groupInfo.getInlongGroupMode())) 
{
-            String errMSg = String.format("no need to switch sync mode group = 
{}", groupId);
+            String errMSg = String.format("no need to switch sync mode group = 
%s", groupId);
             LOGGER.error(errMSg);
             throw new BusinessException(errMSg);
         }
diff --git 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/StreamSinkServiceImpl.java
 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/StreamSinkServiceImpl.java
index e306c1f6f1..6b02ace7c4 100644
--- 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/StreamSinkServiceImpl.java
+++ 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/sink/StreamSinkServiceImpl.java
@@ -25,7 +25,6 @@ import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
 import org.apache.inlong.manager.common.enums.OperationTarget;
 import org.apache.inlong.manager.common.enums.SinkStatus;
 import org.apache.inlong.manager.common.enums.StreamStatus;
-import org.apache.inlong.manager.common.enums.TenantUserTypeEnum;
 import org.apache.inlong.manager.common.exceptions.BusinessException;
 import org.apache.inlong.manager.common.util.CommonBeanUtils;
 import org.apache.inlong.manager.common.util.JsonUtils;
@@ -96,7 +95,6 @@ import 
org.springframework.transaction.annotation.Transactional;
 
 import java.io.StringReader;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -435,17 +433,13 @@ public class StreamSinkServiceImpl implements 
StreamSinkService {
             StreamSinkOperator sinkOperator = 
operatorFactory.getInstance(entry.getKey());
             PageResult<? extends StreamSink> pageInfo = 
sinkOperator.getPageInfo(entry.getValue());
             for (StreamSink streamSink : pageInfo.getList()) {
-                InlongGroupEntity groupEntity =
-                        
groupMapper.selectByGroupId(streamSink.getInlongGroupId());
+                InlongGroupEntity groupEntity = 
groupMapper.selectByGroupId(streamSink.getInlongGroupId());
                 if (groupEntity == null) {
                     continue;
                 }
-                // only the person in charges can query
-                if 
(!opInfo.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode())) {
-                    List<String> inCharges = 
Arrays.asList(groupEntity.getInCharges().split(InlongConstants.COMMA));
-                    if (!inCharges.contains(opInfo.getName())) {
-                        continue;
-                    }
+                // only the person is admin or in charges can query
+                if (!userService.isAdminOrInCharge(opInfo, null, 
groupEntity.getInCharges())) {
+                    continue;
                 }
                 filterResult.add(streamSink);
             }
diff --git 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/source/StreamSourceServiceImpl.java
 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/source/StreamSourceServiceImpl.java
index 04e3941500..b285bfaf6d 100644
--- 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/source/StreamSourceServiceImpl.java
+++ 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/source/StreamSourceServiceImpl.java
@@ -251,7 +251,7 @@ public class StreamSourceServiceImpl implements 
StreamSourceService {
         OrderTypeEnum.checkOrderType(request);
         List<StreamSourceEntity> entityList = 
sourceMapper.selectByCondition(request);
         List<StreamSourceEntity> filteredEntitys = Lists.newArrayList();
-        if 
(opInfo.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode())) {
+        if 
(TenantUserTypeEnum.TENANT_ADMIN.getCode().equals(opInfo.getAccountType())) {
             filteredEntitys.addAll(entityList);
         } else {
             Set<String> totalGroupIds = new HashSet<>();
diff --git 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserService.java
 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserService.java
index be79bb6980..a91238894c 100644
--- 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserService.java
+++ 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserService.java
@@ -22,6 +22,8 @@ import org.apache.inlong.manager.pojo.user.UserInfo;
 import org.apache.inlong.manager.pojo.user.UserLoginRequest;
 import org.apache.inlong.manager.pojo.user.UserRequest;
 
+import javax.annotation.Nullable;
+
 /**
  * User service interface
  */
@@ -91,4 +93,13 @@ public interface UserService {
      */
     void checkUser(String inCharges, String user, String errMsg);
 
+    /**
+     * Check whether the user is admin or in charge.
+     * @param userInfo user info
+     * @param username username, if it is null, will use userInfo.getName()
+     * @param inCharges in charge list, if it is null, will ignore check in 
charge
+     * @return true if the user is admin or in charge
+     */
+    boolean isAdminOrInCharge(UserInfo userInfo, @Nullable String username, 
@Nullable String inCharges);
+
 }
diff --git 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserServiceImpl.java
 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserServiceImpl.java
index 36a75c4cc3..21282d9180 100644
--- 
a/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserServiceImpl.java
+++ 
b/inlong-manager/manager-service/src/main/java/org/apache/inlong/manager/service/user/UserServiceImpl.java
@@ -56,7 +56,7 @@ import com.github.pagehelper.Page;
 import com.github.pagehelper.PageHelper;
 import com.google.common.base.Joiner;
 import com.google.common.collect.Sets;
-import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.SecurityUtils;
@@ -163,7 +163,7 @@ public class UserServiceImpl implements UserService {
         UserEntity entity = userMapper.selectById(userId);
         Preconditions.expectNotNull(entity, "User not exists with id " + 
userId);
         UserEntity curUser = userMapper.selectByName(currentUser);
-        
Preconditions.expectTrue(Objects.equals(TenantUserTypeEnum.TENANT_ADMIN.getCode(),
 curUser.getAccountType())
+        
Preconditions.expectTrue(TenantUserTypeEnum.TENANT_ADMIN.getCode().equals(curUser.getAccountType())
                 || Objects.equals(entity.getName(), currentUser),
                 "Current user does not have permission to get other users' 
info");
 
@@ -229,7 +229,7 @@ public class UserServiceImpl implements UserService {
         // Whether the current user is a manager
         UserEntity currentUserEntity = userMapper.selectByName(currentUser);
         String updateName = request.getName();
-        boolean isAdmin = 
Objects.equals(TenantUserTypeEnum.TENANT_ADMIN.getCode(), 
currentUserEntity.getAccountType());
+        boolean isAdmin = 
TenantUserTypeEnum.TENANT_ADMIN.getCode().equals(currentUserEntity.getAccountType());
         Preconditions.expectTrue(isAdmin || Objects.equals(updateName, 
currentUser),
                 "You are not a manager and do not have permission to update 
other users");
 
@@ -292,7 +292,7 @@ public class UserServiceImpl implements UserService {
         // Whether the current user is an administrator
         UserEntity curUser = userMapper.selectByName(currentUser);
         UserEntity entity = userMapper.selectById(userId);
-        
Preconditions.expectTrue(curUser.getAccountType().equals(TenantUserTypeEnum.TENANT_ADMIN.getCode()),
+        
Preconditions.expectTrue(TenantUserTypeEnum.TENANT_ADMIN.getCode().equals(curUser.getAccountType()),
                 "Current user is not a manager and does not have permission to 
delete users");
         Preconditions.expectTrue(!Objects.equals(entity.getName(), 
currentUser),
                 "Current user does not have permission to delete himself");
@@ -355,13 +355,34 @@ public class UserServiceImpl implements UserService {
 
     @Override
     public void checkUser(String inCharges, String user, String errMsg) {
-        Set<String> userRoles = LoginUserUtils.getLoginUser().getRoles();
-        boolean isAdmin = false;
+        UserInfo loginUser = LoginUserUtils.getLoginUser();
+
+        boolean isAdminOrInCharge = isAdminOrInCharge(loginUser, user, 
inCharges);
+        Preconditions.expectTrue(isAdminOrInCharge, errMsg);
+    }
+
+    @Override
+    public boolean isAdminOrInCharge(UserInfo userInfo, String username, 
String inCharges) {
+        // Check accountType first, then
+        boolean isAdmin = 
TenantUserTypeEnum.TENANT_ADMIN.getCode().equals(userInfo.getAccountType());
+        if (isAdmin) {
+            return true;
+        }
+
+        // Then check userRoles - accountType and userRoles may be inconsistent
+        Set<String> userRoles = userInfo.getRoles();
         if (CollectionUtils.isNotEmpty(userRoles)) {
             isAdmin = userRoles.contains(UserRoleCode.INLONG_ADMIN) || 
userRoles.contains(UserRoleCode.TENANT_ADMIN);
+            if (isAdmin) {
+                return true;
+            }
         }
-        boolean isInCharge = Preconditions.inSeparatedString(user, inCharges, 
InlongConstants.COMMA);
-        Preconditions.expectTrue(isInCharge || isAdmin, errMsg);
+
+        // Not admin, check whether the username is in charge
+        if (StringUtils.isBlank(username)) {
+            username = userInfo.getName();
+        }
+        return Preconditions.inSeparatedString(username, inCharges, 
InlongConstants.COMMA);
     }
 
     public void removeInChargeForGroup(String user, String operator) {
@@ -476,26 +497,28 @@ public class UserServiceImpl implements UserService {
         }
     }
 
-    public void removeUserFromSession(Integer userId, String operator) {
+    private void removeUserFromSession(Integer userId, String operator) {
         DefaultWebSecurityManager securityManager = 
(DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
         DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) 
securityManager.getSessionManager();
         SessionDAO sessionDAO = sessionManager.getSessionDAO();
         Collection<Session> sessions = sessionDAO.getActiveSessions();
-        if (sessions.size() >= 1) {
-            UserInfo user = null;
-            for (Session onlineSession : sessions) {
-                Object attribute = 
onlineSession.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
-                if (attribute == null) {
-                    continue;
-                }
-                user = (UserInfo) ((SimplePrincipalCollection) 
attribute).getPrimaryPrincipal();
-                if (user == null) {
-                    continue;
-                }
-                if (Objects.equals(user.getId(), userId)) {
-                    sessionDAO.delete(onlineSession);
-                    LOGGER.info("success remove user from session by id={}, 
current user={}", user.getId(), operator);
-                }
+        if (CollectionUtils.isEmpty(sessions)) {
+            return;
+        }
+
+        UserInfo user;
+        for (Session onlineSession : sessions) {
+            Object attribute = 
onlineSession.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
+            if (attribute == null) {
+                continue;
+            }
+            user = (UserInfo) ((SimplePrincipalCollection) 
attribute).getPrimaryPrincipal();
+            if (user == null) {
+                continue;
+            }
+            if (Objects.equals(user.getId(), userId)) {
+                sessionDAO.delete(onlineSession);
+                LOGGER.info("success remove user from session by id={}, 
current user={}", user.getId(), operator);
             }
         }
     }
diff --git 
a/inlong-manager/manager-service/src/test/java/org/apache/inlong/manager/service/user/UserServiceImplTest.java
 
b/inlong-manager/manager-service/src/test/java/org/apache/inlong/manager/service/user/UserServiceImplTest.java
new file mode 100644
index 0000000000..ee8d1e4ece
--- /dev/null
+++ 
b/inlong-manager/manager-service/src/test/java/org/apache/inlong/manager/service/user/UserServiceImplTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.inlong.manager.service.user;
+
+import org.apache.inlong.manager.common.consts.InlongConstants;
+import org.apache.inlong.manager.common.enums.TenantUserTypeEnum;
+import org.apache.inlong.manager.common.util.Preconditions;
+import org.apache.inlong.manager.pojo.user.UserInfo;
+import org.apache.inlong.manager.pojo.user.UserRoleCode;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Test for {@link UserServiceImpl}
+ */
+public class UserServiceImplTest {
+
+    private final UserServiceImpl userService = new UserServiceImpl();
+
+    @Test
+    public void testAdminAccountTypeAlwaysTrue() {
+        UserInfo userInfo = new UserInfo();
+        userInfo.setAccountType(TenantUserTypeEnum.TENANT_ADMIN.getCode());
+        userInfo.setName("admin");
+
+        boolean result = userService.isAdminOrInCharge(userInfo, "someone", 
"other");
+        assertTrue(result);
+    }
+
+    @Test
+    public void testAdminRoleOverridesAccountType() {
+        UserInfo userInfo = new UserInfo();
+        userInfo.setAccountType(TenantUserTypeEnum.TENANT_OPERATOR.getCode());
+        userInfo.setName("user");
+        Set<String> roles = new HashSet<>();
+        roles.add(UserRoleCode.INLONG_ADMIN);
+        userInfo.setRoles(roles);
+
+        boolean result = userService.isAdminOrInCharge(userInfo, "user", 
"other");
+        assertTrue(result);
+    }
+
+    @Test
+    public void testInChargeMatchesWhenUsernameBlank() {
+        UserInfo userInfo = new UserInfo();
+        userInfo.setAccountType(TenantUserTypeEnum.TENANT_OPERATOR.getCode());
+        userInfo.setName("alice");
+        userInfo.setRoles(Collections.emptySet());
+
+        String inCharges = String.join(InlongConstants.COMMA, "bob", "alice");
+        boolean result = userService.isAdminOrInCharge(userInfo, "", 
inCharges);
+        assertTrue(result);
+    }
+
+    @Test
+    public void testNotInChargeReturnsFalse() {
+        UserInfo userInfo = new UserInfo();
+        userInfo.setAccountType(TenantUserTypeEnum.TENANT_OPERATOR.getCode());
+        userInfo.setName("alice");
+        userInfo.setRoles(Collections.emptySet());
+
+        String inCharges = String.join(InlongConstants.COMMA, "bob", "carol");
+        boolean result = userService.isAdminOrInCharge(userInfo, "alice", 
inCharges);
+        assertFalse(result);
+    }
+
+    @Test
+    public void testInSeparatedStringEquivalentToSplitContains() {
+        // Explicitly verify Preconditions.inSeparatedString behaves like 
split + List.contains
+        String inCharges = String.join(InlongConstants.COMMA, "alice", "bob", 
"carol");
+        String username = "bob";
+        boolean expected = 
Arrays.asList(inCharges.split(InlongConstants.COMMA)).contains(username);
+        boolean actual = Preconditions.inSeparatedString(username, inCharges, 
InlongConstants.COMMA);
+        assertEquals(expected, actual);
+
+        username = "dave";
+        expected = 
Arrays.asList(inCharges.split(InlongConstants.COMMA)).contains(username);
+        actual = Preconditions.inSeparatedString(username, inCharges, 
InlongConstants.COMMA);
+        assertEquals(expected, actual);
+
+        inCharges = "";
+        username = "alice";
+        expected = 
Arrays.asList(inCharges.split(InlongConstants.COMMA)).contains(username);
+        actual = Preconditions.inSeparatedString(username, inCharges, 
InlongConstants.COMMA);
+        assertEquals(expected, actual);
+    }
+}
\ No newline at end of file
diff --git 
a/inlong-manager/manager-workflow/src/main/java/org/apache/inlong/manager/workflow/core/impl/ProcessServiceImpl.java
 
b/inlong-manager/manager-workflow/src/main/java/org/apache/inlong/manager/workflow/core/impl/ProcessServiceImpl.java
index 699cff3ec2..bbe0023950 100644
--- 
a/inlong-manager/manager-workflow/src/main/java/org/apache/inlong/manager/workflow/core/impl/ProcessServiceImpl.java
+++ 
b/inlong-manager/manager-workflow/src/main/java/org/apache/inlong/manager/workflow/core/impl/ProcessServiceImpl.java
@@ -129,12 +129,18 @@ public class ProcessServiceImpl implements ProcessService 
{
         String groupId = context.getProcessForm().getInlongGroupId();
         Preconditions.expectNotBlank(groupId, ErrorCodeEnum.GROUP_ID_IS_EMPTY,
                 ErrorCodeEnum.GROUP_ID_IS_EMPTY.getMessage());
-        InlongGroupEntity groupEntity = groupMapper.selectByGroupId(groupId);
+
+        // check user accountType first
         UserEntity userEntity = userMapper.selectByName(user);
+        boolean isAdmin = 
TenantUserTypeEnum.TENANT_ADMIN.getCode().equals(userEntity.getAccountType());
+        if (isAdmin) {
+            return;
+        }
+
+        // then query the inlong group, and check in-charges
+        InlongGroupEntity groupEntity = groupMapper.selectByGroupId(groupId);
         boolean isInCharge = Preconditions.inSeparatedString(user, 
groupEntity.getInCharges(), InlongConstants.COMMA);
-        Preconditions.expectTrue(
-                isInCharge || 
TenantUserTypeEnum.TENANT_ADMIN.getCode().equals(userEntity.getAccountType()),
-                errMsg);
+        Preconditions.expectTrue(isInCharge, errMsg);
     }
 
 }

Reply via email to