fix(接口测试): 接口测试增加所属资源校验

This commit is contained in:
wxg0103 2023-12-13 15:20:07 +08:00 committed by 刘瑞斌
parent c02aa7d534
commit fbe9fbab2a
8 changed files with 82 additions and 0 deletions

View File

@ -31,6 +31,7 @@ import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.log.annotation.MsRequestLog; import io.metersphere.log.annotation.MsRequestLog;
import io.metersphere.notice.annotation.SendNotice; import io.metersphere.notice.annotation.SendNotice;
import io.metersphere.request.ResetOrderRequest; import io.metersphere.request.ResetOrderRequest;
import io.metersphere.security.CheckOwner;
import io.metersphere.service.definition.ApiDefinitionService; import io.metersphere.service.definition.ApiDefinitionService;
import io.metersphere.service.definition.FunctionRunService; import io.metersphere.service.definition.FunctionRunService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -113,6 +114,7 @@ public class ApiDefinitionController {
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_EDIT_API) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_EDIT_API)
@MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiDefinitionService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiDefinitionService.class)
// @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.UPDATE, subject = "接口定义通知") // @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.UPDATE, subject = "接口定义通知")
@CheckOwner(resourceId = "#request.id", resourceType = "api_definition")
public ApiDefinitionResult update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> bodyFiles) { public ApiDefinitionResult update(@RequestPart("request") SaveApiDefinitionRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> bodyFiles) {
return apiDefinitionService.update(request, bodyFiles); return apiDefinitionService.update(request, bodyFiles);
} }
@ -120,6 +122,7 @@ public class ApiDefinitionController {
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_API) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_API)
@MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiDefinitionService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiDefinitionService.class)
@CheckOwner(resourceId = "#id", resourceType = "api_definition")
public void delete(@PathVariable String id) { public void delete(@PathVariable String id) {
apiDefinitionService.delete(id); apiDefinitionService.delete(id);
} }
@ -127,6 +130,7 @@ public class ApiDefinitionController {
@PostMapping("/del-ids") @PostMapping("/del-ids")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_API) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_API)
@MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.BATCH_DEL, beforeEvent = "#msClass.getLogDetails(#request.ids)", msClass = ApiDefinitionService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.BATCH_DEL, beforeEvent = "#msClass.getLogDetails(#request.ids)", msClass = ApiDefinitionService.class)
@CheckOwner(resourceId = "#ids", resourceType = "api_definition")
public void deleteBatch(@RequestBody List<String> ids) { public void deleteBatch(@RequestBody List<String> ids) {
apiDefinitionService.deleteBatch(ids); apiDefinitionService.deleteBatch(ids);
} }
@ -149,6 +153,7 @@ public class ApiDefinitionController {
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_API) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_API)
@MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.GC, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiDefinitionService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION, type = OperLogConstants.GC, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiDefinitionService.class)
@SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, target = "#targetClass.getBLOBs(#ids)", targetClass = ApiDefinitionService.class, event = NoticeConstants.Event.DELETE, subject = "接口定义通知") @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, target = "#targetClass.getBLOBs(#ids)", targetClass = ApiDefinitionService.class, event = NoticeConstants.Event.DELETE, subject = "接口定义通知")
@CheckOwner(resourceId = "#ids", resourceType = "api_definition")
public void removeToGc(@RequestBody List<String> ids) { public void removeToGc(@RequestBody List<String> ids) {
apiDefinitionService.removeToGc(ids); apiDefinitionService.removeToGc(ids);
} }

View File

@ -18,6 +18,7 @@ import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.log.annotation.MsRequestLog; import io.metersphere.log.annotation.MsRequestLog;
import io.metersphere.notice.annotation.SendNotice; import io.metersphere.notice.annotation.SendNotice;
import io.metersphere.request.ResetOrderRequest; import io.metersphere.request.ResetOrderRequest;
import io.metersphere.security.CheckOwner;
import io.metersphere.service.definition.ApiDefinitionExecResultService; import io.metersphere.service.definition.ApiDefinitionExecResultService;
import io.metersphere.service.definition.ApiTestCaseService; import io.metersphere.service.definition.ApiTestCaseService;
import io.metersphere.service.scenario.ApiScenarioService; import io.metersphere.service.scenario.ApiScenarioService;
@ -126,6 +127,7 @@ public class ApiTestCaseController {
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_EDIT_CASE) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_EDIT_CASE)
@MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request)", title = "#request.name", content = "#msClass.getLogDetails(#request)", msClass = ApiTestCaseService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request)", title = "#request.name", content = "#msClass.getLogDetails(#request)", msClass = ApiTestCaseService.class)
@SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CASE_UPDATE, subject = "接口用例通知") @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CASE_UPDATE, subject = "接口用例通知")
@CheckOwner(resourceId = "#request.id", resourceType = "api_test_case")
public ApiTestCase update(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> bodyFiles) { public ApiTestCase update(@RequestPart("request") SaveApiTestCaseRequest request, @RequestPart(value = "files", required = false) List<MultipartFile> bodyFiles) {
return apiTestCaseService.update(request, bodyFiles); return apiTestCaseService.update(request, bodyFiles);
} }
@ -140,6 +142,7 @@ public class ApiTestCaseController {
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_CASE) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_CASE)
@MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiTestCaseService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiTestCaseService.class)
@CheckOwner(resourceId = "#id", resourceType = "api_test_case")
public void delete(@PathVariable String id) { public void delete(@PathVariable String id) {
apiTestCaseService.delete(id); apiTestCaseService.delete(id);
} }
@ -148,6 +151,7 @@ public class ApiTestCaseController {
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_CASE) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_CASE)
@MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiTestCaseService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiTestCaseService.class)
@SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CASE_DELETE, target = "#targetClass.get(#id)", targetClass = ApiTestCaseService.class, subject = "接口用例通知") @SendNotice(taskType = NoticeConstants.TaskType.API_DEFINITION_TASK, event = NoticeConstants.Event.CASE_DELETE, target = "#targetClass.get(#id)", targetClass = ApiTestCaseService.class, subject = "接口用例通知")
@CheckOwner(resourceId = "#id", resourceType = "api_test_case")
public void deleteToGc(@PathVariable String id) { public void deleteToGc(@PathVariable String id) {
apiTestCaseService.deleteToGc(id); apiTestCaseService.deleteToGc(id);
} }
@ -188,6 +192,7 @@ public class ApiTestCaseController {
@PostMapping("/del-ids") @PostMapping("/del-ids")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_CASE) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE_CASE)
@MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.BATCH_DEL, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiTestCaseService.class) @MsAuditLog(module = OperLogModule.API_DEFINITION_CASE, type = OperLogConstants.BATCH_DEL, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiTestCaseService.class)
@CheckOwner(resourceId = "#ids", resourceType = "api_test_case")
public void deleteBatch(@RequestBody List<String> ids) { public void deleteBatch(@RequestBody List<String> ids) {
apiTestCaseService.deleteBatch(ids); apiTestCaseService.deleteBatch(ids);
} }

View File

@ -22,6 +22,7 @@ import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.log.annotation.MsRequestLog; import io.metersphere.log.annotation.MsRequestLog;
import io.metersphere.notice.annotation.SendNotice; import io.metersphere.notice.annotation.SendNotice;
import io.metersphere.request.ResetOrderRequest; import io.metersphere.request.ResetOrderRequest;
import io.metersphere.security.CheckOwner;
import io.metersphere.service.ext.ExtApiTaskService; import io.metersphere.service.ext.ExtApiTaskService;
import io.metersphere.service.scenario.ApiScenarioService; import io.metersphere.service.scenario.ApiScenarioService;
import io.metersphere.task.dto.TaskRequestDTO; import io.metersphere.task.dto.TaskRequestDTO;
@ -131,6 +132,7 @@ public class ApiScenarioController {
@MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiScenarioService.class) @MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.UPDATE, beforeEvent = "#msClass.getLogDetails(#request.id)", title = "#request.name", content = "#msClass.getLogDetails(#request.id)", msClass = ApiScenarioService.class)
@RequiresPermissions(value = {PermissionConstants.PROJECT_API_SCENARIO_READ_EDIT, PermissionConstants.PROJECT_API_SCENARIO_READ_COPY}, logical = Logical.OR) @RequiresPermissions(value = {PermissionConstants.PROJECT_API_SCENARIO_READ_EDIT, PermissionConstants.PROJECT_API_SCENARIO_READ_COPY}, logical = Logical.OR)
@SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.UPDATE, subject = "接口自动化通知") @SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.UPDATE, subject = "接口自动化通知")
@CheckOwner(resourceId = "#request.id", resourceType = "api_scenario")
public ApiScenario update(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "bodyFiles", required = false) List<MultipartFile> bodyFiles, @RequestPart(value = "scenarioFiles", required = false) List<MultipartFile> scenarioFiles) { public ApiScenario update(@RequestPart("request") SaveApiScenarioRequest request, @RequestPart(value = "bodyFiles", required = false) List<MultipartFile> bodyFiles, @RequestPart(value = "scenarioFiles", required = false) List<MultipartFile> scenarioFiles) {
return apiAutomationService.update(request, bodyFiles, scenarioFiles); return apiAutomationService.update(request, bodyFiles, scenarioFiles);
} }
@ -144,6 +146,7 @@ public class ApiScenarioController {
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
@MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiScenarioService.class) @MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.DELETE, beforeEvent = "#msClass.getLogDetails(#id)", msClass = ApiScenarioService.class)
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_DELETE) @RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_DELETE)
@CheckOwner(resourceId = "#id", resourceType = "api_scenario")
public void delete(@PathVariable String id) { public void delete(@PathVariable String id) {
apiAutomationService.delete(id); apiAutomationService.delete(id);
} }
@ -152,6 +155,7 @@ public class ApiScenarioController {
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_DELETE) @RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_DELETE)
@MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.BATCH_DEL, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiScenarioService.class) @MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.BATCH_DEL, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiScenarioService.class)
@SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getScenarioCaseByIds(#ids)", targetClass = ApiScenarioService.class, subject = "接口自动化通知") @SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.getScenarioCaseByIds(#ids)", targetClass = ApiScenarioService.class, subject = "接口自动化通知")
@CheckOwner(resourceId = "#ids", resourceType = "api_scenario")
public void deleteBatch(@RequestBody List<String> ids) { public void deleteBatch(@RequestBody List<String> ids) {
apiAutomationService.deleteBatch(ids); apiAutomationService.deleteBatch(ids);
} }
@ -166,6 +170,7 @@ public class ApiScenarioController {
@RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_DELETE) @RequiresPermissions(PermissionConstants.PROJECT_API_SCENARIO_READ_DELETE)
@MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.GC, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiScenarioService.class) @MsAuditLog(module = OperLogModule.API_AUTOMATION, type = OperLogConstants.GC, beforeEvent = "#msClass.getLogDetails(#ids)", msClass = ApiScenarioService.class)
@SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, target = "#targetClass.getScenarioCaseByIds(#ids)", targetClass = ApiScenarioService.class, event = NoticeConstants.Event.DELETE, subject = "接口自动化通知") @SendNotice(taskType = NoticeConstants.TaskType.API_AUTOMATION_TASK, target = "#targetClass.getScenarioCaseByIds(#ids)", targetClass = ApiScenarioService.class, event = NoticeConstants.Event.DELETE, subject = "接口自动化通知")
@CheckOwner(resourceId = "#ids", resourceType = "api_scenario")
public void removeToGc(@RequestBody List<String> ids) { public void removeToGc(@RequestBody List<String> ids) {
apiAutomationService.removeToGc(ids); apiAutomationService.removeToGc(ids);
} }
@ -192,6 +197,7 @@ public class ApiScenarioController {
@GetMapping("/scenario-details/{id}") @GetMapping("/scenario-details/{id}")
@RequiresPermissions(value ={PermissionConstants.PROJECT_API_SCENARIO_READ, PermissionConstants.PROJECT_API_DEFINITION_READ_EDIT_CASE}, logical = Logical.OR) @RequiresPermissions(value ={PermissionConstants.PROJECT_API_SCENARIO_READ, PermissionConstants.PROJECT_API_DEFINITION_READ_EDIT_CASE}, logical = Logical.OR)
@CheckOwner(resourceId = "#id", resourceType = "api_scenario")
public ApiScenarioDTO getScenarioDefinition(@PathVariable String id) { public ApiScenarioDTO getScenarioDefinition(@PathVariable String id) {
return apiAutomationService.getNewApiScenario(id); return apiAutomationService.getNewApiScenario(id);
} }

View File

@ -18,6 +18,7 @@ import io.metersphere.dto.PlanReportCaseDTO;
import io.metersphere.dto.RequestResult; import io.metersphere.dto.RequestResult;
import io.metersphere.log.annotation.MsAuditLog; import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.notice.annotation.SendNotice; import io.metersphere.notice.annotation.SendNotice;
import io.metersphere.service.ApiCheckPermissionService;
import io.metersphere.service.ShareInfoService; import io.metersphere.service.ShareInfoService;
import io.metersphere.service.scenario.ApiScenarioReportService; import io.metersphere.service.scenario.ApiScenarioReportService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -35,6 +36,8 @@ public class ApiScenarioReportController {
private ApiScenarioReportService apiReportService; private ApiScenarioReportService apiReportService;
@Resource @Resource
private ShareInfoService shareInfoService; private ShareInfoService shareInfoService;
@Resource
private ApiCheckPermissionService apiCheckPermissionService;
@GetMapping("/get/{reportId}") @GetMapping("/get/{reportId}")
public ApiScenarioReportResult get(@PathVariable String reportId) { public ApiScenarioReportResult get(@PathVariable String reportId) {
@ -76,6 +79,7 @@ public class ApiScenarioReportController {
@SendNotice(taskType = NoticeConstants.TaskType.API_REPORT_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.get(#request.id, false)", targetClass = ApiScenarioReportService.class, @SendNotice(taskType = NoticeConstants.TaskType.API_REPORT_TASK, event = NoticeConstants.Event.DELETE, target = "#targetClass.get(#request.id, false)", targetClass = ApiScenarioReportService.class,
subject = "接口报告通知") subject = "接口报告通知")
public void delete(@RequestBody DeleteAPIReportRequest request) { public void delete(@RequestBody DeleteAPIReportRequest request) {
apiCheckPermissionService.checkReportOwner(request.getId(), PermissionConstants.PROJECT_API_REPORT_READ_DELETE);
apiReportService.delete(request); apiReportService.delete(request);
} }

View File

@ -0,0 +1,59 @@
package io.metersphere.service;
import io.metersphere.base.domain.ApiDefinitionExecResultWithBLOBs;
import io.metersphere.base.domain.ApiScenarioReportWithBLOBs;
import io.metersphere.base.mapper.ApiDefinitionExecResultMapper;
import io.metersphere.base.mapper.ApiScenarioReportMapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.i18n.Translator;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiCheckPermissionService {
@Resource
private ApiScenarioReportMapper apiScenarioReportMapper;
@Resource
private ApiDefinitionExecResultMapper apiDefinitionExecResultMapper;
@Resource
private BaseCheckPermissionService baseCheckPermissionService;
public void checkReportOwner(String reportId, String permissionId) {
Set<String> projectIds = baseCheckPermissionService.getUserRelatedProjectIds();
if (CollectionUtils.isEmpty(projectIds)) {
return;
}
ApiScenarioReportWithBLOBs scenarioReport = apiScenarioReportMapper.selectByPrimaryKey(reportId);
ApiDefinitionExecResultWithBLOBs apiReport = apiDefinitionExecResultMapper.selectByPrimaryKey(reportId);
if (scenarioReport == null) {
if (apiReport == null) {
MSException.throwException(Translator.get("check_owner_report"));
}
MSException.throwException(Translator.get("check_owner_report"));
}
if (scenarioReport != null) {
if (!projectIds.contains(scenarioReport.getProjectId())) {
MSException.throwException(Translator.get("check_owner_report"));
}
if (SessionUtils.hasPermission(null, scenarioReport.getProjectId(), permissionId)) {
MSException.throwException(Translator.get("check_owner_report"));
}
}
if (apiReport != null) {
if (!projectIds.contains(apiReport.getProjectId())) {
MSException.throwException(Translator.get("check_owner_report"));
}
if (SessionUtils.hasPermission(null, apiReport.getProjectId(), permissionId)) {
MSException.throwException(Translator.get("check_owner_report"));
}
}
}
}

View File

@ -237,6 +237,7 @@ check_owner_test=The current user does not have permission to operate this test
check_owner_case=The current user does not have permission to operate this use case check_owner_case=The current user does not have permission to operate this use case
check_owner_plan=The current user does not have permission to operate this plan check_owner_plan=The current user does not have permission to operate this plan
check_owner_review=The current user does not have permission to operate this review check_owner_review=The current user does not have permission to operate this review
check_owner_report=The current user does not have permission to operate this report
check_owner_comment=The current user does not have permission to manipulate this comment check_owner_comment=The current user does not have permission to manipulate this comment
check_owner_workspace=The current user does not have permission to operate this workspace check_owner_workspace=The current user does not have permission to operate this workspace
upload_content_is_null=Imported content is empty upload_content_is_null=Imported content is empty

View File

@ -236,6 +236,7 @@ check_owner_project=当前用户没有操作此项目的权限
check_owner_test=当前用户没有操作此测试的权限 check_owner_test=当前用户没有操作此测试的权限
check_owner_case=当前用户没有操作此用例的权限 check_owner_case=当前用户没有操作此用例的权限
check_owner_plan=当前用户没有操作此计划的权限 check_owner_plan=当前用户没有操作此计划的权限
check_owner_report=当前用户没有操作此报告的权限
check_owner_review=当前用户没有操作此评审的权限 check_owner_review=当前用户没有操作此评审的权限
check_owner_comment=当前用户没有操作此评论的权限 check_owner_comment=当前用户没有操作此评论的权限
check_owner_workspace=当前用户没有操作此工作空间的权限 check_owner_workspace=当前用户没有操作此工作空间的权限

View File

@ -234,6 +234,7 @@ test_track.length_less_than=標題過長,字數必須小於
check_owner_project=當前用戶沒有操作此項目的權限 check_owner_project=當前用戶沒有操作此項目的權限
check_owner_test=當前用戶沒有操作此測試的權限 check_owner_test=當前用戶沒有操作此測試的權限
check_owner_case=當前用戶沒有操作此用例的權限 check_owner_case=當前用戶沒有操作此用例的權限
check_owner_report=當前用戶沒有操作此報告的權限
check_owner_plan=當前用戶沒有操作此計劃的權限 check_owner_plan=當前用戶沒有操作此計劃的權限
check_owner_review=當前用戶沒有操作此評審的權限 check_owner_review=當前用戶沒有操作此評審的權限
check_owner_comment=當前用戶沒有操作此評論的權限 check_owner_comment=當前用戶沒有操作此評論的權限