refactor(接口测试): 优化场景资源文件存储逻辑

This commit is contained in:
AgAngle 2024-03-28 19:52:08 +08:00 committed by Craftsman
parent 5769ba327f
commit 229c99d280
14 changed files with 257 additions and 108 deletions

View File

@ -56,6 +56,7 @@ public class DefaultRepositoryDir {
*/ */
private static final String PROJECT_API_DEBUG_DIR = PROJECT_DIR + "/api-debug/%s"; private static final String PROJECT_API_DEBUG_DIR = PROJECT_DIR + "/api-debug/%s";
private static final String PROJECT_API_SCENARIO_DIR = PROJECT_DIR + "/api-scenario/%s"; private static final String PROJECT_API_SCENARIO_DIR = PROJECT_DIR + "/api-scenario/%s";
private static final String PROJECT_API_SCENARIO_STEP_DIR = PROJECT_API_SCENARIO_DIR + "/step/%s";
private static final String PROJECT_BUG_DIR = PROJECT_DIR + "/bug/%s"; private static final String PROJECT_BUG_DIR = PROJECT_DIR + "/bug/%s";
/** /**
@ -126,4 +127,12 @@ public class DefaultRepositoryDir {
public static String getApiScenarioDir(String projectId, String apiScenarioId) { public static String getApiScenarioDir(String projectId, String apiScenarioId) {
return String.format(PROJECT_API_SCENARIO_DIR, projectId, apiScenarioId); return String.format(PROJECT_API_SCENARIO_DIR, projectId, apiScenarioId);
} }
public static String getApiScenarioStepDir(String projectId, String apiScenarioId, String stepId) {
return String.format(PROJECT_API_SCENARIO_STEP_DIR, projectId, apiScenarioId, stepId);
}
public static String getProjectDir(String projectId) {
return String.format(PROJECT_DIR, projectId);
}
} }

View File

@ -0,0 +1,26 @@
package io.metersphere.api.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* @Author: jianxing
* @CreateTime: 2024-03-26 17:53
*/
@Data
public class ResourceAddFileParam {
/**
* 新上传的文件ID
* 创建时先按ID创建目录再把文件放入目录
*/
@Schema(description = "新上传的文件ID")
private List<String> uploadFileIds;
/**
* 新关联的文件ID
*/
@Schema(description = "关联文件ID")
private List<String> linkFileIds;
}

View File

@ -0,0 +1,22 @@
package io.metersphere.api.dto;
import lombok.Data;
import java.util.List;
/**
* @Author: jianxing
* @CreateTime: 2024-03-26 17:53
*/
@Data
public class ResourceUpdateFileParam extends ResourceAddFileParam {
/**
* 删除本地上传的文件ID
*/
private List<String> deleteFileIds;
/**
* 删除关联的文件ID
*/
private List<String> unLinkFileIds;
}

View File

@ -1,6 +1,7 @@
package io.metersphere.api.dto.scenario; package io.metersphere.api.dto.scenario;
import io.metersphere.api.constants.ApiScenarioStatus; import io.metersphere.api.constants.ApiScenarioStatus;
import io.metersphere.api.dto.ResourceAddFileParam;
import io.metersphere.system.valid.EnumValue; import io.metersphere.system.valid.EnumValue;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@ -73,15 +74,16 @@ public class ApiScenarioAddRequest {
private Map<String, Object> stepDetails; private Map<String, Object> stepDetails;
/** /**
* 新上传的文件ID * 步骤文件操作相关参数
* 创建时先按ID创建目录再把文件放入目录 * key 为步骤ID
* 值为文件参数
*/ */
@Schema(description = "新上传的文件ID") @Schema(description = "步骤文件操作相关参数")
private List<String> uploadFileIds; private Map<String, ResourceAddFileParam> stepFileParam;
/** /**
* 新关联的文件ID * 步骤文件操作相关参数
*/ */
@Schema(description = "关联文件ID") @Schema(description = "场景文件操作相关参数")
private List<String> linkFileIds; private ResourceAddFileParam fileParam;
} }

View File

@ -1,6 +1,7 @@
package io.metersphere.api.dto.scenario; package io.metersphere.api.dto.scenario;
import io.metersphere.api.constants.ApiScenarioStatus; import io.metersphere.api.constants.ApiScenarioStatus;
import io.metersphere.api.dto.ResourceUpdateFileParam;
import io.metersphere.system.valid.EnumValue; import io.metersphere.system.valid.EnumValue;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
@ -71,25 +72,16 @@ public class ApiScenarioUpdateRequest {
private Map<String, Object> stepDetails; private Map<String, Object> stepDetails;
/** /**
* 新上传的文件ID * 步骤文件操作相关参数
* 创建时先按ID创建目录再把文件放入目录 * key 为步骤ID
* 值为文件参数
*/ */
@Schema(description = "新上传的文件ID") @Schema(description = "步骤文件操作相关参数")
private List<String> uploadFileIds; private Map<String, ResourceUpdateFileParam> stepFileParam;
/** /**
* 新关联的文件ID * 步骤文件操作相关参数
*/ */
@Schema(description = "关联文件ID") @Schema(description = "场景文件操作相关参数")
private List<String> linkFileIds; private ResourceUpdateFileParam fileParam;
/**
* 删除本地上传的文件ID
*/
private List<String> deleteFileIds;
/**
* 删除关联的文件ID
*/
private List<String> unLinkFileIds;
} }

