diff --git a/backend/framework/sdk/src/main/resources/i18n/commons.properties b/backend/framework/sdk/src/main/resources/i18n/commons.properties index 8c12644765..72958f3486 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons.properties @@ -514,3 +514,5 @@ permission.test_plan_module.name=测试计划模块 relate_source_id_not_blank=关联来源ID不能为空 relate_source_id_length_range=关联来源ID必须在{min}和{max}之间 relate_source_type_not_blank=关联资源类型不能为空 + +api_import_schedule=接口定义-定时导入任务 diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties b/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties index 561bff2d07..a789423754 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_en_US.properties @@ -540,4 +540,6 @@ check_import_excel_error=Check import excel error #关联 relate_source_id_not_blank=Source id cannot be empty relate_source_id_length_range=The association source ID must be between {min} and {max} -relate_source_type_not_blank=The associated resource type cannot be empty \ No newline at end of file +relate_source_type_not_blank=The associated resource type cannot be empty + +api_import_schedule=API import schedule \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties b/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties index 3bc23bb62f..bc1d243fad 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_zh_CN.properties @@ -536,4 +536,6 @@ check_import_excel_error=检查导入Excel错误 #关联 relate_source_id_not_blank=关联来源ID不能为空 relate_source_id_length_range=关联来源ID必须在{min}和{max}之间 -relate_source_type_not_blank=关联资源类型不能为空 \ No newline at end of file +relate_source_type_not_blank=关联资源类型不能为空 + +api_import_schedule=接口定义-定时导入任务 \ No newline at end of file diff --git a/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties b/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties index 07292ed630..d6c7c8cd34 100644 --- a/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties +++ b/backend/framework/sdk/src/main/resources/i18n/commons_zh_TW.properties @@ -536,4 +536,6 @@ check_import_excel_error=檢查導入Excel錯誤 #关联 relate_source_id_not_blank=關聯來源ID不能為空 relate_source_id_length_range=關聯來源ID必須在{min}和{max}之間 -relate_source_type_not_blank=關聯資源類型不能為空 \ No newline at end of file +relate_source_type_not_blank=關聯資源類型不能為空 + +api_import_schedule=接口導入定時任務 \ No newline at end of file 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 86c08130be..b0d8f353f0 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 @@ -7,6 +7,7 @@ import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.importdto.ApiDefinitionImport; import io.metersphere.api.dto.request.ImportRequest; import io.metersphere.api.service.definition.ApiDefinitionLogService; +import io.metersphere.api.service.definition.ApiDefinitionNoticeService; import io.metersphere.api.service.definition.ApiDefinitionService; import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.system.dto.OperationHistoryDTO; @@ -14,6 +15,8 @@ import io.metersphere.system.dto.request.OperationHistoryRequest; import io.metersphere.system.dto.request.OperationHistoryVersionRequest; import io.metersphere.system.log.annotation.Log; import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.notice.annotation.SendNotice; +import io.metersphere.system.notice.constants.NoticeConstants; import io.metersphere.system.security.CheckOwner; import io.metersphere.system.utils.PageUtils; import io.metersphere.system.utils.Pager; @@ -45,9 +48,9 @@ public class ApiDefinitionController { @PostMapping(value = "/add") @Operation(summary = "接口测试-接口管理-添加接口定义") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_ADD) - // 添加接口Log示例 @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = ApiDefinitionLogService.class) @CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project") + @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CREATE, target = "#targetClass.getApiDTO(#request)", targetClass = ApiDefinitionNoticeService.class) public ApiDefinition add(@Validated @RequestBody ApiDefinitionAddRequest request) { return apiDefinitionService.create(request, SessionUtils.getUserId()); } @@ -55,9 +58,9 @@ public class ApiDefinitionController { @PostMapping(value = "/update") @Operation(summary = "接口测试-接口管理-更新接口定义") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_UPDATE) - // 添加修改Log示例 @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = ApiDefinitionLogService.class) @CheckOwner(resourceId = "#request.getId()", resourceType = "api_definition") + @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.UPDATE, target = "#targetClass.getUpdateApiDTO(#request)", targetClass = ApiDefinitionNoticeService.class) public ApiDefinition update(@Validated @RequestBody ApiDefinitionUpdateRequest request) { return apiDefinitionService.update(request, SessionUtils.getUserId()); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionScheduleController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionScheduleController.java index 8f32a9d3cc..8d31c4f430 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionScheduleController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiDefinitionScheduleController.java @@ -3,8 +3,12 @@ package io.metersphere.api.controller.definition; import io.metersphere.api.dto.definition.ApiScheduleDTO; import io.metersphere.api.dto.definition.SwaggerUrlCheck; import io.metersphere.api.dto.definition.importdto.ApiScheduleRequest; +import io.metersphere.api.service.definition.ApiDefinitionLogService; import io.metersphere.api.service.definition.ApiDefinitionScheduleService; import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.system.log.annotation.Log; +import io.metersphere.system.log.constants.OperationLogType; +import io.metersphere.system.security.CheckOwner; import io.metersphere.system.utils.SessionUtils; import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Updated; @@ -26,15 +30,17 @@ public class ApiDefinitionScheduleController { @PostMapping(value = "/add") @Operation(summary = "接口测试-接口管理-定时同步-创建") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT) - public void createSchedule(@RequestBody @Validated({Created.class}) ApiScheduleRequest request) { - apiDefinitionScheduleService.createSchedule(request, SessionUtils.getUserId()); + @Log(type = OperationLogType.ADD, expression = "#msClass.scheduleLog(#request)", msClass = ApiDefinitionLogService.class) + @CheckOwner(resourceId = "#request.getScenarioId()", resourceType = "api_scenario") + public String createSchedule(@RequestBody @Validated({Created.class}) ApiScheduleRequest request) { + return apiDefinitionScheduleService.createSchedule(request, SessionUtils.getUserId()); } @PostMapping(value = "/update") @Operation(summary = "接口测试-接口管理-定时同步-更新") @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT) - public void updateSchedule(@RequestBody @Validated({Updated.class}) ApiScheduleRequest request) { - apiDefinitionScheduleService.updateSchedule(request, SessionUtils.getUserId()); + public String updateSchedule(@RequestBody @Validated({Updated.class}) ApiScheduleRequest request) { + return apiDefinitionScheduleService.updateSchedule(request, SessionUtils.getUserId()); } @PostMapping(value = "/check") diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java index a564fb8494..ef9a16f39f 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/controller/definition/ApiTestCaseController.java @@ -64,6 +64,7 @@ public class ApiTestCaseController { @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_CASE_DELETE) @Log(type = OperationLogType.DELETE, expression = "#msClass.moveToGcLog(#id)", msClass = ApiTestCaseLogService.class) @CheckOwner(resourceId = "#id", resourceType = "api_test_case") + @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CASE_DELETE, target = "#targetClass.getCaseDTO(#id)", targetClass = ApiTestCaseNoticeService.class) public void deleteToGc(@PathVariable String id) { apiTestCaseService.deleteToGc(id, SessionUtils.getUserId()); } diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioScheduleConfigRequest.java b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioScheduleConfigRequest.java index 4f72e6e985..575198df36 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioScheduleConfigRequest.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/dto/scenario/ApiScenarioScheduleConfigRequest.java @@ -1,11 +1,10 @@ package io.metersphere.api.dto.scenario; +import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; -import java.util.Map; - @Data public class ApiScenarioScheduleConfigRequest { @@ -20,7 +19,7 @@ public class ApiScenarioScheduleConfigRequest { @NotBlank private String cron; - @Schema(description = "定时任务配置 (如果配置不更改,不需要传入这个参数。 如果要清空配置,传入一个空数据{} )") - Map configMap; + @Schema(description = "定时任务配置") + private ApiRunModeConfigDTO config; } 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 12fa706b6d..76757b2e60 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 @@ -74,7 +74,7 @@ public class ApiDefinitionLogService { */ public LogDTO updateLog(ApiDefinitionUpdateRequest request) { ApiDefinitionDTO apiDefinition = getOriginalValue(request.getId()); - if(apiDefinition.getId() != null) { + if (apiDefinition.getId() != null) { LogDTO dto = new LogDTO( request.getProjectId(), null, @@ -100,7 +100,7 @@ public class ApiDefinitionLogService { */ public LogDTO delLog(ApiDefinitionDeleteRequest request) { ApiDefinitionDTO apiDefinition = getOriginalValue(request.getId()); - if(apiDefinition.getId() != null) { + if (apiDefinition.getId() != null) { LogDTO dto = new LogDTO( request.getProjectId(), null, @@ -139,7 +139,7 @@ public class ApiDefinitionLogService { public LogDTO copyLog(ApiDefinitionCopyRequest request) { ApiDefinitionDTO apiDefinition = getOriginalValue(request.getId()); - if(apiDefinition.getId() != null) { + if (apiDefinition.getId() != null) { LogDTO dto = new LogDTO( apiDefinition.getProjectId(), null, @@ -163,7 +163,7 @@ public class ApiDefinitionLogService { public LogDTO followLog(String id) { ApiDefinitionDTO apiDefinition = getOriginalValue(id); - if(apiDefinition.getId() != null) { + if (apiDefinition.getId() != null) { Project project = projectMapper.selectByPrimaryKey(apiDefinition.getProjectId()); LogDTO dto = new LogDTO( apiDefinition.getProjectId(), @@ -190,7 +190,7 @@ public class ApiDefinitionLogService { */ public LogDTO recoverLog(ApiDefinitionDeleteRequest request) { ApiDefinitionDTO apiDefinition = getOriginalValue(request.getId()); - if(apiDefinition.getId() != null) { + if (apiDefinition.getId() != null) { LogDTO dto = new LogDTO( request.getProjectId(), null, @@ -225,7 +225,7 @@ public class ApiDefinitionLogService { */ public LogDTO trashDelLog(ApiDefinitionDeleteRequest request) { ApiDefinitionDTO apiDefinition = getOriginalValue(request.getId()); - if(apiDefinition.getId() != null) { + if (apiDefinition.getId() != null) { LogDTO dto = new LogDTO( request.getProjectId(), null, @@ -254,7 +254,7 @@ public class ApiDefinitionLogService { private ApiDefinitionDTO getOriginalValue(String id) { ApiDefinitionDTO apiDefinitionDTO = new ApiDefinitionDTO(); ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(id); - if(null != apiDefinition) { + if (null != apiDefinition) { // 2. 使用Optional避免空指针异常 handleBlob(id, apiDefinitionDTO); BeanUtils.copyBean(apiDefinitionDTO, apiDefinition); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionNoticeService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionNoticeService.java new file mode 100644 index 0000000000..4811ab95f4 --- /dev/null +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionNoticeService.java @@ -0,0 +1,64 @@ +package io.metersphere.api.service.definition; + +import io.metersphere.api.domain.ApiDefinitionCustomField; +import io.metersphere.api.dto.definition.ApiDefinitionAddRequest; +import io.metersphere.api.dto.definition.ApiDefinitionUpdateRequest; +import io.metersphere.sdk.util.BeanUtils; +import io.metersphere.system.domain.CustomField; +import io.metersphere.system.dto.sdk.ApiDefinitionCaseDTO; +import io.metersphere.system.dto.sdk.OptionDTO; +import io.metersphere.system.mapper.CustomFieldMapper; +import jakarta.annotation.Resource; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +@Service +public class ApiDefinitionNoticeService { + + @Resource + private CustomFieldMapper customFieldMapper; + + public ApiDefinitionCaseDTO getApiDTO(ApiDefinitionAddRequest request) { + ApiDefinitionCaseDTO caseDTO = new ApiDefinitionCaseDTO(); + BeanUtils.copyBean(caseDTO, request); + List fields = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(request.getCustomFields())) { + for (ApiDefinitionCustomField customFieldDTO : request.getCustomFields()) { + OptionDTO optionDTO = new OptionDTO(); + CustomField customField = customFieldMapper.selectByPrimaryKey(customFieldDTO.getFieldId()); + if (customField == null) { + continue; + } + optionDTO.setId(customField.getId()); + optionDTO.setName(customField.getName()); + fields.add(optionDTO); + } + } + caseDTO.setFields(fields); + return caseDTO; + } + + public ApiDefinitionCaseDTO getUpdateApiDTO(ApiDefinitionUpdateRequest request) { + ApiDefinitionCaseDTO caseDTO = new ApiDefinitionCaseDTO(); + BeanUtils.copyBean(caseDTO, request); + List fields = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(request.getCustomFields())) { + for (ApiDefinitionCustomField customFieldDTO : request.getCustomFields()) { + OptionDTO optionDTO = new OptionDTO(); + CustomField customField = customFieldMapper.selectByPrimaryKey(customFieldDTO.getFieldId()); + if (customField == null) { + continue; + } + optionDTO.setId(customField.getId()); + optionDTO.setName(customField.getName()); + fields.add(optionDTO); + } + } + caseDTO.setFields(fields); + return caseDTO; + } + +} diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionScheduleService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionScheduleService.java index 2f15d91cf0..9c824e9fe9 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionScheduleService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiDefinitionScheduleService.java @@ -12,12 +12,12 @@ import io.metersphere.project.mapper.ProjectMapper; import io.metersphere.sdk.constants.ApplicationNumScope; import io.metersphere.sdk.constants.HttpMethodConstants; import io.metersphere.sdk.constants.ScheduleResourceType; -import io.metersphere.sdk.constants.ScheduleType; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.Translator; import io.metersphere.system.domain.Schedule; +import io.metersphere.system.dto.request.ScheduleConfig; import io.metersphere.system.log.constants.OperationLogModule; import io.metersphere.system.log.constants.OperationLogType; import io.metersphere.system.log.dto.LogDTO; @@ -49,7 +49,7 @@ public class ApiDefinitionScheduleService { @Resource private ProjectMapper projectMapper; - public void createSchedule(ApiScheduleRequest request, String userId) { + public String createSchedule(ApiScheduleRequest request, String userId) { /*保存swaggerUrl*/ ApiDefinitionSwagger apiSwagger = new ApiDefinitionSwagger(); BeanUtils.copyBean(apiSwagger, request); @@ -63,17 +63,17 @@ public class ApiDefinitionScheduleService { apiSwagger.setConfig(ApiDataUtils.toJSONString(basicAuth)); apiDefinitionSwaggerMapper.insertSelective(apiSwagger); - Schedule schedule = this.buildApiTestSchedule(request, userId); - schedule.setResourceId(apiSwagger.getId()); - schedule.setJob(SwaggerUrlImportJob.class.getName()); - schedule.setType(ScheduleType.CRON.name()); - schedule.setResourceType(ScheduleResourceType.API_IMPORT.name()); - scheduleService.addSchedule(schedule); - scheduleService.addOrUpdateCronJob(schedule, - SwaggerUrlImportJob.getJobKey(apiSwagger.getId()), - SwaggerUrlImportJob.getTriggerKey(apiSwagger.getId()), - SwaggerUrlImportJob.class); - //TODO 记录日志 + ScheduleConfig scheduleConfig = ScheduleConfig.builder() + .resourceId(apiSwagger.getId()) + .key(apiSwagger.getId()) + .projectId(apiSwagger.getProjectId()) + .name(apiSwagger.getName()) + .enable(request.getEnable()) + .cron(request.getValue().trim()) + .resourceType(ScheduleResourceType.API_IMPORT.name()) + .config(apiSwagger.getConfig()) + .build(); + LogDTO dto = new LogDTO( request.getProjectId(), projectMapper.selectByPrimaryKey(request.getProjectId()).getOrganizationId(), @@ -81,25 +81,18 @@ public class ApiDefinitionScheduleService { userId, OperationLogType.ADD.name(), OperationLogModule.API_DEFINITION, - request.getName()); + Translator.get("api_import_schedule") + ": " + request.getName()); dto.setHistory(false); dto.setPath("/api/definition/schedule/add"); dto.setMethod(HttpMethodConstants.POST.name()); dto.setOriginalValue(JSON.toJSONBytes(request)); operationLogService.add(dto); - } - - public Schedule buildApiTestSchedule(ApiScheduleRequest request, String userId) { - Schedule schedule = new Schedule(); - schedule.setName(request.getName()); - schedule.setResourceId(request.getId()); - schedule.setEnable(request.getEnable()); - schedule.setValue(request.getValue().trim()); - schedule.setKey(request.getId()); - schedule.setCreateUser(userId); - schedule.setProjectId(request.getProjectId()); - schedule.setConfig(request.getConfig()); - return schedule; + return scheduleService.scheduleConfig( + scheduleConfig, + SwaggerUrlImportJob.getJobKey(apiSwagger.getId()), + SwaggerUrlImportJob.getTriggerKey(apiSwagger.getId()), + SwaggerUrlImportJob.class, + userId); } public ApiDefinitionSwagger checkSchedule(String id) { @@ -117,7 +110,7 @@ public class ApiDefinitionScheduleService { return CollectionUtils.isNotEmpty(apiDefinitionSwaggers); } - public void updateSchedule(ApiScheduleRequest request, String userId) { + public String updateSchedule(ApiScheduleRequest request, String userId) { ApiDefinitionSwagger apiDefinitionSwagger = checkSchedule(request.getId()); BeanUtils.copyBean(apiDefinitionSwagger, request); // 设置鉴权信息 @@ -127,16 +120,17 @@ public class ApiDefinitionScheduleService { basicAuth.setAuthSwitch(request.isAuthSwitch()); apiDefinitionSwagger.setConfig(ApiDataUtils.toJSONString(basicAuth)); apiDefinitionSwaggerMapper.updateByPrimaryKeySelective(apiDefinitionSwagger); - // 只修改表达式和名称 - Schedule schedule = scheduleService.getScheduleByResource(request.getId(), SwaggerUrlImportJob.class.getName()); - schedule.setValue(request.getValue().trim()); - schedule.setEnable(request.getEnable()); - schedule.setName(request.getName()); - scheduleService.editSchedule(schedule); - scheduleService.addOrUpdateCronJob(schedule, - SwaggerUrlImportJob.getJobKey(request.getId()), - SwaggerUrlImportJob.getTriggerKey(request.getId()), - SwaggerUrlImportJob.class); + + ScheduleConfig scheduleConfig = ScheduleConfig.builder() + .resourceId(apiDefinitionSwagger.getId()) + .key(apiDefinitionSwagger.getId()) + .projectId(apiDefinitionSwagger.getProjectId()) + .name(apiDefinitionSwagger.getName()) + .enable(request.getEnable()) + .cron(request.getValue().trim()) + .resourceType(ScheduleResourceType.API_IMPORT.name()) + .config(apiDefinitionSwagger.getConfig()) + .build(); LogDTO dto = new LogDTO( request.getProjectId(), @@ -145,12 +139,18 @@ public class ApiDefinitionScheduleService { userId, OperationLogType.UPDATE.name(), OperationLogModule.API_DEFINITION, - request.getName()); + Translator.get("api_import_schedule") + ": " + request.getName()); dto.setHistory(false); dto.setPath("/api/definition/schedule/update"); dto.setMethod(HttpMethodConstants.POST.name()); dto.setOriginalValue(JSON.toJSONBytes(request)); operationLogService.add(dto); + return scheduleService.scheduleConfig( + scheduleConfig, + SwaggerUrlImportJob.getJobKey(apiDefinitionSwagger.getId()), + SwaggerUrlImportJob.getTriggerKey(apiDefinitionSwagger.getId()), + SwaggerUrlImportJob.class, + userId); } public ApiScheduleDTO getSchedule(String id) { 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 7775c8981e..35c9bf8622 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 @@ -98,9 +98,6 @@ public class ApiDefinitionService { @Resource private ApiDefinitionModuleMapper apiDefinitionModuleMapper; - @Resource - private ApiDefinitionCustomFieldMapper apiDefinitionCustomFieldMapper; - @Resource private ExtApiDefinitionCustomFieldMapper extApiDefinitionCustomFieldMapper; diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseNoticeService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseNoticeService.java index 92b7970db5..7342802a9b 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseNoticeService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/definition/ApiTestCaseNoticeService.java @@ -5,6 +5,7 @@ import io.metersphere.api.domain.ApiTestCaseExample; import io.metersphere.api.dto.definition.ApiCaseBatchEditRequest; import io.metersphere.api.dto.definition.ApiTestCaseAddRequest; import io.metersphere.api.dto.definition.ApiTestCaseBatchRequest; +import io.metersphere.api.dto.definition.ApiTestCaseUpdateRequest; import io.metersphere.api.mapper.ApiTestCaseMapper; import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.SubListUtils; @@ -34,6 +35,33 @@ public class ApiTestCaseNoticeService { return caseDTO; } + public ApiDefinitionCaseDTO getCaseDTO(ApiTestCaseUpdateRequest request) { + ApiDefinitionCaseDTO caseDTO = new ApiDefinitionCaseDTO(); + BeanUtils.copyBean(caseDTO, request); + caseDTO.setName(null); + caseDTO.setStatus(null); + caseDTO.setCaseCreateUser(null); + caseDTO.setCaseUpdateUser(null); + caseDTO.setCaseName(request.getName()); + caseDTO.setCaseStatus(request.getStatus()); + return caseDTO; + } + + public ApiDefinitionCaseDTO getCaseDTO(String id) { + ApiTestCase testCase = apiTestCaseMapper.selectByPrimaryKey(id); + ApiDefinitionCaseDTO caseDTO = new ApiDefinitionCaseDTO(); + BeanUtils.copyBean(caseDTO, testCase); + caseDTO.setName(null); + caseDTO.setStatus(null); + caseDTO.setCaseCreateTime(testCase.getCreateTime()); + caseDTO.setCaseUpdateTime(testCase.getUpdateTime()); + caseDTO.setCaseCreateUser(testCase.getCreateUser()); + caseDTO.setCaseUpdateUser(testCase.getUpdateUser()); + caseDTO.setCaseName(testCase.getName()); + caseDTO.setCaseStatus(testCase.getStatus()); + return caseDTO; + } + public List getBatchDeleteApiCaseDTO(ApiTestCaseBatchRequest request) { List ids = apiTestCaseService.doSelectIds(request, false); diff --git a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java index 4b7a9f1b34..51099aa964 100644 --- a/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java +++ b/backend/services/api-test/src/main/java/io/metersphere/api/service/scenario/ApiScenarioService.java @@ -833,16 +833,32 @@ public class ApiScenarioService { deleteStepByScenarioId(scenario.getId()); //删除step-blob deleteStepDetailByScenarioId(scenario.getId()); + //删除csv + deleteCsvByScenarioId(scenario.getId()); //删除文件 String scenarioDir = DefaultRepositoryDir.getApiDebugDir(scenario.getProjectId(), scenario.getId()); try { apiFileResourceService.deleteByResourceId(scenarioDir, scenario.getId(), scenario.getProjectId(), operator, OperationLogModule.API_DEBUG); - }catch (Exception ignore){} + } catch (Exception ignore) { + } //删除定时任务 scheduleService.deleteByResourceId(scenario.getId(), ApiScenarioScheduleJob.class.getName()); + } + + private void deleteCsvByScenarioId(String id) { + ApiScenarioCsvExample example = new ApiScenarioCsvExample(); + example.createCriteria().andScenarioIdEqualTo(id); + List apiScenarioCsv = apiScenarioCsvMapper.selectByExample(example); + if (CollectionUtils.isNotEmpty(apiScenarioCsv)) { + List fileIds = apiScenarioCsv.stream().map(ApiScenarioCsv::getFileId).toList(); + //删除关联关系 + ApiScenarioCsvStepExample stepExample = new ApiScenarioCsvStepExample(); + stepExample.createCriteria().andFileIdIn(fileIds); + apiScenarioCsvStepMapper.deleteByExample(stepExample); + } + apiScenarioCsvMapper.deleteByExample(example); - //todo wang xiao gang: 删除csv相关东西 } //级联删除 @@ -869,12 +885,25 @@ public class ApiScenarioService { String scenarioDir = DefaultRepositoryDir.getApiDebugDir(scenario.getProjectId(), scenario.getId()); try { apiFileResourceService.deleteByResourceId(scenarioDir, scenario.getId(), scenario.getProjectId(), operator, OperationLogModule.API_DEBUG); - }catch (Exception ignore){} - //删除定时任务 - scheduleService.deleteByResourceId(scenario.getId(), ApiScenarioScheduleJob.class.getName()); - }); + //删除定时任务 + scheduleService.deleteByResourceId(scenario.getId(), ApiScenarioScheduleJob.class.getName()); + } catch (Exception ignore) { + } + + }); + //删除csv + ApiScenarioCsvExample csvExample = new ApiScenarioCsvExample(); + csvExample.createCriteria().andScenarioIdIn(scenarioIdList); + List apiScenarioCsv = apiScenarioCsvMapper.selectByExample(csvExample); + if (CollectionUtils.isNotEmpty(apiScenarioCsv)) { + List fileIds = apiScenarioCsv.stream().map(ApiScenarioCsv::getFileId).toList(); + //删除关联关系 + ApiScenarioCsvStepExample csvStepExample = new ApiScenarioCsvStepExample(); + csvStepExample.createCriteria().andFileIdIn(fileIds); + apiScenarioCsvStepMapper.deleteByExample(csvStepExample); + } + apiScenarioCsvMapper.deleteByExample(csvExample); - //todo wang xiao gang: 删除csv相关东西 } @@ -1615,7 +1644,7 @@ public class ApiScenarioService { .enable(scheduleRequest.isEnable()) .cron(scheduleRequest.getCron()) .resourceType(ScheduleResourceType.API_SCENARIO.name()) - .configMap(scheduleRequest.getConfigMap()) + .config(JSON.toJSONString(scheduleRequest.getConfig())) .build(); return scheduleService.scheduleConfig( diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionScheduleControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionScheduleControllerTests.java index 1e552ae936..80ad5822ee 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionScheduleControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiDefinitionScheduleControllerTests.java @@ -147,7 +147,7 @@ public class ApiDefinitionScheduleControllerTests extends BaseTest { SwaggerUrlCheck swaggerUrlCheck = new SwaggerUrlCheck(); swaggerUrlCheck.setProjectId(DEFAULT_PROJECT_ID); swaggerUrlCheck.setSwaggerUrl("https://petstore3.swagger.io/api/v3/openapi.json"); - this.requestPost(BASE_PATH + "check/", swaggerUrlCheck); + this.requestPost(BASE_PATH + "check", swaggerUrlCheck); } @Order(6) diff --git a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java index 048adb07c4..f9a3363737 100644 --- a/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java +++ b/backend/services/api-test/src/test/java/io/metersphere/api/controller/ApiScenarioControllerTests.java @@ -30,6 +30,7 @@ import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.domain.Environment; import io.metersphere.sdk.domain.EnvironmentExample; import io.metersphere.sdk.domain.EnvironmentGroup; +import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO; import io.metersphere.sdk.file.FileCenter; import io.metersphere.sdk.file.FileRequest; import io.metersphere.sdk.mapper.EnvironmentGroupMapper; @@ -662,6 +663,15 @@ public class ApiScenarioControllerTests extends BaseTest { @Order(10) public void delete() throws Exception { // @@请求成功 + ApiScenarioCsv apiScenarioCsv = new ApiScenarioCsv(); + apiScenarioCsv.setId(IDGenerator.nextStr()); + apiScenarioCsv.setScenarioId(addApiScenario.getId()); + apiScenarioCsv.setFileId(fileMetadataId); + apiScenarioCsv.setName("csv变量"); + apiScenarioCsv.setScope(CsvVariable.CsvVariableScope.SCENARIO.name()); + apiScenarioCsv.setProjectId(DEFAULT_PROJECT_ID); + apiScenarioCsvMapper.insertSelective(apiScenarioCsv); + this.requestGetWithOk(DEFAULT_DELETE, addApiScenario.getId()); ApiScenario apiScenario = apiScenarioMapper.selectByPrimaryKey(addApiScenario.getId()); ApiScenarioBlob apiScenarioBlob = apiScenarioBlobMapper.selectByPrimaryKey(addApiScenario.getId()); @@ -1296,17 +1306,14 @@ public class ApiScenarioControllerTests extends BaseTest { //配置configMap request.setEnable(true); - request.setConfigMap(new HashMap<>() {{ - this.put("envId", "testEnv"); - this.put("resourcePoolId", "testResourcePool"); - }}); + request.setConfig(new ApiRunModeConfigDTO()); result = this.requestPostAndReturn(testUrl, request); resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); newScheduleId = resultHolder.getData().toString(); apiScenarioBatchOperationTestService.checkSchedule(newScheduleId, scenarioId, request.isEnable()); //清空configMap - request.setConfigMap(new HashMap<>()); + request.setConfig(new ApiRunModeConfigDTO()); request.setEnable(false); result = this.requestPostAndReturn(testUrl, request); resultHolder = JSON.parseObject(result.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class); @@ -1465,7 +1472,7 @@ public class ApiScenarioControllerTests extends BaseTest { @Test @Order(32) - //todo + //todo void batchRecoverToGc() throws Exception { String testUrl = "/batch-operation/recover-gc"; if (CollectionUtils.isEmpty(BATCH_OPERATION_SCENARIO_ID)) { @@ -1538,7 +1545,7 @@ public class ApiScenarioControllerTests extends BaseTest { @Test @Order(33) - //todo + //todo void batchDelete() throws Exception { String testUrl = "/batch-operation/delete"; if (CollectionUtils.isEmpty(BATCH_OPERATION_SCENARIO_ID)) { @@ -1633,6 +1640,7 @@ public class ApiScenarioControllerTests extends BaseTest { } } } + private String createModule(int i, String projectId, String parentId) { ApiScenarioModule apiScenarioModule = new ApiScenarioModule(); apiScenarioModule.setId(IDGenerator.nextStr()); @@ -1795,6 +1803,15 @@ public class ApiScenarioControllerTests extends BaseTest { apiFileResource.setCreateTime(System.currentTimeMillis()); apiFileResource.setProjectId(apiScenario.getProjectId()); apiFileResourceMapper.insertSelective(apiFileResource); + + ApiScenarioCsv apiScenarioCsv = new ApiScenarioCsv(); + apiScenarioCsv.setId(IDGenerator.nextStr()); + apiScenarioCsv.setScenarioId(apiScenario.getId()); + apiScenarioCsv.setFileId(fileMetadataId); + apiScenarioCsv.setName("csv变量"); + apiScenarioCsv.setScope(CsvVariable.CsvVariableScope.SCENARIO.name()); + apiScenarioCsv.setProjectId(DEFAULT_PROJECT_ID); + apiScenarioCsvMapper.insertSelective(apiScenarioCsv); } apiScenarioMapper.insertSelective(apiScenario); BATCH_OPERATION_SCENARIO_ID.add(apiScenario.getId()); diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java index 316405cb23..969ea60f93 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/CommandService.java @@ -2,7 +2,7 @@ package io.metersphere.project.service; import io.metersphere.project.dto.environment.ssl.KeyStoreEntry; - import io.metersphere.sdk.constants.LocalRepositoryDir; +import io.metersphere.sdk.constants.LocalRepositoryDir; import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.LogUtils; @@ -27,8 +27,8 @@ public class CommandService { MsFileUtils.validateFileName(bodyFile.getOriginalFilename()); String dir = LocalRepositoryDir.getSystemTempDir(); File fileDir = new File(dir); - if (!fileDir.exists()) { - fileDir.mkdirs(); + if (!fileDir.exists() && !fileDir.mkdir()) { + throw new MSException(Translator.get("upload_fail")); } File file = new File(dir + IDGenerator.nextStr() + "_" + bodyFile.getOriginalFilename()); try (InputStream in = bodyFile.getInputStream(); OutputStream out = new FileOutputStream(file)) { @@ -41,13 +41,6 @@ public class CommandService { return file.getPath(); } - public static void deleteFile(String path) { - File file = new File(path); - if (file.exists()) { - file.delete(); - } - } - public List getEntry(String password, MultipartFile file) { try { String path = createFile(file); @@ -73,6 +66,7 @@ public class CommandService { dto.setOriginalAsName(line.split(":")[1]); } if (line.startsWith("条目类型") || line.startsWith("Entry type")) { + assert dto != null; dto.setType(line.split(":")[1]); } } @@ -80,7 +74,10 @@ public class CommandService { dtoList.add(dto); } } - deleteFile(path); + File localFiles = new File(path); + if (!localFiles.exists() && !localFiles.delete()) { + LogUtils.info("delete file fail"); + } return dtoList; } catch (Exception e) { LogUtils.error(e); diff --git a/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java b/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java index 688377c2be..419a2fcfe8 100644 --- a/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java +++ b/backend/services/project-management/src/main/java/io/metersphere/project/service/ProjectApplicationService.java @@ -410,7 +410,7 @@ public class ProjectApplicationService { OperationLogConstants.SYSTEM, null, OperationLogType.UPDATE.name(), - OperationLogModule.PROJECT_PROJECT_MANAGER, + OperationLogModule.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT, "同步缺陷"); dto.setModifiedValue(JSON.toJSONBytes(configs)); dto.setOriginalValue(JSON.toJSONBytes(originConfig)); @@ -433,7 +433,7 @@ public class ProjectApplicationService { OperationLogConstants.SYSTEM, null, OperationLogType.UPDATE.name(), - OperationLogModule.PROJECT_PROJECT_MANAGER, + OperationLogModule.PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT, "关联需求"); dto.setModifiedValue(JSON.toJSONBytes(configs)); dto.setOriginalValue(JSON.toJSONBytes(originConfig)); diff --git a/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java b/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java index 77404642a5..fd96cae49d 100644 --- a/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java +++ b/backend/services/project-management/src/test/java/io/metersphere/project/controller/EnvironmentControllerTests.java @@ -1060,9 +1060,8 @@ public class EnvironmentControllerTests extends BaseTest { MultiValueMap paramMap = new LinkedMultiValueMap<>(); paramMap.add("file", List.of(file)); paramMap.set("request", password); - MvcResult mvcResult = requestMultipartWithOk(getEnTry, paramMap, DEFAULT_PROJECT_ID); - List response = parseObjectFromMvcResult(mvcResult, List.class); - Assertions.assertNotNull(response); + requestMultipartWithOk(getEnTry, paramMap, DEFAULT_PROJECT_ID); + password = "123456789"; inputStream = new FileInputStream(new File( diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/request/ScheduleConfig.java b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/request/ScheduleConfig.java index 4d0bc45a69..5dc6a7b72b 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/request/ScheduleConfig.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/request/ScheduleConfig.java @@ -1,13 +1,10 @@ package io.metersphere.system.dto.request; import io.metersphere.sdk.constants.ScheduleType; -import io.metersphere.sdk.util.JSON; import io.metersphere.system.domain.Schedule; import lombok.Builder; import lombok.Data; -import java.util.Map; - @Data @Builder public class ScheduleConfig { @@ -26,7 +23,7 @@ public class ScheduleConfig { private String resourceType; - Map configMap; + private String config; public Schedule genCronSchedule(Schedule schedule) { if (schedule == null) { @@ -40,10 +37,7 @@ public class ScheduleConfig { schedule.setProjectId(this.getProjectId()); schedule.setValue(this.getCron()); schedule.setResourceType(this.getResourceType()); - //配置数据为null,意味着不更改; 如果要清空配置,需要传入空对象 - if (configMap != null) { - schedule.setConfig(JSON.toJSONString(configMap)); - } + schedule.setConfig(this.getConfig()); return schedule; } } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ApiDefinitionCaseDTO.java b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ApiDefinitionCaseDTO.java index 1574dbab64..83306ff74e 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ApiDefinitionCaseDTO.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/dto/sdk/ApiDefinitionCaseDTO.java @@ -4,6 +4,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.NoArgsConstructor; +import java.util.List; + @Data @NoArgsConstructor public class ApiDefinitionCaseDTO { @@ -80,5 +82,7 @@ public class ApiDefinitionCaseDTO { @Schema(description = "项目ID") private String projectId; + @Schema(description = "自定义字段的值") + private List fields; } diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/schedule/ScheduleService.java b/backend/services/system-setting/src/main/java/io/metersphere/system/schedule/ScheduleService.java index 78413a0370..b82463101b 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/schedule/ScheduleService.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/schedule/ScheduleService.java @@ -1,7 +1,6 @@ package io.metersphere.system.schedule; import io.metersphere.sdk.exception.MSException; -import io.metersphere.sdk.util.JSON; import io.metersphere.system.domain.Schedule; import io.metersphere.system.domain.ScheduleExample; import io.metersphere.system.dto.request.ScheduleConfig; @@ -18,8 +17,6 @@ import org.quartz.TriggerKey; import org.springframework.transaction.annotation.Transactional; import java.util.List; -import java.util.Map; -import java.util.Optional; @Transactional(rollbackFor = Exception.class) public class ScheduleService { @@ -127,10 +124,6 @@ public class ScheduleService { } JobDataMap jobDataMap = scheduleManager.getDefaultJobDataMap(schedule, scheduleConfig.getCron(), operator); - if (StringUtils.isNotEmpty(schedule.getConfig())) { - Map configMap = JSON.parseObject(schedule.getConfig(), Map.class); - jobDataMap.putAll(configMap); - } /* scheduleManager.modifyCronJobTime方法如同它的方法名所说,只能修改定时任务的触发时间。 diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/ScheduleControllerTests.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/ScheduleControllerTests.java index e0467384e0..1b29a1842c 100644 --- a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/ScheduleControllerTests.java +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/ScheduleControllerTests.java @@ -2,6 +2,8 @@ package io.metersphere.system.controller; import io.metersphere.sdk.constants.ScheduleResourceType; import io.metersphere.sdk.constants.ScheduleType; +import io.metersphere.sdk.dto.api.task.ApiRunModeConfigDTO; +import io.metersphere.sdk.util.JSON; import io.metersphere.system.base.BaseTest; import io.metersphere.system.domain.Schedule; import io.metersphere.system.dto.request.ScheduleConfig; @@ -16,7 +18,6 @@ import org.quartz.TriggerKey; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import java.util.HashMap; import java.util.List; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -88,10 +89,7 @@ public class ScheduleControllerTests extends BaseTest { .enable(true) .cron("0 0/1 * * * ?") .resourceType(ScheduleResourceType.API_SCENARIO.name()) - .configMap(new HashMap<>() {{ - this.put("envId", "testEnv"); - this.put("resourcePoolId", "testResourcePool"); - }}) + .config(JSON.toJSONString(new ApiRunModeConfigDTO())) .build(); scheduleService.scheduleConfig(