fix #493: add effective access matrix
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
package com.cloudhandson.vpdbackoffice.service;
|
||||
|
||||
import com.cloudhandson.vpdbackoffice.domain.effective.EffectiveMatrixView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.effective.GroupEffectiveAccessView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.effective.RoleEffectiveImpactView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.effective.UserEffectiveAccessView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.group.AppGroup;
|
||||
import com.cloudhandson.vpdbackoffice.domain.group.GroupRoleView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.group.GroupUserView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.permission.AppRole;
|
||||
import com.cloudhandson.vpdbackoffice.domain.permission.PermissionView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.user.AppUser;
|
||||
import com.cloudhandson.vpdbackoffice.domain.user.UserRoleView;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class EffectiveMatrixService {
|
||||
|
||||
private final UserService userService;
|
||||
private final GroupService groupService;
|
||||
private final PermissionService permissionService;
|
||||
|
||||
public EffectiveMatrixService(
|
||||
UserService userService,
|
||||
GroupService groupService,
|
||||
PermissionService permissionService
|
||||
) {
|
||||
this.userService = userService;
|
||||
this.groupService = groupService;
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public EffectiveMatrixView matrix() {
|
||||
List<AppUser> users = userService.findAll();
|
||||
List<AppGroup> groups = groupService.findAll();
|
||||
List<AppRole> roles = permissionService.findRoles();
|
||||
List<UserRoleView> userRoles = userService.findUserRoles();
|
||||
List<GroupUserView> groupUsers = groupService.findGroupUsers();
|
||||
List<GroupRoleView> groupRoles = groupService.findGroupRoles();
|
||||
List<PermissionView> permissions = permissionService.findPermissionViews();
|
||||
|
||||
Map<Long, Set<Long>> directRoleIdsByUser = directRoleIdsByUser(userRoles);
|
||||
Map<Long, List<String>> directRoleNamesByUser = directRoleNamesByUser(userRoles);
|
||||
Map<Long, Set<Long>> groupIdsByUser = groupIdsByUser(groupUsers);
|
||||
Map<Long, List<String>> groupNamesByUser = groupNamesByUser(groupUsers);
|
||||
Map<Long, List<String>> userNamesByGroup = userNamesByGroup(groupUsers);
|
||||
Map<Long, Set<Long>> roleIdsByGroup = roleIdsByGroup(groupRoles);
|
||||
Map<Long, List<String>> roleNamesByGroup = roleNamesByGroup(groupRoles);
|
||||
Map<Long, List<String>> groupNamesByRole = groupNamesByRole(groupRoles);
|
||||
Map<Long, List<String>> directUserNamesByRole = directUserNamesByRole(userRoles);
|
||||
Map<Long, List<PermissionView>> permissionsByRole = permissionsByRole(permissions);
|
||||
Map<Long, String> roleNameById = roleNameById(roles);
|
||||
|
||||
List<UserEffectiveAccessView> userViews = users.stream()
|
||||
.map(user -> userView(
|
||||
user,
|
||||
directRoleIdsByUser,
|
||||
directRoleNamesByUser,
|
||||
groupIdsByUser,
|
||||
groupNamesByUser,
|
||||
roleIdsByGroup,
|
||||
roleNameById,
|
||||
permissionsByRole
|
||||
))
|
||||
.toList();
|
||||
|
||||
List<GroupEffectiveAccessView> groupViews = groups.stream()
|
||||
.map(group -> groupView(group, userNamesByGroup, roleIdsByGroup, roleNamesByGroup, permissionsByRole))
|
||||
.toList();
|
||||
|
||||
List<RoleEffectiveImpactView> roleViews = roles.stream()
|
||||
.map(role -> roleView(role, directUserNamesByRole, groupNamesByRole, groupUsers, groupRoles, permissionsByRole))
|
||||
.toList();
|
||||
|
||||
return new EffectiveMatrixView(userViews, groupViews, roleViews, permissions.size());
|
||||
}
|
||||
|
||||
private UserEffectiveAccessView userView(
|
||||
AppUser user,
|
||||
Map<Long, Set<Long>> directRoleIdsByUser,
|
||||
Map<Long, List<String>> directRoleNamesByUser,
|
||||
Map<Long, Set<Long>> groupIdsByUser,
|
||||
Map<Long, List<String>> groupNamesByUser,
|
||||
Map<Long, Set<Long>> roleIdsByGroup,
|
||||
Map<Long, String> roleNameById,
|
||||
Map<Long, List<PermissionView>> permissionsByRole
|
||||
) {
|
||||
Set<Long> directRoleIds = directRoleIdsByUser.getOrDefault(user.userId(), Set.of());
|
||||
Set<Long> inheritedRoleIds = new LinkedHashSet<>();
|
||||
for (Long groupId : groupIdsByUser.getOrDefault(user.userId(), Set.of())) {
|
||||
inheritedRoleIds.addAll(roleIdsByGroup.getOrDefault(groupId, Set.of()));
|
||||
}
|
||||
|
||||
Set<Long> effectiveRoleIds = new LinkedHashSet<>(directRoleIds);
|
||||
effectiveRoleIds.addAll(inheritedRoleIds);
|
||||
|
||||
return new UserEffectiveAccessView(
|
||||
user.userId(),
|
||||
user.username(),
|
||||
user.empNo(),
|
||||
user.deptCode(),
|
||||
user.active(),
|
||||
directRoleNamesByUser.getOrDefault(user.userId(), List.of()),
|
||||
groupNamesByUser.getOrDefault(user.userId(), List.of()),
|
||||
names(inheritedRoleIds, roleNameById),
|
||||
names(effectiveRoleIds, roleNameById),
|
||||
permissionCount(effectiveRoleIds, permissionsByRole),
|
||||
objectNames(effectiveRoleIds, permissionsByRole)
|
||||
);
|
||||
}
|
||||
|
||||
private GroupEffectiveAccessView groupView(
|
||||
AppGroup group,
|
||||
Map<Long, List<String>> userNamesByGroup,
|
||||
Map<Long, Set<Long>> roleIdsByGroup,
|
||||
Map<Long, List<String>> roleNamesByGroup,
|
||||
Map<Long, List<PermissionView>> permissionsByRole
|
||||
) {
|
||||
Set<Long> roleIds = roleIdsByGroup.getOrDefault(group.groupId(), Set.of());
|
||||
return new GroupEffectiveAccessView(
|
||||
group.groupId(),
|
||||
group.groupCode(),
|
||||
group.groupName(),
|
||||
group.active(),
|
||||
userNamesByGroup.getOrDefault(group.groupId(), List.of()),
|
||||
roleNamesByGroup.getOrDefault(group.groupId(), List.of()),
|
||||
permissionCount(roleIds, permissionsByRole),
|
||||
objectNames(roleIds, permissionsByRole)
|
||||
);
|
||||
}
|
||||
|
||||
private RoleEffectiveImpactView roleView(
|
||||
AppRole role,
|
||||
Map<Long, List<String>> directUserNamesByRole,
|
||||
Map<Long, List<String>> groupNamesByRole,
|
||||
List<GroupUserView> groupUsers,
|
||||
List<GroupRoleView> groupRoles,
|
||||
Map<Long, List<PermissionView>> permissionsByRole
|
||||
) {
|
||||
Set<Long> roleIds = Set.of(role.roleId());
|
||||
Set<String> inheritedUsers = new LinkedHashSet<>();
|
||||
Set<Long> roleGroupIds = new LinkedHashSet<>();
|
||||
for (GroupRoleView groupRole : groupRoles) {
|
||||
if (groupRole.roleId() == role.roleId()) {
|
||||
roleGroupIds.add(groupRole.groupId());
|
||||
}
|
||||
}
|
||||
for (GroupUserView groupUser : groupUsers) {
|
||||
if (roleGroupIds.contains(groupUser.groupId())) {
|
||||
inheritedUsers.add(groupUser.username());
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> affectedUsers = new LinkedHashSet<>(directUserNamesByRole.getOrDefault(role.roleId(), List.of()));
|
||||
affectedUsers.addAll(inheritedUsers);
|
||||
|
||||
return new RoleEffectiveImpactView(
|
||||
role.roleId(),
|
||||
role.roleName(),
|
||||
role.maxSensitivityLevel(),
|
||||
directUserNamesByRole.getOrDefault(role.roleId(), List.of()),
|
||||
groupNamesByRole.getOrDefault(role.roleId(), List.of()),
|
||||
new ArrayList<>(inheritedUsers),
|
||||
new ArrayList<>(affectedUsers),
|
||||
permissionCount(roleIds, permissionsByRole),
|
||||
objectNames(roleIds, permissionsByRole)
|
||||
);
|
||||
}
|
||||
|
||||
private Map<Long, Set<Long>> directRoleIdsByUser(List<UserRoleView> userRoles) {
|
||||
Map<Long, Set<Long>> result = new LinkedHashMap<>();
|
||||
for (UserRoleView view : userRoles) {
|
||||
result.computeIfAbsent(view.userId(), key -> new LinkedHashSet<>()).add(view.roleId());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<Long, List<String>> directRoleNamesByUser(List<UserRoleView> userRoles) {
|
||||
Map<Long, Set<String>> result = new LinkedHashMap<>();
|
||||
for (UserRoleView view : userRoles) {
|
||||
result.computeIfAbsent(view.userId(), key -> new LinkedHashSet<>()).add(view.roleName());
|
||||
}
|
||||
return toListMap(result);
|
||||
}
|
||||
|
||||
private Map<Long, Set<Long>> groupIdsByUser(List<GroupUserView> groupUsers) {
|
||||
Map<Long, Set<Long>> result = new LinkedHashMap<>();
|
||||
for (GroupUserView view : groupUsers) {
|
||||
result.computeIfAbsent(view.userId(), key -> new LinkedHashSet<>()).add(view.groupId());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<Long, List<String>> groupNamesByUser(List<GroupUserView> groupUsers) {
|
||||
Map<Long, Set<String>> result = new LinkedHashMap<>();
|
||||
for (GroupUserView view : groupUsers) {
|
||||
result.computeIfAbsent(view.userId(), key -> new LinkedHashSet<>()).add(groupLabel(view.groupCode(), view.groupName()));
|
||||
}
|
||||
return toListMap(result);
|
||||
}
|
||||
|
||||
private Map<Long, List<String>> userNamesByGroup(List<GroupUserView> groupUsers) {
|
||||
Map<Long, Set<String>> result = new LinkedHashMap<>();
|
||||
for (GroupUserView view : groupUsers) {
|
||||
result.computeIfAbsent(view.groupId(), key -> new LinkedHashSet<>()).add(view.username());
|
||||
}
|
||||
return toListMap(result);
|
||||
}
|
||||
|
||||
private Map<Long, Set<Long>> roleIdsByGroup(List<GroupRoleView> groupRoles) {
|
||||
Map<Long, Set<Long>> result = new LinkedHashMap<>();
|
||||
for (GroupRoleView view : groupRoles) {
|
||||
result.computeIfAbsent(view.groupId(), key -> new LinkedHashSet<>()).add(view.roleId());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<Long, List<String>> roleNamesByGroup(List<GroupRoleView> groupRoles) {
|
||||
Map<Long, Set<String>> result = new LinkedHashMap<>();
|
||||
for (GroupRoleView view : groupRoles) {
|
||||
result.computeIfAbsent(view.groupId(), key -> new LinkedHashSet<>()).add(view.roleName());
|
||||
}
|
||||
return toListMap(result);
|
||||
}
|
||||
|
||||
private Map<Long, List<String>> groupNamesByRole(List<GroupRoleView> groupRoles) {
|
||||
Map<Long, Set<String>> result = new LinkedHashMap<>();
|
||||
for (GroupRoleView view : groupRoles) {
|
||||
result.computeIfAbsent(view.roleId(), key -> new LinkedHashSet<>()).add(groupLabel(view.groupCode(), view.groupName()));
|
||||
}
|
||||
return toListMap(result);
|
||||
}
|
||||
|
||||
private Map<Long, List<String>> directUserNamesByRole(List<UserRoleView> userRoles) {
|
||||
Map<Long, Set<String>> result = new LinkedHashMap<>();
|
||||
for (UserRoleView view : userRoles) {
|
||||
result.computeIfAbsent(view.roleId(), key -> new LinkedHashSet<>()).add(view.username());
|
||||
}
|
||||
return toListMap(result);
|
||||
}
|
||||
|
||||
private Map<Long, List<PermissionView>> permissionsByRole(List<PermissionView> permissions) {
|
||||
Map<Long, List<PermissionView>> result = new LinkedHashMap<>();
|
||||
for (PermissionView permission : permissions) {
|
||||
result.computeIfAbsent(permission.roleId(), key -> new ArrayList<>()).add(permission);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<Long, String> roleNameById(List<AppRole> roles) {
|
||||
Map<Long, String> result = new LinkedHashMap<>();
|
||||
for (AppRole role : roles) {
|
||||
result.put(role.roleId(), role.roleName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<String> names(Set<Long> ids, Map<Long, String> nameById) {
|
||||
return ids.stream()
|
||||
.map(nameById::get)
|
||||
.filter(name -> name != null && !name.isBlank())
|
||||
.toList();
|
||||
}
|
||||
|
||||
private int permissionCount(Set<Long> roleIds, Map<Long, List<PermissionView>> permissionsByRole) {
|
||||
return roleIds.stream()
|
||||
.mapToInt(roleId -> permissionsByRole.getOrDefault(roleId, List.of()).size())
|
||||
.sum();
|
||||
}
|
||||
|
||||
private List<String> objectNames(Set<Long> roleIds, Map<Long, List<PermissionView>> permissionsByRole) {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
for (Long roleId : roleIds) {
|
||||
for (PermissionView permission : permissionsByRole.getOrDefault(roleId, List.of())) {
|
||||
result.add(permission.objectName() + " / " + permission.permissionEffect());
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(result);
|
||||
}
|
||||
|
||||
private Map<Long, List<String>> toListMap(Map<Long, Set<String>> source) {
|
||||
Map<Long, List<String>> result = new LinkedHashMap<>();
|
||||
source.forEach((key, value) -> result.put(key, new ArrayList<>(value)));
|
||||
return result;
|
||||
}
|
||||
|
||||
private String groupLabel(String groupCode, String groupName) {
|
||||
return groupCode + " / " + groupName;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user