View File

@ -234,6 +234,53 @@ public class ApiFileResourceService {
fileAssociationService.deleteBySourceIds(List.of(resourceId), fileLogRecord); fileAssociationService.deleteBySourceIds(List.of(resourceId), fileLogRecord);
} }
/**
* 删除资源下所有的文件或者关联关系
*
* @param dirPrefix 本地上传文件目录前缀
* @param resourceIds 资源ID
* @param projectId 项目ID
* @param operator 操作人
*/
public void deleteByResourceIds(String dirPrefix, List<String> resourceIds, String projectId, String operator, String logModule) {
// 处理本地上传的文件
List<ApiFileResource> apiFileResources = getByResourceIds(resourceIds);
List<String> hasFileResourceIds = apiFileResources.stream()
.map(ApiFileResource::getResourceId)
.toList();
deleteByResourceIds(hasFileResourceIds);
for (String resourceId : hasFileResourceIds) {
// 删除文件
FileRequest request = new FileRequest();
request.setFolder(dirPrefix + resourceId);
try {
FileCenter.getDefaultRepository().deleteFolder(request);
} catch (Exception e) {
LogUtils.error(e);
}
}
// 处理关联文件
FileLogRecord fileLogRecord = FileLogRecord.builder()
.logModule(logModule)
.operator(operator)
.projectId(projectId)
.build();
fileAssociationService.deleteBySourceIds(resourceIds, fileLogRecord);
}
private void deleteByResourceIds(List<String> resourceIds) {
if (CollectionUtils.isEmpty(resourceIds)) {
return;
}
ApiFileResourceExample example = new ApiFileResourceExample();
example.createCriteria().andResourceIdIn(resourceIds);
apiFileResourceMapper.deleteByExample(example);
}
public List<ApiFileResource> getByResourceId(String resourceId) { public List<ApiFileResource> getByResourceId(String resourceId) {
ApiFileResourceExample example = new ApiFileResourceExample(); ApiFileResourceExample example = new ApiFileResourceExample();
example.createCriteria() example.createCriteria()
@ -242,6 +289,9 @@ public class ApiFileResourceService {
} }
public List<ApiFileResource> getByResourceIds(List<String> resourceIds) { public List<ApiFileResource> getByResourceIds(List<String> resourceIds) {
if (CollectionUtils.isEmpty(resourceIds)) {
return List.of();
}
ApiFileResourceExample example = new ApiFileResourceExample(); ApiFileResourceExample example = new ApiFileResourceExample();
example.createCriteria() example.createCriteria()
.andResourceIdIn(resourceIds); .andResourceIdIn(resourceIds);

View File

@ -19,6 +19,7 @@ import io.metersphere.system.service.CleanupProjectResourceService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotEmpty;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -126,13 +127,13 @@ public class CleanupApiResourceServiceImpl implements CleanupProjectResourceServ
List<String> scenarioIds = extApiScenarioMapper.selectByProjectId(projectId); List<String> scenarioIds = extApiScenarioMapper.selectByProjectId(projectId);
if (CollectionUtils.isNotEmpty(scenarioIds)) { if (CollectionUtils.isNotEmpty(scenarioIds)) {
SubListUtils.dealForSubList(scenarioIds, 500, subList -> { SubListUtils.dealForSubList(scenarioIds, 500, subList -> {
cascadeDelete(subList, OperationLogConstants.SYSTEM); cascadeDelete(subList, projectId, OperationLogConstants.SYSTEM);
}); });
} }
} }
public void cascadeDelete(@NotEmpty List<String> subList, String operator) { public void cascadeDelete(@NotEmpty List<String> subList, String projectId, String operator) {
ApiScenarioBlobExample example = new ApiScenarioBlobExample(); ApiScenarioBlobExample example = new ApiScenarioBlobExample();
example.createCriteria().andIdIn(subList); example.createCriteria().andIdIn(subList);
//删除blob //删除blob
@ -148,18 +149,9 @@ public class CleanupApiResourceServiceImpl implements CleanupProjectResourceServ
blobExample.createCriteria().andScenarioIdIn(subList); blobExample.createCriteria().andScenarioIdIn(subList);
apiScenarioStepBlobMapper.deleteByExample(blobExample); apiScenarioStepBlobMapper.deleteByExample(blobExample);
ApiScenarioExample apiScenarioExample = new ApiScenarioExample(); String scenarioDirPrefix = DefaultRepositoryDir.getApiScenarioDir(projectId, StringUtils.EMPTY);
apiScenarioExample.createCriteria().andIdIn(subList); apiFileResourceService.deleteByResourceIds(scenarioDirPrefix, subList, projectId, operator, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO);
List<ApiScenario> scenarioList = apiScenarioMapper.selectByExample(apiScenarioExample);
scenarioList.forEach(scenario -> {
//删除文件
String scenarioDir = DefaultRepositoryDir.getApiDebugDir(scenario.getProjectId(), scenario.getId());
try {
apiFileResourceService.deleteByResourceId(scenarioDir, scenario.getId(), scenario.getProjectId(), operator, OperationLogModule.API_TEST_DEBUG_MANAGEMENT_DEBUG);
} catch (Exception ignore) {
}
});
//删除csv //删除csv
ApiScenarioCsvExample csvExample = new ApiScenarioCsvExample(); ApiScenarioCsvExample csvExample = new ApiScenarioCsvExample();
csvExample.createCriteria().andScenarioIdIn(subList); csvExample.createCriteria().andScenarioIdIn(subList);
@ -172,7 +164,10 @@ public class CleanupApiResourceServiceImpl implements CleanupProjectResourceServ
apiScenarioCsvStepMapper.deleteByExample(csvStepExample); apiScenarioCsvStepMapper.deleteByExample(csvStepExample);
} }
apiScenarioCsvMapper.deleteByExample(csvExample); apiScenarioCsvMapper.deleteByExample(csvExample);
//删除场景 //删除场景
ApiScenarioExample apiScenarioExample = new ApiScenarioExample();
apiScenarioExample.createCriteria().andIdIn(subList);
apiScenarioMapper.deleteByExample(apiScenarioExample); apiScenarioMapper.deleteByExample(apiScenarioExample);
} }
@ -230,10 +225,11 @@ public class CleanupApiResourceServiceImpl implements CleanupProjectResourceServ
private void deleteCase(List<String> ids, String projectId) { private void deleteCase(List<String> ids, String projectId) {
deleteCaseFollows(ids); deleteCaseFollows(ids);
ids.forEach(id -> {
String apiCaseDir = DefaultRepositoryDir.getApiCaseDir(projectId, id); // 批量删除文件
apiFileResourceService.deleteByResourceId(apiCaseDir, id, projectId, OperationLogConstants.SYSTEM, OperationLogModule.API_TEST_MANAGEMENT_CASE); String apiCaseDirPrefix = DefaultRepositoryDir.getApiCaseDir(projectId, StringUtils.EMPTY);
}); apiFileResourceService.deleteByResourceIds(apiCaseDirPrefix, ids, projectId, OperationLogConstants.SYSTEM, OperationLogModule.API_TEST_MANAGEMENT_CASE);
ApiTestCaseExample example = new ApiTestCaseExample(); ApiTestCaseExample example = new ApiTestCaseExample();
example.createCriteria().andIdIn(ids); example.createCriteria().andIdIn(ids);
apiTestCaseMapper.deleteByExample(example); apiTestCaseMapper.deleteByExample(example);
@ -243,10 +239,9 @@ public class CleanupApiResourceServiceImpl implements CleanupProjectResourceServ
} }
private void deleteMock(List<String> ids, String projectId) { private void deleteMock(List<String> ids, String projectId) {
ids.forEach(id -> { String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, StringUtils.EMPTY);
String apiCaseDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, id); apiFileResourceService.deleteByResourceIds(apiDefinitionDir, ids, projectId, OperationLogConstants.SYSTEM, OperationLogModule.API_TEST_MANAGEMENT_MOCK);
apiFileResourceService.deleteByResourceId(apiCaseDir, id, projectId, OperationLogConstants.SYSTEM, OperationLogModule.API_TEST_MANAGEMENT_CASE);
});
ApiDefinitionMockConfigExample configExample = new ApiDefinitionMockConfigExample(); ApiDefinitionMockConfigExample configExample = new ApiDefinitionMockConfigExample();
configExample.createCriteria().andIdIn(ids); configExample.createCriteria().andIdIn(ids);
apiDefinitionMockConfigMapper.deleteByExample(configExample); apiDefinitionMockConfigMapper.deleteByExample(configExample);
@ -257,10 +252,9 @@ public class CleanupApiResourceServiceImpl implements CleanupProjectResourceServ
private void deleteApi(List<String> ids, String projectId) { private void deleteApi(List<String> ids, String projectId) {
deleteApiFollows(ids); deleteApiFollows(ids);
ids.forEach(id -> { String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, StringUtils.EMPTY);
String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, id); apiFileResourceService.deleteByResourceIds(apiDefinitionDir, ids, projectId, OperationLogConstants.SYSTEM, OperationLogModule.API_TEST_MANAGEMENT_DEFINITION);
apiFileResourceService.deleteByResourceId(apiDefinitionDir, id, projectId, OperationLogConstants.SYSTEM, OperationLogModule.API_TEST_MANAGEMENT_DEFINITION);
});
ApiDefinitionExample example = new ApiDefinitionExample(); ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(ids); example.createCriteria().andIdIn(ids);
apiDefinitionMapper.deleteByExample(example); apiDefinitionMapper.deleteByExample(example);

