diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties index 860c37c842..24b9ab35ab 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties @@ -407,4 +407,13 @@ http_result_validate=parameter validate failure http_result_unauthorized=user authentication failure http_result_forbidden=permission authentication failure -enum_value_valid_message=The enumeration value is invalid, must be \ No newline at end of file +enum_value_valid_message=The enumeration value is invalid, must be + +#system project +project_admin=Project admin +project_member=Project member +project=Project +add=Add +delete=Delete +update=Update +project_is_not_exist=Project is not exist \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties index 1c9870dd8f..cd70a449bc 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties @@ -407,9 +407,11 @@ http_result_forbidden=权限认证失败 enum_value_valid_message=枚举值不合法,必须为 -project_admin=添加项目管理员 -project_member=添加项目成员 +#system project +project_admin=项目管理员 +project_member=项目成员 project=项目 add=添加 delete=删除 -update=更新 \ No newline at end of file +update=更新 +project_is_not_exist=项目不存在 diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties index a7277a57ae..2f932d09f1 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties @@ -404,4 +404,13 @@ http_result_validate=參數校驗失敗 http_result_unauthorized=用戶認證失敗 http_result_forbidden=權限認證失敗 -enum_value_valid_message=枚舉值不合法,必須為 \ No newline at end of file +enum_value_valid_message=枚舉值不合法,必須為 + +#system project +project_admin=項目管理員 +project_member=項目成員 +project=項目 +add=添加 +delete=删除 +update=更新 +project_is_not_exist=項目不存在 \ No newline at end of file diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemProjectController.java b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemProjectController.java index a38d4dbad3..e9c89de706 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemProjectController.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemProjectController.java @@ -16,6 +16,7 @@ import io.metersphere.sdk.util.Pager; import io.metersphere.sdk.util.SessionUtils; import io.metersphere.sdk.util.Translator; import io.metersphere.system.dto.UserExtend; +import io.metersphere.system.request.ProjectAddMemberBatchRequest; import io.metersphere.system.request.ProjectAddMemberRequest; import io.metersphere.system.request.ProjectMemberRequest; import io.metersphere.system.request.ProjectRequest; @@ -107,7 +108,10 @@ public class SystemProjectController { @RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_UPDATE) @Operation(summary = "添加项目成员") public void addProjectMember(@Validated @RequestBody ProjectAddMemberRequest request) { - systemProjectService.addProjectMember(request, SessionUtils.getUserId(), false, "/system/project/add-member", + ProjectAddMemberBatchRequest batchRequest = new ProjectAddMemberBatchRequest(); + batchRequest.setProjectIds(List.of(request.getProjectId())); + batchRequest.setUserIds(request.getUserIds()); + systemProjectService.addProjectMember(batchRequest, SessionUtils.getUserId(), false, "/system/project/add-member", OperationLogType.ADD.name(), HttpMethodConstants.POST.name(), Translator.get("add")); } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/request/ProjectAddMemberBatchRequest.java b/backend/services/system-setting/src/main/java/io/metersphere/system/request/ProjectAddMemberBatchRequest.java new file mode 100644 index 0000000000..78daf0c8cd --- /dev/null +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/request/ProjectAddMemberBatchRequest.java @@ -0,0 +1,15 @@ +package io.metersphere.system.request; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.util.List; + +@Data +public class ProjectAddMemberBatchRequest extends ProjectAddMemberRequest{ + @Schema(title = "项目ID集合", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "{project.id.not_blank}") + private List projectIds; + +} diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/service/SystemProjectService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/service/SystemProjectService.java index d31000ff1d..83f0452528 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/service/SystemProjectService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/service/SystemProjectService.java @@ -25,13 +25,17 @@ import io.metersphere.system.dto.UserExtend; import io.metersphere.system.mapper.ExtSystemProjectMapper; import io.metersphere.system.mapper.UserMapper; import io.metersphere.system.mapper.UserRoleRelationMapper; -import io.metersphere.system.request.ProjectAddMemberRequest; +import io.metersphere.system.request.ProjectAddMemberBatchRequest; import io.metersphere.system.request.ProjectMemberRequest; import io.metersphere.system.request.ProjectRequest; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.session.ExecutorType; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.SqlSessionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -57,6 +61,8 @@ public class SystemProjectService { private OperationLogService operationLogService; private final ProjectServiceInvoker serviceInvoker; + @Resource + private SqlSessionFactory sqlSessionFactory; private final static String prefix = "/system/project"; private final static String addProject = prefix + "/add"; @@ -73,19 +79,16 @@ public class SystemProjectService { } /** - * - * @param addProjectDTO - * 添加项目的时候 默认给用户组添加管理员和成员的权限 + * @param addProjectDTO 添加项目的时候 默认给用户组添加管理员和成员的权限 * @return */ - public Project add(AddProjectRequest addProjectDTO , String createUser) { - //TODO 添加项目需要检查配额 这个需要等后续定下来补全逻辑 + public Project add(AddProjectRequest addProjectDTO, String createUser) { Project project = new Project(); project.setId(UUID.randomUUID().toString()); project.setName(addProjectDTO.getName()); project.setOrganizationId(addProjectDTO.getOrganizationId()); - checkProjectExist(project); + checkProjectExistByName(project); project.setCreateTime(System.currentTimeMillis()); project.setUpdateTime(System.currentTimeMillis()); project.setUpdateUser(createUser); @@ -93,14 +96,14 @@ public class SystemProjectService { project.setEnable(addProjectDTO.getEnable()); project.setDescription(addProjectDTO.getDescription()); projectMapper.insertSelective(project); - ProjectAddMemberRequest memberRequest = new ProjectAddMemberRequest(); - memberRequest.setProjectId(project.getId()); + ProjectAddMemberBatchRequest memberRequest = new ProjectAddMemberBatchRequest(); + memberRequest.setProjectIds(List.of(project.getId())); memberRequest.setUserIds(addProjectDTO.getUserIds()); this.addProjectMember(memberRequest, createUser, true, addProject, OperationLogType.ADD.name(), HttpMethodConstants.POST.name(), Translator.get("add")); return project; } - private void checkProjectExist(Project project) { + private void checkProjectExistByName(Project project) { ProjectExample example = new ProjectExample(); example.createCriteria().andNameEqualTo(project.getName()).andOrganizationIdEqualTo(project.getOrganizationId()); if (projectMapper.selectByExample(example).size() > 0) { @@ -108,6 +111,17 @@ public class SystemProjectService { } } + /** + * 检查项目是否存在 + * + * @param id + */ + private void checkProjectNotExist(String id) { + if (projectMapper.selectByPrimaryKey(id) == null) { + throw new MSException(Translator.get("project_is_not_exist")); + } + } + public List getProjectList(ProjectRequest request) { List projectList = extSystemProjectMapper.getProjectList(request); return buildUserInfo(projectList); @@ -132,10 +146,8 @@ public class SystemProjectService { project.setCreateUser(null); project.setCreateTime(null); project.setUpdateTime(System.currentTimeMillis()); - checkProjectExist(project); - if (ObjectUtils.isEmpty(projectMapper.selectByPrimaryKey(project.getId()))) { - return null; - } + checkProjectExistByName(project); + checkProjectNotExist(project.getId()); UserRoleRelationExample example = new UserRoleRelationExample(); example.createCriteria().andSourceIdEqualTo(project.getId()).andRoleIdEqualTo(InternalUserRole.PROJECT_ADMIN.getValue()); List userRoleRelations = userRoleRelationMapper.selectByExample(example); @@ -154,8 +166,8 @@ public class SystemProjectService { userRoleRelationMapper.deleteByExample(deleteExample); } if (CollectionUtils.isNotEmpty(insertIds)) { - ProjectAddMemberRequest memberRequest = new ProjectAddMemberRequest(); - memberRequest.setProjectId(project.getId()); + ProjectAddMemberBatchRequest memberRequest = new ProjectAddMemberBatchRequest(); + memberRequest.setProjectIds(List.of(project.getId())); memberRequest.setUserIds(insertIds); this.addProjectMember(memberRequest, updateUser, true, updateProject, OperationLogType.UPDATE.name(), HttpMethodConstants.POST.name(), Translator.get("update")); @@ -167,6 +179,7 @@ public class SystemProjectService { public int delete(String id, String deleteUser) { //TODO 删除项目删除全部资源 这里的删除只是假删除 + checkProjectNotExist(id); Project project = new Project(); project.setId(id); project.setDeleteUser(deleteUser); @@ -180,41 +193,62 @@ public class SystemProjectService { return projectMemberList; } - public void addProjectMember(ProjectAddMemberRequest request, String createUser, boolean isAdmin, String path, String type, + /*** + * 添加项目成员 + * @param request + * @param createUser + * @param isAdmin 是否需要创建管理员 + * @param path 请求路径 + * @param type 操作类型 + * @param method 请求方法 + * @param content 操作内容 + */ + public void addProjectMember(ProjectAddMemberBatchRequest request, String createUser, boolean isAdmin, String path, String type, String method, String content) { List logDTOList = new ArrayList<>(); - //TODO 添加项目成员需要检查配额 这个需要等后续定下来补全逻辑 - request.getUserIds().forEach(userId -> { - User user = userMapper.selectByPrimaryKey(userId); - if (ObjectUtils.isEmpty(user)) { - throw new MSException(Translator.get("user_not_exist")); - } - if (isAdmin) { - UserRoleRelation adminRole = new UserRoleRelation( - UUID.randomUUID().toString(), - userId, - InternalUserRole.PROJECT_ADMIN.getValue(), - request.getProjectId(), - System.currentTimeMillis(), - createUser); - userRoleRelationMapper.insertSelective(adminRole); - setLog(request.getProjectId(), path, content + Translator.get("project_admin") +": "+ user.getName(), createUser, "", type, method, logDTOList); - } - UserRoleRelationExample userRoleRelationExample = new UserRoleRelationExample(); - userRoleRelationExample.createCriteria().andUserIdEqualTo(userId) - .andSourceIdEqualTo(request.getProjectId()).andRoleIdEqualTo(InternalUserRole.PROJECT_MEMBER.getValue()); - if (userRoleRelationMapper.selectByExample(userRoleRelationExample).size() == 0) { - UserRoleRelation memberRole = new UserRoleRelation( - UUID.randomUUID().toString(), - userId, - InternalUserRole.PROJECT_MEMBER.getValue(), - request.getProjectId(), - System.currentTimeMillis(), - createUser); - userRoleRelationMapper.insertSelective(memberRole); - setLog(request.getProjectId(), path, content + Translator.get("project_member")+": "+ user.getName(), createUser, "", type, method, logDTOList); - } + SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); + UserRoleRelationMapper batchMapper = sqlSession.getMapper(UserRoleRelationMapper.class); + request.getProjectIds().forEach(projectId -> { + checkProjectNotExist(projectId); + request.getUserIds().forEach(userId -> { + User user = userMapper.selectByPrimaryKey(userId); + if (ObjectUtils.isEmpty(user)) { + throw new MSException(Translator.get("user_not_exist")); + } + if (isAdmin) { + UserRoleRelationExample userRoleRelationExample = new UserRoleRelationExample(); + userRoleRelationExample.createCriteria().andUserIdEqualTo(userId) + .andSourceIdEqualTo(projectId).andRoleIdEqualTo(InternalUserRole.PROJECT_MEMBER.getValue()); + if (userRoleRelationMapper.selectByExample(userRoleRelationExample).size() == 0) { + UserRoleRelation adminRole = new UserRoleRelation( + UUID.randomUUID().toString(), + userId, + InternalUserRole.PROJECT_ADMIN.getValue(), + projectId, + System.currentTimeMillis(), + createUser); + batchMapper.insert(adminRole); + setLog(projectId, path, content + Translator.get("project_admin") + ": " + user.getName(), createUser, "", type, method, logDTOList); + } + } + UserRoleRelationExample userRoleRelationExample = new UserRoleRelationExample(); + userRoleRelationExample.createCriteria().andUserIdEqualTo(userId) + .andSourceIdEqualTo(projectId).andRoleIdEqualTo(InternalUserRole.PROJECT_MEMBER.getValue()); + if (userRoleRelationMapper.selectByExample(userRoleRelationExample).size() == 0) { + UserRoleRelation memberRole = new UserRoleRelation( + UUID.randomUUID().toString(), + userId, + InternalUserRole.PROJECT_MEMBER.getValue(), + projectId, + System.currentTimeMillis(), + createUser); + batchMapper.insert(memberRole); + setLog(projectId, path, content + Translator.get("project_member") + ": " + user.getName(), createUser, "", type, method, logDTOList); + } + }); + sqlSession.flushStatements(); + SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory); }); operationLogService.batchAdd(logDTOList); } @@ -229,14 +263,15 @@ public class SystemProjectService { userMapper.updateByPrimaryKeySelective(user); } List logDTOList = new ArrayList<>(); - setLog(projectId, removeProjectMember + "/" + projectId + "/" +userId, - Translator.get("delete") + Translator.get("project_member") +": "+ user.getName(), - userId, "", OperationLogType.DELETE.name() , HttpMethodConstants.GET.name(), logDTOList); + setLog(projectId, removeProjectMember + "/" + projectId + "/" + userId, + Translator.get("delete") + Translator.get("project_member") + ": " + user.getName(), + userId, "", OperationLogType.DELETE.name(), HttpMethodConstants.GET.name(), logDTOList); operationLogService.batchAdd(logDTOList); return userRoleRelationMapper.deleteByExample(userRoleRelationExample); } public int revoke(String id) { + checkProjectNotExist(id); Project project = new Project(); project.setId(id); project.setDeleted(false); @@ -271,7 +306,7 @@ public class SystemProjectService { return extSystemProjectMapper.selectProjectOptions(); } - private static void setLog( String projectId, String path, String content, String userId, Object originalValue, + private static void setLog(String projectId, String path, String content, String userId, Object originalValue, String type, String method, List logDTOList) { LogDTO dto = new LogDTO( "system", diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/SystemProjectControllerTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/SystemProjectControllerTests.java index 7179fa3ace..e0fcbc9a69 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/SystemProjectControllerTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/SystemProjectControllerTests.java @@ -100,6 +100,14 @@ public class SystemProjectControllerTests extends BaseTest { .andExpect(status().isOk()).andDo(print()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); } + private void responseGet(String url, ResultMatcher resultMatcher) throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get(url) + .header(SessionConstants.HEADER_TOKEN, sessionId) + .header(SessionConstants.CSRF_TOKEN, csrfToken) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(resultMatcher).andDo(print()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn(); + } public static T parseObjectFromMvcResult(MvcResult mvcResult, Class parseClass) { try { @@ -338,10 +346,7 @@ public class SystemProjectControllerTests extends BaseTest { this.requestPost(updateProject, project, BAD_REQUEST_MATCHER); //项目不存在 project = this.generatorUpdate("organizationId", "1111","123", null, true, List.of("admin")); - MvcResult mvcResult = this.responsePost(updateProject, project); - String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); - ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); - Assertions.assertNull(resultHolder.getData()); + this.requestPost(updateProject, project, ERROR_REQUEST_MATCHER); } @@ -363,9 +368,7 @@ public class SystemProjectControllerTests extends BaseTest { @Order(10) public void testDeleteProjectError() throws Exception { String id = "1111"; - MvcResult mvcResult = this.responseGet(deleteProject + id); - int count = parseObjectFromMvcResult(mvcResult, Integer.class); - Assertions.assertTrue(count == 0); + this.responseGet(deleteProject + id, ERROR_REQUEST_MATCHER); } @Test @@ -386,9 +389,7 @@ public class SystemProjectControllerTests extends BaseTest { @Order(12) public void testRevokeProjectError() throws Exception { String id = "1111"; - MvcResult mvcResult = this.responseGet(revokeProject + id); - int count = parseObjectFromMvcResult(mvcResult, Integer.class); - Assertions.assertTrue(count == 0); + this.responseGet(revokeProject + id, ERROR_REQUEST_MATCHER); } @Test @@ -404,6 +405,7 @@ public class SystemProjectControllerTests extends BaseTest { List userRoleRelations = userRoleRelationMapper.selectByExample(userRoleRelationExample); Assertions.assertEquals(userRoleRelations.stream().map(UserRoleRelation::getUserId).collect(Collectors.toList()).containsAll(userIds), true); Assertions.assertTrue(userRoleRelations.stream().map(UserRoleRelation::getUserId).collect(Collectors.toList()).containsAll(userIds)); + this.requestPost(addProjectMember, projectAddMemberRequest, status().isOk()); } @Test