From b04f23615f148d12a4d0511b4b235e351f1a17c0 Mon Sep 17 00:00:00 2001 From: WangXu10 Date: Thu, 6 Jul 2023 10:52:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E7=B3=BB=E7=BB=9F=E8=AE=BE=E7=BD=AE):=20?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=8F=82=E6=95=B0=E8=AE=BE=E7=BD=AE=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sdk/service/SystemParameterService.java | 5 + .../controller/AuthSourceController.java | 2 + .../controller/SystemParameterController.java | 7 +- .../AuthSourceNonePermissionTest.java | 393 ++++++++++++++++++ .../resources/dml/init_permission_test.sql | 14 + 5 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 backend/services/system-setting/src/test/java/io/metersphere/system/controller/AuthSourceNonePermissionTest.java create mode 100644 backend/services/system-setting/src/test/resources/dml/init_permission_test.sql diff --git a/backend/framework/sdk/src/main/java/io/metersphere/sdk/service/SystemParameterService.java b/backend/framework/sdk/src/main/java/io/metersphere/sdk/service/SystemParameterService.java index 79de94c5c3..5ef11e3409 100644 --- a/backend/framework/sdk/src/main/java/io/metersphere/sdk/service/SystemParameterService.java +++ b/backend/framework/sdk/src/main/java/io/metersphere/sdk/service/SystemParameterService.java @@ -41,15 +41,20 @@ public class SystemParameterService { if (StringUtils.equals(param.getParamKey(), "base.url")) { example.createCriteria().andParamKeyEqualTo(param.getParamKey()); List baseUrlParameterList = systemParameterMapper.selectByExample(example); + String oldBaseUrl = null; if (CollectionUtils.isNotEmpty(baseUrlParameterList)) { SystemParameter parameter = baseUrlParameterList.get(0); if (!StringUtils.equals(parameter.getParamValue(), param.getParamValue())) { + oldBaseUrl = parameter.getParamValue(); systemParameterMapper.updateByPrimaryKey(param); } } else { systemParameterMapper.insert(param); } example.clear(); + if (StringUtils.isNotEmpty(oldBaseUrl)) { + //TODO 当前站点改变,mock环境的站点也需要改变 + } } else { example.createCriteria().andParamKeyEqualTo(param.getParamKey()); if (systemParameterMapper.countByExample(example) > 0) { diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/AuthSourceController.java b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/AuthSourceController.java index 333f4ea805..c4b948fba8 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/AuthSourceController.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/AuthSourceController.java @@ -72,6 +72,8 @@ public class AuthSourceController { @GetMapping("/update/{authId}/status/{status}") + @Operation(summary = "更新状态") + @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_UPDATE) @Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, details = "认证设置", sourceId = "#authSource.authId") public void updateStatus(@PathVariable(value = "authId") String authId, @PathVariable("status") String status) { diff --git a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemParameterController.java b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemParameterController.java index 73dba6f7c9..422ef0870c 100644 --- a/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemParameterController.java +++ b/backend/services/system-setting/src/main/java/io/metersphere/system/controller/SystemParameterController.java @@ -12,6 +12,7 @@ import io.metersphere.system.domain.SystemParameter; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; +import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -30,8 +31,8 @@ public class SystemParameterController { @PostMapping("/save/base-info") @Operation(summary = "保存基本信息") - @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_UPDATE) - @Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, details = "基本配置", sourceId = "#systemParameter.get(0).paramKey") + @RequiresPermissions(value= {PermissionConstants.SYSTEM_SETTING_READ_UPDATE, PermissionConstants.SYSTEM_SETTING_READ_CREAT}, logical = Logical.OR) + @Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, details = "基本配置", sourceId = "#systemParameter.get(0).paramKey") public void saveBaseParameter(@Validated @RequestBody List systemParameter) { systemParameterService.saveBaseInfo(systemParameter); } @@ -55,7 +56,7 @@ public class SystemParameterController { @PostMapping("/edit/email-info") @Operation(summary = "保存邮件信息") - @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_UPDATE) + @RequiresPermissions(value= {PermissionConstants.SYSTEM_SETTING_READ_UPDATE, PermissionConstants.SYSTEM_SETTING_READ_CREAT}, logical = Logical.OR) @Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, details = "邮件配置", sourceId = "#systemParameter.get(0).paramKey") public void editEMailInfo(@Validated @RequestBody List systemParameter) { systemParameterService.editEMailInfo(systemParameter); diff --git a/backend/services/system-setting/src/test/java/io/metersphere/system/controller/AuthSourceNonePermissionTest.java b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/AuthSourceNonePermissionTest.java new file mode 100644 index 0000000000..9b1676f9bf --- /dev/null +++ b/backend/services/system-setting/src/test/java/io/metersphere/system/controller/AuthSourceNonePermissionTest.java @@ -0,0 +1,393 @@ +package io.metersphere.system.controller; + +import com.jayway.jsonpath.JsonPath; +import io.metersphere.sdk.constants.PermissionConstants; +import io.metersphere.sdk.constants.SessionConstants; +import io.metersphere.sdk.dto.BasePageRequest; +import io.metersphere.sdk.util.JSON; +import io.metersphere.system.domain.SystemParameter; +import io.metersphere.system.domain.UserRolePermission; +import io.metersphere.system.mapper.UserRolePermissionMapper; +import io.metersphere.system.request.AuthSourceRequest; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.*; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.context.jdbc.SqlConfig; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.ResultMatcher; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) + +public class AuthSourceNonePermissionTest { + + @Resource + private MockMvc mockMvc; + + private static String sessionId; + private static String csrfToken; + + private static final String NONE_ROLE_USERNAME = "permission@fit2cloud.com"; + + private static final String NONE_ROLE_PASSWORD = "permission@fit2cloud.com"; + + private static final String ROLE_ID = "org_admin"; + + public static final String AUTH_SOURCE_ADD = "/system/authsource/add"; + + public static final String AUTH_SOURCE_List = "/system/authsource/list"; + + public static final String AUTH_SOURCE_UPDATE = "/system/authsource/update"; + + public static final String AUTH_SOURCE_GET = "/system/authsource/get/"; + + public static final String AUTH_SOURCE_DELETE = "/system/authsource/delete/"; + + private static final ResultMatcher CHECK_RESULT_MATHER = status().isForbidden(); + + private static final ResultMatcher CHECK_RESULT_OK = status().isOk(); + + + public static final String BASE_INFO_SAVE_URL = "/system/parameter/save/base-info"; + + public static final String BASE_INFO_URL = "/system/parameter/get/base-info"; + + public static final String EMAIL_INFO_URL = "/system/parameter/get/email-info"; + + public static final String EMAIL_INFO_SAVE_URL = "/system/parameter/edit/email-info"; + + public static final String EMAIL_INFO_TEST_CONNECT_URL = "/system/parameter/test/email"; + + private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError(); + + @Resource + private UserRolePermissionMapper userRolePermissionMapper; + + @BeforeEach + public void login() throws Exception { + MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/login") + .content("{\"username\":\"" + NONE_ROLE_USERNAME + "\",\"password\":\"" + NONE_ROLE_PASSWORD + "\"}") + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)) + .andReturn(); + sessionId = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.sessionId"); + csrfToken = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.csrfToken"); + } + + public AuthSourceRequest getAuthSource() { + AuthSourceRequest authSource = new AuthSourceRequest(); + authSource.setId(UUID.randomUUID().toString()); + authSource.setConfiguration("123"); + authSource.setName("测试CAS_" + UUID.randomUUID().toString()); + authSource.setType("CAS"); + return authSource; + } + + + /** + * 无权限 + * + * @throws Exception + */ + @Test + @Order(1) + @Sql(scripts = {"/dml/init_permission_test.sql"}, + config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED), + executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) + public void testNoPermission() throws Exception { + + //认证配置 + AuthSourceRequest authSource = this.getAuthSource(); + //校验权限: 添加认证权限 + this.requestPost(AUTH_SOURCE_ADD, authSource, CHECK_RESULT_MATHER); + + //权限校验: 查询认证权限 + this.testGetSourceList(CHECK_RESULT_MATHER); + + //权限校验: 修改认证权限 + authSource.setName("测试CAS修改"); + this.testUpdateSource(authSource, CHECK_RESULT_MATHER); + + //权限校验: 修改认证权限状态 + this.testUpdateStatus(authSource, CHECK_RESULT_MATHER); + + //权限校验: 查询认证权限详情 + this.testGetSourceById(authSource, CHECK_RESULT_MATHER); + + //权限校验: 删除认证权限 + this.testDelSourceById(authSource, CHECK_RESULT_MATHER); + + + //基本配置 + List systemParameters = getSystemParameters(); + //403 + //权限校验: 保存+编辑基础信息 + this.testSaveBaseInfo(systemParameters, CHECK_RESULT_MATHER); + //权限校验: 获取用户信息 + this.testGetBaseInfo(CHECK_RESULT_MATHER); + //权限校验: 保存+编辑邮件设置 + this.testEditEmailInfo(CHECK_RESULT_MATHER); + //权限校验: 获取邮件设置 + this.testGetEmailInfo(CHECK_RESULT_MATHER); + //权限校验: 测试邮件连接 + this.testEmailConnect(CHECK_RESULT_MATHER); + + } + + /** + * 只读权限 + * + * @throws Exception + */ + @Test + @Order(2) + public void testReadPermission() throws Exception { + //添加读权限 + addPermission(PermissionConstants.SYSTEM_SETTING_READ); + + + //获取最新权限 + this.requestGet("/is-login", CHECK_RESULT_OK); + //认证配置 + AuthSourceRequest authSource = this.getAuthSource(); + //403 + this.testAddSource(authSource, CHECK_RESULT_MATHER); + //200 + this.testGetSourceList(CHECK_RESULT_OK); + this.testGetSourceById(authSource, CHECK_RESULT_OK); + //403 + authSource.setName("测试CAS修改"); + this.testUpdateSource(authSource, CHECK_RESULT_MATHER); + this.testUpdateStatus(authSource, CHECK_RESULT_MATHER); + this.testDelSourceById(authSource, CHECK_RESULT_MATHER); + + + //基本配置 + List systemParameters = getSystemParameters(); + //403 + this.testSaveBaseInfo(systemParameters, CHECK_RESULT_MATHER); + //200 + this.testGetBaseInfo(CHECK_RESULT_OK); + //403 + this.testEditEmailInfo(CHECK_RESULT_MATHER); + //200 + this.testGetEmailInfo(CHECK_RESULT_OK); + //有权限 连接不通返回500 + this.testEmailConnect(ERROR_REQUEST_MATCHER); + } + + + @Test + @Order(3) + public void testAddPermission() throws Exception { + + addPermission(PermissionConstants.SYSTEM_SETTING_READ_CREAT); + //获取最新权限 + this.requestGet("/is-login", CHECK_RESULT_OK); + + AuthSourceRequest authSource = this.getAuthSource(); + //200 + this.testAddSource(authSource, CHECK_RESULT_OK); + this.testGetSourceList(CHECK_RESULT_OK); + this.testGetSourceById(authSource, CHECK_RESULT_OK); + + //403 + authSource.setName("测试CAS修改"); + this.testUpdateSource(authSource, CHECK_RESULT_MATHER); + this.testUpdateStatus(authSource, CHECK_RESULT_MATHER); + this.testDelSourceById(authSource, CHECK_RESULT_MATHER); + + + + //基本配置 + List systemParameters = getSystemParameters(); + //200 + this.testSaveBaseInfo(systemParameters, CHECK_RESULT_OK); + this.testGetBaseInfo(CHECK_RESULT_OK); + this.testEditEmailInfo(CHECK_RESULT_OK); + this.testGetEmailInfo(CHECK_RESULT_OK); + this.testEmailConnect(ERROR_REQUEST_MATCHER); + + } + + + @Test + @Order(4) + public void testUpdatePermission() throws Exception { + + addPermission(PermissionConstants.SYSTEM_SETTING_READ_UPDATE); + //获取最新权限 + this.requestGet("/is-login", CHECK_RESULT_OK); + + //认证配置 + AuthSourceRequest authSource = this.getAuthSource(); + //200 + this.testAddSource(authSource, CHECK_RESULT_OK); + this.testGetSourceList(CHECK_RESULT_OK); + this.testGetSourceById(authSource, CHECK_RESULT_OK); + authSource.setName("测试CAS修改"); + this.testUpdateSource(authSource, CHECK_RESULT_OK); + this.testUpdateStatus(authSource, CHECK_RESULT_OK); + //403 + this.testDelSourceById(authSource, CHECK_RESULT_MATHER); + + } + + @Test + @Order(5) + public void testDeletePermission() throws Exception { + addPermission(PermissionConstants.SYSTEM_SETTING_READ_DELETE); + //获取最新权限 + this.requestGet("/is-login", CHECK_RESULT_OK); + + AuthSourceRequest authSource = this.getAuthSource(); + //200 + this.testAddSource(authSource, CHECK_RESULT_OK); + this.testGetSourceList(CHECK_RESULT_OK); + this.testGetSourceById(authSource, CHECK_RESULT_OK); + authSource.setName("测试CAS修改"); + this.testUpdateSource(authSource, CHECK_RESULT_OK); + this.testUpdateStatus(authSource, CHECK_RESULT_OK); + this.testDelSourceById(authSource, CHECK_RESULT_OK); + + } + + + private void addPermission(String permissionId) { + UserRolePermission permission = new UserRolePermission(); + permission.setId(UUID.randomUUID().toString()); + permission.setRoleId(ROLE_ID); + permission.setPermissionId(permissionId); + userRolePermissionMapper.insert(permission); + } + + private void testSaveBaseInfo(List systemParameters, ResultMatcher resultMatcher) throws Exception { + this.requestPost(BASE_INFO_SAVE_URL, systemParameters, resultMatcher); + } + + public void testGetBaseInfo(ResultMatcher resultMatcher) throws Exception { + this.requestGet(BASE_INFO_URL, resultMatcher); + } + + + public void testGetEmailInfo(ResultMatcher resultMatcher) throws Exception { + this.requestGet(EMAIL_INFO_URL, resultMatcher); + } + + public void testEditEmailInfo(ResultMatcher resultMatcher) throws Exception { + + List systemParameters = new ArrayList<>() {{ + add(new SystemParameter() {{ + setParamKey("smtp.host"); + setParamValue("https://baidu.com"); + setType("text"); + }}); + add(new SystemParameter() {{ + setParamKey("smtp.port"); + setParamValue("8080"); + setType("text"); + }}); + add(new SystemParameter() {{ + setParamKey("smtp.account"); + setParamValue("aaa@fit2cloud.com"); + setType("text"); + }}); + add(new SystemParameter() {{ + setParamKey("smtp.ssl"); + setParamValue("true"); + setType("text"); + }}); + }}; + this.requestPost(EMAIL_INFO_SAVE_URL, systemParameters, resultMatcher); + } + + + public void testEmailConnect(ResultMatcher resultMatcher) throws Exception { + HashMap hashMap = new HashMap<>(); + hashMap.put("smtp.host", "https://baidu.com"); + hashMap.put("smtp.port", "80"); + hashMap.put("smtp.account", "aaa@fit2cloud.com"); + hashMap.put("smtp.password", "test"); + hashMap.put("smtp.from", "aaa@fit2cloud.com"); + hashMap.put("smtp.recipient", "aaa@fit2cloud.com"); + hashMap.put("smtp.ssl", "ture"); + hashMap.put("smtp.tls", "false"); + this.requestPost(EMAIL_INFO_TEST_CONNECT_URL, hashMap, resultMatcher); + } + + private List getSystemParameters() { + List systemParameters = new ArrayList<>() {{ + add(new SystemParameter() {{ + setParamKey("base.url"); + setParamValue("https://baidu.com"); + setType("text"); + }}); + add(new SystemParameter() {{ + setParamKey("base.prometheus.host"); + setParamValue("http://127.0.0.1:1111"); + setType("text"); + }}); + }}; + return systemParameters; + } + + private void testAddSource(AuthSourceRequest authSource, ResultMatcher resultMatcher) throws Exception { + this.requestPost(AUTH_SOURCE_ADD, authSource, resultMatcher); + } + + public void testGetSourceList(ResultMatcher resultMatcher) throws Exception { + BasePageRequest basePageRequest = new BasePageRequest(); + basePageRequest.setCurrent(1); + basePageRequest.setPageSize(10); + this.requestPost(AUTH_SOURCE_List, basePageRequest, resultMatcher); + } + + public void testUpdateSource(AuthSourceRequest authSource, ResultMatcher resultMatcher) throws Exception { + this.requestPost(AUTH_SOURCE_UPDATE, authSource, resultMatcher); + } + + public void testUpdateStatus(AuthSourceRequest authSource, ResultMatcher resultMatcher) throws Exception { + this.requestGet(AUTH_SOURCE_UPDATE + "/" + authSource.getId() + "/status/false", resultMatcher); + } + + public void testGetSourceById(AuthSourceRequest authSource, ResultMatcher resultMatcher) throws Exception { + this.requestGet(AUTH_SOURCE_GET + authSource.getId(), resultMatcher); + } + + public void testDelSourceById(AuthSourceRequest authSource, ResultMatcher resultMatcher) throws Exception { + this.requestGet(AUTH_SOURCE_DELETE + authSource.getId(), resultMatcher); + } + + private MvcResult requestGet(String url, ResultMatcher resultMatcher) throws Exception { + return mockMvc.perform(MockMvcRequestBuilders.get(url) + .header(SessionConstants.HEADER_TOKEN, sessionId) + .header(SessionConstants.CSRF_TOKEN, csrfToken)) + .andExpect(resultMatcher).andDo(print()).andReturn(); + } + + private void requestPost(String url, Object param, ResultMatcher resultMatcher) throws Exception { + mockMvc.perform(MockMvcRequestBuilders.post(url) + .header(SessionConstants.HEADER_TOKEN, sessionId) + .header(SessionConstants.CSRF_TOKEN, csrfToken) + .content(JSON.toJSONString(param)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(resultMatcher).andDo(print()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)); + } +} diff --git a/backend/services/system-setting/src/test/resources/dml/init_permission_test.sql b/backend/services/system-setting/src/test/resources/dml/init_permission_test.sql new file mode 100644 index 0000000000..ee9fbf6a0b --- /dev/null +++ b/backend/services/system-setting/src/test/resources/dml/init_permission_test.sql @@ -0,0 +1,14 @@ +-- 初始化一个没有任何权限的用户 +insert into user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source, + last_project_id, create_user, update_user, deleted) +VALUES ('permission1', 'permission_test', 'permission@fit2cloud.com', MD5('permission@fit2cloud.com'), UNIX_TIMESTAMP() * 1000, + UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', false); + +-- 初始化一个没有任何权限的用户组 +INSERT INTO user_role (id, name, description, internal, type, create_time, update_time, create_user, scope_id) +VALUES ('permission_member', '权限测试账号', '权限测试账号', 1, 'SYSTEM', 1620674220005, 1620674220000, 'admin', + 'GLOBAL'); + +-- 初始化用户和组的关系 +INSERT INTO user_role_relation (id, user_id, role_id, source_id, create_time, create_user) +VALUES (uuid(), 'permission1', 'org_admin', 'SYSTEM', 1684747668375, 'admin');