From c37acbcbe69dd6dd81a5f6f5472200d18e438f9f Mon Sep 17 00:00:00 2001 From: lan-yonghui Date: Thu, 30 Nov 2023 20:22:32 +0800 Subject: [PATCH] =?UTF-8?q?refactor(=E6=8E=A5=E5=8F=A3=E6=B5=8B=E8=AF=95):?= =?UTF-8?q?=20=E6=8E=A5=E5=8F=A3=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E5=AE=9A=E4=B9=89=E6=8E=A5=E5=8F=A3=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=BB=A5=E5=8F=8A=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sdk/util/FileAssociationSourceUtil.java | 2 + .../definition/ApiDefinitionController.java | 44 ++- .../debug/ApiFileResourceUpdateRequest.java | 8 + .../definition/ApiDefinitionAddRequest.java | 13 +- .../ApiDefinitionUpdateRequest.java | 14 +- .../api/service/ApiFileResourceService.java | 18 +- .../service/debug/ApiDebugModuleService.java | 5 +- .../api/service/debug/ApiDebugService.java | 4 +- .../definition/ApiDefinitionLogService.java | 80 ++-- .../definition/ApiDefinitionService.java | 205 ++++++----- .../definition/ApiTestCaseService.java | 16 +- .../ApiDefinitionControllerTests.java | 347 +++++++++++------- 12 files changed, 464 insertions(+), 292 deletions(-) diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FileAssociationSourceUtil.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FileAssociationSourceUtil.java index 03ac016410..ed8b6e9f92 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FileAssociationSourceUtil.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/util/FileAssociationSourceUtil.java @@ -15,6 +15,7 @@ public class FileAssociationSourceUtil { public static final String SOURCE_TYPE_FUNCTIONAL_CASE = "FUNCTIONAL_CASE"; public static final String SOURCE_TYPE_API_DEBUG = "API_DEBUG"; public static final String SOURCE_TYPE_API_TEST_CASE = "API_TEST_CASE"; + public static final String SOURCE_TYPE_API_DEFINITION = "API_DEFINITION"; public static final Map QUERY_SQL = new HashMap<>(); static { @@ -22,6 +23,7 @@ public class FileAssociationSourceUtil { QUERY_SQL.put(SOURCE_TYPE_FUNCTIONAL_CASE, "SELECT id AS sourceId,name AS sourceName FROM functional_case"); QUERY_SQL.put(SOURCE_TYPE_API_DEBUG, "SELECT id AS sourceId,name AS sourceName FROM api_debug"); QUERY_SQL.put(SOURCE_TYPE_API_TEST_CASE, "SELECT id AS sourceId,name AS sourceName FROM api_test_case"); + QUERY_SQL.put(SOURCE_TYPE_API_DEFINITION, "SELECT id AS sourceId,name AS sourceName FROM api_definition"); } public static void validate(String type) { diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java index c4efd0327a..e24165ab22 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionController.java @@ -16,6 +16,7 @@ import io.swagger.v3.oas.annotations.Operation; import jakarta.annotation.Resource; import jakarta.validation.constraints.NotBlank; import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -38,9 +39,8 @@ public class ApiDefinitionController { @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_ADD) // 添加接口Log示例 @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = ApiDefinitionLogService.class) - public ApiDefinition add(@Validated @RequestPart("request") ApiDefinitionAddRequest request, - @RequestPart(value = "files", required = false) List bodyFiles) { - return apiDefinitionService.create(request, bodyFiles, SessionUtils.getUserId()); + public ApiDefinition add(@Validated @RequestBody ApiDefinitionAddRequest request) { + return apiDefinitionService.create(request, SessionUtils.getUserId()); } @PostMapping(value = "/update") @@ -48,9 +48,8 @@ public class ApiDefinitionController { @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_UPDATE) // 添加修改Log示例 @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = ApiDefinitionLogService.class) - public ApiDefinition update(@Validated @RequestPart("request") ApiDefinitionUpdateRequest request, - @RequestPart(value = "files", required = false) List bodyFiles) { - return apiDefinitionService.update(request, bodyFiles, SessionUtils.getUserId()); + public ApiDefinition update(@Validated @RequestBody ApiDefinitionUpdateRequest request) { + return apiDefinitionService.update(request, SessionUtils.getUserId()); } @PostMapping(value = "/batch-update") @@ -116,7 +115,7 @@ public class ApiDefinitionController { } @PostMapping("/page") - @Operation(summary = "接口测试-接口管理-接口列表(deleted 状态为 0 时为回收站数据)") + @Operation(summary = "接口测试-接口管理-接口列表(deleted 状态为 1 时为回收站数据)") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) public Pager> getPage(@Validated @RequestBody ApiDefinitionPageRequest request) { Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), @@ -131,12 +130,12 @@ public class ApiDefinitionController { public void restore(@Validated @RequestBody ApiDefinitionDeleteRequest request) { apiDefinitionService.restore(request, SessionUtils.getUserId()); } - @PostMapping(value = "/recycle-del") + @PostMapping(value = "/trash-del") @Operation(summary = "接口测试-接口管理-删除回收站接口定义") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE) - @Log(type = OperationLogType.DELETE, expression = "#msClass.recycleDelLog(#request)", msClass = ApiDefinitionLogService.class) - public void recycleDel(@Validated @RequestBody ApiDefinitionDeleteRequest request) { - apiDefinitionService.recycleDel(request, SessionUtils.getUserId()); + @Log(type = OperationLogType.DELETE, expression = "#msClass.trashDelLog(#request)", msClass = ApiDefinitionLogService.class) + public void trashDel(@Validated @RequestBody ApiDefinitionDeleteRequest request) { + apiDefinitionService.trashDel(request, SessionUtils.getUserId()); } @PostMapping(value = "/batch-restore") @Operation(summary = "接口测试-接口管理-批量从回收站恢复接口定义") @@ -146,11 +145,28 @@ public class ApiDefinitionController { apiDefinitionService.batchRestore(request, SessionUtils.getUserId()); } - @PostMapping(value = "/batch-recycle-del") + @PostMapping(value = "/batch-trash-del") @Operation(summary = "接口测试-接口管理-批量从回收站删除接口定义") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE) - public void batchRecycleDel(@Validated @RequestBody ApiDefinitionBatchRequest request) { - apiDefinitionService.batchRecycleDel(request, SessionUtils.getUserId()); + @Log(type = OperationLogType.UPDATE, expression = "#msClass.batchTrashDelLog(#request)", msClass = ApiDefinitionLogService.class) + public void batchTrashDel(@Validated @RequestBody ApiDefinitionBatchRequest request) { + apiDefinitionService.batchTrashDel(request, SessionUtils.getUserId()); + } + + @PostMapping("/page-doc") + @Operation(summary = "接口测试-接口管理-接口文档列表") + @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ) + public Pager> getDocPage(@Validated @RequestBody ApiDefinitionPageRequest request) { + Page page = PageHelper.startPage(request.getCurrent(), request.getPageSize(), + StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc"); + return PageUtils.setPageInfo(page, apiDefinitionService.getDocPage(request)); + } + + @PostMapping("/upload/temp/file") + @Operation(summary = "上传接口定义所需的文件资源,并返回文件ID") + @RequiresPermissions(logical = Logical.OR, value = {PermissionConstants.PROJECT_API_DEFINITION_ADD, PermissionConstants.PROJECT_API_DEFINITION_UPDATE}) + public String uploadTempFile(@RequestParam("file") MultipartFile file) { + return apiDefinitionService.uploadTempFile(file); } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/debug/ApiFileResourceUpdateRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/debug/ApiFileResourceUpdateRequest.java index eaf4f39dfe..0353c2ea2d 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/debug/ApiFileResourceUpdateRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/debug/ApiFileResourceUpdateRequest.java @@ -3,6 +3,7 @@ package io.metersphere.api.dto.debug; import io.metersphere.api.constants.ApiResourceType; import lombok.Data; +import java.io.Serial; import java.io.Serializable; import java.util.List; @@ -13,6 +14,7 @@ import java.util.List; @Data public class ApiFileResourceUpdateRequest implements Serializable { + @Serial private static final long serialVersionUID = 1L; /** @@ -58,4 +60,10 @@ public class ApiFileResourceUpdateRequest implements Serializable { * 记录文件相关操作日志 */ private String operator; + + /** + * 记录日志模块 + * 记录文件相关操作日志 + */ + private String logModule; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionAddRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionAddRequest.java index e3d165ae09..cd6e6b4515 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionAddRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionAddRequest.java @@ -70,11 +70,14 @@ public class ApiDefinitionAddRequest implements Serializable { private String response; /** - * 文件ID列表 - * 需要和上传的文件顺序保持一致 - * 为了解决文件名称重复的问题,需要把文件和ID一一对应 + * 新上传的文件ID * 创建时先按ID创建目录,再把文件放入目录 */ - @Schema(description = "接口所需的所有文件资源ID,与上传的文件顺序保持一致") - private List fileIds; + @Schema(description = "新上传的文件ID") + private List uploadFileIds; + /** + * 新关联的文件ID + */ + @Schema(description = "关联文件ID") + private List linkFileIds; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionUpdateRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionUpdateRequest.java index 2b4bf28ab0..9c5e5478a3 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionUpdateRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/definition/ApiDefinitionUpdateRequest.java @@ -25,10 +25,14 @@ public class ApiDefinitionUpdateRequest extends ApiDefinitionAddRequest { private String id; /** - * 新上传的文件ID - * 为了解决文件名称重复的问题,需要把文件和ID一一对应 - * 创建时先按ID创建目录,再把文件放入目录 + * 删除本地上传的文件ID */ - @Schema(description = "新上传的文件ID,与上传的文件顺序保持一致") - private List addFileIds; + @Schema(description = "删除的文件ID") + private List deleteFileIds; + + /** + * 删除关联的文件ID + */ + @Schema(description = "取消关联文件ID") + private List unLinkRefIds; } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiFileResourceService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiFileResourceService.java index a7e5b9e496..a6d476280a 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiFileResourceService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/ApiFileResourceService.java @@ -15,7 +15,6 @@ import io.metersphere.system.file.FileCenter; import io.metersphere.system.file.FileCopyRequest; import io.metersphere.system.file.FileRepository; import io.metersphere.system.file.FileRequest; -import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.uid.IDGenerator; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; @@ -28,7 +27,6 @@ import org.springframework.web.multipart.MultipartFile; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * @Author: jianxing @@ -125,7 +123,7 @@ public class ApiFileResourceService { apiFileResource.setFileName(fileName); addFileMap.put(fileId, fileName); return apiFileResource; - }).collect(Collectors.toList()); + }).toList(); apiFileResourceMapper.batchInsert(apiFileResources); // 上传文件到对象存储 @@ -135,13 +133,13 @@ public class ApiFileResourceService { // 处理关联文件 if (CollectionUtils.isNotEmpty(resourceUpdateRequest.getLinkFileIds())) { fileAssociationService.association(resourceId, resourceUpdateRequest.getFileAssociationSourceType(), resourceUpdateRequest.getLinkFileIds(), - createFileLogRecord(resourceUpdateRequest.getOperator(), projectId)); + createFileLogRecord(resourceUpdateRequest.getOperator(), projectId, resourceUpdateRequest.getLogModule())); } } - private FileLogRecord createFileLogRecord(String operator, String projectId) { + private FileLogRecord createFileLogRecord(String operator, String projectId, String logModule) { return FileLogRecord.builder() - .logModule(OperationLogModule.API_DEBUG) + .logModule(logModule) .operator(operator) .projectId(projectId) .build(); @@ -184,7 +182,7 @@ public class ApiFileResourceService { List unLinkRefIds = resourceUpdateRequest.getUnLinkRefIds(); if (CollectionUtils.isNotEmpty(unLinkRefIds)) { fileAssociationService.deleteBySourceIdAndFileIds(resourceUpdateRequest.getResourceId(), unLinkRefIds, - createFileLogRecord(resourceUpdateRequest.getOperator(), resourceUpdateRequest.getProjectId())); + createFileLogRecord(resourceUpdateRequest.getOperator(), resourceUpdateRequest.getProjectId(), resourceUpdateRequest.getLogModule())); } } @@ -195,7 +193,7 @@ public class ApiFileResourceService { * @param projectId * @param operator */ - public void deleteByResourceId(String apiDebugDir, String resourceId, String projectId, String operator) { + public void deleteByResourceId(String apiDebugDir, String resourceId, String projectId, String operator, String logModule) { // 处理本地上传的文件 ApiFileResourceExample example = new ApiFileResourceExample(); example.createCriteria() @@ -211,7 +209,7 @@ public class ApiFileResourceService { // 处理关联文件 FileLogRecord fileLogRecord = FileLogRecord.builder() - .logModule(OperationLogModule.PROJECT_FILE_MANAGEMENT) + .logModule(logModule) .operator(operator) .projectId(projectId) .build(); @@ -228,7 +226,7 @@ public class ApiFileResourceService { public List getFileIdsByResourceId(String resourceId) { return getByResourceId(resourceId).stream() .map(ApiFileResource::getFileId) - .collect(Collectors.toList()); + .toList(); } /** diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleService.java index a8817b0335..76dc097973 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugModuleService.java @@ -19,6 +19,7 @@ import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.Translator; import io.metersphere.system.dto.sdk.BaseTreeNode; import io.metersphere.system.dto.sdk.request.NodeMoveRequest; +import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.uid.IDGenerator; import jakarta.annotation.Resource; import org.apache.commons.collections4.CollectionUtils; @@ -197,7 +198,7 @@ public class ApiDebugModuleService extends ModuleTreeService { example.createCriteria().andModuleIdIn(deleteIds); List apiDebugs = apiDebugMapper.selectByExample(example); if (CollectionUtils.isNotEmpty(apiDebugs)) { - List apiDebugIds = apiDebugs.stream().map(ApiDebug::getId).collect(Collectors.toList()); + List apiDebugIds = apiDebugs.stream().map(ApiDebug::getId).toList(); apiDebugMapper.deleteByExample(example); ApiDebugBlobExample blobExample = new ApiDebugBlobExample(); blobExample.createCriteria().andIdIn(apiDebugIds); @@ -205,7 +206,7 @@ public class ApiDebugModuleService extends ModuleTreeService { //删除文件关联关系 apiDebugs.forEach(apiDebug -> { String apiDebugDir = DefaultRepositoryDir.getApiDebugDir(apiDebug.getProjectId(), apiDebug.getId()); - apiFileResourceService.deleteByResourceId(apiDebugDir, apiDebug.getId(), projectId, currentUser); + apiFileResourceService.deleteByResourceId(apiDebugDir, apiDebug.getId(), projectId, currentUser, OperationLogModule.API_DEBUG); }); apiDebugModuleLogService.saveDeleteDataLog(apiDebugs, currentUser, projectId); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java index 5183a48857..14114580b0 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/debug/ApiDebugService.java @@ -16,6 +16,7 @@ import io.metersphere.sdk.constants.DefaultRepositoryDir; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.FileAssociationSourceUtil; +import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.utils.ServiceUtils; import jakarta.annotation.Resource; @@ -93,6 +94,7 @@ public class ApiDebugService { resourceUpdateRequest.setResourceId(sourceId); resourceUpdateRequest.setApiResourceType(ApiResourceType.API_DEBUG); resourceUpdateRequest.setOperator(operator); + resourceUpdateRequest.setLogModule(OperationLogModule.API_DEBUG); resourceUpdateRequest.setFileAssociationSourceType(FileAssociationSourceUtil.SOURCE_TYPE_API_DEBUG); return resourceUpdateRequest; } @@ -125,7 +127,7 @@ public class ApiDebugService { ApiDebug apiDebug = apiDebugMapper.selectByPrimaryKey(id); checkResourceExist(id); String apiDebugDir = DefaultRepositoryDir.getApiDebugDir(apiDebug.getProjectId(), apiDebug.getId()); - apiFileResourceService.deleteByResourceId(apiDebugDir, id, apiDebug.getProjectId(), operator); + apiFileResourceService.deleteByResourceId(apiDebugDir, id, apiDebug.getProjectId(), operator, OperationLogModule.API_DEBUG); apiDebugMapper.deleteByPrimaryKey(id); apiDebugBlobMapper.deleteByPrimaryKey(id); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java index ce52291261..b48e1d813a 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionLogService.java @@ -4,17 +4,15 @@ import io.metersphere.api.domain.ApiDefinition; import io.metersphere.api.domain.ApiDefinitionExample; import io.metersphere.api.dto.definition.*; import io.metersphere.api.mapper.ApiDefinitionMapper; -import io.metersphere.api.mapper.ExtApiDefinitionMapper; import io.metersphere.project.domain.Project; import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.Translator; -import io.metersphere.system.dto.table.TableBatchProcessDTO; import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.dto.LogDTO; -import io.metersphere.system.log.service.OperationLogService; +import io.metersphere.system.utils.SessionUtils; import jakarta.annotation.Resource; import org.apache.commons.collections.CollectionUtils; import org.springframework.stereotype.Service; @@ -30,14 +28,11 @@ public class ApiDefinitionLogService { @Resource private ApiDefinitionMapper apiDefinitionMapper; - @Resource - private ExtApiDefinitionMapper extApiDefinitionMapper; - @Resource private ProjectMapper projectMapper; @Resource - private OperationLogService operationLogService; + private ApiDefinitionService apiDefinitionService; /** * 添加接口日志 @@ -68,7 +63,7 @@ public class ApiDefinitionLogService { * @return */ public LogDTO updateLog(ApiDefinitionUpdateRequest request) { - ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(request.getId()); + ApiDefinition apiDefinition = apiDefinitionService.get(request.getId(), SessionUtils.getUserId()); if(apiDefinition != null){ LogDTO dto = new LogDTO( request.getProjectId(), @@ -94,7 +89,7 @@ public class ApiDefinitionLogService { * @return */ public LogDTO delLog(ApiDefinitionDeleteRequest request) { - ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(request.getId()); + ApiDefinition apiDefinition = apiDefinitionService.get(request.getId(), SessionUtils.getUserId()); if(apiDefinition != null){ LogDTO dto = new LogDTO( request.getProjectId(), @@ -120,7 +115,7 @@ public class ApiDefinitionLogService { * @return */ public List batchDelLog(ApiDefinitionBatchRequest request) { - List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); + List ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); List dtoList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(ids)) { ApiDefinitionExample example = new ApiDefinitionExample(); @@ -152,7 +147,7 @@ public class ApiDefinitionLogService { * @return */ public List batchUpdateLog(ApiDefinitionBatchUpdateRequest request) { - List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); + List ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); List dtoList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(ids)) { ApiDefinitionExample example = new ApiDefinitionExample(); @@ -178,7 +173,7 @@ public class ApiDefinitionLogService { } public LogDTO copyLog(ApiDefinitionCopyRequest request) { - ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(request.getId()); + ApiDefinition apiDefinition = apiDefinitionService.get(request.getId(), SessionUtils.getUserId()); if(apiDefinition != null){ LogDTO dto = new LogDTO( apiDefinition.getProjectId(), @@ -198,7 +193,7 @@ public class ApiDefinitionLogService { } public List batchMoveLog(ApiDefinitionBatchMoveRequest request) { - List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); + List ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); List dtoList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(ids)) { ApiDefinitionExample example = new ApiDefinitionExample(); @@ -224,7 +219,7 @@ public class ApiDefinitionLogService { } public LogDTO followLog(String id) { - ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(id); + ApiDefinition apiDefinition = apiDefinitionService.get(id, SessionUtils.getUserId()); if(apiDefinition != null){ Project project = projectMapper.selectByPrimaryKey(apiDefinition.getProjectId()); LogDTO dto = new LogDTO( @@ -251,7 +246,7 @@ public class ApiDefinitionLogService { * @return */ public LogDTO restoreLog(ApiDefinitionDeleteRequest request) { - ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(request.getId()); + ApiDefinition apiDefinition = apiDefinitionService.get(request.getId(), SessionUtils.getUserId()); if(apiDefinition != null){ LogDTO dto = new LogDTO( request.getProjectId(), @@ -278,7 +273,7 @@ public class ApiDefinitionLogService { * @return */ public List batchRestoreLog(ApiDefinitionBatchRequest request) { - List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); + List ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); List dtoList = new ArrayList<>(); if (CollectionUtils.isNotEmpty(ids)) { ApiDefinitionExample example = new ApiDefinitionExample(); @@ -308,40 +303,55 @@ public class ApiDefinitionLogService { /** * 删除回收站接口定义接口日志 */ - public void recycleDelLog(List apiDefinitions, String operator, Boolean isBatch) { + public LogDTO trashDelLog(ApiDefinitionDeleteRequest request) { + ApiDefinition apiDefinition = apiDefinitionService.get(request.getId(), SessionUtils.getUserId()); + if(apiDefinition != null){ + LogDTO dto = new LogDTO( + request.getProjectId(), + null, + request.getId(), + null, + OperationLogType.DELETE.name(), + OperationLogModule.API_DEFINITION, + apiDefinition.getName()); + + dto.setPath("/api/definition/trash-del"); + dto.setMethod(HttpMethodConstants.POST.name()); + dto.setOriginalValue(JSON.toJSONBytes(apiDefinition)); + return dto; + } + + return null; + } + + /** + * 删除回收站接口定义接口日志 + */ + public List batchTrashDelLog(ApiDefinitionBatchRequest request) { + List ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); List dtoList = new ArrayList<>(); - if (CollectionUtils.isNotEmpty(apiDefinitions)) { + if (CollectionUtils.isNotEmpty(ids)) { + ApiDefinitionExample example = new ApiDefinitionExample(); + example.createCriteria().andIdIn(ids).andDeletedEqualTo(true); + List apiDefinitions = apiDefinitionMapper.selectByExample(example); apiDefinitions.forEach(item -> { LogDTO dto = new LogDTO( item.getProjectId(), "", item.getId(), - operator, + item.getCreateUser(), OperationLogType.DELETE.name(), OperationLogModule.API_DEFINITION, item.getName()); - String path = isBatch ? "/api/definition/batch-recycle-del" : "/api/definition/recycle-del"; - dto.setPath(path); + + dto.setPath("/api/definition/batch-trash-del"); dto.setMethod(HttpMethodConstants.POST.name()); dto.setOriginalValue(JSON.toJSONBytes(item)); dtoList.add(dto); }); } - operationLogService.batchAdd(dtoList); - } - // 获取批量操作选中的ID - public List getBatchApiIds(T dto, String projectId, String protocol, boolean deleted) { - TableBatchProcessDTO request = (TableBatchProcessDTO) dto; - if (request.isSelectAll()) { - List ids = extApiDefinitionMapper.getIds(request, projectId, protocol, deleted); - if (CollectionUtils.isNotEmpty(request.getExcludeIds())) { - ids.removeAll(request.getExcludeIds()); - } - return ids; - } else { - return request.getSelectIds(); - } + return dtoList; } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java index f03765b232..966cb8217c 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionService.java @@ -1,7 +1,9 @@ package io.metersphere.api.service.definition; +import io.metersphere.api.constants.ApiResourceType; import io.metersphere.api.controller.result.ApiResultCode; import io.metersphere.api.domain.*; +import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest; import io.metersphere.api.dto.definition.*; import io.metersphere.api.enums.ApiReportStatus; import io.metersphere.api.mapper.*; @@ -14,10 +16,9 @@ import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.DefaultRepositoryDir; import io.metersphere.sdk.constants.ModuleConstants; import io.metersphere.sdk.exception.MSException; -import io.metersphere.sdk.util.BeanUtils; -import io.metersphere.sdk.util.JSON; -import io.metersphere.sdk.util.LogUtils; -import io.metersphere.sdk.util.SubListUtils; +import io.metersphere.sdk.util.*; +import io.metersphere.system.dto.table.TableBatchProcessDTO; +import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.service.UserLoginService; import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.NumGenerator; @@ -70,8 +71,6 @@ public class ApiDefinitionService { @Resource private ApiTestCaseService apiTestCaseService; - @Resource - private ApiDefinitionLogService apiDefinitionLogService; @Resource private ApiFileResourceService apiFileResourceService; @@ -84,6 +83,36 @@ public class ApiDefinitionService { return list; } + public List getDocPage(ApiDefinitionPageRequest request){ + List list = extApiDefinitionMapper.list(request); + if (!CollectionUtils.isEmpty(list)) { + processApiDefinitionsDoc(list); + } + return list; + } + + private void processApiDefinitionsDoc(List list){ + Set userIds = extractUserIds(list); + Map userMap = userLoginService.getUserNameMap(new ArrayList<>(userIds)); + + list.forEach(item -> { + // Convert User IDs to Names + item.setCreateUserName(userMap.get(item.getCreateUser())); + item.setDeleteUserName(userMap.get(item.getDeleteUser())); + item.setUpdateUserName(userMap.get(item.getUpdateUser())); + + // Convert Blob + Optional apiDefinitionBlobOptional = Optional.ofNullable(apiDefinitionBlobMapper.selectByPrimaryKey(item.getId())); + apiDefinitionBlobOptional.ifPresent(blob -> { + item.setRequest(ApiDataUtils.parseObject(new String(blob.getRequest()), AbstractMsTestElement.class)); + // blob.getResponse() 为 null 时不进行转换 + if (blob.getResponse() != null) { + item.setResponse(ApiDataUtils.parseArray(new String(blob.getResponse()), HttpResponse.class)); + } + }); + }); + } + public ApiDefinitionDTO get(String id, String userId){ ApiDefinitionDTO apiDefinitionDTO = new ApiDefinitionDTO(); // 1. 避免重复查询数据库,将查询结果传递给get方法 @@ -105,7 +134,7 @@ public class ApiDefinitionService { return apiDefinitionDTO; } - public ApiDefinition create(ApiDefinitionAddRequest request, List bodyFiles, String userId) { + public ApiDefinition create(ApiDefinitionAddRequest request, String userId) { ProjectService.checkResourceExist(request.getProjectId()); ApiDefinition apiDefinition = new ApiDefinition(); BeanUtils.copyBean(apiDefinition, request); @@ -131,28 +160,35 @@ public class ApiDefinitionService { apiDefinitionBlob.setResponse(request.getResponse().getBytes()); apiDefinitionBlobMapper.insertSelective(apiDefinitionBlob); - // 处理文件 todo - if (CollectionUtils.isNotEmpty(request.getFileIds()) && CollectionUtils.isNotEmpty(bodyFiles)) { -// String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(request.getProjectId(), apiDefinition.getId()); -// ApiFileResourceUpdateRequest resourceUpdateRequest = new ApiFileResourceUpdateRequest(); -// resourceUpdateRequest.setProjectId(apiDefinition.getProjectId()); -// resourceUpdateRequest.setFileIds(request.getFileIds()); -// resourceUpdateRequest.setAddFileIds(request.getFileIds()); -// resourceUpdateRequest.setFolder(apiDefinitionDir); -// resourceUpdateRequest.setResourceId(apiDefinition.getId()); -// resourceUpdateRequest.setApiResourceType(ApiResourceType.API); -// apiFileResourceService.addFileResource(resourceUpdateRequest, bodyFiles); - } + // 处理文件 + ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(apiDefinition.getId(), apiDefinition.getProjectId(), userId); + resourceUpdateRequest.setUploadFileIds(request.getUploadFileIds()); + resourceUpdateRequest.setLinkFileIds(request.getLinkFileIds()); + apiFileResourceService.addFileResource(resourceUpdateRequest); + return apiDefinition; } - public ApiDefinition update(ApiDefinitionUpdateRequest request, List bodyFiles, String userId) { + private static ApiFileResourceUpdateRequest getApiFileResourceUpdateRequest(String sourceId, String projectId, String operator) { + String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, sourceId); + ApiFileResourceUpdateRequest resourceUpdateRequest = new ApiFileResourceUpdateRequest(); + resourceUpdateRequest.setProjectId(projectId); + resourceUpdateRequest.setFolder(apiDefinitionDir); + resourceUpdateRequest.setResourceId(sourceId); + resourceUpdateRequest.setApiResourceType(ApiResourceType.API); + resourceUpdateRequest.setOperator(operator); + resourceUpdateRequest.setLogModule(OperationLogModule.API_DEFINITION); + resourceUpdateRequest.setFileAssociationSourceType(FileAssociationSourceUtil.SOURCE_TYPE_API_DEFINITION); + return resourceUpdateRequest; + } + + public ApiDefinition update(ApiDefinitionUpdateRequest request, String userId) { ProjectService.checkResourceExist(request.getProjectId()); ApiDefinition originApiDefinition = checkApiDefinition(request.getId()); ApiDefinition apiDefinition = new ApiDefinition(); BeanUtils.copyBean(apiDefinition, request); if(request.getProtocol().equals(ModuleConstants.NODE_PROTOCOL_HTTP)){ - checkUpdateExist(apiDefinition, originApiDefinition); + checkUpdateExist(apiDefinition); } apiDefinition.setStatus(request.getStatus()); apiDefinition.setUpdateUser(userId); @@ -168,23 +204,20 @@ public class ApiDefinitionService { apiDefinitionBlob.setResponse(request.getResponse().getBytes()); apiDefinitionBlobMapper.updateByPrimaryKeySelective(apiDefinitionBlob); - // 处理文件 todo -// String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(originApiDefinition.getProjectId(), apiDefinition.getId()); -// ApiFileResourceUpdateRequest resourceUpdateRequest = new ApiFileResourceUpdateRequest(); -// resourceUpdateRequest.setProjectId(originApiDefinition.getProjectId()); -// resourceUpdateRequest.setFileIds(request.getFileIds()); -// resourceUpdateRequest.setAddFileIds(request.getAddFileIds()); -// resourceUpdateRequest.setFolder(apiDefinitionDir); -// resourceUpdateRequest.setResourceId(apiDefinition.getId()); -// resourceUpdateRequest.setApiResourceType(ApiResourceType.API); -// apiFileResourceService.updateFileResource(resourceUpdateRequest, bodyFiles); + // 处理文件 + ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(originApiDefinition.getId(), originApiDefinition.getProjectId(), userId); + resourceUpdateRequest.setUploadFileIds(request.getUploadFileIds()); + resourceUpdateRequest.setLinkFileIds(request.getLinkFileIds()); + resourceUpdateRequest.setUnLinkRefIds(request.getUnLinkRefIds()); + resourceUpdateRequest.setDeleteFileIds(request.getDeleteFileIds()); + apiFileResourceService.updateFileResource(resourceUpdateRequest); return apiDefinition; } public void batchUpdate(ApiDefinitionBatchUpdateRequest request, String userId) { ProjectService.checkResourceExist(request.getProjectId()); - List ids = apiDefinitionLogService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); + List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); if (CollectionUtils.isNotEmpty(ids)) { if (request.getType().equals("tags")) { handleTags(request, userId, ids); @@ -235,14 +268,14 @@ public class ApiDefinitionService { } public void batchDelete(ApiDefinitionBatchRequest request, String userId) { - List ids = apiDefinitionLogService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); + List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); if (CollectionUtils.isNotEmpty(ids)) { handleDeleteApiDefinition(ids, request.getDeleteAll(), request.getProjectId(), userId); } } public void batchMove(ApiDefinitionBatchMoveRequest request, String userId) { - List ids = apiDefinitionLogService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); + List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false); if (!ids.isEmpty()) { List refIds = extApiDefinitionMapper.getRefIds(ids, false); if (!refIds.isEmpty()) { @@ -305,7 +338,7 @@ public class ApiDefinitionService { /** * 校验接口是否存在 * - * @param apiId + * @param apiId 接口id */ private ApiDefinition checkApiDefinition(String apiId) { ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiId); @@ -319,18 +352,17 @@ public class ApiDefinitionService { ApiDefinitionExample example = new ApiDefinitionExample(); example.createCriteria() .andPathEqualTo(apiDefinition.getPath()).andMethodEqualTo(apiDefinition.getMethod()) - .andModuleIdEqualTo(apiDefinition.getModuleId()).andProtocolEqualTo(apiDefinition.getProtocol()); + .andProtocolEqualTo(apiDefinition.getProtocol()); if (CollectionUtils.isNotEmpty(apiDefinitionMapper.selectByExample(example))) { throw new MSException(ApiResultCode.API_DEFINITION_EXIST); } } - private void checkUpdateExist(ApiDefinition apiDefinition, ApiDefinition originApiDefinition) { + private void checkUpdateExist(ApiDefinition apiDefinition) { if (StringUtils.isNotEmpty(apiDefinition.getPath()) && StringUtils.isNotEmpty(apiDefinition.getMethod())) { ApiDefinitionExample example = new ApiDefinitionExample(); example.createCriteria() .andIdNotEqualTo(apiDefinition.getId()).andProtocolEqualTo(apiDefinition.getProtocol()) - .andModuleIdEqualTo(apiDefinition.getModuleId() == null ? originApiDefinition.getModuleId() : apiDefinition.getModuleId()) .andPathEqualTo(apiDefinition.getPath()).andMethodEqualTo(apiDefinition.getMethod()); if (apiDefinitionMapper.countByExample(example) > 0) { throw new MSException(ApiResultCode.API_DEFINITION_EXIST); @@ -347,8 +379,7 @@ public class ApiDefinitionService { /** * 根据接口id 获取接口是否存在多个版本 * - * @param apiId - * @return + * @param apiId 接口id */ public List getApiDefinitionVersion(String apiId) { ApiDefinition apiDefinition = checkApiDefinition(apiId); @@ -415,24 +446,26 @@ public class ApiDefinitionService { return copyName; } - private void handleDeleteApiDefinition(List ids, Boolean deleteAll, String projectId, String userId) { + private void handleDeleteApiDefinition(List ids, boolean deleteAll, String projectId, String userId) { if (deleteAll) { //全部删除 进入回收站 List refIds = extApiDefinitionMapper.getRefIds(ids, false); if(CollectionUtils.isNotEmpty(refIds)){ - List delApiIds = extApiDefinitionMapper.getIdsByRefId(refIds, false); - extApiDefinitionMapper.batchDeleteByRefId(refIds, userId, projectId); - if(CollectionUtils.isNotEmpty(delApiIds)){ - // 删除接口相关数据到回收站 - deleteApiRelatedData(delApiIds, userId, projectId); - } + SubListUtils.dealForSubList(refIds, 2000, subRefIds -> { + extApiDefinitionMapper.batchDeleteByRefId(subRefIds, userId, projectId); + List delApiIds = extApiDefinitionMapper.getIdsByRefId(subRefIds, false); + SubListUtils.dealForSubList(delApiIds, 2000, subList -> { + if(CollectionUtils.isNotEmpty(delApiIds)){ + // 删除接口相关数据到回收站 + deleteApiRelatedData(subList, userId, projectId); + } + }); + }); } } else { // 列表删除 if (!ids.isEmpty()) { - SubListUtils.dealForSubList(ids, 2000, subList -> { - doDelete(subList, userId, projectId); - }); + SubListUtils.dealForSubList(ids, 2000, subList -> doDelete(subList, userId, projectId)); } } } @@ -494,7 +527,6 @@ public class ApiDefinitionService { List caseIds = caseLists.stream().map(ApiTestCase::getId).distinct().toList(); apiTestCaseService.batchDeleteToGc(caseIds, userId, projectId, true); } - // todo 删除文档到回收站? } private void deleteFollower(String apiId, String userId) { @@ -507,9 +539,7 @@ public class ApiDefinitionService { } private void handleRestoreApiDefinition(List ids, String userId, String projectId){ if (CollectionUtils.isNotEmpty(ids)) { - SubListUtils.dealForSubList(ids, 2000, subList -> { - doRestore(subList, userId, projectId); - }); + SubListUtils.dealForSubList(ids, 2000, subList -> doRestore(subList, userId, projectId)); } } @@ -543,62 +573,54 @@ public class ApiDefinitionService { private void recoverApiRelatedData(List apiIds, String userId, String projectId){ // 是否存在 case 恢复 case - List caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(apiIds, false); + List caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(apiIds, true); if(CollectionUtils.isNotEmpty(caseLists)) { - List caseIds = caseLists.stream().map(ApiTestCase::getId).distinct().toList(); - // todo case 批量恢复方法 - LogUtils.info("caseIds" + JSON.toJSONString(caseIds)); - // todo 恢复文档? + apiTestCaseService.batchRecover(caseLists, userId, projectId); } } - public void recycleDel(ApiDefinitionDeleteRequest request, String userId) { - handleRecycleDelApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId(), false); + public void trashDel(ApiDefinitionDeleteRequest request, String userId) { + handleTrashDelApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId()); } public void batchRestore(ApiDefinitionBatchRequest request, String userId) { - List ids = apiDefinitionLogService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true); + List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true); if (CollectionUtils.isNotEmpty(ids)) { handleRestoreApiDefinition(ids, userId, request.getProjectId()); } } - public void batchRecycleDel(ApiDefinitionBatchRequest request, String userId) { - List ids = apiDefinitionLogService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true); + public void batchTrashDel(ApiDefinitionBatchRequest request, String userId) { + List ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true); if (CollectionUtils.isNotEmpty(ids)) { - handleRecycleDelApiDefinition(ids, userId, request.getProjectId(), true); + handleTrashDelApiDefinition(ids, userId, request.getProjectId()); } } - private void handleRecycleDelApiDefinition(List ids, String userId, String projectId, Boolean isBatch){ + private void handleTrashDelApiDefinition(List ids, String userId, String projectId){ if (CollectionUtils.isNotEmpty(ids)) { - SubListUtils.dealForSubList(ids, 2000, subList -> { - doRecycleDel(subList, userId, projectId, isBatch); - }); + SubListUtils.dealForSubList(ids, 2000, subList -> doTrashDel(subList, userId, projectId)); } } - private void doRecycleDel(List ids, String userId, String projectId, Boolean isBatch){ + private void doTrashDel(List ids, String userId, String projectId){ if(CollectionUtils.isNotEmpty(ids)){ - ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample(); - apiDefinitionExample.createCriteria().andIdIn(ids).andDeletedEqualTo(true).andProjectIdEqualTo(projectId); - List apiDefinitions = apiDefinitionMapper.selectByExample(apiDefinitionExample); - // 删除接口 - apiDefinitionMapper.deleteByExample(apiDefinitionExample); + // 删除上传的文件 + ids.forEach(id -> { + String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, id); + apiFileResourceService.deleteByResourceId(apiDefinitionDir, id, projectId, userId, OperationLogModule.API_DEFINITION); + }); // 删除接口关注人 ApiDefinitionFollowerExample apiDefinitionFollowerExample = new ApiDefinitionFollowerExample(); apiDefinitionFollowerExample.createCriteria().andApiDefinitionIdIn(ids).andUserIdEqualTo(userId); apiDefinitionFollowerMapper.deleteByExample(apiDefinitionFollowerExample); - // 删除上传的文件 - ids.forEach(id -> { - String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, id); - apiFileResourceService.deleteByResourceId(apiDefinitionDir, id, projectId, userId); - }); // 删除接口关联数据 recycleDelApiRelatedData(ids, userId, projectId); - // 写入删除日志 - apiDefinitionLogService.recycleDelLog(apiDefinitions, userId, isBatch); + // 删除接口 + ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample(); + apiDefinitionExample.createCriteria().andIdIn(ids).andDeletedEqualTo(true).andProjectIdEqualTo(projectId); + apiDefinitionMapper.deleteByExample(apiDefinitionExample); } } @@ -609,8 +631,25 @@ public class ApiDefinitionService { List caseIds = caseLists.stream().map(ApiTestCase::getId).distinct().toList(); // case 批量删除回收站 apiTestCaseService.deleteResourceByIds(caseIds, projectId, userId); - // todo 删除文档? } } + + // 获取批量操作选中的ID + public List getBatchApiIds(T dto, String projectId, String protocol, boolean deleted) { + TableBatchProcessDTO request = (TableBatchProcessDTO) dto; + if (request.isSelectAll()) { + List ids = extApiDefinitionMapper.getIds(request, projectId, protocol, deleted); + if (CollectionUtils.isNotEmpty(request.getExcludeIds())) { + ids.removeAll(request.getExcludeIds()); + } + return ids; + } else { + return request.getSelectIds(); + } + } + + public String uploadTempFile(MultipartFile file) { + return apiFileResourceService.uploadTempFile(file); + } } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java index cbe10982d3..750d351b81 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseService.java @@ -18,6 +18,7 @@ import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.mapper.EnvironmentMapper; import io.metersphere.sdk.util.*; import io.metersphere.system.dto.sdk.request.PosRequest; +import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.service.UserLoginService; import io.metersphere.system.uid.IDGenerator; import io.metersphere.system.uid.NumGenerator; @@ -115,6 +116,7 @@ public class ApiTestCaseService { resourceUpdateRequest.setResourceId(sourceId); resourceUpdateRequest.setApiResourceType(ApiResourceType.API_CASE); resourceUpdateRequest.setOperator(operator); + resourceUpdateRequest.setLogModule(OperationLogModule.API_DEFINITION_CASE); resourceUpdateRequest.setFileAssociationSourceType(FileAssociationSourceUtil.SOURCE_TYPE_API_TEST_CASE); return resourceUpdateRequest; } @@ -318,9 +320,7 @@ public class ApiTestCaseService { if (CollectionUtils.isEmpty(ids)) { return; } - SubListUtils.dealForSubList(ids, 2000, subList -> { - deleteResourceByIds(subList, request.getProjectId(), userId); - }); + SubListUtils.dealForSubList(ids, 2000, subList -> deleteResourceByIds(subList, request.getProjectId(), userId)); } public void deleteResourceByIds(List ids, String projectId, String userId) { @@ -329,7 +329,7 @@ public class ApiTestCaseService { //删除文件关联关系 ids.forEach(id -> { String apiCaseDir = DefaultRepositoryDir.getApiCaseDir(projectId, id); - apiFileResourceService.deleteByResourceId(apiCaseDir, id, projectId, userId); + apiFileResourceService.deleteByResourceId(apiCaseDir, id, projectId, userId, OperationLogModule.API_DEFINITION_CASE); }); ApiTestCaseExample example = new ApiTestCaseExample(); example.createCriteria().andIdIn(ids); @@ -371,9 +371,7 @@ public class ApiTestCaseService { if (CollectionUtils.isEmpty(ids)) { return; } - SubListUtils.dealForSubList(ids, 2000, subList -> { - batchMoveToGc(subList, userId, projectId, saveLog); - }); + SubListUtils.dealForSubList(ids, 2000, subList -> batchMoveToGc(subList, userId, projectId, saveLog)); } private void batchMoveToGc(List ids, String userId, String projectId, boolean saveLog) { @@ -389,9 +387,7 @@ public class ApiTestCaseService { if (CollectionUtils.isEmpty(ids)) { return; } - SubListUtils.dealForSubList(ids, 2000, subList -> { - batchEditByType(request, subList, userId, request.getProjectId()); - }); + SubListUtils.dealForSubList(ids, 2000, subList -> batchEditByType(request, subList, userId, request.getProjectId())); } private void batchEditByType(ApiCaseBatchEditRequest request, List ids, String userId, String projectId) { diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java index 58a46ccb72..abcad3649d 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionControllerTests.java @@ -8,13 +8,15 @@ import io.metersphere.api.mapper.*; import io.metersphere.api.service.ApiFileResourceService; import io.metersphere.api.util.ApiDataUtils; import io.metersphere.plugin.api.spi.AbstractMsTestElement; +import io.metersphere.project.dto.filemanagement.FileInfo; +import io.metersphere.project.dto.filemanagement.request.FileUploadRequest; import io.metersphere.project.mapper.ExtBaseProjectVersionMapper; +import io.metersphere.project.service.FileAssociationService; +import io.metersphere.project.service.FileMetadataService; import io.metersphere.sdk.constants.DefaultRepositoryDir; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.dto.api.request.http.MsHTTPElement; -import io.metersphere.sdk.util.BeanUtils; -import io.metersphere.sdk.util.JSON; -import io.metersphere.sdk.util.LogUtils; +import io.metersphere.sdk.util.*; import io.metersphere.system.base.BaseTest; import io.metersphere.system.controller.handler.ResultHolder; import io.metersphere.system.dto.sdk.BaseCondition; @@ -28,6 +30,8 @@ import org.apache.commons.collections.CollectionUtils; import org.junit.jupiter.api.*; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.context.jdbc.SqlConfig; import org.springframework.test.web.servlet.MvcResult; @@ -58,13 +62,15 @@ public class ApiDefinitionControllerTests extends BaseTest { private final static String RESTORE = BASE_PATH + "restore"; private final static String BATCH_RESTORE = BASE_PATH + "batch-restore"; - private final static String RECYCLE_DEL = BASE_PATH + "recycle-del"; - private final static String BATCH_RECYCLE_DEL = BASE_PATH + "batch-recycle-del"; + private final static String TRASH_DEL = BASE_PATH + "trash-del"; + private final static String BATCH_TRASH_DEL = BASE_PATH + "batch-trash-del"; private final static String PAGE = BASE_PATH + "page"; + private final static String PAGE_DOC = BASE_PATH + "page-doc"; private static final String GET = BASE_PATH + "get-detail/"; private static final String FOLLOW = BASE_PATH + "follow/"; private static final String VERSION = BASE_PATH + "version/"; + private static final String UPLOAD_TEMP_FILE = BASE_PATH + "/upload/temp/file"; private static final String DEFAULT_MODULE_ID = "10001"; private static ApiDefinition apiDefinition; @@ -89,6 +95,45 @@ public class ApiDefinitionControllerTests extends BaseTest { @Resource private ExtApiTestCaseMapper extApiTestCaseMapper; + @Resource + private FileMetadataService fileMetadataService; + private static String fileMetadataId; + private static String uploadFileId; + + @Test + @Order(0) + public void uploadTempFile() throws Exception { + // 准备数据,上传文件管理文件 + uploadFileMetadata(); + // @@请求成功 + MockMultipartFile file = getMockMultipartFile("file_upload.JPG"); + String fileId = doUploadTempFile(file); + + // 校验文件存在 + FileRequest fileRequest = new FileRequest(); + fileRequest.setFolder(DefaultRepositoryDir.getSystemTempDir() + "/" + fileId); + fileRequest.setFileName(file.getOriginalFilename()); + Assertions.assertNotNull(FileCenter.getDefaultRepository().getFile(fileRequest)); + + requestUploadPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_ADD, UPLOAD_TEMP_FILE, file); + requestUploadPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_UPDATE, UPLOAD_TEMP_FILE, file); + } + + private String doUploadTempFile(MockMultipartFile file) throws Exception { + return JSON.parseObject(requestUploadFileWithOkAndReturn(UPLOAD_TEMP_FILE, file) + .getResponse() + .getContentAsString(), ResultHolder.class) + .getData().toString(); + } + + private static MockMultipartFile getMockMultipartFile(String fileName) { + return new MockMultipartFile( + "file", + fileName, + MediaType.APPLICATION_OCTET_STREAM_VALUE, + "Hello, World!".getBytes() + ); + } @Test @Order(1) @@ -100,38 +145,33 @@ public class ApiDefinitionControllerTests extends BaseTest { request.setRequest(ApiDataUtils.toJSONString(msHttpElement)); List msHttpResponse = MsHTTPElementTest.getMsHttpResponse(); request.setResponse(ApiDataUtils.toJSONString(msHttpResponse)); - // 构造请求参数 - MultiValueMap paramMap = new LinkedMultiValueMap<>(); - File file = new File( - Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/file_upload.JPG")).getPath() - ); - request.setFileIds(List.of(IDGenerator.nextStr())); - paramMap.add("files", List.of(file)); - paramMap.add("request", JSON.toJSONString(request)); + + uploadFileId = doUploadTempFile(getMockMultipartFile("file_upload.JPG")); + request.setUploadFileIds(List.of(uploadFileId)); + request.setLinkFileIds(List.of(fileMetadataId)); // 执行方法调用 - MvcResult mvcResult = this.requestMultipartWithOkAndReturn(ADD, paramMap); + MvcResult mvcResult = this.requestPostWithOkAndReturn(ADD, request); // 校验请求成功数据 ApiDefinition resultData = getResultData(mvcResult, ApiDefinition.class); - apiDefinition = assertAddApiDefinition(request, msHttpElement, resultData.getId(), request.getFileIds()); + apiDefinition = assertAddApiDefinition(request, msHttpElement, resultData.getId()); + assertUploadFile(apiDefinition.getId(), List.of(uploadFileId)); + assertLinkFile(apiDefinition.getId(), List.of(fileMetadataId)); // 再插入一条数据,便于修改时重名校验 request.setMethod("GET"); request.setPath("/api/admin/posts"); - request.setFileIds(null); - paramMap.clear(); - paramMap.add("request", JSON.toJSONString(request)); - mvcResult = this.requestMultipartWithOkAndReturn(ADD, paramMap); + request.setUploadFileIds(null); + request.setLinkFileIds(null); + mvcResult = this.requestPostWithOkAndReturn(ADD, request); resultData = getResultData(mvcResult, ApiDefinition.class); - assertAddApiDefinition(request, msHttpElement, resultData.getId(), request.getFileIds()); + assertAddApiDefinition(request, msHttpElement, resultData.getId()); // @@重名校验异常 - assertErrorCode(this.requestMultipart(ADD, paramMap), ApiResultCode.API_DEFINITION_EXIST); + assertErrorCode(this.requestPost(ADD, request), ApiResultCode.API_DEFINITION_EXIST); // 校验项目是否存在 request.setProjectId("111"); request.setName("test123"); - paramMap.clear(); - paramMap.add("request", JSON.toJSONString(request)); - assertErrorCode(this.requestMultipart(ADD, paramMap), NOT_FOUND); + assertErrorCode(this.requestPost(ADD, request), NOT_FOUND); // @@校验日志 checkLog(apiDefinition.getId(), OperationLogType.ADD); @@ -139,12 +179,10 @@ public class ApiDefinitionControllerTests extends BaseTest { createdGroupParamValidateTest(ApiDefinitionAddRequest.class, ADD); // @@校验权限 request.setProjectId(DEFAULT_PROJECT_ID); - paramMap.clear(); request.setName("permission-st-6"); request.setMethod("DELETE"); request.setPath("/api/admin/posts"); - paramMap.add("request", JSON.toJSONString(request)); - requestMultipartPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_ADD, ADD, paramMap); + requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_ADD, ADD, request); } private ApiDefinitionAddRequest createApiDefinitionAddRequest() { @@ -164,7 +202,7 @@ public class ApiDefinitionControllerTests extends BaseTest { return request; } - private ApiDefinition assertAddApiDefinition(Object request, MsHTTPElement msHttpElement, String id, List fileIds) throws Exception { + private ApiDefinition assertAddApiDefinition(Object request, MsHTTPElement msHttpElement, String id) { ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(id); ApiDefinitionBlob apiDefinitionBlob = apiDefinitionBlobMapper.selectByPrimaryKey(id); ApiDefinition copyApiDefinition = BeanUtils.copyBean(new ApiDefinition(), apiDefinition); @@ -174,27 +212,6 @@ public class ApiDefinitionControllerTests extends BaseTest { if(apiDefinitionBlob != null){ Assertions.assertEquals(msHttpElement, ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), AbstractMsTestElement.class)); } - // todo 可以直接调用 ApiDebugControllerTests.assertUploadFile 和 ApiDebugControllerTests.assertLinkFile -// if (fileIds != null) { -// // 验证文件的关联关系,以及是否存入对象存储 -// List apiFileResources = apiFileResourceService.getByResourceId(id); -// Assertions.assertEquals(apiFileResources.size(), fileIds.size()); -// -// String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(apiDefinition.getProjectId(), id); -// FileRequest fileRequest = new FileRequest(); -// if (fileIds.size() > 0) { -// for (ApiFileResource apiFileResource : apiFileResources) { -// Assertions.assertEquals(apiFileResource.getProjectId(), apiDefinition.getProjectId()); -// fileRequest.setFolder(apiDefinitionDir + "/" + apiFileResource.getFileId()); -// fileRequest.setFileName(apiFileResource.getFileName()); -// Assertions.assertNotNull(FileCenter.getDefaultRepository().getFile(fileRequest)); -// } -// fileRequest.setFolder(apiDefinitionDir); -// } else { -// fileRequest.setFolder(apiDefinitionDir); -// Assertions.assertTrue(CollectionUtils.isEmpty(FileCenter.getDefaultRepository().getFolderFileNames(fileRequest))); -// } -// } return apiDefinition; } @@ -247,64 +264,68 @@ public class ApiDefinitionControllerTests extends BaseTest { List msHttpResponse = MsHTTPElementTest.getMsHttpResponse(); request.setResponse(ApiDataUtils.toJSONString(msHttpResponse)); - // 构造请求参数 - MultiValueMap paramMap = new LinkedMultiValueMap<>(); - File file = new File( - Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/file_update_upload.JPG")).getPath() - ); - // 带文件的更新 - request.setAddFileIds(List.of(IDGenerator.nextStr())); - request.setFileIds(request.getAddFileIds()); - paramMap.add("files", List.of(file)); - paramMap.add("request", JSON.toJSONString(request)); - - // 执行方法调用 - MvcResult mvcResult = this.requestMultipartWithOkAndReturn(UPDATE, paramMap); + // 清除文件的更新 + request.setUnLinkRefIds(List.of(fileMetadataId)); + request.setDeleteFileIds(List.of(uploadFileId)); + this.requestPostWithOk(UPDATE, request); // 校验请求成功数据 - ApiDefinition resultData = getResultData(mvcResult, ApiDefinition.class); - apiDefinition = assertAddApiDefinition(request, msHttpElement, resultData.getId(), request.getFileIds()); + apiDefinition = assertAddApiDefinition(request, msHttpElement, request.getId()); + assertUploadFile(apiDefinition.getId(), List.of()); + assertLinkFile(apiDefinition.getId(), List.of()); + + // 带文件的更新 + String fileId = doUploadTempFile(getMockMultipartFile("file_upload.JPG")); + request.setUploadFileIds(List.of(fileId)); + request.setLinkFileIds(List.of(fileMetadataId)); + request.setDeleteFileIds(null); + request.setUnLinkRefIds(null); + this.requestPostWithOk(UPDATE, request); + // 校验请求成功数据 + apiDefinition = assertAddApiDefinition(request, msHttpElement, request.getId()); + assertUploadFile(apiDefinition.getId(), List.of(fileId)); + assertLinkFile(apiDefinition.getId(), List.of(fileMetadataId)); // 删除了上一次上传的文件,重新上传一个文件 - request.setAddFileIds(List.of(IDGenerator.nextStr())); - request.setFileIds(request.getAddFileIds()); - paramMap.clear(); - paramMap.add("files", List.of(file)); - paramMap.add("request", JSON.toJSONString(request)); - this.requestMultipartWithOk(UPDATE, paramMap); - assertAddApiDefinition(request, msHttpElement, request.getId(), request.getFileIds()); + request.setDeleteFileIds(List.of(fileId)); + String newFileId1 = doUploadTempFile(getMockMultipartFile("file_upload.JPG")); + request.setUploadFileIds(List.of(newFileId1)); + request.setUnLinkRefIds(List.of(fileMetadataId)); + request.setLinkFileIds(List.of(fileMetadataId)); + this.requestPostWithOk(UPDATE, request); + apiDefinition = assertAddApiDefinition(request, msHttpElement, request.getId()); + assertUploadFile(apiDefinition.getId(), List.of(newFileId1)); + assertLinkFile(apiDefinition.getId(), List.of(fileMetadataId)); // 已有一个文件,再上传一个文件 - request.setAddFileIds(List.of(IDGenerator.nextStr())); - List fileIds = apiFileResourceService.getFileIdsByResourceId(request.getId()); - fileIds.addAll(request.getAddFileIds()); - request.setFileIds(fileIds); - paramMap.clear(); - paramMap.add("files", List.of(file)); - paramMap.add("request", JSON.toJSONString(request)); - this.requestMultipartWithOk(UPDATE, paramMap); - assertAddApiDefinition(request, msHttpElement, request.getId(), request.getFileIds()); + String newFileId2 = doUploadTempFile(getMockMultipartFile("file_update_upload.JPG")); + request.setUploadFileIds(List.of(newFileId2)); + request.setUnLinkRefIds(null); + request.setDeleteFileIds(null); + request.setLinkFileIds(null); + this.requestPostWithOk(UPDATE, request); + apiDefinition = assertAddApiDefinition(request, msHttpElement, request.getId()); + assertUploadFile(apiDefinition.getId(), List.of(newFileId1, newFileId2)); + assertLinkFile(apiDefinition.getId(), List.of(fileMetadataId)); // @@重名校验异常 request.setModuleId("default"); request.setPath("/api/admin/posts"); request.setMethod("GET"); - paramMap.clear(); - paramMap.add("request", JSON.toJSONString(request)); - assertErrorCode(this.requestMultipart(UPDATE, paramMap), ApiResultCode.API_DEFINITION_EXIST); + request.setUploadFileIds(null); + request.setLinkFileIds(null); + request.setDeleteFileIds(null); + request.setUnLinkRefIds(null); + assertErrorCode(this.requestPost(UPDATE, request), ApiResultCode.API_DEFINITION_EXIST); // 校验数据是否存在 request.setId("111"); request.setName("test123"); - paramMap.clear(); - paramMap.add("request", JSON.toJSONString(request)); - assertErrorCode(this.requestMultipart(UPDATE, paramMap), ApiResultCode.API_DEFINITION_NOT_EXIST); + assertErrorCode(this.requestPost(UPDATE, request), ApiResultCode.API_DEFINITION_NOT_EXIST); // 校验项目是否存在 request.setProjectId("111"); request.setName("test123"); - paramMap.clear(); - paramMap.add("request", JSON.toJSONString(request)); - assertErrorCode(this.requestMultipart(UPDATE, paramMap), NOT_FOUND); + assertErrorCode(this.requestPost(UPDATE, request), NOT_FOUND); // @@校验日志 checkLog(apiDefinition.getId(), OperationLogType.UPDATE); @@ -312,10 +333,63 @@ public class ApiDefinitionControllerTests extends BaseTest { createdGroupParamValidateTest(ApiDefinitionUpdateRequest.class, UPDATE); // @@校验权限 request.setProjectId(DEFAULT_PROJECT_ID); - paramMap.clear(); request.setName("permission-st-6"); - paramMap.add("request", JSON.toJSONString(request)); - requestMultipartPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_UPDATE, UPDATE, paramMap); + requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_UPDATE, UPDATE, request); + } + + /** + * 文件管理插入一条数据 + * 便于测试关联文件 + */ + private void uploadFileMetadata() throws Exception { + FileUploadRequest fileUploadRequest = new FileUploadRequest(); + fileUploadRequest.setProjectId(DEFAULT_PROJECT_ID); + //导入正常文件 + MockMultipartFile file = new MockMultipartFile("file", "file_upload.JPG", MediaType.APPLICATION_OCTET_STREAM_VALUE, "aa".getBytes()); + fileMetadataId = fileMetadataService.upload(fileUploadRequest, "admin", file); + } + + /** + * 校验上传的文件 + * @param id + * @param fileIds 全部的文件ID + */ + public static void assertUploadFile(String id, List fileIds) throws Exception { + if (fileIds != null) { + ApiFileResourceService apiFileResourceService = CommonBeanFactory.getBean(ApiFileResourceService.class); + // 验证文件的关联关系,以及是否存入对象存储 + List apiFileResources = apiFileResourceService.getByResourceId(id); + Assertions.assertEquals(apiFileResources.size(), fileIds.size()); + + String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(DEFAULT_PROJECT_ID, id); + FileRequest fileRequest = new FileRequest(); + if (!fileIds.isEmpty()) { + for (ApiFileResource apiFileResource : apiFileResources) { + Assertions.assertEquals(apiFileResource.getProjectId(), DEFAULT_PROJECT_ID); + fileRequest.setFolder(apiDefinitionDir + "/" + apiFileResource.getFileId()); + fileRequest.setFileName(apiFileResource.getFileName()); + Assertions.assertNotNull(FileCenter.getDefaultRepository().getFile(fileRequest)); + } + fileRequest.setFolder(apiDefinitionDir); + } else { + fileRequest.setFolder(apiDefinitionDir); + Assertions.assertTrue(CollectionUtils.isEmpty(FileCenter.getDefaultRepository().getFolderFileNames(fileRequest))); + } + } + } + + /** + * 校验上传的文件 + * @param id + * @param fileIds 全部的文件ID + */ + private static void assertLinkFile(String id, List fileIds) { + FileAssociationService fileAssociationService = CommonBeanFactory.getBean(FileAssociationService.class); + List linkFileIds = fileAssociationService.getFiles(id, FileAssociationSourceUtil.SOURCE_TYPE_API_DEFINITION) + .stream() + .map(FileInfo::getFileId) + .toList(); + Assertions.assertEquals(fileIds, linkFileIds); } @Test @@ -612,14 +686,14 @@ public class ApiDefinitionControllerTests extends BaseTest { @Order(11) @Sql(scripts = {"/dml/init_api_definition.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) public void getPage() throws Exception { - doApiDefinitionPage("All"); - doApiDefinitionPage("KEYWORD"); - doApiDefinitionPage("FILTER"); - doApiDefinitionPage("COMBINE"); - doApiDefinitionPage("DELETED"); + doApiDefinitionPage("All", PAGE); + doApiDefinitionPage("KEYWORD", PAGE); + doApiDefinitionPage("FILTER", PAGE); + doApiDefinitionPage("COMBINE", PAGE); + doApiDefinitionPage("DELETED", PAGE); } - private void doApiDefinitionPage(String search) throws Exception { + private void doApiDefinitionPage(String search, String url) throws Exception { ApiDefinitionPageRequest request = new ApiDefinitionPageRequest(); request.setProjectId(DEFAULT_PROJECT_ID); request.setCurrent(1); @@ -636,7 +710,7 @@ public class ApiDefinitionControllerTests extends BaseTest { default -> {} } - MvcResult mvcResult = this.requestPostWithOkAndReturn(PAGE, request); + MvcResult mvcResult = this.requestPostWithOkAndReturn(url, request); // 获取返回值 String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8); ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class); @@ -723,15 +797,14 @@ public class ApiDefinitionControllerTests extends BaseTest { Assertions.assertTrue(apiDefinitionInfo.getLatest()); } } - // todo 效验 关联数据 -// List caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(Collections.singletonList(apiDefinition.getId()), false); -// if(!caseLists.isEmpty()) { -// caseLists.forEach(item -> { -// Assertions.assertFalse(item.getDeleted()); -// Assertions.assertNull(item.getDeleteUser()); -// Assertions.assertNull(item.getDeleteTime()); -// }); -// } + // 效验 关联数据 + List caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(Collections.singletonList(apiDefinition.getId()), false); + if(!caseLists.isEmpty()) { + caseLists.forEach(item -> { + Assertions.assertNull(item.getDeleteUser()); + Assertions.assertNull(item.getDeleteTime()); + }); + } // @恢复一条数据 apiDefinitionDeleteRequest.setId("111"); @@ -745,13 +818,23 @@ public class ApiDefinitionControllerTests extends BaseTest { @Test @Order(13) @Sql(scripts = {"/dml/init_api_definition.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) - public void testRecycleDel() throws Exception { - LogUtils.info("recycleDel api test"); + public void testTrashDel() throws Exception { + LogUtils.info("trashDel api test"); if(apiDefinition == null){ apiDefinition = apiDefinitionMapper.selectByPrimaryKey("1001"); } if(!apiDefinition.getDeleted()){ - testDel(); + ApiDefinitionDeleteRequest apiDefinitionDeleteRequest = new ApiDefinitionDeleteRequest(); + apiDefinitionDeleteRequest.setId(apiDefinition.getId()); + apiDefinitionDeleteRequest.setProjectId(DEFAULT_PROJECT_ID); + apiDefinitionDeleteRequest.setDeleteAll(false); + // @@请求成功 + this.requestPostWithOkAndReturn(DELETE, apiDefinitionDeleteRequest); + checkLog(apiDefinition.getId(), OperationLogType.DELETE); + apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiDefinition.getId()); + Assertions.assertTrue(apiDefinition.getDeleted()); + Assertions.assertEquals("admin", apiDefinition.getDeleteUser()); + Assertions.assertNotNull(apiDefinition.getDeleteTime()); } // @只存在一个版本 ApiDefinitionDeleteRequest apiDefinitionDeleteRequest = new ApiDefinitionDeleteRequest(); @@ -759,7 +842,7 @@ public class ApiDefinitionControllerTests extends BaseTest { apiDefinitionDeleteRequest.setProjectId(DEFAULT_PROJECT_ID); apiDefinitionDeleteRequest.setDeleteAll(false); // @@请求成功 - this.requestPostWithOkAndReturn(RECYCLE_DEL, apiDefinitionDeleteRequest); + this.requestPostWithOk(TRASH_DEL, apiDefinitionDeleteRequest); checkLog(apiDefinition.getId(), OperationLogType.DELETE); // 验证数据 ApiDefinition apiDefinitionInfo = apiDefinitionMapper.selectByPrimaryKey(apiDefinition.getId()); @@ -774,7 +857,7 @@ public class ApiDefinitionControllerTests extends BaseTest { Assertions.assertEquals(0, caseLists.size()); // @@校验权限 - requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_DELETE, RECYCLE_DEL, apiDefinitionDeleteRequest); + requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_DELETE, TRASH_DEL, apiDefinitionDeleteRequest); } @Test @@ -788,7 +871,7 @@ public class ApiDefinitionControllerTests extends BaseTest { request.setSelectIds(List.of("1002","1004","1005")); request.setExcludeIds(List.of("1005")); request.setSelectAll(false); - this.requestPostWithOkAndReturn(BATCH_RESTORE, request); + this.requestPostWithOk(BATCH_RESTORE, request); // 效验数据结果 ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample(); @@ -799,15 +882,14 @@ public class ApiDefinitionControllerTests extends BaseTest { Assertions.assertFalse(item.getDeleted()); Assertions.assertNull(item.getDeleteUser()); Assertions.assertNull(item.getDeleteTime()); - // todo 效验 关联数据 -// List caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(Collections.singletonList(item.getId()), false); -// if(!caseLists.isEmpty()) { -// caseLists.forEach(test -> { -// Assertions.assertFalse(test.getDeleted()); -// Assertions.assertNull(test.getDeleteUser()); -// Assertions.assertNull(test.getDeleteTime()); -// }); -// } + // 效验 关联数据 + List caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(Collections.singletonList(item.getId()), false); + if(!caseLists.isEmpty()) { + caseLists.forEach(test -> { + Assertions.assertNull(test.getDeleteUser()); + Assertions.assertNull(test.getDeleteTime()); + }); + } }); } @@ -822,7 +904,7 @@ public class ApiDefinitionControllerTests extends BaseTest { BaseCondition baseCondition = new BaseCondition(); baseCondition.setKeyword("st-6"); request.setCondition(baseCondition); - this.requestPostWithOkAndReturn(BATCH_RESTORE, request); + this.requestPostWithOk(BATCH_RESTORE, request); // @@校验日志 checkLog("1006", OperationLogType.UPDATE); @@ -842,7 +924,7 @@ public class ApiDefinitionControllerTests extends BaseTest { // 删除选中 request.setSelectIds(List.of("1002","1004")); request.setSelectAll(false); - this.requestPostWithOkAndReturn(BATCH_RECYCLE_DEL, request); + this.requestPostWithOk(BATCH_TRASH_DEL, request); // 效验数据结果 ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample(); apiDefinitionExample.createCriteria().andIdIn(request.getSelectIds()); @@ -867,11 +949,22 @@ public class ApiDefinitionControllerTests extends BaseTest { BaseCondition baseCondition = new BaseCondition(); baseCondition.setKeyword("st-6"); request.setCondition(baseCondition); - this.requestPostWithOkAndReturn(BATCH_RECYCLE_DEL, request); + this.requestPostWithOk(BATCH_TRASH_DEL, request); // @@校验日志 checkLog("1006", OperationLogType.DELETE); // @@校验权限 - requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_DELETE, BATCH_RECYCLE_DEL, request); + requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_DELETE, BATCH_TRASH_DEL, request); + } + + @Test + @Order(16) + @Sql(scripts = {"/dml/init_api_definition.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED)) + public void getPageDoc() throws Exception { + doApiDefinitionPage("All", PAGE_DOC); + doApiDefinitionPage("KEYWORD", PAGE_DOC); + doApiDefinitionPage("FILTER", PAGE_DOC); + doApiDefinitionPage("COMBINE", PAGE_DOC); + doApiDefinitionPage("DELETED", PAGE_DOC); } }