View File

@ -211,10 +211,9 @@ public class ApiDebugModuleService extends ModuleTreeService {
blobExample.createCriteria().andIdIn(apiDebugIds); blobExample.createCriteria().andIdIn(apiDebugIds);
apiDebugBlobMapper.deleteByExample(blobExample); apiDebugBlobMapper.deleteByExample(blobExample);
//删除文件关联关系 //删除文件关联关系
apiDebugs.forEach(apiDebug -> { String apiDebugDir = DefaultRepositoryDir.getApiDebugDir(projectId, StringUtils.EMPTY);
String apiDebugDir = DefaultRepositoryDir.getApiDebugDir(apiDebug.getProjectId(), apiDebug.getId()); apiFileResourceService.deleteByResourceIds(apiDebugDir, apiDebugIds, projectId, currentUser, OperationLogModule.API_TEST_DEBUG_MANAGEMENT_DEBUG);
apiFileResourceService.deleteByResourceId(apiDebugDir, apiDebug.getId(), projectId, currentUser, OperationLogModule.API_TEST_DEBUG_MANAGEMENT_DEBUG);
});
apiDebugModuleLogService.saveDeleteDataLog(apiDebugs, currentUser, projectId); apiDebugModuleLogService.saveDeleteDataLog(apiDebugs, currentUser, projectId);
} }

View File

@ -30,6 +30,7 @@ import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.ServiceUtils; import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -255,19 +256,16 @@ public class ApiDefinitionMockService {
apiDefinitionMockMapper.updateByPrimaryKeySelective(update); apiDefinitionMockMapper.updateByPrimaryKeySelective(update);
} }
public void deleteByApiIds(List<String> apiIds, String userId) { public void deleteByApiIds(List<String> apiIds, String userId, String projectId) {
ApiDefinitionMockExample apiDefinitionMockExample = new ApiDefinitionMockExample(); ApiDefinitionMockExample apiDefinitionMockExample = new ApiDefinitionMockExample();
apiDefinitionMockExample.createCriteria().andApiDefinitionIdIn(apiIds); apiDefinitionMockExample.createCriteria().andApiDefinitionIdIn(apiIds);
List<ApiDefinitionMock> apiDefinitionMocks = apiDefinitionMockMapper.selectByExample(apiDefinitionMockExample); List<ApiDefinitionMock> apiDefinitionMocks = apiDefinitionMockMapper.selectByExample(apiDefinitionMockExample);
if (!apiDefinitionMocks.isEmpty()) { if (!apiDefinitionMocks.isEmpty()) {
apiDefinitionMocks.forEach(item -> {
String apiDefinitionMockDir = DefaultRepositoryDir.getApiDefinitionDir(item.getProjectId(), item.getId());
apiFileResourceService.deleteByResourceId(apiDefinitionMockDir, item.getId(), item.getProjectId(), userId, OperationLogModule.API_TEST_MANAGEMENT_MOCK);
});
List<String> mockIds = apiDefinitionMocks.stream().map(ApiDefinitionMock::getId).toList(); List<String> mockIds = apiDefinitionMocks.stream().map(ApiDefinitionMock::getId).toList();
String apiDefinitionMockDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, StringUtils.EMPTY);
apiFileResourceService.deleteByResourceIds(apiDefinitionMockDir, mockIds, projectId, userId, OperationLogModule.API_TEST_MANAGEMENT_MOCK);
ApiDefinitionMockConfigExample apiDefinitionMockConfigExample = new ApiDefinitionMockConfigExample(); ApiDefinitionMockConfigExample apiDefinitionMockConfigExample = new ApiDefinitionMockConfigExample();
apiDefinitionMockConfigExample.createCriteria().andIdIn(mockIds); apiDefinitionMockConfigExample.createCriteria().andIdIn(mockIds);

View File

@ -806,6 +806,9 @@ public class ApiDefinitionService extends MoveNodeService {
if (CollectionUtils.isNotEmpty(ids)) { if (CollectionUtils.isNotEmpty(ids)) {
handleTrashDelApiDefinition(ids, userId, request.getProjectId(), true); handleTrashDelApiDefinition(ids, userId, request.getProjectId(), true);
} }
String apiDefinitionDirPrefix = DefaultRepositoryDir.getApiDefinitionDir(request.getProjectId(), StringUtils.EMPTY);
apiFileResourceService.deleteByResourceIds(apiDefinitionDirPrefix, ids, request.getProjectId(), userId, OperationLogModule.API_TEST_MANAGEMENT_DEFINITION);
} }
private void handleTrashDelApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch) { private void handleTrashDelApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch) {
@ -817,10 +820,9 @@ public class ApiDefinitionService extends MoveNodeService {
private void doTrashDel(List<String> ids, String userId, String projectId, boolean isBatch) { private void doTrashDel(List<String> ids, String userId, String projectId, boolean isBatch) {
if (CollectionUtils.isNotEmpty(ids)) { if (CollectionUtils.isNotEmpty(ids)) {
// 删除上传的文件 // 删除上传的文件
ids.forEach(id -> { String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, StringUtils.EMPTY);
String apiDefinitionDir = DefaultRepositoryDir.getApiDefinitionDir(projectId, id); apiFileResourceService.deleteByResourceIds(apiDefinitionDir, ids, projectId, userId, OperationLogModule.API_TEST_MANAGEMENT_DEFINITION);
apiFileResourceService.deleteByResourceId(apiDefinitionDir, id, projectId, userId, OperationLogModule.API_TEST_MANAGEMENT_DEFINITION);
});
// 删除接口关注人 // 删除接口关注人
ApiDefinitionFollowerExample apiDefinitionFollowerExample = new ApiDefinitionFollowerExample(); ApiDefinitionFollowerExample apiDefinitionFollowerExample = new ApiDefinitionFollowerExample();
apiDefinitionFollowerExample.createCriteria().andApiDefinitionIdIn(ids).andUserIdEqualTo(userId); apiDefinitionFollowerExample.createCriteria().andApiDefinitionIdIn(ids).andUserIdEqualTo(userId);
@ -851,7 +853,7 @@ public class ApiDefinitionService extends MoveNodeService {
} }
// 删除 mock // 删除 mock
apiDefinitionMockService.deleteByApiIds(apiIds, userId); apiDefinitionMockService.deleteByApiIds(apiIds, userId, projectId);
} }
// 获取批量操作选中的ID // 获取批量操作选中的ID

View File

@ -368,11 +368,11 @@ public class ApiTestCaseService extends MoveNodeService {
public void deleteResourceByIds(List<String> ids, String projectId, String userId) { public void deleteResourceByIds(List<String> ids, String projectId, String userId) {
deleteFollows(ids); deleteFollows(ids);
List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByIds(ids, true); List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByIds(ids, true);
//删除文件关联关系
ids.forEach(id -> { // 批量删除关联文件
String apiCaseDir = DefaultRepositoryDir.getApiCaseDir(projectId, id); String apiCaseDirPrefix = DefaultRepositoryDir.getApiCaseDir(projectId, StringUtils.EMPTY);
apiFileResourceService.deleteByResourceId(apiCaseDir, id, projectId, userId, OperationLogModule.API_TEST_MANAGEMENT_CASE); apiFileResourceService.deleteByResourceIds(apiCaseDirPrefix, ids, projectId, userId, OperationLogModule.API_TEST_MANAGEMENT_CASE);
});
ApiTestCaseExample example = new ApiTestCaseExample(); ApiTestCaseExample example = new ApiTestCaseExample();
example.createCriteria().andIdIn(ids); example.createCriteria().andIdIn(ids);
apiTestCaseMapper.deleteByExample(example); apiTestCaseMapper.deleteByExample(example);

View File

@ -434,17 +434,40 @@ public class ApiScenarioService extends MoveNodeService {
saveStepCsv(steps, csvSteps); saveStepCsv(steps, csvSteps);
} }
// 处理文件 // 处理步骤文件
handleStepFiles(request, creator, scenario);
// 处理场景文件csv等
handScenarioFiles(request, creator, scenario);
return scenario;
}
private void handScenarioFiles(ApiScenarioAddRequest request, String creator, ApiScenario scenario) {
ResourceAddFileParam fileParam = request.getFileParam();
if (fileParam == null) {
return;
}
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), creator); ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), creator);
resourceUpdateRequest.setUploadFileIds(request.getUploadFileIds()); resourceUpdateRequest.setUploadFileIds(fileParam.getUploadFileIds());
resourceUpdateRequest.setLinkFileIds(request.getLinkFileIds()); resourceUpdateRequest.setLinkFileIds(fileParam.getLinkFileIds());
apiFileResourceService.addFileResource(resourceUpdateRequest); apiFileResourceService.addFileResource(resourceUpdateRequest);
//处理csv变量
if (request.getScenarioConfig() != null if (request.getScenarioConfig() != null
&& request.getScenarioConfig().getVariable() != null) { && request.getScenarioConfig().getVariable() != null) {
saveCsv(request.getScenarioConfig().getVariable().getCsvVariables(), resourceUpdateRequest); saveCsv(request.getScenarioConfig().getVariable().getCsvVariables(), resourceUpdateRequest);
} }
return scenario; }
private void handleStepFiles(ApiScenarioAddRequest request, String creator, ApiScenario scenario) {
Map<String, ResourceAddFileParam> stepFileParam = request.getStepFileParam();
if (MapUtils.isNotEmpty(stepFileParam)) {
stepFileParam.forEach((stepId, fileParam) -> {
// 处理步骤文件
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(stepId, scenario.getProjectId(), creator);
resourceUpdateRequest.setUploadFileIds(fileParam.getUploadFileIds());
resourceUpdateRequest.setLinkFileIds(fileParam.getLinkFileIds());
apiFileResourceService.addFileResource(resourceUpdateRequest);
});
}
} }
private void saveStepCsv(List<ApiScenarioStep> steps, List<ApiScenarioCsvStep> csvSteps) { private void saveStepCsv(List<ApiScenarioStep> steps, List<ApiScenarioCsvStep> csvSteps) {
@ -639,17 +662,28 @@ public class ApiScenarioService extends MoveNodeService {
apiScenarioBlobMapper.updateByPrimaryKeyWithBLOBs(apiScenarioBlob); apiScenarioBlobMapper.updateByPrimaryKeyWithBLOBs(apiScenarioBlob);
} }
// 更新场景步骤
updateApiScenarioStep(request, scenario);
ApiScenario originScenario = apiScenarioMapper.selectByPrimaryKey(request.getId()); ApiScenario originScenario = apiScenarioMapper.selectByPrimaryKey(request.getId());
// 处理文件
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), originScenario.getProjectId(), updater); // 处理步骤文件
resourceUpdateRequest.setUploadFileIds(request.getUploadFileIds()); handleStepFiles(request, updater, originScenario);
resourceUpdateRequest.setLinkFileIds(request.getLinkFileIds());
resourceUpdateRequest.setUnLinkFileIds(request.getUnLinkFileIds()); // 处理场景文件
resourceUpdateRequest.setDeleteFileIds(request.getDeleteFileIds()); handleScenarioFiles(request, updater, originScenario);
// 更新场景步骤
updateApiScenarioStep(request, originScenario, updater);
return scenario;
}
private void handleScenarioFiles(ApiScenarioUpdateRequest request, String updater, ApiScenario scenario) {
// 处理场景文件
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(scenario.getId(), scenario.getProjectId(), updater);
ResourceAddFileParam fileParam = request.getFileParam();
if (fileParam != null) {
resourceUpdateRequest = BeanUtils.copyBean(resourceUpdateRequest, fileParam);
apiFileResourceService.updateFileResource(resourceUpdateRequest); apiFileResourceService.updateFileResource(resourceUpdateRequest);
}
//处理csv变量 //处理csv变量
if (request.getScenarioConfig() != null if (request.getScenarioConfig() != null
@ -658,13 +692,24 @@ public class ApiScenarioService extends MoveNodeService {
} else { } else {
saveCsv(new ArrayList<>(), resourceUpdateRequest); saveCsv(new ArrayList<>(), resourceUpdateRequest);
} }
return scenario; }
private void handleStepFiles(ApiScenarioUpdateRequest request, String updater, ApiScenario scenario) {
Map<String, ResourceUpdateFileParam> stepFileParam = request.getStepFileParam();
if (MapUtils.isNotEmpty(stepFileParam)) {
stepFileParam.forEach((stepId, fileParam) -> {
// 处理步骤文件
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(stepId, scenario.getProjectId(), updater);
resourceUpdateRequest = BeanUtils.copyBean(resourceUpdateRequest, fileParam);
apiFileResourceService.addFileResource(resourceUpdateRequest);
});
}
} }
/** /**
* 更新场景步骤 * 更新场景步骤
*/ */
private void updateApiScenarioStep(ApiScenarioUpdateRequest request, ApiScenario scenario) { private void updateApiScenarioStep(ApiScenarioUpdateRequest request, ApiScenario scenario, String userId) {
// steps 不为 null 则修改 // steps 不为 null 则修改
if (request.getSteps() != null) { if (request.getSteps() != null) {
if (CollectionUtils.isEmpty(request.getSteps())) { if (CollectionUtils.isEmpty(request.getSteps())) {
@ -697,6 +742,9 @@ public class ApiScenarioService extends MoveNodeService {
ApiScenarioStepBlobExample stepBlobExample = new ApiScenarioStepBlobExample(); ApiScenarioStepBlobExample stepBlobExample = new ApiScenarioStepBlobExample();
stepBlobExample.createCriteria().andIdIn(subIds); stepBlobExample.createCriteria().andIdIn(subIds);
apiScenarioStepBlobMapper.deleteByExample(stepBlobExample); apiScenarioStepBlobMapper.deleteByExample(stepBlobExample);
// 批量删除关联文件
String scenarioStepDirPrefix = DefaultRepositoryDir.getApiScenarioStepDir(scenario.getProjectId(), scenario.getId(), StringUtils.EMPTY);
apiFileResourceService.deleteByResourceIds(scenarioStepDirPrefix, subIds, scenario.getProjectId(), userId, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO);
}); });
// 查询原有的步骤详情 // 查询原有的步骤详情
@ -1004,7 +1052,7 @@ public class ApiScenarioService extends MoveNodeService {
return enableSteps; return enableSteps;
} }
private static ApiFileResourceUpdateRequest getApiFileResourceUpdateRequest(String sourceId, String projectId, String operator) { private ApiFileResourceUpdateRequest getApiFileResourceUpdateRequest(String sourceId, String projectId, String operator) {
String apiScenarioDir = DefaultRepositoryDir.getApiScenarioDir(projectId, sourceId); String apiScenarioDir = DefaultRepositoryDir.getApiScenarioDir(projectId, sourceId);
ApiFileResourceUpdateRequest resourceUpdateRequest = new ApiFileResourceUpdateRequest(); ApiFileResourceUpdateRequest resourceUpdateRequest = new ApiFileResourceUpdateRequest();
resourceUpdateRequest.setProjectId(projectId); resourceUpdateRequest.setProjectId(projectId);
@ -1033,7 +1081,7 @@ public class ApiScenarioService extends MoveNodeService {
apiScenarioMapper.deleteByPrimaryKey(id); apiScenarioMapper.deleteByPrimaryKey(id);
} }
public ApiScenarioBatchOperationResponse delete(@NotEmpty List<String> idList, String operator) { public ApiScenarioBatchOperationResponse delete(@NotEmpty List<String> idList, String projectId, String operator) {
ApiScenarioBatchOperationResponse response = new ApiScenarioBatchOperationResponse(); ApiScenarioBatchOperationResponse response = new ApiScenarioBatchOperationResponse();
ApiScenarioExample example = new ApiScenarioExample(); ApiScenarioExample example = new ApiScenarioExample();
@ -1041,7 +1089,7 @@ public class ApiScenarioService extends MoveNodeService {
List<ApiScenario> scenarioList = apiScenarioMapper.selectByExample(example); List<ApiScenario> scenarioList = apiScenarioMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(scenarioList)) { if (CollectionUtils.isNotEmpty(scenarioList)) {
apiScenarioMapper.deleteByExample(example); apiScenarioMapper.deleteByExample(example);
cascadeDelete(scenarioList, operator); cascadeDelete(scenarioList, projectId, operator);
} }
//构建返回值 //构建返回值
@ -1064,7 +1112,7 @@ public class ApiScenarioService extends MoveNodeService {
//删除文件 //删除文件
String scenarioDir = DefaultRepositoryDir.getApiScenarioDir(scenario.getProjectId(), scenario.getId()); String scenarioDir = DefaultRepositoryDir.getApiScenarioDir(scenario.getProjectId(), scenario.getId());
try { try {
apiFileResourceService.deleteByResourceId(scenarioDir, scenario.getId(), scenario.getProjectId(), operator, OperationLogModule.API_TEST_DEBUG_MANAGEMENT_DEBUG); apiFileResourceService.deleteByResourceId(scenarioDir, scenario.getId(), scenario.getProjectId(), operator, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO);
} catch (Exception ignore) { } catch (Exception ignore) {
} }
@ -1088,7 +1136,7 @@ public class ApiScenarioService extends MoveNodeService {
} }
//级联删除 //级联删除
public void cascadeDelete(@NotEmpty List<ApiScenario> scenarioList, String operator) { public void cascadeDelete(@NotEmpty List<ApiScenario> scenarioList, String projectId, String operator) {
List<String> scenarioIdList = scenarioList.stream().map(ApiScenario::getId).toList(); List<String> scenarioIdList = scenarioList.stream().map(ApiScenario::getId).toList();
ApiScenarioBlobExample example = new ApiScenarioBlobExample(); ApiScenarioBlobExample example = new ApiScenarioBlobExample();
example.createCriteria().andIdIn(scenarioIdList); example.createCriteria().andIdIn(scenarioIdList);
@ -1106,17 +1154,12 @@ public class ApiScenarioService extends MoveNodeService {
blobExample.createCriteria().andScenarioIdIn(scenarioIdList); blobExample.createCriteria().andScenarioIdIn(scenarioIdList);
apiScenarioStepBlobMapper.deleteByExample(blobExample); apiScenarioStepBlobMapper.deleteByExample(blobExample);
scenarioList.forEach(scenario -> {
//删除文件 //删除文件
String scenarioDir = DefaultRepositoryDir.getApiScenarioDir(scenario.getProjectId(), scenario.getId()); String scenarioDir = DefaultRepositoryDir.getApiScenarioDir(projectId, StringUtils.EMPTY);
try { apiFileResourceService.deleteByResourceIds(scenarioDir, scenarioIdList, projectId, operator, OperationLogModule.API_SCENARIO_MANAGEMENT_SCENARIO);
apiFileResourceService.deleteByResourceId(scenarioDir, scenario.getId(), scenario.getProjectId(), operator, OperationLogModule.API_TEST_DEBUG_MANAGEMENT_DEBUG);
//删除定时任务 //删除定时任务
scheduleService.deleteByResourceId(scenario.getId(), ApiScenarioScheduleJob.class.getName()); scheduleService.deleteByResourceIds(scenarioIdList, ApiScenarioScheduleJob.class.getName());
} catch (Exception ignore) {
}
});
//删除csv //删除csv
ApiScenarioCsvExample csvExample = new ApiScenarioCsvExample(); ApiScenarioCsvExample csvExample = new ApiScenarioCsvExample();
csvExample.createCriteria().andScenarioIdIn(scenarioIdList); csvExample.createCriteria().andScenarioIdIn(scenarioIdList);
@ -2309,7 +2352,7 @@ public class ApiScenarioService extends MoveNodeService {
ApiScenarioBatchOperationResponse response = ApiScenarioBatchOperationUtils.executeWithBatchOperationResponse( ApiScenarioBatchOperationResponse response = ApiScenarioBatchOperationUtils.executeWithBatchOperationResponse(
scenarioIds, scenarioIds,
sublist -> delete(sublist, logInsertModule.getOperator())); sublist -> delete(sublist, request.getProjectId(), logInsertModule.getOperator()));
apiScenarioLogService.saveBatchOperationLog(response, request.getProjectId(), OperationLogType.DELETE.name(), logInsertModule); apiScenarioLogService.saveBatchOperationLog(response, request.getProjectId(), OperationLogType.DELETE.name(), logInsertModule);
return response; return response;
} }

View File

@ -5,6 +5,7 @@ import io.metersphere.api.domain.*;
import io.metersphere.api.dto.ApiFile; import io.metersphere.api.dto.ApiFile;
import io.metersphere.api.dto.ApiRunModeRequest; import io.metersphere.api.dto.ApiRunModeRequest;
import io.metersphere.api.dto.ReferenceRequest; import io.metersphere.api.dto.ReferenceRequest;
import io.metersphere.api.dto.ResourceAddFileParam;
import io.metersphere.api.dto.assertion.MsAssertionConfig; import io.metersphere.api.dto.assertion.MsAssertionConfig;
import io.metersphere.api.dto.debug.ModuleCreateRequest; import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.*;
@ -328,7 +329,8 @@ public class ApiScenarioControllerTests extends BaseTest {
request.setStepDetails(steptDetailMap); request.setStepDetails(steptDetailMap);
request.setScenarioConfig(getScenarioConfig()); request.setScenarioConfig(getScenarioConfig());
String fileId = doUploadTempFile(getMockMultipartFile()); String fileId = doUploadTempFile(getMockMultipartFile());
request.setUploadFileIds(List.of(fileId)); request.setFileParam(new ResourceAddFileParam());
request.getFileParam().setUploadFileIds(List.of(fileId));
MvcResult mvcResult = this.requestPostWithOkAndReturn(DEFAULT_ADD, request); MvcResult mvcResult = this.requestPostWithOkAndReturn(DEFAULT_ADD, request);
ApiScenario resultData = getResultData(mvcResult, ApiScenario.class); ApiScenario resultData = getResultData(mvcResult, ApiScenario.class);
this.addApiScenario = apiScenarioMapper.selectByPrimaryKey(resultData.getId()); this.addApiScenario = apiScenarioMapper.selectByPrimaryKey(resultData.getId());
@ -336,7 +338,7 @@ public class ApiScenarioControllerTests extends BaseTest {
assertUpdateSteps(steps, steptDetailMap); assertUpdateSteps(steps, steptDetailMap);
request.setName("anOther name"); request.setName("anOther name");
request.setUploadFileIds(List.of()); request.getFileParam().setUploadFileIds(List.of());
request.setGrouped(true); request.setGrouped(true);
request.setEnvironmentId(envGroupId); request.setEnvironmentId(envGroupId);
ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest(); ApiScenarioStepRequest stepRequest = new ApiScenarioStepRequest();

View File

@ -6,11 +6,10 @@ import io.metersphere.project.domain.ProjectTestResourcePool;
import io.metersphere.project.domain.ProjectTestResourcePoolExample; import io.metersphere.project.domain.ProjectTestResourcePoolExample;
import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.mapper.ProjectTestResourcePoolMapper; import io.metersphere.project.mapper.ProjectTestResourcePoolMapper;
import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.*;
import io.metersphere.sdk.constants.InternalUserRole;
import io.metersphere.sdk.constants.OperationLogConstants;
import io.metersphere.sdk.constants.UserRoleType;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.file.FileCenter;
import io.metersphere.sdk.file.FileRequest;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
@ -556,6 +555,17 @@ public class CommonProjectService {
projectMapper.deleteByPrimaryKey(project.getId()); projectMapper.deleteByPrimaryKey(project.getId());
LogDTO logDTO = new LogDTO(OperationLogConstants.SYSTEM, project.getOrganizationId(), project.getId(), Translator.get("scheduled_tasks"), OperationLogType.DELETE.name(), OperationLogModule.SETTING_ORGANIZATION_PROJECT, Translator.get("delete") + Translator.get("project") + ": " + project.getName()); LogDTO logDTO = new LogDTO(OperationLogConstants.SYSTEM, project.getOrganizationId(), project.getId(), Translator.get("scheduled_tasks"), OperationLogType.DELETE.name(), OperationLogModule.SETTING_ORGANIZATION_PROJECT, Translator.get("delete") + Translator.get("project") + ": " + project.getName());
setLog(logDTO, StringUtils.EMPTY, StringUtils.EMPTY, logDTOList); setLog(logDTO, StringUtils.EMPTY, StringUtils.EMPTY, logDTOList);
// 删除项目目录避免资源删除有遗漏
String projectDir = DefaultRepositoryDir.getProjectDir(project.getId());
FileRequest request = new FileRequest();
request.setFolder(projectDir);
try {
FileCenter.getDefaultRepository().deleteFolder(request);
} catch (Exception e) {
LogUtils.error(e);
}
}); });
operationLogService.batchAdd(logDTOList); operationLogService.batchAdd(logDTOList);
} }