feat(工作台): 工作台首页用户权限开通模块的项目查询
This commit is contained in:
parent
8212fb094a
commit
93779a655a
|
@ -0,0 +1,40 @@
|
|||
package io.metersphere.dashboard.constants;
|
||||
|
||||
public enum DashboardUserLayoutKeys {
|
||||
/**
|
||||
* default
|
||||
*/
|
||||
CREATE_BY_ME, //我创建的
|
||||
PROJECT_VIEW,//项目概览
|
||||
PROJECT_MEMBER_VIEW,//项目成员概览
|
||||
/**
|
||||
* functional
|
||||
*/
|
||||
CASE_COUNT, //用例数量统计
|
||||
ASSOCIATE_CASE_COUNT,//关联用例统计
|
||||
REVIEW_CASE_COUNT,//用例评审数量统计
|
||||
REVIEWING_BY_ME, //待我评审
|
||||
/**
|
||||
* api
|
||||
*/
|
||||
API_COUNT,//接口数量统计
|
||||
API_CASE_COUNT,//接口用例数量统计
|
||||
SCENARIO_COUNT,//场景用例数量统计
|
||||
API_CHANGE,//接口变更统计
|
||||
/**
|
||||
* test_plan
|
||||
*/
|
||||
TEST_PLAN_COUNT,//测试计划数量统计
|
||||
PLAN_LEGACY_BUG,//计划遗留bug统计
|
||||
/**
|
||||
* bug
|
||||
*/
|
||||
BUG_COUNT,//缺陷数量统计
|
||||
CREATE_BUG_BY_ME, //我创建的缺陷
|
||||
HANDLE_BUG_BY_ME, //待我处理的缺陷
|
||||
BUG_HANDLE_USER // 缺陷处理人统计
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package io.metersphere.dashboard.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class LayoutDTO {
|
||||
@Schema(description = "布局卡片key")
|
||||
private String id;
|
||||
@Schema(description = "排序")
|
||||
private Integer pos;
|
||||
@Schema(description = "全屏/半屏")
|
||||
private Boolean fullScreen;
|
||||
@Schema(description = "选中的项目ID")
|
||||
private List<String> projectIds;
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package io.metersphere.dashboard.request;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author guoyuqi
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class DashboardBaseRequest {
|
||||
|
||||
@Schema(description = "组织ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{organization.id.not_blank}")
|
||||
private String organizationId;
|
||||
|
||||
@Min(value = 1, message = "当前页码必须大于0")
|
||||
@Schema(description = "当前页码")
|
||||
private int current;
|
||||
|
||||
@Min(value = 5, message = "每页显示条数必须不小于5")
|
||||
@Max(value = 500, message = "每页显示条数不能大于500")
|
||||
@Schema(description = "每页显示条数")
|
||||
private int pageSize;
|
||||
|
||||
@Schema(description = "过滤字段")
|
||||
private Map<String, List<String>> filter;
|
||||
|
||||
@Schema(description = "排序字段(model中的字段 : asc/desc)")
|
||||
private Map<@Valid @Pattern(regexp = "^[A-Za-z]+$") String, @Valid @NotBlank String> sort;
|
||||
|
||||
|
||||
public String getSortString() {
|
||||
if (sort == null || sort.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Map.Entry<String, String> entry : sort.entrySet()) {
|
||||
String column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, entry.getKey());
|
||||
sb.append(column)
|
||||
.append(StringUtils.SPACE)
|
||||
.append(StringUtils.equalsIgnoreCase(entry.getValue(), "DESC") ? "DESC" : "ASC")
|
||||
.append(",");
|
||||
}
|
||||
return sb.substring(0, sb.length() - 1);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.dashboard.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class DashboardFrontPageRequest extends DashboardBaseRequest{
|
||||
|
||||
@Schema(description = "项目ID集合")
|
||||
private List<String> projectIds;
|
||||
|
||||
@Schema(description = "人员集合")
|
||||
private List<String> handleUsers;
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package io.metersphere.dashboard.service;
|
||||
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.domain.ProjectExample;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.project.service.PermissionCheckService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.dto.user.UserDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class DashboardProjectService {
|
||||
|
||||
@Resource
|
||||
private PermissionCheckService permissionCheckService;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
|
||||
public static final String API_TEST = "apiTest";
|
||||
public static final String TEST_PLAN = "testPlan";
|
||||
public static final String FUNCTIONAL_CASE = "caseManagement";
|
||||
public static final String BUG = "bugManagement";
|
||||
|
||||
public Map<String, Set<String>> getPermissionModuleProjectIds(String organizationId, List<String> projectIds, String userId) {
|
||||
boolean isAdmin = isAdmin(userId);
|
||||
Set<String> projectSet;
|
||||
Map<String, String> moduleMap;
|
||||
if (CollectionUtils.isNotEmpty(projectIds)) {
|
||||
projectSet = new HashSet<>(projectIds);
|
||||
ProjectExample projectExample = new ProjectExample();
|
||||
projectExample.createCriteria().andIdIn(projectIds);
|
||||
List<Project> projects = projectMapper.selectByExample(projectExample);
|
||||
moduleMap = projects.stream().collect(Collectors.toMap(Project::getId, Project::getModuleSetting));
|
||||
} else {
|
||||
ProjectExample projectExample = new ProjectExample();
|
||||
projectExample.createCriteria().andOrganizationIdEqualTo(organizationId);
|
||||
List<Project> projects = projectMapper.selectByExample(projectExample);
|
||||
projectSet = projects.stream().map(Project::getId).collect(Collectors.toSet());
|
||||
moduleMap = projects.stream().collect(Collectors.toMap(Project::getId, Project::getModuleSetting));
|
||||
}
|
||||
|
||||
Map<String, Set<String>> hasModuleProjectIds = new HashMap<>();
|
||||
Map<String, String> finalModuleMap = moduleMap;
|
||||
Set<String> searchCaseProjectIds = new HashSet<>();
|
||||
Set<String> searchReviewProjectIds = new HashSet<>();
|
||||
Set<String> searchApiProjectIds = new HashSet<>();
|
||||
Set<String> searchApiCaseProjectIds = new HashSet<>();
|
||||
Set<String> searchScenarioProjectIds = new HashSet<>();
|
||||
Set<String> searchPlanProjectIds = new HashSet<>();
|
||||
Set<String> searchBugProjectIds = new HashSet<>();
|
||||
//查出用户在选中的项目中有读取权限的, admin所有项目都有权限
|
||||
if (!isAdmin) {
|
||||
Set<String> permissionSet = getPermissionSet();
|
||||
Map<String, Set<String>> hasUserPermissionProjectIds = permissionCheckService.getHasUserPermissionProjectIds(userId, projectSet, permissionSet);
|
||||
//查出这些项目分别有模块的
|
||||
Set<String> functionalProjectIds = hasUserPermissionProjectIds.get(PermissionConstants.FUNCTIONAL_CASE_READ);
|
||||
//检查是否开启功能用例模块
|
||||
if (CollectionUtils.isNotEmpty(functionalProjectIds)) {
|
||||
searchCaseProjectIds = functionalProjectIds.stream().filter(t -> finalModuleMap.get(t).contains(FUNCTIONAL_CASE)).collect(Collectors.toSet());
|
||||
}
|
||||
Set<String> reviewProjectIds = hasUserPermissionProjectIds.get(PermissionConstants.CASE_REVIEW_READ);
|
||||
if (CollectionUtils.isNotEmpty(reviewProjectIds)) {
|
||||
searchReviewProjectIds = reviewProjectIds.stream().filter(t -> finalModuleMap.get(t).contains(FUNCTIONAL_CASE)).collect(Collectors.toSet());
|
||||
}
|
||||
//检查是否开启接口模块
|
||||
Set<String> apiProjectIds = hasUserPermissionProjectIds.get(PermissionConstants.PROJECT_API_DEFINITION_READ);
|
||||
if (CollectionUtils.isNotEmpty(apiProjectIds)) {
|
||||
searchApiProjectIds = apiProjectIds.stream().filter(t -> finalModuleMap.get(t).contains(API_TEST)).collect(Collectors.toSet());
|
||||
}
|
||||
Set<String> apiCaseProjectIds = hasUserPermissionProjectIds.get(PermissionConstants.PROJECT_API_DEFINITION_CASE_READ);
|
||||
if (CollectionUtils.isNotEmpty(apiCaseProjectIds)) {
|
||||
searchApiCaseProjectIds = apiCaseProjectIds.stream().filter(t -> finalModuleMap.get(t).contains(API_TEST)).collect(Collectors.toSet());
|
||||
}
|
||||
Set<String> scenarioProjectIds = hasUserPermissionProjectIds.get(PermissionConstants.PROJECT_API_SCENARIO_READ);
|
||||
if (CollectionUtils.isNotEmpty(scenarioProjectIds)) {
|
||||
searchScenarioProjectIds = scenarioProjectIds.stream().filter(t -> finalModuleMap.get(t).contains(API_TEST)).collect(Collectors.toSet());
|
||||
}
|
||||
//检查是否开启测试计划模块
|
||||
Set<String> planProjectIds = hasUserPermissionProjectIds.get(PermissionConstants.TEST_PLAN_READ);
|
||||
if (CollectionUtils.isNotEmpty(scenarioProjectIds)) {
|
||||
searchPlanProjectIds = planProjectIds.stream().filter(t -> finalModuleMap.get(t).contains(TEST_PLAN)).collect(Collectors.toSet());
|
||||
}
|
||||
//检查是否开启缺陷模块
|
||||
Set<String> bugProjectIds = hasUserPermissionProjectIds.get(PermissionConstants.PROJECT_BUG_READ);
|
||||
if (CollectionUtils.isNotEmpty(bugProjectIds)) {
|
||||
searchBugProjectIds = bugProjectIds.stream().filter(t -> finalModuleMap.get(t).contains(BUG)).collect(Collectors.toSet());
|
||||
}
|
||||
} else {
|
||||
//查出这些项目分别有模块的
|
||||
searchCaseProjectIds = projectSet.stream().filter(t -> finalModuleMap.get(t).contains(FUNCTIONAL_CASE)).collect(Collectors.toSet());
|
||||
searchReviewProjectIds = projectSet.stream().filter(t -> finalModuleMap.get(t).contains(FUNCTIONAL_CASE)).collect(Collectors.toSet());
|
||||
searchApiProjectIds = projectSet.stream().filter(t -> finalModuleMap.get(t).contains(API_TEST)).collect(Collectors.toSet());
|
||||
searchApiCaseProjectIds = projectSet.stream().filter(t -> finalModuleMap.get(t).contains(API_TEST)).collect(Collectors.toSet());
|
||||
searchScenarioProjectIds = projectSet.stream().filter(t -> finalModuleMap.get(t).contains(API_TEST)).collect(Collectors.toSet());
|
||||
searchPlanProjectIds = projectSet.stream().filter(t -> finalModuleMap.get(t).contains(TEST_PLAN)).collect(Collectors.toSet());
|
||||
searchBugProjectIds = projectSet.stream().filter(t -> finalModuleMap.get(t).contains(BUG)).collect(Collectors.toSet());
|
||||
}
|
||||
hasModuleProjectIds.put(PermissionConstants.FUNCTIONAL_CASE_READ, searchCaseProjectIds);
|
||||
hasModuleProjectIds.put(PermissionConstants.CASE_REVIEW_READ, searchReviewProjectIds);
|
||||
hasModuleProjectIds.put(PermissionConstants.PROJECT_API_DEFINITION_READ, searchApiProjectIds);
|
||||
hasModuleProjectIds.put(PermissionConstants.PROJECT_API_DEFINITION_CASE_READ, searchApiCaseProjectIds);
|
||||
hasModuleProjectIds.put(PermissionConstants.PROJECT_API_SCENARIO_READ, searchScenarioProjectIds);
|
||||
hasModuleProjectIds.put(PermissionConstants.TEST_PLAN_READ, searchPlanProjectIds);
|
||||
hasModuleProjectIds.put(PermissionConstants.PROJECT_BUG_READ, searchBugProjectIds);
|
||||
|
||||
return hasModuleProjectIds;
|
||||
}
|
||||
|
||||
private static Set<String> getPermissionSet() {
|
||||
Set<String> permissionSet = new HashSet<>();
|
||||
permissionSet.add(PermissionConstants.FUNCTIONAL_CASE_READ);
|
||||
permissionSet.add(PermissionConstants.CASE_REVIEW_READ);
|
||||
permissionSet.add(PermissionConstants.PROJECT_API_DEFINITION_READ);
|
||||
permissionSet.add(PermissionConstants.PROJECT_API_DEFINITION_CASE_READ);
|
||||
permissionSet.add(PermissionConstants.PROJECT_API_SCENARIO_READ);
|
||||
permissionSet.add(PermissionConstants.TEST_PLAN_READ);
|
||||
permissionSet.add(PermissionConstants.PROJECT_BUG_READ);
|
||||
return permissionSet;
|
||||
}
|
||||
|
||||
private boolean isAdmin(String userId) {
|
||||
UserDTO userDTO = permissionCheckService.getUserDTO(userId);
|
||||
return permissionCheckService.checkAdmin(userDTO);
|
||||
}
|
||||
}
|
|
@ -8,14 +8,12 @@ import io.metersphere.system.domain.UserRolePermission;
|
|||
import io.metersphere.system.dto.user.UserDTO;
|
||||
import io.metersphere.system.service.UserLoginService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
|
@ -25,34 +23,88 @@ public class PermissionCheckService {
|
|||
private UserLoginService userLoginService;
|
||||
|
||||
public boolean userHasProjectPermission(String userId, String projectId, String permission) {
|
||||
UserDTO user = getUserDTO(userId);
|
||||
if (user == null) return false;
|
||||
// 判断是否是超级管理员
|
||||
if (checkAdmin(user)) return true;
|
||||
return checkHasPermission(projectId, permission, user);
|
||||
}
|
||||
|
||||
private static boolean checkHasPermission(String projectId, String permission, UserDTO user) {
|
||||
Map<String, List<UserRolePermission>> userRolePermissions = new HashMap<>();
|
||||
Map<String, UserRole> role = new HashMap<>();
|
||||
UserDTO user = userLoginService.getUserDTO(userId);
|
||||
if (user != null) {
|
||||
user.getUserRoleRelations().forEach(ug -> user.getUserRolePermissions().forEach(gp -> {
|
||||
if (StringUtils.equalsIgnoreCase(gp.getUserRole().getId(), ug.getRoleId())) {
|
||||
userRolePermissions.put(ug.getId(), gp.getUserRolePermissions());
|
||||
role.put(ug.getId(), gp.getUserRole());
|
||||
}
|
||||
}));
|
||||
// 判断是否是超级管理员
|
||||
long count = user.getUserRoles()
|
||||
.stream()
|
||||
.filter(g -> StringUtils.equalsIgnoreCase(g.getId(), InternalUserRole.ADMIN.getValue()))
|
||||
.count();
|
||||
if (count > 0) {
|
||||
return true;
|
||||
getUserAllPermissions(user, userRolePermissions, role);
|
||||
Set<String> currentProjectPermissions = user.getUserRoleRelations().stream()
|
||||
.filter(ug -> role.get(ug.getId()) != null && StringUtils.equalsIgnoreCase(role.get(ug.getId()).getType(), UserRoleType.PROJECT.name()))
|
||||
.filter(ug -> StringUtils.equalsIgnoreCase(ug.getSourceId(), projectId))
|
||||
.flatMap(ug -> userRolePermissions.get(ug.getId()).stream())
|
||||
.map(UserRolePermission::getPermissionId)
|
||||
.collect(Collectors.toSet());
|
||||
return currentProjectPermissions.contains(permission);
|
||||
}
|
||||
|
||||
public UserDTO getUserDTO(String userId) {
|
||||
return userLoginService.getUserDTO(userId);
|
||||
}
|
||||
|
||||
public boolean checkAdmin(UserDTO user) {
|
||||
long count = user.getUserRoles()
|
||||
.stream()
|
||||
.filter(g -> StringUtils.equalsIgnoreCase(g.getId(), InternalUserRole.ADMIN.getValue()))
|
||||
.count();
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
private static void getUserAllPermissions(UserDTO user, Map<String, List<UserRolePermission>> userRolePermissions, Map<String, UserRole> role) {
|
||||
user.getUserRoleRelations().forEach(ug -> user.getUserRolePermissions().forEach(gp -> {
|
||||
if (StringUtils.equalsIgnoreCase(gp.getUserRole().getId(), ug.getRoleId())) {
|
||||
userRolePermissions.put(ug.getId(), gp.getUserRolePermissions());
|
||||
role.put(ug.getId(), gp.getUserRole());
|
||||
}
|
||||
Set<String> currentProjectPermissions = user.getUserRoleRelations().stream()
|
||||
.filter(ug -> role.get(ug.getId()) != null && StringUtils.equalsIgnoreCase(role.get(ug.getId()).getType(), UserRoleType.PROJECT.name()))
|
||||
.filter(ug -> StringUtils.equalsIgnoreCase(ug.getSourceId(), projectId))
|
||||
.flatMap(ug -> userRolePermissions.get(ug.getId()).stream())
|
||||
.map(UserRolePermission::getPermissionId)
|
||||
.collect(Collectors.toSet());
|
||||
return currentProjectPermissions.contains(permission);
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户某些权限所占据的项目集合
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param projectIds 项目ids
|
||||
* @param permissions 需要判断的权限集合
|
||||
* @return 有该类型权限的项目ids的map
|
||||
*/
|
||||
public Map<String, Set<String>> getHasUserPermissionProjectIds(String userId, Set<String>projectIds, Set<String> permissions) {
|
||||
UserDTO user = getUserDTO(userId);
|
||||
if (user == null) return new HashMap<>();
|
||||
// 注意超级管理员包含所有权限,这里不予返回,请在方法外自行判断
|
||||
Map<String, Set<String>> permissionProjectIdMap = new HashMap<>();
|
||||
Map<String, List<UserRolePermission>> projectPermissionMap = new HashMap<>();
|
||||
Map<String, List<UserRolePermission>>rolePermissionMap = new HashMap<>();
|
||||
|
||||
user.getUserRolePermissions().forEach(t->{
|
||||
if (StringUtils.equalsIgnoreCase(t.getUserRole().getType(), UserRoleType.PROJECT.name())) {
|
||||
rolePermissionMap.put(t.getUserRole().getId(),t.getUserRolePermissions());
|
||||
}
|
||||
});
|
||||
user.getUserRoleRelations().forEach(ug -> {
|
||||
List<UserRolePermission> userRolePermissions = rolePermissionMap.get(ug.getRoleId());
|
||||
if (CollectionUtils.isNotEmpty(userRolePermissions) && projectIds.contains(ug.getSourceId())) {
|
||||
projectPermissionMap.put(ug.getSourceId(),userRolePermissions);
|
||||
}
|
||||
});
|
||||
projectPermissionMap.forEach((projectId, userRolePermissions)->{
|
||||
for (UserRolePermission userRolePermission : userRolePermissions) {
|
||||
if (permissions.contains(userRolePermission.getPermissionId())) {
|
||||
permissionProjectIdMap.computeIfAbsent(userRolePermission.getPermissionId(), key -> new HashSet<>()).add(projectId);
|
||||
}
|
||||
}
|
||||
});
|
||||
return permissionProjectIdMap;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue