diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.java b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.java index a6c9bc9d07..8b7fbd5e67 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.java +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.java @@ -9,4 +9,6 @@ import java.util.List; public interface ExtLoadTestReportMapper { List getReportList(@Param("reportRequest")ReportRequest request); + + ReportDTO getReportTestAndProInfo(@Param("id") String id); } diff --git a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.xml b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.xml index bf74baf18a..9fd854409b 100644 --- a/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.xml +++ b/backend/src/main/java/io/metersphere/base/mapper/ext/ExtLoadTestReportMapper.xml @@ -13,4 +13,12 @@ + + \ No newline at end of file diff --git a/backend/src/main/java/io/metersphere/controller/LoginController.java b/backend/src/main/java/io/metersphere/controller/LoginController.java index 11da340770..48f621dcc9 100644 --- a/backend/src/main/java/io/metersphere/controller/LoginController.java +++ b/backend/src/main/java/io/metersphere/controller/LoginController.java @@ -1,19 +1,27 @@ package io.metersphere.controller; +import io.metersphere.base.domain.UserRole; import io.metersphere.controller.request.LoginRequest; +import io.metersphere.dto.UserDTO; import io.metersphere.i18n.Translator; -import io.metersphere.user.SessionUtils; +import io.metersphere.service.UserService; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.subject.Subject; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import java.util.List; +import java.util.stream.Collectors; @RestController @RequestMapping public class LoginController { + @Resource + private UserService userService; + @GetMapping(value = "/isLogin") public ResultHolder isLogin() { if (SecurityUtils.getSubject().isAuthenticated()) { @@ -37,6 +45,20 @@ public class LoginController { try { subject.login(token); if (subject.isAuthenticated()) { + UserDTO user = (UserDTO) subject.getSession().getAttribute("user"); + // 自动选中组织,工作空间 + if (StringUtils.isBlank(user.getLastOrganizationId())) { + List userRoles = user.getUserRoles(); + List test = userRoles.stream().filter(ur -> ur.getRoleId().indexOf("test") > -1).collect(Collectors.toList()); + List org = userRoles.stream().filter(ur -> ur.getRoleId().indexOf("org") > -1).collect(Collectors.toList()); + if (test.size() > 0) { + String wsId = test.get(0).getSourceId(); + userService.switchUserRole(user, "workspace", wsId); + } else if (org.size() > 0) { + String orgId = org.get(0).getSourceId(); + userService.switchUserRole(user, "organization", orgId); + } + } // 返回 userDTO return ResultHolder.success(subject.getSession().getAttribute("user")); } else { diff --git a/backend/src/main/java/io/metersphere/controller/OrganizationController.java b/backend/src/main/java/io/metersphere/controller/OrganizationController.java index 158ceb53be..cfd103e5f9 100644 --- a/backend/src/main/java/io/metersphere/controller/OrganizationController.java +++ b/backend/src/main/java/io/metersphere/controller/OrganizationController.java @@ -37,6 +37,7 @@ public class OrganizationController { } @GetMapping("/delete/{organizationId}") + @RequiresRoles(RoleConstants.ADMIN) public void deleteOrganization(@PathVariable(value = "organizationId") String organizationId) { organizationService.deleteOrganization(organizationId); } @PostMapping("/update") diff --git a/backend/src/main/java/io/metersphere/controller/ReportController.java b/backend/src/main/java/io/metersphere/controller/ReportController.java index ad35d0c6fb..57fc4275e5 100644 --- a/backend/src/main/java/io/metersphere/controller/ReportController.java +++ b/backend/src/main/java/io/metersphere/controller/ReportController.java @@ -45,4 +45,12 @@ public class ReportController { public void deleteReport(@PathVariable String reportId) { reportService.deleteReport(reportId); } + + + @GetMapping("/test/pro/info/{reportId}") + public ReportDTO getReportTestAndProInfo(@PathVariable String reportId) { + return reportService.getReportTestAndProInfo(reportId); + } + + } diff --git a/backend/src/main/java/io/metersphere/controller/UserController.java b/backend/src/main/java/io/metersphere/controller/UserController.java index 6c7df388c1..8fc38ecb06 100644 --- a/backend/src/main/java/io/metersphere/controller/UserController.java +++ b/backend/src/main/java/io/metersphere/controller/UserController.java @@ -2,7 +2,6 @@ package io.metersphere.controller; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; -import io.metersphere.base.domain.Role; import io.metersphere.base.domain.User; import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.utils.PageUtils; @@ -12,10 +11,10 @@ import io.metersphere.controller.request.member.AddMemberRequest; import io.metersphere.controller.request.member.QueryMemberRequest; import io.metersphere.controller.request.organization.AddOrgMemberRequest; import io.metersphere.controller.request.organization.QueryOrgMemberRequest; -import io.metersphere.dto.OrganizationMemberDTO; import io.metersphere.dto.UserDTO; -import io.metersphere.dto.UserRoleDTO; +import io.metersphere.service.OrganizationService; import io.metersphere.service.UserService; +import io.metersphere.service.WorkspaceService; import io.metersphere.user.SessionUser; import io.metersphere.user.SessionUtils; import org.apache.shiro.authz.annotation.Logical; @@ -31,40 +30,94 @@ public class UserController { @Resource private UserService userService; + @Resource + private OrganizationService organizationService; + @Resource + private WorkspaceService workspaceService; - @PostMapping("/add") + // admin api + @PostMapping("/special/add") @RequiresRoles(RoleConstants.ADMIN) public UserDTO insertUser(@RequestBody User user) { return userService.insert(user); } - @GetMapping("/list") - public List getUserList() { - return userService.getUserList(); - } - - @PostMapping("/list/{goPage}/{pageSize}") + @PostMapping("/special/list/{goPage}/{pageSize}") @RequiresRoles(RoleConstants.ADMIN) public Pager> getUserList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody UserRequest request) { Page page = PageHelper.startPage(goPage, pageSize, true); return PageUtils.setPageInfo(page, userService.getUserListWithRequest(request)); } - @GetMapping("/delete/{userId}") + @GetMapping("/special/delete/{userId}") @RequiresRoles(RoleConstants.ADMIN) public void deleteUser(@PathVariable(value = "userId") String userId) { userService.deleteUser(userId); } - @PostMapping("/update") + @PostMapping("/special/update") @RequiresRoles(RoleConstants.ADMIN) public void updateUser(@RequestBody User user) { userService.updateUser(user); } - /** - * 修改登录用户信息 - */ + @PostMapping("/special/ws/member/list/{goPage}/{pageSize}") + @RequiresRoles(RoleConstants.ADMIN) + public Pager> getMemberListByAdmin(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryMemberRequest request) { + Page page = PageHelper.startPage(goPage, pageSize, true); + return PageUtils.setPageInfo(page, userService.getMemberList(request)); + } + + @PostMapping("/special/ws/member/list/all") + @RequiresRoles(RoleConstants.ADMIN) + public List getMemberListByAdmin(@RequestBody QueryMemberRequest request) { + return userService.getMemberList(request); + } + + @PostMapping("/special/ws/member/add") + @RequiresRoles(RoleConstants.ADMIN) + public void addMemberByAdmin(@RequestBody AddMemberRequest request) { + userService.addMember(request); + } + + @GetMapping("/special/ws/member/delete/{workspaceId}/{userId}") + @RequiresRoles(RoleConstants.ADMIN) + public void deleteMemberByAdmin(@PathVariable String workspaceId, @PathVariable String userId) { + userService.deleteMember(workspaceId, userId); + } + + @PostMapping("/special/org/member/add") + @RequiresRoles(RoleConstants.ADMIN) + public void addOrganizationMemberByAdmin(@RequestBody AddOrgMemberRequest request) { + userService.addOrganizationMember(request); + } + + @GetMapping("/special/org/member/delete/{organizationId}/{userId}") + @RequiresRoles(RoleConstants.ADMIN) + public void delOrganizationMemberByAdmin(@PathVariable String organizationId, @PathVariable String userId) { + userService.delOrganizationMember(organizationId, userId); + } + + @PostMapping("/special/org/member/list/{goPage}/{pageSize}") + @RequiresRoles(RoleConstants.ADMIN) + public Pager> getOrgMemberListByAdmin(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryOrgMemberRequest request) { + Page page = PageHelper.startPage(goPage, pageSize, true); + return PageUtils.setPageInfo(page, userService.getOrgMemberList(request)); + } + + @PostMapping("/special/org/member/list/all") + @RequiresRoles(RoleConstants.ADMIN) + public List getOrgMemberListByAdmin(@RequestBody QueryOrgMemberRequest request) { + return userService.getOrgMemberList(request); + } + // admin api + + @GetMapping("/list") + @RequiresRoles(value = {RoleConstants.ADMIN,RoleConstants.ORG_ADMIN}, logical = Logical.OR) + public List getUserList() { + return userService.getUserList(); + } + @PostMapping("/update/currentuser") public UserDTO updateCurrentUser(@RequestBody User user) { SessionUser sessionUser = SessionUtils.getUser(); @@ -73,20 +126,19 @@ public class UserController { return SessionUtils.getUser(); } - @GetMapping("/role/list/{userId}") - public List getUserRolesList(@PathVariable(value = "userId") String userId) { - return userService.getUserRolesList(userId); - } - - @GetMapping("/rolelist/{userId}") - public List convertUserRoleDTO(@PathVariable(value = "userId") String userId) { - return userService.getUserRoleList(userId); - } - - @PostMapping("/switch/source/{sign}/{sourceId}") - public UserDTO switchUserRole(@PathVariable String sign, @PathVariable(value = "sourceId") String sourceId) { + @PostMapping("/switch/source/org/{sourceId}") + @RequiresRoles(RoleConstants.ORG_ADMIN) + public UserDTO switchOrganization(@PathVariable(value = "sourceId") String sourceId) { UserDTO user = SessionUtils.getUser(); - userService.switchUserRole(user, sign, sourceId); + userService.switchUserRole(user,"organization",sourceId); + return SessionUtils.getUser(); + } + + @PostMapping("/switch/source/ws/{sourceId}") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER,RoleConstants.TEST_VIEWER,RoleConstants.TEST_USER}, logical = Logical.OR) + public UserDTO switchWorkspace(@PathVariable(value = "sourceId") String sourceId) { + UserDTO user = SessionUtils.getUser(); + userService.switchUserRole(user, "workspace", sourceId); return SessionUtils.getUser(); } @@ -98,8 +150,9 @@ public class UserController { /** * 获取工作空间成员用户 */ - @PostMapping("/member/list/{goPage}/{pageSize}") - //@RequiresRoles(RoleConstants.TEST_MANAGER) + @PostMapping("/ws/member/list/{goPage}/{pageSize}") + @RequiresRoles(value = {RoleConstants.ORG_ADMIN,RoleConstants.TEST_MANAGER, + RoleConstants.TEST_USER,RoleConstants.TEST_VIEWER}, logical = Logical.OR) public Pager> getMemberList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryMemberRequest request) { Page page = PageHelper.startPage(goPage, pageSize, true); return PageUtils.setPageInfo(page, userService.getMemberList(request)); @@ -108,51 +161,59 @@ public class UserController { /** * 获取工作空间成员用户 不分页 */ - @PostMapping("/member/list/all") + @PostMapping("/ws/member/list/all") + @RequiresRoles(value = {RoleConstants.ORG_ADMIN,RoleConstants.TEST_MANAGER, + RoleConstants.TEST_USER,RoleConstants.TEST_VIEWER}, logical = Logical.OR) public List getMemberList(@RequestBody QueryMemberRequest request) { return userService.getMemberList(request); } /** - * 添加成员 + * 添加工作空间成员 */ - @PostMapping("/member/add") - @RequiresRoles(value = {RoleConstants.TEST_MANAGER,RoleConstants.ORG_ADMIN,RoleConstants.ADMIN}, logical = Logical.OR) + @PostMapping("/ws/member/add") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER,RoleConstants.ORG_ADMIN}, logical = Logical.OR) public void addMember(@RequestBody AddMemberRequest request) { + String wsId = request.getWorkspaceId(); + workspaceService.checkWorkspaceOwner(wsId); userService.addMember(request); } /** - * 删除成员 + * 删除工作空间成员 */ - @GetMapping("/member/delete/{workspaceId}/{userId}") - @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.ADMIN, RoleConstants.ORG_ADMIN}, logical = Logical.OR) + @GetMapping("/ws/member/delete/{workspaceId}/{userId}") + @RequiresRoles(value = {RoleConstants.TEST_MANAGER,RoleConstants.ORG_ADMIN}, logical = Logical.OR) public void deleteMember(@PathVariable String workspaceId, @PathVariable String userId) { + workspaceService.checkWorkspaceOwner(workspaceId); userService.deleteMember(workspaceId, userId); } /** * 添加组织成员 */ - @PostMapping("/orgmember/add") - @RequiresRoles(value = {RoleConstants.ADMIN, RoleConstants.ORG_ADMIN}, logical = Logical.OR) + @PostMapping("/org/member/add") + @RequiresRoles(RoleConstants.ORG_ADMIN) public void addOrganizationMember(@RequestBody AddOrgMemberRequest request) { + organizationService.checkOrgOwner(request.getOrganizationId()); userService.addOrganizationMember(request); } /** * 删除组织成员 */ - @GetMapping("/orgmember/delete/{organizationId}/{userId}") - @RequiresRoles(value = {RoleConstants.ADMIN,RoleConstants.ORG_ADMIN}, logical = Logical.OR) + @GetMapping("/org/member/delete/{organizationId}/{userId}") + @RequiresRoles(RoleConstants.ORG_ADMIN) public void delOrganizationMember(@PathVariable String organizationId, @PathVariable String userId) { + organizationService.checkOrgOwner(organizationId); userService.delOrganizationMember(organizationId, userId); } /** * 查询组织成员列表 */ - @PostMapping("/orgmember/list/{goPage}/{pageSize}") + @PostMapping("/org/member/list/{goPage}/{pageSize}") + @RequiresRoles(value = {RoleConstants.ORG_ADMIN,RoleConstants.TEST_MANAGER}, logical = Logical.OR) public Pager> getOrgMemberList(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryOrgMemberRequest request) { Page page = PageHelper.startPage(goPage, pageSize, true); return PageUtils.setPageInfo(page, userService.getOrgMemberList(request)); @@ -161,23 +222,12 @@ public class UserController { /** * 组织成员列表不分页 */ - @PostMapping("/orgmember/list/all") + @PostMapping("/org/member/list/all") + @RequiresRoles(value = {RoleConstants.ORG_ADMIN,RoleConstants.TEST_MANAGER}, logical = Logical.OR) public List getOrgMemberList(@RequestBody QueryOrgMemberRequest request) { return userService.getOrgMemberList(request); } - /** - * 查询组织成员列表 带角色信息 - */ - @PostMapping("/orgmemberdto/list/{goPage}/{pageSize}") - public Pager> getOrganizationMemberDTO(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody QueryOrgMemberRequest request) { - Page page = PageHelper.startPage(goPage, pageSize, true); - return PageUtils.setPageInfo(page, userService.getOrganizationMemberDTO(request)); - } - - /** - * - */ @GetMapping("/besideorg/list/{orgId}") public List getBesideOrgMemberList(@PathVariable String orgId) { return userService.getBesideOrgMemberList(orgId); diff --git a/backend/src/main/java/io/metersphere/controller/UserRoleController.java b/backend/src/main/java/io/metersphere/controller/UserRoleController.java index d0c6e24ea0..35a3645201 100644 --- a/backend/src/main/java/io/metersphere/controller/UserRoleController.java +++ b/backend/src/main/java/io/metersphere/controller/UserRoleController.java @@ -26,6 +26,7 @@ public class UserRoleController { } @GetMapping("/list/ws/{workspaceId}/{userId}") + @RequiresRoles(value = {RoleConstants.ADMIN,RoleConstants.ORG_ADMIN}, logical = Logical.OR) public List getWorkspaceMemberRole(@PathVariable String workspaceId, @PathVariable String userId) { return userRoleService.getWorkspaceMemberRoles(workspaceId, userId); } diff --git a/backend/src/main/java/io/metersphere/controller/WorkspaceController.java b/backend/src/main/java/io/metersphere/controller/WorkspaceController.java index b5f458baaa..4277b4358d 100644 --- a/backend/src/main/java/io/metersphere/controller/WorkspaceController.java +++ b/backend/src/main/java/io/metersphere/controller/WorkspaceController.java @@ -40,7 +40,7 @@ public class WorkspaceController { @PostMapping("update") @RequiresRoles(RoleConstants.ORG_ADMIN) public Workspace updateWorkspace(@RequestBody Workspace workspace) { - workspaceService.checkOwner(workspace.getId()); + workspaceService.checkWorkspaceOwnerByOrgAdmin(workspace.getId()); return workspaceService.saveWorkspace(workspace); } @@ -53,7 +53,7 @@ public class WorkspaceController { @GetMapping("delete/{workspaceId}") @RequiresRoles(RoleConstants.ORG_ADMIN) public void deleteWorkspace(@PathVariable String workspaceId) { - workspaceService.checkOwner(workspaceId); + workspaceService.checkWorkspaceOwnerByOrgAdmin(workspaceId); workspaceService.deleteWorkspace(workspaceId); } diff --git a/backend/src/main/java/io/metersphere/dto/ReportDTO.java b/backend/src/main/java/io/metersphere/dto/ReportDTO.java index a8a3a3ac7c..1897c7bc12 100644 --- a/backend/src/main/java/io/metersphere/dto/ReportDTO.java +++ b/backend/src/main/java/io/metersphere/dto/ReportDTO.java @@ -11,6 +11,24 @@ public class ReportDTO { private String status; private String content; private String testName; + private String projectId; + private String projectName; + + public String getProjectId() { + return projectId; + } + + public void setProjectId(String projectId) { + this.projectId = projectId; + } + + public String getProjectName() { + return projectName; + } + + public void setProjectName(String projectName) { + this.projectName = projectName; + } public String getId() { return id; diff --git a/backend/src/main/java/io/metersphere/service/FileService.java b/backend/src/main/java/io/metersphere/service/FileService.java index dd718be1e0..d73b730acc 100644 --- a/backend/src/main/java/io/metersphere/service/FileService.java +++ b/backend/src/main/java/io/metersphere/service/FileService.java @@ -4,18 +4,11 @@ import io.metersphere.base.domain.*; import io.metersphere.base.mapper.FileContentMapper; import io.metersphere.base.mapper.FileMetadataMapper; import io.metersphere.base.mapper.LoadTestFileMapper; -import org.springframework.core.io.InputStreamResource; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; -import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @Service @@ -27,17 +20,6 @@ public class FileService { @Resource private FileContentMapper fileContentMapper; - // 将上传的文件保存在内存,方便测试 - private Map fileMap = new ConcurrentHashMap<>(); - - public void upload(String name, MultipartFile file) throws IOException { - String result = new BufferedReader(new InputStreamReader(file.getInputStream())) - .lines().collect(Collectors.joining("\n")); - System.out.println(String.format("upload file: %s, content: \n%s", name, result)); - - fileMap.put(name, file); - } - public byte[] loadFileAsBytes(String id) { FileContent fileContent = fileContentMapper.selectByPrimaryKey(id); diff --git a/backend/src/main/java/io/metersphere/service/OrganizationService.java b/backend/src/main/java/io/metersphere/service/OrganizationService.java index 1a6465e303..ac651ead6a 100644 --- a/backend/src/main/java/io/metersphere/service/OrganizationService.java +++ b/backend/src/main/java/io/metersphere/service/OrganizationService.java @@ -6,8 +6,13 @@ import io.metersphere.base.mapper.UserMapper; import io.metersphere.base.mapper.UserRoleMapper; import io.metersphere.base.mapper.ext.ExtOrganizationMapper; import io.metersphere.base.mapper.ext.ExtUserRoleMapper; +import io.metersphere.commons.constants.RoleConstants; +import io.metersphere.commons.exception.MSException; import io.metersphere.dto.OrganizationMemberDTO; import io.metersphere.dto.UserRoleHelpDTO; +import io.metersphere.i18n.Translator; +import io.metersphere.user.SessionUser; +import io.metersphere.user.SessionUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; @@ -109,4 +114,16 @@ public class OrganizationService { public Integer checkSourceRole(String orgId, String userId, String roleId) { return extOrganizationMapper.checkSourceRole(orgId, userId, roleId); } + + public void checkOrgOwner(String organizationId) { + SessionUser user = SessionUtils.getUser(); + List collect = user.getUserRoles().stream() + .filter(ur -> RoleConstants.ORG_ADMIN.equals(ur.getRoleId())) + .map(UserRole::getSourceId) + .collect(Collectors.toList()); + if (!collect.contains(organizationId)) { + MSException.throwException(Translator.get("organization_does_not_belong_to_user")); + } + + } } diff --git a/backend/src/main/java/io/metersphere/service/ReportService.java b/backend/src/main/java/io/metersphere/service/ReportService.java index 6367992488..b2d6ebe4e8 100644 --- a/backend/src/main/java/io/metersphere/service/ReportService.java +++ b/backend/src/main/java/io/metersphere/service/ReportService.java @@ -37,4 +37,8 @@ public class ReportService { public void deleteReport(String reportId) { loadTestReportMapper.deleteByPrimaryKey(reportId); } + + public ReportDTO getReportTestAndProInfo(String reportId) { + return extLoadTestReportMapper.getReportTestAndProInfo(reportId); + } } diff --git a/backend/src/main/java/io/metersphere/service/UserService.java b/backend/src/main/java/io/metersphere/service/UserService.java index 687b10cb81..dc7246aa0a 100644 --- a/backend/src/main/java/io/metersphere/service/UserService.java +++ b/backend/src/main/java/io/metersphere/service/UserService.java @@ -128,7 +128,7 @@ public class UserService { userMapper.updateByPrimaryKeySelective(user); } - public List getUserRolesList(String userId) { + /*public List getUserRolesList(String userId) { UserRoleExample userRoleExample = new UserRoleExample(); userRoleExample.createCriteria().andUserIdEqualTo(userId); List userRolesList = userRoleMapper.selectByExample(userRoleExample); @@ -143,7 +143,7 @@ public class UserService { return new ArrayList<>(); } return convertUserRoleDTO(extUserRoleMapper.getUserRoleHelpList(userId)); - } + }*/ private List convertUserRoleDTO(List helpDTOList) { StringBuilder buffer = new StringBuilder(); diff --git a/backend/src/main/java/io/metersphere/service/WorkspaceService.java b/backend/src/main/java/io/metersphere/service/WorkspaceService.java index d2ae432f07..5b9281419a 100644 --- a/backend/src/main/java/io/metersphere/service/WorkspaceService.java +++ b/backend/src/main/java/io/metersphere/service/WorkspaceService.java @@ -91,15 +91,16 @@ public class WorkspaceService { } /** - * ORG_ADMIN 需要检查是否有操作此工作空间的权限 + * ORG_ADMIN需要检查是否有操作此工作空间的权限 */ - public void checkOwner(String workspaceId) { + public void checkWorkspaceOwnerByOrgAdmin(String workspaceId) { + checkWorkspaceIsExist(workspaceId); + WorkspaceExample example = new WorkspaceExample(); SessionUser user = SessionUtils.getUser(); List orgIds = user.getUserRoles().stream() .filter(ur -> RoleConstants.ORG_ADMIN.equals(ur.getRoleId())) .map(UserRole::getSourceId) .collect(Collectors.toList()); - WorkspaceExample example = new WorkspaceExample(); example.createCriteria() .andOrganizationIdIn(orgIds) .andIdEqualTo(workspaceId); @@ -108,6 +109,48 @@ public class WorkspaceService { } } + public void checkWorkspaceOwnerByTestManager(String workspaceId) { + checkWorkspaceIsExist(workspaceId); + SessionUser user = SessionUtils.getUser(); + List wsIds = user.getUserRoles().stream() + .filter(ur -> RoleConstants.TEST_MANAGER.equals(ur.getRoleId())) + .map(UserRole::getSourceId) + .collect(Collectors.toList()); + boolean contains = wsIds.contains(workspaceId); + if (!contains) { + MSException.throwException(Translator.get("workspace_does_not_belong_to_user")); + } + } + + public void checkWorkspaceOwner(String workspaceId) { + checkWorkspaceIsExist(workspaceId); + WorkspaceExample example = new WorkspaceExample(); + SessionUser user = SessionUtils.getUser(); + List orgIds = user.getUserRoles().stream() + .filter(ur -> RoleConstants.ORG_ADMIN.equals(ur.getRoleId())) + .map(UserRole::getSourceId) + .collect(Collectors.toList()); + example.createCriteria() + .andOrganizationIdIn(orgIds) + .andIdEqualTo(workspaceId); + List wsIds = user.getUserRoles().stream() + .filter(ur -> RoleConstants.TEST_MANAGER.equals(ur.getRoleId())) + .map(UserRole::getSourceId) + .collect(Collectors.toList()); + boolean contains = wsIds.contains(workspaceId); + if (workspaceMapper.countByExample(example) == 0 && !contains) { + MSException.throwException(Translator.get("workspace_does_not_belong_to_user")); + } + } + + public void checkWorkspaceIsExist(String workspaceId) { + WorkspaceExample example = new WorkspaceExample(); + example.createCriteria().andIdEqualTo(workspaceId); + if (workspaceMapper.countByExample(example) == 0) { + MSException.throwException("workspace_not_exist"); + } + } + public List getWorkspaceListByUserId(String userId) { List userRoleHelpList = extUserRoleMapper.getUserRoleHelpList(userId); List workspaceIds = new ArrayList<>(); diff --git a/backend/src/main/resources/i18n/en-US.json b/backend/src/main/resources/i18n/en-US.json index 679dffb8b1..8b66b212cf 100644 --- a/backend/src/main/resources/i18n/en-US.json +++ b/backend/src/main/resources/i18n/en-US.json @@ -5,5 +5,6 @@ "project_name_already_exists": "The project name already exists", "workspace_name_is_null": "Workspace name cannot be null", "workspace_name_already_exists": "The workspace name already exists", - "workspace_does_not_belong_to_user": "The current workspace does not belong to the current user" + "workspace_does_not_belong_to_user": "The current workspace does not belong to the current user", + "organization_does_not_belong_to_user": "The current organization does not belong to the current user" } \ No newline at end of file diff --git a/backend/src/main/resources/i18n/zh-CN.json b/backend/src/main/resources/i18n/zh-CN.json index 23fe3b54ed..58a2502874 100644 --- a/backend/src/main/resources/i18n/zh-CN.json +++ b/backend/src/main/resources/i18n/zh-CN.json @@ -5,5 +5,6 @@ "project_name_already_exists": "项目名称已存在", "workspace_name_is_null": "工作空间名不能为空", "workspace_name_already_exists": "工作空间名已存在", - "workspace_does_not_belong_to_user": "当前工作空间不属于当前用户" + "workspace_does_not_belong_to_user": "当前工作空间不属于当前用户", + "organization_does_not_belong_to_user": "当前组织不属于当前用户" } \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index e89a493951..8f5054cf9d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -40,7 +40,9 @@ "plugin:vue/essential", "eslint:recommended" ], - "rules": {}, + "rules": { + "vue/no-unused-components": "off" + }, "parserOptions": { "parser": "babel-eslint" } diff --git a/frontend/src/common/utils.js b/frontend/src/common/utils.js new file mode 100644 index 0000000000..4aa4fe946d --- /dev/null +++ b/frontend/src/common/utils.js @@ -0,0 +1,30 @@ +import {ROLE_ORG_ADMIN, ROLE_TEST_MANAGER, ROLE_TEST_USER, ROLE_TEST_VIEWER, TokenKey} from "./constants"; + +export function hasRole(role) { + let user = JSON.parse(localStorage.getItem(TokenKey)); + let roles = user.roles.map(r => r.id); + return roles.indexOf(role) > -1; +} + +export function hasRoles(...roles) { + let user = JSON.parse(localStorage.getItem(TokenKey)); + let rs = user.roles.map(r => r.id); + for (let item of roles) { + if (rs.indexOf(item) > -1) { + return true; + } + } + return false; +} + +export function checkoutCurrentOrganization() { + let user = JSON.parse(localStorage.getItem(TokenKey)); + // 查看当前用户是否是 lastOrganizationId 的组织管理员 + return user.userRoles.filter(ur => hasRole(ROLE_ORG_ADMIN) && user.lastOrganizationId === ur.sourceId).length > 0; +} + +export function checkoutCurrentWorkspace() { + let user = JSON.parse(localStorage.getItem(TokenKey)); + // 查看当前用户是否是 lastWorkspaceId 的工作空间用户 + return user.userRoles.filter(ur => hasRoles(ROLE_TEST_MANAGER, ROLE_TEST_USER, ROLE_TEST_VIEWER) && user.lastWorkspaceId === ur.sourceId).length > 0; +} diff --git a/frontend/src/i18n/en-US.js b/frontend/src/i18n/en-US.js index 17276855d2..dd9cf451e1 100644 --- a/frontend/src/i18n/en-US.js +++ b/frontend/src/i18n/en-US.js @@ -33,6 +33,13 @@ export default { 'status': 'Enable/Disable', 'show_all': 'Show All', 'report': 'Report', + 'user': 'User', + 'system': 'System', + 'personal_setting': 'Personal Setting', + 'test_resource_pool': 'Resource Pool', + 'system_setting': 'Settings', + 'functional': 'Functional', + 'performance': 'Performance', }, workspace: { 'create': 'Create Workspace', @@ -71,6 +78,7 @@ export default { 'search_by_name': 'Search by name', 'modify_personal_info': 'Modify Personal Information', 'input_name': 'Please enter a user name', + 'input_email': 'Please enter a email', 'special_characters_are_not_supported': 'Special characters are not supported', 'mobile_number_format_is_incorrect': 'Mobile number format is incorrect', 'email_format_is_incorrect': 'Email format is incorrect', @@ -93,6 +101,10 @@ export default { 'recent': 'Recent Report', 'search_by_name': 'Search by Name', 'test_name': 'Test', + 'test_overview': 'Test Overview', + 'test_request_statistics': 'Test Request Statistics', + 'test_error_log': 'Test Error Log', + 'test_log_details': 'Test Log Details' }, load_test: { 'recent': 'Recent Tests', diff --git a/frontend/src/i18n/zh-CN.js b/frontend/src/i18n/zh-CN.js index 66503cddb4..7c09633911 100644 --- a/frontend/src/i18n/zh-CN.js +++ b/frontend/src/i18n/zh-CN.js @@ -33,6 +33,13 @@ export default { 'status': '启用/禁用', 'show_all': '显示全部', 'report': '报告', + 'user': '用户', + 'system': '系统', + 'personal_setting': '个人设置', + 'test_resource_pool': '测试资源池', + 'system_setting': '系统设置', + 'functional': '功能测试', + 'performance': '性能测试', }, workspace: { 'create': '创建工作空间', @@ -94,6 +101,10 @@ export default { 'recent': '最近的报告', 'search_by_name': '根据名称搜索', 'test_name': '所属测试', + 'test_overview': '测试概览', + 'test_request_statistics': '请求统计', + 'test_error_log': '错误记录', + 'test_log_details': '日志详情' }, load_test: { 'recent': '最近的测试', diff --git a/frontend/src/performance/App.vue b/frontend/src/performance/App.vue index 38da7f623c..10e4c613ff 100644 --- a/frontend/src/performance/App.vue +++ b/frontend/src/performance/App.vue @@ -11,6 +11,7 @@ + @@ -26,7 +27,7 @@ name: 'app', data() { return { - auth: false, + auth: false } }, beforeCreate() { diff --git a/frontend/src/performance/components/HeaderMenus.vue b/frontend/src/performance/components/HeaderMenus.vue index 429b52d2c7..c2433e3f65 100644 --- a/frontend/src/performance/components/HeaderMenus.vue +++ b/frontend/src/performance/components/HeaderMenus.vue @@ -6,9 +6,11 @@ {{ $t("i18n.home") }} - + + - + + @@ -18,7 +20,9 @@ {{$t('project.create')}} - + + @@ -31,7 +35,9 @@ {{$t('load_test.create')}} - + + @@ -41,9 +47,12 @@ {{$t('commons.show_all')}} - + + {{$t('load_test.create')}} + @@ -53,19 +62,31 @@ import PerformanceRecentTestPlan from "./testPlan/PerformanceRecentTestPlan"; import FunctionalRecentTestPlan from "./testPlan/FunctionalRecentTestPlan"; - import MsRecentProject from "./project/RecentProject"; + import PerformanceRecentProject from "./project/PerformanceRecentProject"; + import FunctionalRecentProject from "./project/FunctionalRecentProject"; import PerformanceRecentReport from "./report/PerformanceRecentReport"; import FunctionalRecentReport from "./report/FunctionalRecentReport"; + import {checkoutCurrentWorkspace} from "../../common/utils"; export default { name: "MsMenus", - components: {PerformanceRecentReport, PerformanceRecentTestPlan, MsRecentProject, FunctionalRecentTestPlan, FunctionalRecentReport}, - props: { - beaseUrl: { - type: String + components: {PerformanceRecentReport, PerformanceRecentTestPlan, FunctionalRecentTestPlan, FunctionalRecentReport, + PerformanceRecentProject,FunctionalRecentProject}, + data() { + return { + isCurrentWorkspaceUser: false, } + }, + props: { + beaseUrl: { + type: String + } + }, + mounted() { + this.isCurrentWorkspaceUser = checkoutCurrentWorkspace(); } } + diff --git a/frontend/src/performance/components/HeaderTopMenus.vue b/frontend/src/performance/components/HeaderTopMenus.vue index 72c04e7c17..400b55f4f5 100644 --- a/frontend/src/performance/components/HeaderTopMenus.vue +++ b/frontend/src/performance/components/HeaderTopMenus.vue @@ -7,14 +7,17 @@ :default-active="activeIndex" @select="handleSelect" router> + - 功能测试 + {{$t('commons.functional')}} - 性能测试 + {{$t('commons.performance')}} + + + {{$t('commons.system_setting')}} - 系统设置 diff --git a/frontend/src/performance/components/HeaderUser.vue b/frontend/src/performance/components/HeaderUser.vue index 25c5da52f4..0bfa08ec6f 100644 --- a/frontend/src/performance/components/HeaderUser.vue +++ b/frontend/src/performance/components/HeaderUser.vue @@ -42,7 +42,8 @@ diff --git a/frontend/src/performance/components/project/PerformanceRecentProject.vue b/frontend/src/performance/components/project/PerformanceRecentProject.vue new file mode 100644 index 0000000000..6b6489c3ee --- /dev/null +++ b/frontend/src/performance/components/project/PerformanceRecentProject.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/frontend/src/performance/components/report/FunctionalRecentReport.vue b/frontend/src/performance/components/report/FunctionalRecentReport.vue index f1bd4fd454..6a9656d537 100644 --- a/frontend/src/performance/components/report/FunctionalRecentReport.vue +++ b/frontend/src/performance/components/report/FunctionalRecentReport.vue @@ -5,7 +5,7 @@ {{$t('load_test.recent')}} + :index="'/functional/report/view/' + p.id" :route="{path: '/functional/report/view/' + p.id}"> {{ p.name }} diff --git a/frontend/src/performance/components/report/FunctionalTestReport.vue b/frontend/src/performance/components/report/FunctionalTestReport.vue index ce6b0e0e0d..d3b960d59f 100644 --- a/frontend/src/performance/components/report/FunctionalTestReport.vue +++ b/frontend/src/performance/components/report/FunctionalTestReport.vue @@ -8,9 +8,9 @@ {{$t('commons.report')}} + prefix-icon="el-icon-search" + maxlength="60" + v-model="condition" @change="search" clearable/> @@ -129,8 +129,10 @@ handleSelectionChange(val) { this.multipleSelection = val; }, - handleEdit() { - + handleEdit(report) { + this.$router.push({ + path: '/functional/reportView/' + report.id + }) }, handleDelete(report) { this.$alert(this.$t('load_test.delete_confirm') + report.name + "?", '', { diff --git a/frontend/src/performance/components/report/PerformanceRecentReport.vue b/frontend/src/performance/components/report/PerformanceRecentReport.vue index f1bd4fd454..c614b060cd 100644 --- a/frontend/src/performance/components/report/PerformanceRecentReport.vue +++ b/frontend/src/performance/components/report/PerformanceRecentReport.vue @@ -5,7 +5,7 @@ {{$t('load_test.recent')}} + :index="'/performance/report/view/' + p.id" :route="{path: '/performance/report/view/' + p.id}"> {{ p.name }} @@ -13,14 +13,13 @@ + + diff --git a/frontend/src/performance/components/report/PerformanceTestReport.vue b/frontend/src/performance/components/report/PerformanceTestReport.vue index f488af3533..75c54461da 100644 --- a/frontend/src/performance/components/report/PerformanceTestReport.vue +++ b/frontend/src/performance/components/report/PerformanceTestReport.vue @@ -129,8 +129,10 @@ handleSelectionChange(val) { this.multipleSelection = val; }, - handleEdit() { - + handleEdit(report) { + this.$router.push({ + path: '/performance/report/view/' + report.id + }) }, handleDelete(report) { this.$alert(this.$t('load_test.delete_confirm') + report.name + "?", '', { diff --git a/frontend/src/performance/components/report/components/ErrorLog.vue b/frontend/src/performance/components/report/components/ErrorLog.vue new file mode 100644 index 0000000000..51e8166f4b --- /dev/null +++ b/frontend/src/performance/components/report/components/ErrorLog.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/frontend/src/performance/components/report/components/LogDetails.vue b/frontend/src/performance/components/report/components/LogDetails.vue new file mode 100644 index 0000000000..10c7200afd --- /dev/null +++ b/frontend/src/performance/components/report/components/LogDetails.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/frontend/src/performance/components/report/components/RequestStatistics.vue b/frontend/src/performance/components/report/components/RequestStatistics.vue new file mode 100644 index 0000000000..55a26e0c58 --- /dev/null +++ b/frontend/src/performance/components/report/components/RequestStatistics.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/frontend/src/performance/components/report/components/TestOverview.vue b/frontend/src/performance/components/report/components/TestOverview.vue new file mode 100644 index 0000000000..1745b0bca7 --- /dev/null +++ b/frontend/src/performance/components/report/components/TestOverview.vue @@ -0,0 +1,229 @@ + + + + + diff --git a/frontend/src/performance/components/router/router.js b/frontend/src/performance/components/router/router.js index 02248a760c..02d9f30f64 100644 --- a/frontend/src/performance/components/router/router.js +++ b/frontend/src/performance/components/router/router.js @@ -22,6 +22,7 @@ import EditFunctionalTestPlan from "../testPlan/EditFunctionalTestPlan"; import PerformanceTestHome from "../testPlan/PerformanceTestHome"; import FunctionalTestPlan from "../testPlan/FunctionalTestPlan"; import FunctionalTestHome from "../testPlan/FunctionalTestHome"; +import PerformanceReportView from "../report/PerformanceReportView"; Vue.use(VueRouter); @@ -84,6 +85,7 @@ const router = new VueRouter({ children: [ { path: 'home', + name: 'fucHome', component: FunctionalTestHome, }, { @@ -93,6 +95,7 @@ const router = new VueRouter({ }, { path: "plan/edit/:testId", + name: "editFucTest", component: EditFunctionalTestPlan, props: { content: (route) => { @@ -104,14 +107,17 @@ const router = new VueRouter({ }, { path: "plan/:projectId", + name: "fucPlan", component: FunctionalTestPlan }, { path: "project/:type", + name: "fucProject", component: MsProject }, { path: "report/:type", + name: "fucReport", component: FunctionalTestReport } ] @@ -126,6 +132,7 @@ const router = new VueRouter({ children: [ { path: 'home', + name: 'perHome', component: PerformanceTestHome, }, { @@ -135,6 +142,7 @@ const router = new VueRouter({ }, { path: "plan/edit/:testId", + name: "editPerTest", component: EditPerformanceTestPlan, props: { content: (route) => { @@ -146,19 +154,28 @@ const router = new VueRouter({ }, { path: "plan/:projectId", + name: "perPlan", component: PerformanceTestPlan }, { path: "project/:type", + name: "perProject", component: MsProject }, { path: "report/:type", + name: "perReport", component: PerformanceTestReport }, { path: "chart", + name: "perChart", component: PerformanceChart + }, + { + path: "report/view/:reportId", + name: "perReportView", + component: PerformanceReportView } ] } diff --git a/frontend/src/performance/components/settings/SettingMenu.vue b/frontend/src/performance/components/settings/SettingMenu.vue index 36b0e0d223..22b0fac87e 100644 --- a/frontend/src/performance/components/settings/SettingMenu.vue +++ b/frontend/src/performance/components/settings/SettingMenu.vue @@ -3,45 +3,59 @@ - 用户 - 组织 - 工作空间 - 测试资源池 + {{$t('commons.user')}} + {{$t('commons.organization')}} + {{$t('commons.workspace')}} + {{$t('commons.test_resource_pool')}} - + - 成员 - 工作空间 + {{$t('commons.member')}} + + {{$t('commons.workspace')}} + - + - 成员 + {{$t('commons.member')}} - 个人设置 + {{$t('commons.personal_setting')}} diff --git a/frontend/src/performance/components/settings/organization/OrganizationMember.vue b/frontend/src/performance/components/settings/organization/OrganizationMember.vue index 31c6c21daa..24a1b69c94 100644 --- a/frontend/src/performance/components/settings/organization/OrganizationMember.vue +++ b/frontend/src/performance/components/settings/organization/OrganizationMember.vue @@ -129,7 +129,7 @@ createVisible: false, updateVisible: false, form: {}, - queryPath: "/user/orgmember/list", + queryPath: "/user/org/member/list", condition: "", tableData: [], rules: { @@ -221,7 +221,7 @@ cancelButtonText: this.$t('commons.cancel'), type: 'warning' }).then(() => { - this.result = this.$get('/user/orgmember/delete/' + this.currentUser().lastOrganizationId + '/' + row.id, () => { + this.result = this.$get('/user/org/member/delete/' + this.currentUser().lastOrganizationId + '/' + row.id, () => { this.$message({ type: 'success', message: this.$t('commons.delete_success') @@ -262,7 +262,7 @@ roleIds: this.form.roleIds, organizationId: orgId }; - this.result = this.$post("user/orgmember/add", param,() => { + this.result = this.$post("user/org/member/add", param,() => { this.initTableData(); this.createVisible = false; }) diff --git a/frontend/src/performance/components/settings/organization/OrganizationWorkspace.vue b/frontend/src/performance/components/settings/organization/OrganizationWorkspace.vue index f32d6ce535..42334fbfc6 100644 --- a/frontend/src/performance/components/settings/organization/OrganizationWorkspace.vue +++ b/frontend/src/performance/components/settings/organization/OrganizationWorkspace.vue @@ -256,7 +256,7 @@ name: '', workspaceId: this.items[i].id } - let path = "user/member/list/all"; + let path = "user/ws/member/list/all"; this.$post(path, param, res => { let member = res.data; this.$set(this.items[i], "memberSize", member.length); @@ -297,7 +297,7 @@ name: '', workspaceId: row.id }; - let path = "/user/member/list"; + let path = "/user/ws/member/list"; this.result = this.$post(this.buildPagePath(path), param, res => { let data = res.data; this.memberLineData = data.listObject; @@ -335,7 +335,7 @@ roleIds: this.memberForm.roleIds, workspaceId: this.currentWorkspaceRow.id }; - this.result = this.$post("user/member/add", param,() => { + this.result = this.$post("user/ws/member/add", param,() => { this.cellClick(this.currentWorkspaceRow); this.addMemberVisible = false; }) @@ -360,7 +360,7 @@ cancelButtonText: this.$t('commons.cancel'), type: 'warning' }).then(() => { - this.result = this.$get('/user/member/delete/' + this.currentWorkspaceRow.id + '/' + row.id, () => { + this.result = this.$get('/user/ws/member/delete/' + this.currentWorkspaceRow.id + '/' + row.id, () => { this.$message({ type: 'success', message: this.$t('commons.delete_success') diff --git a/frontend/src/performance/components/settings/system/Organization.vue b/frontend/src/performance/components/settings/system/Organization.vue index 861a2e2117..c075b88ba2 100644 --- a/frontend/src/performance/components/settings/system/Organization.vue +++ b/frontend/src/performance/components/settings/system/Organization.vue @@ -290,7 +290,7 @@ name: '', organizationId: row.id }; - let path = "/user/orgmember/list"; + let path = "/user/special/org/member/list"; this.result = this.$post(this.buildPagePath(path), param, res => { let data = res.data; this.memberLineData = data.listObject; @@ -330,7 +330,7 @@ cancelButtonText: this.$t('commons.cancel'), type: 'warning' }).then(() => { - this.result = this.$get('/user/orgmember/delete/' + this.currentRow.id + '/' + row.id, () => { + this.result = this.$get('/user/special/org/member/delete/' + this.currentRow.id + '/' + row.id, () => { this.$message({ type: 'success', message: this.$t('commons.delete_success') @@ -385,7 +385,7 @@ name: '', organizationId: this.tableData[i].id } - let path = "user/orgmember/list/all"; + let path = "user/special/org/member/list/all"; this.$post(path, param, res => { let member = res.data; this.$set(this.tableData[i], "memberSize", member.length); @@ -431,7 +431,7 @@ roleIds: this.memberForm.roleIds, organizationId: this.currentRow.id }; - this.result = this.$post("user/orgmember/add", param,() => { + this.result = this.$post("user/special/org/member/add", param,() => { this.cellClick(this.currentRow); this.addMemberVisible = false; }) diff --git a/frontend/src/performance/components/settings/system/SystemWorkspace.vue b/frontend/src/performance/components/settings/system/SystemWorkspace.vue index 9e64e36a28..1a4765517c 100644 --- a/frontend/src/performance/components/settings/system/SystemWorkspace.vue +++ b/frontend/src/performance/components/settings/system/SystemWorkspace.vue @@ -270,7 +270,7 @@ name: '', workspaceId: row.id }; - let path = "/user/member/list"; + let path = "/user/special/ws/member/list"; this.result = this.$post(this.buildPagePath(path), param, res => { let data = res.data; this.memberLineData = data.listObject; @@ -340,7 +340,7 @@ name: '', workspaceId: this.items[i].id } - let path = "user/member/list/all"; + let path = "user/special/ws/member/list/all"; this.$post(path, param, res => { let member = res.data; this.$set(this.items[i], "memberSize", member.length); @@ -376,7 +376,7 @@ roleIds: this.memberForm.roleIds, workspaceId: this.currentWorkspaceRow.id }; - this.result = this.$post("user/member/add", param,() => { + this.result = this.$post("user/special/ws/member/add", param,() => { this.cellClick(this.currentWorkspaceRow); this.addMemberVisible = false; }) @@ -401,7 +401,7 @@ cancelButtonText: this.$t('commons.cancel'), type: 'warning' }).then(() => { - this.result = this.$get('/user/member/delete/' + this.currentWorkspaceRow.id + '/' + row.id, () => { + this.result = this.$get('/user/special/ws/member/delete/' + this.currentWorkspaceRow.id + '/' + row.id, () => { this.$message({ type: 'success', message: this.$t('commons.delete_success') diff --git a/frontend/src/performance/components/settings/system/User.vue b/frontend/src/performance/components/settings/system/User.vue index a49bf2d4de..f1d5b92060 100644 --- a/frontend/src/performance/components/settings/system/User.vue +++ b/frontend/src/performance/components/settings/system/User.vue @@ -113,10 +113,10 @@ export default { data() { return { - queryPath: '/user/list', - deletePath: '/user/delete/', - createPath: '/user/add', - updatePath: '/user/update', + queryPath: '/user/special/list', + deletePath: '/user/special/delete/', + createPath: '/user/special/add', + updatePath: '/user/special/update', result: {}, createVisible: false, updateVisible: false, diff --git a/frontend/src/performance/components/settings/workspace/WorkspaceMember.vue b/frontend/src/performance/components/settings/workspace/WorkspaceMember.vue index 00e5b0ae6c..9c6cd7c4e4 100644 --- a/frontend/src/performance/components/settings/workspace/WorkspaceMember.vue +++ b/frontend/src/performance/components/settings/workspace/WorkspaceMember.vue @@ -3,7 +3,7 @@
- 成员 + {{$t('commons.member')}} @@ -126,7 +126,7 @@ btnTips: "添加工作空间成员", createVisible: false, updateVisible: false, - queryPath: "/user/member/list", + queryPath: "/user/ws/member/list", condition: "", tableData: [], rules: { @@ -198,7 +198,7 @@ type: 'warning' }).then(() => { this.loading = true; - this.$get('/user/member/delete/' + this.currentUser().lastWorkspaceId + '/' + row.id).then(() => { + this.$get('/user/ws/member/delete/' + this.currentUser().lastWorkspaceId + '/' + row.id).then(() => { this.initTableData(); this.loading = false; }); @@ -256,7 +256,7 @@ }); return false; } - this.$post('/user/orgmember/list/all', param,response => { + this.$post('/user/org/member/list/all', param,response => { this.createVisible = true; this.$set(this.form, "userList", response.data); }) @@ -272,7 +272,7 @@ roleIds: this.form.roleIds, workspaceId: this.currentUser().lastWorkspaceId }; - this.result = this.$post("user/member/add", param, () => { + this.result = this.$post("user/ws/member/add", param, () => { this.initTableData(); this.createVisible = false; }) diff --git a/frontend/src/performance/components/testPlan/EditPerformanceTestPlan.vue b/frontend/src/performance/components/testPlan/EditPerformanceTestPlan.vue index b492df2ddb..732e17c91a 100644 --- a/frontend/src/performance/components/testPlan/EditPerformanceTestPlan.vue +++ b/frontend/src/performance/components/testPlan/EditPerformanceTestPlan.vue @@ -81,10 +81,13 @@ window.location.reload(); return; } + let testId = to.path.split('/')[4]; // find testId if (testId) { this.$get('/testplan/get/' + testId, response => { - this.testPlan = response.data; + if(response.data){ + this.testPlan = response.data; + } }); } } diff --git a/frontend/src/performance/components/testPlan/FunctionalRecentTestPlan.vue b/frontend/src/performance/components/testPlan/FunctionalRecentTestPlan.vue index 478c88bc7b..4101bbbc0a 100644 --- a/frontend/src/performance/components/testPlan/FunctionalRecentTestPlan.vue +++ b/frontend/src/performance/components/testPlan/FunctionalRecentTestPlan.vue @@ -4,7 +4,7 @@ {{$t('load_test.recent')}}
- + {{ t.name }} @@ -12,14 +12,13 @@ diff --git a/frontend/src/performance/components/testPlan/components/PerformanceAdvancedConfig.vue b/frontend/src/performance/components/testPlan/components/PerformanceAdvancedConfig.vue index cb250546a3..d0264a9054 100644 --- a/frontend/src/performance/components/testPlan/components/PerformanceAdvancedConfig.vue +++ b/frontend/src/performance/components/testPlan/components/PerformanceAdvancedConfig.vue @@ -217,7 +217,10 @@ } }, watch: { - '$route'(to) { + '$route'(to, from) { + if(from.name != 'createPerTest' || from.name != 'editPerTest'){ + return; + } let testId = to.path.split('/')[4]; if (testId) { this.getAdvancedConfig(testId); diff --git a/frontend/src/performance/components/testPlan/components/PerformancePressureConfig.vue b/frontend/src/performance/components/testPlan/components/PerformancePressureConfig.vue index 12bca9879f..0e37d84e95 100644 --- a/frontend/src/performance/components/testPlan/components/PerformancePressureConfig.vue +++ b/frontend/src/performance/components/testPlan/components/PerformancePressureConfig.vue @@ -64,7 +64,7 @@ @@ -75,8 +75,7 @@ - 压力预估图 - + @@ -113,7 +112,10 @@ } }, watch: { - '$route'(to) { + '$route'(to, from) { + if(from.name != 'createPerTest' || from.name != 'editPerTest'){ + return; + } let testId = to.path.split('/')[4]; if (testId) { this.getLoadConfig(testId); @@ -124,52 +126,56 @@ }, methods: { getLoadConfig(testId) { - this.$get('/testplan/get-load-config/' + testId, (response) => { - if (response.data) { - let data = JSON.parse(response.data); + if(testId) { - data.forEach(d => { - switch (d.key) { - case TARGET_LEVEL: - this.threadNumber = d.value; - break; - case RAMP_UP: - this.rampUpTime = d.value; - break; - case DURATION: - this.duration = d.value; - break; - case STEPS: - this.step = d.value; - break; - case RPS_LIMIT: - this.rpsLimit = d.value; - break; - default: - break; - } - }); + this.$get('/testplan/get-load-config/' + testId, (response) => { + if (response.data && response.data != "") { + let data = JSON.parse(response.data); - this.threadNumber = this.threadNumber || 10; - this.duration = this.duration || 30; - this.rampUpTime = this.rampUpTime || 12; - this.step = this.step || 3; - this.rpsLimit = this.rpsLimit || 10; + data.forEach(d => { + switch (d.key) { + case TARGET_LEVEL: + this.threadNumber = d.value; + break; + case RAMP_UP: + this.rampUpTime = d.value; + break; + case DURATION: + this.duration = d.value; + break; + case STEPS: + this.step = d.value; + break; + case RPS_LIMIT: + this.rpsLimit = d.value; + break; + default: + break; + } + }); - this.calculateChart(); - } - }); + this.threadNumber = this.threadNumber || 10; + this.duration = this.duration || 30; + this.rampUpTime = this.rampUpTime || 12; + this.step = this.step || 3; + this.rpsLimit = this.rpsLimit || 10; + + this.calculateChart(); + } + }); + } }, calculateChart() { if (this.duration < this.rampUpTime) { this.rampUpTime = this.duration; } - if (this.threadNumber < this.step) { - this.step = this.threadNumber; + if (this.rampUpTime < this.step) { + this.step = this.rampUpTime; } this.orgOptions = { xAxis: { type: 'category', + boundaryGap: false, data: [] }, yAxis: { @@ -177,6 +183,7 @@ }, tooltip: { trigger: 'axis', + formatter: '{a}: {c0}', axisPointer: { lineStyle: { color: '#57617B' @@ -184,11 +191,11 @@ } }, series: [{ + name: 'User', data: [], type: 'line', step: 'start', smooth: false, - symbol: 'circle', symbolSize: 5, showSymbol: false, lineStyle: { @@ -219,16 +226,23 @@ }] }; let timePeriod = Math.floor(this.rampUpTime / this.step); - let threadPeriod = Math.floor(this.threadNumber / this.step); - let threadInc = threadPeriod; let timeInc = timePeriod; - for (let i = 0; i < this.duration; i++) { + let threadPeriod = Math.floor(this.threadNumber / this.step); + let threadInc1 = Math.floor(this.threadNumber / this.step); + let threadInc2 = Math.ceil(this.threadNumber / this.step); + let inc2count = this.threadNumber - this.step * threadInc1; + for (let i = 0; i <= this.duration; i++) { // x 轴 this.orgOptions.xAxis.data.push(i); if (i > timePeriod) { - threadPeriod = threadPeriod + threadInc; timePeriod += timeInc; + if (inc2count > 0) { + threadPeriod = threadPeriod + threadInc2; + inc2count--; + } else { + threadPeriod = threadPeriod + threadInc1; + } if (threadPeriod > this.threadNumber) { threadPeriod = this.threadNumber; } @@ -237,9 +251,6 @@ this.orgOptions.series[0].data.push(threadPeriod); } } - // - this.orgOptions.xAxis.data.push(this.duration); - this.orgOptions.series[0].data.push(this.threadNumber); }, convertProperty() { /// todo:下面4个属性是jmeter ConcurrencyThreadGroup plugin的属性,这种硬编码不太好吧,在哪能转换这种属性?