package jnpf.dmsPermission;
|
|
import jnpf.dmsEntity.permission.model.DmsSubjectSet;
|
import jnpf.permission.RoleRelationApi;
|
import jnpf.permission.UserApi;
|
import jnpf.permission.UserRelationApi;
|
import jnpf.permission.entity.RoleRelationEntity;
|
import jnpf.permission.entity.UserEntity;
|
import jnpf.permission.entity.UserRelationEntity;
|
import jnpf.permission.model.rolerelaiton.RoleRelationModel;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Component;
|
|
import java.util.ArrayList;
|
import java.util.Collection;
|
import java.util.Collections;
|
import java.util.LinkedHashMap;
|
import java.util.LinkedHashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
|
@Component
|
@RequiredArgsConstructor
|
public class DmsUserSubjectBatchResolver {
|
private static final String ORGANIZE = "organize";
|
private static final String POSITION = "position";
|
private static final String GROUP = "group";
|
private static final String USER = "user";
|
|
private final UserApi userApi;
|
private final UserRelationApi userRelationApi;
|
private final RoleRelationApi roleRelationApi;
|
private final DmsSubjectHierarchyResolver hierarchyResolver;
|
|
public List<DmsSubjectSet> resolve(String tenantId, List<String> normalizedUserIds) {
|
String normalizedTenantId = trimToNull(tenantId);
|
if (normalizedTenantId == null) {
|
throw invalidRequest("租户标识不能为空");
|
}
|
List<String> userIds = normalizeUserIds(normalizedUserIds);
|
validateUsers(normalizedTenantId, userIds);
|
|
Map<String, DmsSubjectSet> subjectsByUserId = new LinkedHashMap<>();
|
for (String userId : userIds) {
|
DmsSubjectSet subjects = new DmsSubjectSet();
|
subjects.setUserId(userId);
|
subjectsByUserId.put(userId, subjects);
|
}
|
|
applyUserRelations(subjectsByUserId, userRelationApi.getListByUserIdAll(userIds));
|
hierarchyResolver.resolveStrict(subjectsByUserId.values());
|
applyRoles(subjectsByUserId);
|
return new ArrayList<>(subjectsByUserId.values());
|
}
|
|
private List<String> normalizeUserIds(List<String> normalizedUserIds) {
|
if (normalizedUserIds == null || normalizedUserIds.isEmpty()) {
|
throw invalidRequest("用户列表不能为空");
|
}
|
Set<String> uniqueUserIds = new LinkedHashSet<>();
|
for (String userId : normalizedUserIds) {
|
String normalized = trimToNull(userId);
|
if (normalized == null) {
|
throw invalidRequest("用户标识不能为空");
|
}
|
uniqueUserIds.add(normalized);
|
}
|
return new ArrayList<>(uniqueUserIds);
|
}
|
|
private void validateUsers(String tenantId, List<String> userIds) {
|
List<UserEntity> users = userApi.getUserName(userIds);
|
Set<String> found = new LinkedHashSet<>();
|
if (users != null) {
|
for (UserEntity user : users) {
|
if (user == null) {
|
continue;
|
}
|
String userId = trimToNull(user.getId());
|
String userTenantId = trimToNull(user.getTenantId());
|
if (userId != null && userIds.contains(userId) && tenantId.equals(userTenantId)) {
|
found.add(userId);
|
}
|
}
|
}
|
Set<String> missing = new LinkedHashSet<>(userIds);
|
missing.removeAll(found);
|
if (!missing.isEmpty()) {
|
throw DmsPermissionException.of(DmsPermissionError.PRINCIPAL_NOT_FOUND,
|
"USER 主体不存在、不属于当前租户或主体服务不可用: " + missing);
|
}
|
}
|
|
private void applyUserRelations(Map<String, DmsSubjectSet> subjectsByUserId,
|
List<UserRelationEntity> relations) {
|
if (relations == null) {
|
return;
|
}
|
for (UserRelationEntity relation : relations) {
|
if (relation == null) {
|
continue;
|
}
|
DmsSubjectSet subjects = subjectsByUserId.get(trimToNull(relation.getUserId()));
|
String objectId = trimToNull(relation.getObjectId());
|
String objectType = trimToNull(relation.getObjectType());
|
if (subjects == null || objectId == null || objectType == null) {
|
continue;
|
}
|
if (ORGANIZE.equalsIgnoreCase(objectType)) {
|
subjects.getDirectOrgIds().add(objectId);
|
} else if (POSITION.equalsIgnoreCase(objectType)) {
|
subjects.getPositionIds().add(objectId);
|
} else if (GROUP.equalsIgnoreCase(objectType)) {
|
subjects.getPlatformGroupIds().add(objectId);
|
}
|
}
|
}
|
|
private void applyRoles(Map<String, DmsSubjectSet> subjectsByUserId) {
|
Map<String, Set<String>> userIdsByObjectId = new LinkedHashMap<>();
|
for (DmsSubjectSet subject : subjectsByUserId.values()) {
|
addRoleTarget(userIdsByObjectId, subject.getUserId(), subject.getUserId());
|
addRoleTargets(userIdsByObjectId, subject.getDirectOrgIds(), subject.getUserId());
|
addRoleTargets(userIdsByObjectId, subject.getPositionIds(), subject.getUserId());
|
}
|
|
RoleRelationModel request = new RoleRelationModel(
|
new ArrayList<>(userIdsByObjectId.keySet()), null);
|
List<RoleRelationEntity> relations = roleRelationApi.getListByObjectId(request);
|
if (relations == null) {
|
return;
|
}
|
for (RoleRelationEntity relation : relations) {
|
if (relation == null) {
|
continue;
|
}
|
String objectId = trimToNull(relation.getObjectId());
|
String roleId = trimToNull(relation.getRoleId());
|
String objectType = trimToNull(relation.getObjectType());
|
if (objectId == null || roleId == null) {
|
continue;
|
}
|
for (String userId : userIdsByObjectId.getOrDefault(objectId,
|
Collections.<String>emptySet())) {
|
DmsSubjectSet subjects = subjectsByUserId.get(userId);
|
subjects.getRoleIds().add(roleId);
|
if (userId.equals(objectId) && USER.equalsIgnoreCase(objectType)) {
|
subjects.getDirectUserRoleIds().add(roleId);
|
}
|
}
|
}
|
}
|
|
private void addRoleTargets(Map<String, Set<String>> userIdsByObjectId,
|
Collection<String> objectIds, String userId) {
|
for (String objectId : objectIds) {
|
addRoleTarget(userIdsByObjectId, objectId, userId);
|
}
|
}
|
|
private void addRoleTarget(Map<String, Set<String>> userIdsByObjectId,
|
String objectId, String userId) {
|
String normalized = trimToNull(objectId);
|
if (normalized != null) {
|
userIdsByObjectId.computeIfAbsent(normalized, key -> new LinkedHashSet<>()).add(userId);
|
}
|
}
|
|
private DmsPermissionException invalidRequest(String message) {
|
return DmsPermissionException.of(DmsPermissionError.INVALID_REQUEST, message);
|
}
|
|
private String trimToNull(String value) {
|
return value == null || value.trim().isEmpty() ? null : value.trim();
|
}
|
}
|